小組內部培訓-關於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()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章