ビジョンライブラリを使った高位合成の方法【(3)C/RTL協調シミュレーション】

ビジョンライブラリ
スポンサーリンク

本記事の概要

概要

Vitisビジョンライブラリを使った高位合成におけるC/RTL協調シミュレーションの方法を解説。
用例のcustomconvに含まれるFilter2D_accelを例にラプラシアンフィルタの高位合成と実装をめざす。本記事ではC/RTL協調シミュレーションから理解したIPのタイミングチャートをまとめる。

Xilinxの統合ソフトウェア開発環境では、Vitisビジョンライブラリ(以下、ビジョンライブラリ)をインクルードすることによって、画像処理機能を高速化(アクセラレーション)することが可能です。例えば、OpenCVのフィルタ処理などを、FPGAに実装可能なロジックへと高位合成することができます。

ビジョンライブラリのインクルードの方法は以下の記事にまとめています。

本サイトでは実際にVitisビジョンライブラリのFilter2D_accel関数を例に、ラプラシアンフィルタを行う画像処理IPのCシミュレーション、高位合成、C/RTL協調シミュレーション、そして実装を進めています。

実装は以前の記事で紹介したZynqで構成した静止画をディスプレイに表示するプロジェクトと組み合わせるつもりで、最終的にラプラシアンフィルタで処理した画像をディスプレイに表示させてみようと思います。

前回の記事で高位合成を行いました。

今回の記事ではC/RTL協調シミュレーションの方法を示した後、IPの入出力バス、そのタイミングチャートを確認できればと思います。

この記事の対象読者
  • Vitisビジョンライブラリを初めて扱う
  • ビジョンライブラリのC/RTL協調シミュレーションの方法を知りたい
  • 高位合成後のIPの入出力タイミングチャートを理解したい

C/RTL協調シミュレーション

実行

前記事で示した通り高位合成の完了後、その結果をC/RTL協調シミュレーションで確認しました。
図の通り、[▶]をクリックし、[Cosimulation]を選択します。

新しく[Co-Simulation Dialog]ダイアログボックスが立ち上がりますので、協調シミュレーションの設定をして、[OK]をクリックします。

Input Argumentsには、入力画像のビットマップのパスを選択しました。ビットマップ画像は、Cシミュレーションと同様に、次の解像度160×120の画像としています。

また、[Dump Trace]では[all]を選択しました。[Dump Trace]で波形を保存する変数を選択でき、[all]とすれば下位階層も含めて信号を確認することができます。

以上の設定のもと、[OK]をクリックし協調シミュレーションを実行します。

結果

220秒(3-4分)ほどかかり、協調シミュレーションが完了しました。

Filter2d_accelのレイテンシーは、22,287クロック(約220us)でした。

高位合成したIPの入出力信号のタイミングチャート

[Open Wave Viewer…]をクリックして、波形を確認しました。Vivadoが立ち上がり、各タイミングを確認することができます。

本記事では、このタイミングチャートのポイント、特に入出力変数のタイミングをそれぞれ図解しようと思います。

タイミングチャート全体

まずはタイミングチャート全体をざっと眺め一連の処理の大枠をつかみます。
波形の[Design Top Signal]を中心に確認しましょう。

[Design Top Signal]の各変数がFilter2d_accel IPのどのバスに対応しているかを図と表で整理しておきます。

Design Top Signalsの最上位のグループとその対応
分類Design Top Signalの変数IPのバス各バスでやり取りする信号
C InOuts
(入出力)
shift__rows__cols__…__returncontrol_s_axi・プロセッサからのパラメータ
・プロセッサに送るステータス
C Outputs
(出力)
img_outgmem2画像処理後の出力画像
C Inputs
(入力)
filtergmem1空間フィルタリング
img_ingmem0入力画像
img_in__filter__img_outcontrol_r_s_axi各配列のポインタ
Block-level IO
(内部バス)
ap_ctrl内部生成されるIPのステータス

RTLシミュレーションにおける変数とIPのバスの対応関係を踏まえて、全体のタイミングチャートをVivado Simulation の波形で確認しました。

まず、AXI4-Liteを通じて、(a)コントロールレジスタにデータを入力します。入力数によってレイテンシーは変わりますが、およそ数100nsくらいです。今回の協調シミュレーションでは320 nsかけて、データを入力し、その後コントロールレジスタのスタートビットに1を入力して、画像処理を開始します。

画像処理中はAXI4-Liteのcontrol_s_axiを通じてステータス(ap_ctrlの状態)を定期的に読み出し続けていました。それとは並列にまず(b)filter、次に(c)img_inをメモリから読み出し、(d)計算して得たimg_outをパイプライン処理でメモリに書き込んでいます

160×120ピクセルの画像(19,200)を処理するのに、22,287クロックかかっていました。1ピクセルあたり約1.16クロックです。

この一連の処理の流れの各過程をもう少し細かく見てみます。

(a) コントロールレジスタの設定

コントロールレジスタはcontrol_s_axiモジュールとcontrol_r_s_axiモジュールの2つが存在し、その両方でレジスタを設定する必要があります。

まず、control_r_s_axiモジュールについて。
こちらでは、画像とフィルタを格納する配列のポインタを設定します。

設定するコントロールレジスタ(配列のポインタ)
変数意味アドレスシミュレーションでの値
img_in入力画像の配列のポインタ0x1000
filterラプラシアンフィルタの配列のポインタ0x1800
img_out出力画像の配列のポインタ0x2000

control_r_s_axiに対応するimg_in__filter__img_outのグループ内の変数の波形を確認しましょう。
img_out, img_in, filterの順にフィルタを格納する配列のポインタを入力しているのがわかります。今回は、メモリとやり取りしていないので書き込む値は0となっていますが、Zynqに実装するときには実際の値を書き込まないといけませんね。

AXI4-Liteの書き込みや読み出しのプロトコルのイメージは以下の記事に記載しています。

AXI4における読み出し・書き込みのプロトコル

書き込み
M側のIP(今回はプロセッサ)が、AWチャネルに書き込むレジスタのアドレス、Wチャネルに書き込むデータを乗せて、S側のIP(今回はIPコアFilter_2d_accel)に送信します。
S側のIPが無事にアドレスとデータを受信したら、Bチャネルに無事に受信したかどうかを示す成否判定信号を乗せて、M側のIPに送信します。

読み出し
M側のIPが、ARチャネルに読み出したいレジスタのアドレスを乗せて、S側のIPに送信します。
S側のIPはアドレスを受信したら、Rチャネルに読みだしたデータを乗せて、M側のIPに送信します。

次に、control_s_axiについて。こちらでは、次の3パラメータを設定した後、画像処理を開始するスタート信号を送信します。

設定するコントロールレジスタ(値)
変数意味アドレスシミュレーションでの値
SHIFT空間フィルタリングのカーネルを定義するときのビット右シフトの回数0x108 (16進数で0x08)
ROWS入力画像の行数0x18120 (16進数で0x78)
COLS入力画像の列数0x20160 (16進数で0xa0)

波形を確認しましょう。何回か読み出しと書き込みが行われていました。

この各タイミングでの書き込み、読み出しをまとめると、以下の表のようになります。

タイミング書き込み or 読み出しアドレス意味
読み出し0x000x04ステータス読み出し。ap_idle(0x04)を確認
書き込み0x100x08shiftに8を代入
書き込み0x180x78rowsに120を代入
書き込み0x200xa0colsに160を代入
読み出し0x000x04ステータス読み出し。ap_idle(0x04)を確認
書き込み0x000x01スタートビットに1を代入。

ちなみに、アドレス0x00のap_ctrlのステータスを示すコントロールレジスタは次の通りです。

ap_ctrlのステータスを表すレジスタ
  • bit 0 : ap_start (R/W/COH)
  • bit 1 : ap_done (R/COR)
  • bit 2 : ap_idle (R)
  • bit 3 : ap_ready (R/COR)
  • bit 7 : auto_restart (R/W)

(R: read, W: write, COR: Clear on Read(読み出し時にレジスタ消去), COH: Clear on Handshake (ハンドシェイク時にレジスタ消去))

今回は、bit2でidle状態になっていることを確認したうえでパラメータの書き込みを行い、bit0をHighにして画像処理の開始を指示しています。

(b) gmem1 ラプラシアンフィルタ

スタートビットをHigh状態にすると、IPコアが自動でメモリ内のラプラシアンフィルタの配列からIPコアへの値の読み出しを開始します。
前回の記事で示した通り、ラプラシアンフィルタの配列はshort int型で、値はこのように指定しました(SHIFTは8)。

    filter_ptr[0] = 0; //0;
    filter_ptr[1] = 1 << SHIFT;
    filter_ptr[2] = 0; //0;

    filter_ptr[3] = 1 << SHIFT;
    filter_ptr[4] = -4 << SHIFT;
    filter_ptr[5] = 1 << SHIFT;

    filter_ptr[6] = 0; //0;
    filter_ptr[7] = 1 << SHIFT;
    filter_ptr[8] = 0; //0;

配列を絵にするとこんな感じです。この配列を1ワード(32bit)ずつリトルエンディアンで読み出しています。

また、バースト転送で5ワード、つまり配列全体を一気に読みだしています。
まず、バースト転送の方法を、ARチャネルを通じてIPコア(M側)からDDRメモリ(S側)に指示しています。今回、VitisHLSで生成された協調シミュレーションでは、ADDR=0x00、LEN=0x04、SIZE=010b、BURST=01bという風にARチャネルから信号を送っていました。信号の意味はこの通りです。

アドレス0x00からのデータを、転送回数5回(LEN=0x04)、バイト数4(SIZE=010b)、バースト転送タイプがインクリメント(BURST=01b)で読み出す

ここで、インクリメントはアドレス順に順次読み出すという意味になります。

このようにして、ラプラシアンフィルタを配列からバースト転送で一気に読み出します。

おすすめ書籍

AXI4バスの各チャネル信号の説明はFPGAプログラミング大全にまとめられています。
例えば、ARBURSTにどんな値を代入するとバースト転送タイプが何に変わるかなどがまとめられています。ZynqなどのXilinxのSoCを扱ううえでの必読書だと思いますので、ぜひ購入を検討してみてはいかがでしょうか?

(c) gmem0 入力画像

次に、入力画像img_inを読み出しが開始されます。
前回の記事で見た通り、入力画像は4バイト(1ワード)ずつ配列に格納されています。

ラプラシアンフィルタと同様にバースト転送で複数ワードが連続で読み出されます。このとき、入力画像を転送するAXIバスでのARチャネルの設定は

  • ARADDR : 0x0000, 0x0040, 0x0080, 0x00c0, …
  • ARLEN : 0x0f (転送回数16回)
  • ARSIZE : 010b (バイト数4 = 1ワード)
  • ARBURST : 01b (インクリメント)

となっています。つまり、アドレスを順次インクリメントしながら4バイトずつ転送回数16回で、メモリの配列img_inから値を読み出すように指示しています。

図にすると16ワードのバースト転送を行い、バースト転送が完了したら、アドレスを0x40(64バイト=16ワード)だけ更新し次のバースト転送を実行しています。

(d) gmem2 出力画像

img_outはimg_inで行った読み出し操作と同じことを書き込み操作で行います。
AWチャネルの設定もimg_inの読み出しにおけるARチャネルの設定と全く同じで、

  • AWADDR : 0x0000, 0x0040, 0x0080, 0x00c0, …
  • AWLEN : 0x0f (転送回数16回)
  • AWSIZE : 010b (バイト数4 = 1ワード)
  • AWBURST : 01b (インクリメント)

となっています。

16ワードずつバースト転送でメモリに画像処理後の出力画像を配列img_outに書き込み、バースト転送が終わったらアドレスを0x40更新して、次のバースト転送を行います。

まとめ

本記事では、Filter2D_accel関数のC/RTL協調シミュレーションを行い、高位合成したIPのタイミングチャートを確認できました。事前に確認しておくと、実際にVitisでアプリケーションを構築するときに何をレジスタに書けばよいのか・読み出せばよいのかが理解できます。
また、今回のIPで使用しているAXI4バスの使い方は覚えることが多く最初は理解に時間がかかります。しかし、実際に作成されたIPの動作を例にして読み解いていけば、理解を深めて、扱いにも慣れていけると思います。

最後までご覧いただきありがとうございました!

スポンサーリンク


参考:開発環境

環境
  • 開発用PC: Windows 10, 64bit
    • Vitis コア開発キット – 2021.2

次回の記事のリンク

コメント