小组内部培训-关于PCIe P2P传输软件设计

培训过程记录,

|   DDR(eg. 2GB)   |      |     DDR(eg. 8GB) |
        |                           |
||||||||||||||||||||      ||||||||||||||||||||
|       Z7         |      |         V7       |
|       CPU        | PCIe |        DMA       |-|SATA Disk|
|       DMA        |      |                  | 
||||||||||||||||||||      ||||||||||||||||||||

DMA:Direct Memory Access
non OS:
unsigned int *buf = (unsigned int *)0x50000000 //phy
*buf -> ldr访存汇编指令

OS:
unsigned int *buf = malloc(64); //virt

V7通过PCIe给Z7提供了64MB可见内存

CPU上的OS执行物理地址到虚拟地址的映射,映射的时候可以设置是否需要Cache
CPU -> Cache -> Memory(DDR/PCIe)
CPU -> Memory(DDR/PCIe)

为什么需要不带Cache的内存,不带Cache速度慢
eg. 外设/IP的寄存器就不能带Cache

系统中除了CPU还有DMA具有主动访问内存的能力
Direct: 搬运连续内存
Source -> Destination

SG: 提供了一次操作访问不连续的内存的能力
| Descriptor0 | Descriptor1 | Descriptor2 | ... | DescriptorN |  
  Src -> Dst    Src -> Dst    Src -> Dst          Src -> Dst   

假设搬运同样长度的数据1MB,SG比Direct慢多少呢?
Direct搬运连续1MB内存,SG的1MB内存假设分为5个块,5*64B,相对于1MB,5*64B/1MB~0%

                 8GB DDR
                  V7_1
                   |
 Z7(host)  --  PCIe Switch   --  V7_2 8GB DDR
             /      |     \  
           NVMe_1 NVMe_2 NVMe_3
           
CPU内存空间(物理地址)
0
         DDR
2GB           
         PCIe   0~64MB(BAR0,数据传输) 64~65(BAR1,寄存器控制) V7_1            64~128 V7_2 128~129 NVMe_1 129~130 NVMe_2...    
                0x6c000000~0x6d000000      
2GB+1GB

怎样用64MB的空间来访问V7板载的8GB的内存呢,显然需要FPGA实现一个滑动窗口,把这64MB的空间对准的8GB的任意一个位置
FPGA添加一个基地址寄存器比如base

|64MB|
   |
    -----------
         base+ |    
|   |   |    |64MB|           8GB                |

                       0x6c000000~0x6d000000 0~64MB
CPU   addr0(虚拟地址) -> addr1(物理地址) -> addr2(8GB内存的地址)
                                          |
                                         base

P2P:
NVMe_1(内部包含DMA) -> addr1 -> addr2(8GB内存的地址)
                     |
                    base
CRP中PCIMEM用于实现base
V7_1                    
PLCIRCBUF0 = {   0GB, 1GB  , add &PCIMEM0}
PLCIRCBUF1 = {   1GB, 1GB  , add &PCIMEM0}
PLCIRCBUF2 = {   2GB, 1GB  , add &PCIMEM0}

jsfsWrite(buf, len) buf > 64MB超过空间,所以在把buf写入文件系统之前,需要执行一个转换函数,把0~8GB的地址映射到0x6c000000~0x6d000000空间中
V7_2                    
PLCIRCBUF3 = {   0GB, 1GB  , add &PCIMEM1}
PLCIRCBUF4 = {   1GB, 1GB  , add &PCIMEM1}
PLCIRCBUF5 = {   2GB, 1GB  , add &PCIMEM1}

假设一个地址在1GB+1MB的位置即0x40100000,转换函数实现流程:
offset = 0x40100000 & 64MB = 0x100000 1MB
base = 0x40100000 - offset = 0x40000000
jsfsWrite(0x6c000000 + offset, len)
or
base = 0x40100000
jsfsWrite(0x6c000000, len)

在ft2000/4上,jsfsWrite里面传入的buf地址是虚拟地址,64MB虚拟地址,
ipraid_write()/nvme_write()在访问CPU DDR时传入的地址是虚拟地址,在访问FPGA DDR传入的地址是物理地址
所以在驱动中需要判断该虚拟地址属于CPU DDR还是FPGA DDR,对于FPGA DDR,需要将虚拟地址转换为物理地址,再调用ipraid_write()/nvme_write()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章