首页 > 解决方案 > mmap、axi 和来自 pcie 的多次读取

问题描述

我正在尝试通过 mmap 优化通过 pcie 读取数据。当时我们有一些工具允许从 PCIe 通信中读取/写入一个单词,但我想在一个请求中获取/写入尽可能多的单词。

我的项目使用带有 AXI 桥接器(2 个 PCIe 条)的 PCIe Gen3。

我可以成功地从总线上读取任何单词,但是在请求数据时我注意到了一种模式:

该模式一直持续到 addr 是 4 的倍数。似乎如果我请求第一个地址,AXI 会发送前 4 个值。有什么提示吗?这可能在我正在使用的驱动程序上吗?

以下是我使用 mmap 的方法:

        length_offset = tmp_offset_rw & ~(sysconf (_SC_PAGESIZE)-1);
    mmap_offset = (u_long)(tmp_barx_rw << 12) + length_offset;
    mmap_len = (u_long)(tmp_size * sizeof(int));
    mmap_address = mmap(NULL, mmap_len + (int)(tmp_offset_rw) - length_offset,
            PROT_READ | PROT_WRITE, MAP_SHARED, fd, mmap_offset);

    close(fd);
    // tmp_reg_buf = new u_int[tmp_size];
    // memcpy(tmp_reg_buf, mmap_address , tmp_size*sizeof(int));
  
    // for(int i = 0; i < 4; i++)
    //   printf("0x%08X\n", tmp_reg_buf[i]);
    
    for(int i = 0; i < tmp_size; i++)
      printf("0x%08X\n", *((u_int*)mmap_address + (int)tmp_offset_rw - length_offset + i));

标签: fpgammappci-e

解决方案


首先,驱动程序只是建立应用程序虚拟地址和物理地址之间的映射,而不涉及CPU和FPGA之间的请求。

PCIe 内存区域通常以非缓存方式映射,因此您在 FPGA 中看到的内存请求与 CPU 正在读取或写入的值的宽度完全对应。

如果你反汇编你写的代码,你会看到加载和存储指令在不同宽度的数据上运行。根据 CPU 架构,请求更宽数据宽度的加载/存储指令可能具有地址对齐限制,或者可能会因获取未对齐的数据而导致性能下降。

不同memcpy()的实现通常有特殊情况,以便它们可以用尽可能少的指令来传输一定数量的数据。

memcpy()可能不适合 MMIO的原因是memcpy()可能会读取比指定更多的内存位置,以便使用更大的传输大小。如果 MMIO 内存位置对读取造成副作用,则可能会导致问题。如果您要暴露一些行为类似于内存的东西,则可以memcpy()与 MMIO 一起使用。

如果您想要更高的性能并且在 PCIe 的主机端有一个可用的 DMA 引擎,或者您可以在 FPGA 中包含一个 DMA 引擎,那么您可以安排传输达到 PCIe 协议、BIOS 和配置所施加的限制FPGA 上的 PCIe 端点。DMA 是最大化吞吐量的方法,通常可以使用 128 或 256 字节的突发。

下一个需要解决以最大化吞吐量的问题是延迟,它可能会很长。DMA 引擎需要能够对请求进行流水线处理,以屏蔽从 FPGA 到内存系统并返回的延迟。


推荐阅读