Vitis_Accel_Examples内の cpp_kernels/burst_rw のソースを読みます。
3部作になっています。
- 環境設定など(このページ)
- ソースを読む(このページ)
- 内部構造の話
ソースを眺める
ソースは src のしたにあります
- host.cpp :ホスト側のソース(OpenCL で結構難しい。コピペして使うことになりそう)
- - vadd.cpp :FPGA 側のソース
さて、ポイントは HLS のソースでもある vadd.cpp です。冒頭部分を引用します。
#pragma HLS INTERFACE s_axilite port = size
#pragma HLS INTERFACE s_axilite port = inc_value
#pragma HLS INTERFACE s_axilite port = return
ここでのポイントは2つ。1つは gmem で bundle された HLS INTERFACE m_axi の変数 a。もう1つは HLS INTERFACE s_axilite 。Vivado HLS(Vitis HLS) に慣れた人なら見覚えがある記述でしょう。OpenCL であるため extern "C" というのがちょっとした違いかもしれません。
通常の HLS とは違い、XRT でつかえるカーネルはある一定の命名規則とインタフェースを持っている必要があります。どうやら ap_fifo などは使えないようです。
XRT(Xilinx Runtime library)
突然出てきたキーワード XRT。ソースも github で公開されています。FPGA とユーザの間の API はSDSoC では UIO とか使ってました(Deprecated!!)が、XRT の導入によって整理されました。OpenCL をつかっているので、メモリの管理も整理されたと言ってよいでしょう。
XRT Controlled Kernel Execution Modelsでは幾つかの Model のケースを掲げています。図中の CU は Compute Unit の略。(Host Programingを参照)
XRT のモデルは Vitis HLS で生成される信号線(ap_start, ap_ready, ap_done, ap_continue)で見覚えがあるものばかりです。それが U50 のような PCIe の場合、レジスタとして CPU 側から見えます。(:a :href "https://www.xilinx.com/html_docs/xilinx2021_1/vitis_doc/devrtlkernel.html" "RTL Kernels")参照
オフセット | 名称 | 説明 |
---|---|---|
0x0 | 制御 | カーネル ステータスを制御および示します。 |
0x4 | グローバル割り込みイネーブル | ホストへの割り込みをイネーブルにします。 |
0x8 | IP 割り込みイネーブル | 割り込みの生成に使用する IP で生成された信号を制御します。 |
0xC | IP 割り込みステータス | 割り込みステータスを示します。 |
0x10 | カーネル引数 (アドレス 0x10 で開始) | スカラーおよびグローバル メモリ引数を含みます。 |
このように規定されており、0x10 以降が HLS の axilite と対応します。制御の為の信号線を on/off しないといけないか等は気にしなくてよく、OpenCL の仕組み(API)で吸収されます。
ホスト側の呼び出し
確認はしていませんが、、、buffer_rw はアドレスで AXIM は 64bit のアドレスを用意しているので、64bit になるはずです。また buffer はユーザ側が用意しなければならず、このソースでは次のようにしています。
結果を得る
次のようにして結果を得ています。 enqueueTask がカーネルの実行。つまり、なかで ap_start とかの信号線をアサートしているのでしょう。enqueueMigrateMemObjects で buffer_rw から情報を書き戻してます。つまり FPGA 側にあるメモリから HOST(すなわち Intel CPU) へ転送しています。
vadd 側のソース
これが内部バッファを使っていてバースト転送するソースになっていてちょっと難しいですが、やっていることは a というバッファのアドレスから値を読んで値を足して書き戻しています。
burstbuffer をつかって内部の SRAM を使うようにしています。a のバッファは FPGA 内のバッファです。あれ?いつ誰が FPGA 内のバッファへ情報を転送したのだ?
どうやってメモリを転送しているのだ?
OpenCL として host.cpp から転送命令はあるものの、vadd.cpp のソースに現れない誰かが HOST(CPU) から DEVICE(FPGA) へそしてその逆の転送をしています。