PCIeに乗せるXilinx FPGAのBRAMとのDMA通信のサンプルを動かす


自分用メモ。

丁寧にやる場合は以下のリンク先を参照してください。

要約

自作ipを試す前段階として、Alveo 280上にVivado使ってxdma controllerとBRAM置いて、ホスト(Linux)から叩くサンプルを動かした。

環境

項目 概要
Linux Distribution CentOS Linux release 7.9.2009 (Core)
Linux Kernel 3.10.0-1160.45.1.el7.x86_64
FPGA Board Alveo u280
Vivado 2021.1

Vivadoでやること

プロジェクト作成

ボード選ぶだけ、特記なし。

Blockデザイン

[Create Block Design]で作っていく。
[Board] > [Miscellaneous] > [PCI Express]を選択し、[DMA/Bridge Subsystem for PCI Express]を選択し、[OK]

DMAのブロックが出たら[Run Block Automation]をクリックし、今回がデフォルトで[OK]をクリック。

こんな感じになる。

[Add IP]で[AXI BRAM Controller]と[Block Memory Generator]を追加。
[AXI BRAM Controller]をダブルクリックして、[BRAM Options]の[Number of BRAM interfaces]を1に変更し、[OK]。

終わったら[Run Connection Automation]。
[AXI SmartConnect]が追加されてこんな感じになる。

ホストからアクセスするアドレスを変更

上部の[Address Editor]をクリック。
[/axi_bram_ctrl_0/S_AXI]の[Master Base Address]を

[ 0x0000_C000_0000 ]
[ 0x0000_0000_0000 ]

に変更。

後は[Create HDL Wrapper]して[Generate Bitstream]。
終わったら[Open Hardware Manager]して書き込み。

書き込みが終わったらrebootしておいた方がいいかもしれない。(自分の環境だとrebootしないと実行に失敗した)

ホストでやること

ドライバのコード取得

git clone https://github.com/Xilinx/dma_ip_drivers.git
chmod 777 -R dma_ip_driver/XDMA/linux-kernel/

ドライバのmake

cd dma_ip_driver/XDMA/linux-kernel/xdma
sudo make install

ここで

cp: cannot create regular file '/lib/modules/[linuxカーネルのバージョン的なの]/extra/xdma.ko': Permission denied

が出る場合は、あまり良くないが以下を実行。(rootでやっても自分の環境でもできなかった)

chmod 777 -R /lib 

toolのmake

cd ../tools
make

実行

modprobe xdma
cd ../tests
sudo ./run_test.sh # sudoじゃないと動かなかった

結果

Error at line 91, file reg_rw.c (22) [Invalid argument]                                                                                                       │
./run_test.sh: line 28: [: ==: unary operator expected                                                                                                        │
Error at line 91, file reg_rw.c (22) [Invalid argument]                                                                                                       │
./run_test.sh: line 28: [: ==: unary operator expected                                                                                                        │
Error at line 91, file reg_rw.c (22) [Invalid argument]                                                                                                       │
./run_test.sh: line 28: [: ==: unary operator expected                                                                                                        │
Info: Number of enabled h2c channels = 1                                                                                                                      │
./run_test.sh: line 44: [: ==: unary operator expected                                                                                                        │
Error at line 91, file reg_rw.c (22) [Invalid argument]                                                                                                       │
Error at line 91, file reg_rw.c (22) [Invalid argument]                                                                                                       │
Error at line 91, file reg_rw.c (22) [Invalid argument]                                                                                                       │
Info: Number of enabled c2h channels = 1                                                                                                                      │
Info: The PCIe DMA core is memory mapped.                                                                                                                     │
Info: Running PCIe DMA memory mapped write read test                                                                                                          │
      transfer size:  1024                                                                                                                                    │
      transfer count: 1                                                                                                                                       │
Info: Writing to h2c channel 0 at address offset 0.                                                                                                           │
Info: Wait for current transactions to complete.                                                                                                              │
/dev/xdma0_h2c_0 ** Average BW = 1024, 15.291114                                                                                                              │
Info: Writing to h2c channel 0 at address offset 1024.                                                                                                        │
Info: Wait for current transactions to complete.                                                                                                              │
/dev/xdma0_h2c_0 ** Average BW = 1024, 13.748103                                                                                                              │
Info: Writing to h2c channel 0 at address offset 2048.                                                                                                        │
Info: Wait for current transactions to complete.                                                                                                              │
/dev/xdma0_h2c_0 ** Average BW = 1024, 13.576580                                                                                                              │
Info: Writing to h2c channel 0 at address offset 3072.                                                                                                        │
Info: Wait for current transactions to complete.                                                                                                              │
/dev/xdma0_h2c_0 ** Average BW = 1024, 13.801841                                                                                                              │
Info: Reading from c2h channel 0 at address offset 0.                                                                                                         │
Info: Wait for the current transactions to complete.                                                                                                          │
/dev/xdma0_c2h_0 ** Average BW = 1024, 16.508408                                                                                                              │
Info: Reading from c2h channel 0 at address offset 1024.                                                                                                      │
Info: Wait for the current transactions to complete.                                                                                                          │
/dev/xdma0_c2h_0 ** Average BW = 1024, 16.165699                                                                                                              │
Info: Reading from c2h channel 0 at address offset 2048.                                                                                                      │
Info: Wait for the current transactions to complete.                                                                                                          │
/dev/xdma0_c2h_0 ** Average BW = 1024, 13.808727                                                                                                              │
Info: Reading from c2h channel 0 at address offset 3072.                                                                                                      │
Info: Wait for the current transactions to complete.                                                                                                          │
/dev/xdma0_c2h_0 ** Average BW = 1024, 13.420708                                                                                                              │
Info: Checking data integrity.                                                                                                                                │
Info: Data check passed for address range 0 - 1024.                                                                                                           │
Info: Data check passed for address range 1024 - 2048.                                                                                                        │
Info: Data check passed for address range 2048 - 3072.                                                                                                        │
Info: Data check passed for address range 3072 - 4096.                                                                                                        │
Info: All PCIe DMA memory mapped tests passed.                                                                                                                │
Info: All tests in run_tests.sh passed.

上の方にエラーが出て少しびっくりしてしまったが、
run_test.shの当該箇所はh2c(Host to Card)及びc2h(Card to Host)のチャンネル数を数えており、チャンネル数が4未満の場合はエラーが出るっぽい。

BRAMに転送、受診は出来ているっぽいので、ホストコードとipを少し弄り、DMAシステムへのipの接続を試していきたい。