我正试图通过mmap优化通过pcie读取数据。我们有一些工具可以一次从PCIe通信中读取/写入一个单词,但我希望在一个请求中获得/写入所需的单词。
我的项目使用PCIe Gen3和AXI桥接器(2个PCIe条(。
我可以成功地从总线上读取任何单词,但在请求数据时我注意到了一个模式:
- 请求地址0中的数据:AXI主机请求4个地址的数据,初始地址为0
- 请求地址0和1中的数据:两个AXI请求:第一个类似于上面的请求,后面是3个地址的数据的读取请求,初始addr为1
- 请求数据从地址0到2:3 AXI请求:前两个与前一个相似,后面是读取请求的2个地址的数据,初始addr为2
模式一直持续到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%08Xn", tmp_reg_buf[i]);
for(int i = 0; i < tmp_size; i++)
printf("0x%08Xn", *((u_int*)mmap_address + (int)tmp_offset_rw - length_offset + i));
首先,驱动程序只设置应用程序虚拟地址和物理地址之间的映射,但不涉及CPU和FPGA之间的请求。
PCIe内存区域通常以未缓存的方式进行映射,因此您在FPGA中看到的内存请求与CPU正在读取或写入的值的宽度完全对应。
如果您对编写的代码进行反汇编,您将看到加载和存储指令对不同宽度的数据进行操作。根据CPU架构的不同,请求更宽数据宽度的加载/存储指令可能具有地址对齐限制,或者获取未对齐的数据可能会带来性能损失。
不同的memcpy()
实现通常具有特殊情况,因此它们可以使用尽可能少的指令来传输一定量的数据。
CCD_ 2可能不适合MMIO的原因是CCD_。如果MMIO内存位置对读取造成副作用,则可能会导致问题。如果您要公开一些行为类似内存的东西,那么可以将memcpy()
与MMIO一起使用。
如果您想要更高的性能,并且PCIe的主机端有可用的DMA引擎,或者您可以在FPGA中包含DMA引擎,那么您可以安排传输,最高可达PCIe协议、BIOS和FPGA上PCIe端点的配置所施加的限制。DMA是最大化吞吐量的方法,通常可以使用128或256字节的突发。
为了最大限度地提高吞吐量,需要解决的下一个问题是延迟,它可能相当长。DMA引擎需要能够对请求进行流水线处理,以掩盖从FPGA到存储器系统再到存储器系统的延迟。