EDKでPCIe+DDR3のアクセラレータフレームワークを作る(1)

技術紹介

C705はじめ,ちょっと大規模なFPGAの評価キットにはPCIeとDDR3メモリが搭載されています.パソコンに接続するアクセラレータを簡単に開発できるように,という想定だと思うのですが,意外とDDR3コントローラやPCIeを使いこなすのに時間がかかって,本来自分が作りたいカーネル部分の構築までの道のりが遠かったりします.

というわけで,EDK(XPS)を使って,手軽にPCIeとDDR3を使ったアクセラレータ開発のためのフレームワークを用意する手順をまとめてみました.簡単に言うと,「目指せ!!GPUみたいに簡単に使えるFPGAアクセラレータフレームワーク」なわけです.

このエントリでは,作るもののイメージとサンプルプロジェクト一式,試し方を紹介します.作り方の手順は「EDKでPCIe+DDR3のアクセラレータフレームワークを作る(2)」をどうぞ.

はじめに

DDR3はMIG,PCIeはハードIPを使うIPコアがXilinxから提供されています.それらは,ISE Logic Editionでも使えるので,価格という意味ではお手軽なのですが,いざ使おうとすると,AXI4-Stream上でPCIeのTLPを制御したり,メモリコントローラの上位部分を書いたりしないといけません.

EDKを使えば,お手軽にPCIeとDDR3を使うことができます.残念ながらEDKが上位エディションなので,お金の面ではコストがかかってしまいますが,開発コストはかなり削減できます.もし,KC705をこれから購入しようとしていてEDKのライセンスのない人は,KC705 Embedded Kitを購入するといいかもしれません(普通のより$200くらい高い).

今回作るシステム

今回作るシステムの概略は,次の通りです.

cdma_pcie_axi_overview

ホストPC上のソフトウェアからFPGA上のロジックにデータを投入→動作をキック→結果を取得といった一連の操作ができるようなフレームワークの開発を想定しています.冒頭にも書いた通り,GPUのようにFPGAが使えるようになるといいな,というのが目論みです!!

AXIで手軽にIPコアをつなごう

PCIe,DDR3コントローラを個別に活用するコアの部品はXilinxから提供されていますが,実際に使うためにはそれら(と,自分のロジック)を接続する必要があります.

ここで登場するのがAMBA AXI4です.詳しくは,Xilinxのページをみてください.乱暴にまとめると,

  • 標準規格でIPコア同士をつないじゃおうぜ
  • 各コアを,メモリ空間上の一意のアドレスでアクセスできるようにしちゃおうぜ

というような規格です.

もう一人の立役者CDMA

AXI4でコア同士が接続,メモリ空間にマッピングできたとしても,メモリ空間上のデータのやりとりを誰か(たとえばホストPC)がハンドリングするのは面倒です.そこで登場いただく,もう一人の立役者がCentral DMA Controller(CDMA)です.

CDMAに「AXI空間上のどこからどこにデータを送れ!」と指示すると,CDMAはデータの読み書きを自動的にハンドリングしてくれます.便利ですね.

CDMA自体もAXI4メモリ空間上に配置され,制御レジスタへはメモリ読み書きでアクセスできます.

作ってみよう…の前に

作ってみるのは,話が長くなるので,ここにサンプルプロジェクト一式をおいておくことにします.

pcie_ddr3_test.zip

合成,配置配線済みのbitファイルは,↓

axi_cdma_system_top.bit

ちなみに,試すためのLinux上のソースコード一式は↓です

axi-pcie.tar

試し方

用意するもの
  • 上記ソースコード一式
  • KC705
  • LinuxなホストPC(メモリ512MB以上搭載,かつカーネルは512MB以内で動作するよう設定)
やってみよう

DDR3/PC -(PCIe)-> DDR3/FPGA -(DMA/AXI)-> -(PCIe)-> DDR3/PC というテストをします.PCIe上に次のように見えていることを想定しています.アドレスが異なる場合には,Makefileのパラメタを変更してmakeする必要があります(…ダサい)

02:00.0 Memory controller: Xilinx Corporation Default PCIe endpoint ID
 Subsystem: Device 0007:10ee
 Flags: bus master, fast devsel, latency 0, IRQ 7
 Memory at e0000000 (64-bit, prefetchable) [size=128K]
 Memory at d0000000 (64-bit, prefetchable) [size=256M]
 Capabilities: <access denied>

さすがにダサいのでBAR0を動的に取得するように書き直しました.詳しくは,こちらをご覧ください.

(0) 0x40000000を読み出してみる

例えば,↓のようにすると0x40000000から1024バイトのデータを読み表示します.

 ./axi-pcie/test-read 0x40000000 1024

適当な値が表示されるはずです

(1) BAR1にデータを書きます.

例えば,↓のようにするとBAR1(0xd0000000)から1024バイトの数列を書きます.実際には,データはPCIe経由でFPGAボード上のDDR3メモリに書き出されます.

./axi-pcie/test-seq 0xd0000000 1024

(2) DMAを実行する dma_testを実行してFPGAのCDMAを動作させます.

 ./dma_test AXIソースアドレス AXIディスティネーションアドレス 長さ PCメモリ空間アドレス

例えば

 ./dma_test 0x40000000 0x20000000 1024 0x40000000

実は,FPGA上の回路的に,ソースアドレスの0x40000000はAXI4メモリ空間でのDDR3の先頭アドレスに,ディスティネーションアドレスの0x20000000はAXI4メモリ空間でのPCIeエンドポイントの先頭アドレスに対応させています.(a)つまり,このコマンドで,FPGAボード上のDDR3の先頭から1024バイトがPCIeに書き出されることになります.(b)PCIeエンドポイントに書き出されたデータの書き出し先は最後の引数で指定したPCメモリ空間アドレスにマッピンされます.

(a)→(b)の一連の結果,DDR3メモリの先頭から1024バイトのデータがホストPCの0x40000000にコピーする,という操作になります.

(3) 0x40000000を読み出す

0x40000000から1024バイトのデータを読み表示します.

./axi-pcie/test-read 0x40000000 1024

(0)で確認したときと違って,0x40000000に0xd0000000に書いたのと同じように数列が読み出されていることでメモリコピーができていることが確認できます.

コメント

タイトルとURLをコピーしました