【问题标题】:forcing 32 bit access using python mmap?使用 python mmap 强制 32 位访问?
【发布时间】:2019-07-29 01:42:58
【问题描述】:

我在 64 位 arm 处理器上运行 64 位 python。 该处理器的 AXI 总线上的一个连接到 FPGA(将总线和时钟域更改为 32 位宽的总线)。 这块硬件不喜欢64位访问...

我正在尝试像这样(在一个类中)通过 python mmap 访问这个 FPGA:

def __init__(self, base, len):
    self.base = base
    self.fd = open("/dev/mem", "r+")
    self.lw = mmap.mmap(self.fd.fileno(),
                        len,
                        mmap.MAP_SHARED,
                        mmap.PROT_READ | mmap.PROT_WRITE,
                        offset=base)

def get_U32(self, offset):
    s = self.lw[offset:offset+4]
    return struct.unpack("<I", s)[0]

这个想法是get_U32() 将从总线读取一个 32 位字(因此偏移到偏移+4 读取)。 可悲的是,似乎 mmap 无论如何都要对总线执行 64 位访问(我假设是某种用于性能优化的缓存),然后执行 32 位“转换”。底层的 FPGA 不爽……

在 C 程序中,我只写:

data = *((uint32_t *) address);

...CPU 似乎在其 AXI 总线上轻轻地执行 32 位访问,这是底层硬件更喜欢的...。 (所以现在,我有一个(缓慢的)解决方法,python 需要一个 C 程序通过管道连接硬件)

有没有办法强制 64 位 python 执行 32 位访问,因为前面的 C 行显然成功了?

这里写的是关于读32位的问题,但是当然也需要写32位...

【问题讨论】:

  • 你确定吗?在 FPGA 上,查看最后的 32 位总线,使用 C 程序时我只看到一个频闪灯,而使用 python 时我看到 2 个频闪灯:因此我的假设是 C 程序只访问 32 位。据我了解,AXI 上的一些信号允许比最大 64 位更短的访问。也许我错了,因为我看不到那条总线,但是 C 和 python 的访问在远端明显不同。
  • 如果那个 C 程序是 64 位的,它仍然使用 64 位来读取地址。假设它与总线大小有关并没有真正的意义。此外,您在应用程序中所做的一切都在它的虚拟内存空间中,您甚至不处理物理内存地址。
  • mmap 使用操作系统访问内存。 C 代码通过其地址直接访问 32 位量。你在比较苹果和橘子。
  • @martineau。同意。那么,你能从 python 进行“苹果”访问吗?
  • 您可以使用this answer 中显示的di() 函数执行类似的操作。您可能还想尝试使用 32 位版本的 Python 解释器来运行您的脚本。

标签: python 32bit-64bit mmap


【解决方案1】:

基于@martineau 的想法,可以使用python ctypes 修复双探针,例如:

s = ctypes.c_uint32.from_buffer(self.lw, offset).value #read

types.c_uint32.from_buffer(self.lw, offset).value = s #write

这似乎确实迫使 python 进行与 C 中相同的 32 位访问,并移除 32 位总线上的双重读取或写入探针。

然而,遗憾的是,python 似乎在每次写入之前都会进行读取。 所以上面的解决方案非常适合阅读,但是在写入时,我仍然在写入访问之前获得了读取访问权限。在 C 中,我当然可以在编写时获得一次写入访问权限。

我将这个发布给其他可能感兴趣的人。如果您对最后一个问题有解决方案(先读后写),请发布。

【讨论】:

  • 我们很幸运地使用了来自this answermemoryview 解决方案来解决同一问题。
【解决方案2】:

解决这个thread

你可以试试这样的:

 def __init__(self,offset,size=0x10000):
    self.offset = offset
    self.size = size
    
    mmap_file = os.open('/dev/mem', os.O_RDWR | os.O_SYNC)
    mem = mmap.mmap(mmap_file, self.size,
                    mmap.MAP_SHARED,
                    mmap.PROT_READ | mmap.PROT_WRITE,
                    offset=self.offset)
    os.close(mmap_file)
    self.array = np.frombuffer(mem, np.uint32, self.size >> 2)
    
def wread(self,address):
    idx = address >> 2
    return_val = int(self.array[idx])
    return return_val
    
def wwrite(self,address,data):
    idx = address >> 2
    self.array[idx] = np.uint32(data)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-17
    • 2012-09-22
    • 2011-01-06
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    • 2012-11-01
    相关资源
    最近更新 更多