タイトルからしてネタバレですが、とりあえず失敗してみましょう。ソフトウェア技術者がなぜハードウェア設計につまずくかがわかると思います。
(この連載、いつになったら終わるんだろう。。。)
準備
1 環境
- OS: Ubuntu 16.04 LTS (or 18.04 LTS), win10版はできますがサポート外です
- Vivado 2019.1 を /tools/Xilinx/Vivado/2019.1 にインストール
(他のバージョン、特にVivado 2019.2はサポート外です!!)
2 Board Definition File (BDF) を設定
搭載されているFPGAに合わせて予め色々設定がされているので、初心者の方は設定しておくことをお勧めします。Ultra96のメーカ(AvNet)からBoard Definition Fileをクローンして所定のディレクトリに置きます。
$ git clone git://github.com/Avnet/bdf
$ sudo cp -R bdf/* /tools/Xilinx/Vivado/2019.1/data/boards/board_files/
3 今回のソースコードを準備
コンテストチュートリアルのリポジトリに置いています。Vivado HLS(高位合成ツール)でプロジェクト作成後にコピーするので、予めcloneしておいてください。
テストベンチ、パラメータは前回と同じものを使います。
- testbench_input.txt
- testbench_output.txt
- weight_l0.txt
- bias_l0.txt
以降、管理者権限で実行します。
Vivado HLSの起動と初期設定
Vivado HLSのパスを通してから起動します。.bashrc
に書いておけばパスは最初から通ります。
# source /tools/Xilinx/Vivado/2019.1/settings64.sh
# Vivado_hls &
Vivado HLSが起動するのでNew Project
を選択→New Project ウインドウで
- Project name: HW_conv_l0_1 (好みの名前でよいですが。。)
- Location: (home directory)/xilinx/HLS_proj/
としてNext
, 次のAdd/Remove Files C-based source files
,C-based testbench files
は共にNext
をクリック。
Solution Configurationで Part Selection ->「...」をクリックし
Boards
でUltra96v2 Evaluation Platform
を選択しOK -> Finish.
Ultra96V2 Evaluation Platformが表示されない場合はBDFが適切な場所に置かれてないと思います。設定を確認してください。
プロジェクト設定が終わるとGUIが起動してコードが書ける状態になります。次に、ソース一式をプロジェクトに読み込みます。HLS設計の鉄則は予め合成対象コードをソフトウェアで確実に動作するように検証しておくことです。つまり、Vivado HLSで一からソフトコードを書くことはないはずです!
まずクローンしたサンプルコードをプロジェクトのディレクトリ直下に作ったsrc
に置きましょう。
# cd (home directory)/xilinx/HLS_proj/HW_conv_l0_1
# mkdir src
# cp (コンテストのリポジトリをクローンした場所)/Inference_HLS_1/* ./src
- HW_kernel.cpp
- HW_main.cpp
に加えて、テストベンチ・パラメータ
- testbench_input.txt
- testbench_output.txt
- weight_l0.txt
- bias_l0.txt
一式をコピーします。
メイン画面で Source -> 右クリック -> Add Files... を選択しソースファイルを置いたsrc
からtestbench_input.txt, testbench_output.txt, weight_l0.txt, bias_l0.txt, HW_kernel.cpp, HW_main.cpp を読み込みます。
こうなります↓
Project -> Project Settings ... をクリックして Simulation -> Add Files ... をクリックし、HW_main.cpp
を読み込み、 Options -> Optimizing Compile を選択
Synthesis -> Top Function -> Browse をクリックして kernel (HW_kernel.cpp
) を選択しOKをクリック
SimulationとSynthesisを設定したらOKをクリックしてProject Settingsを閉じる.
Vivado HLSツールのお約束として、検証(C-Simulation)のメイン関数(今回はHW_main.cpp
)を別に読み込む必要があったので、設定しています。
シミュレーションの実行
ソフトウェア検証と同じことをしていますが、一応、Vivado HLSでもやってみましょう。Run C SimulationをクリックしてOKをクリックください。シミュレーションが実行されてUbuntuで実行した場合と同じ結果になるはずです。
↑こんな感じにログが出力される。今回はお試しですが、回路設計時にはこれを繰り返してソフトの検証を行ってください。
ハードウェア合成
まずはHW_main.cpp
とHW_kernel.cpp
のプリプロセッサの定義をアンコメントします
//#define HLS
↓
#define HLS
これで高位合成記述を対象に合成が行われます。
いよいよ高位合成です!メニューのC Synthesis
をクリックして高位合成を行いましょう。
しばらくするとVivado HLS Console にFinished C Cynthesisが表示されて合成が終わります。レポートを見て合成結果を見てみましょう。どれどれ、Latencyってのがデータを送って処理が終わるまでの時間だから‥
ちょっとびっくりしましたが、`Detail`をクリックすると詳細が表示されます。どうやらLoop1〜Loop3が`?(わかりませーん)`だから性能が見積もれない、ということです。 これはデータの読み出しにwhile()文を使っている→ループ回数が不明だからですね。データ出力転送は固定回数のfor()文で記述しましたから665859サイクル(クロック)なので、もし100MHz(10nsクロック周期)の場合は6658590ns、つまり6.8ms間隔で処理が終わるということです。肝心の畳み込みは、、
え、2227967424サイクル??てことは100MHz(10ns)で22,279,674,240nsですか、、つまり**約22秒??**遅い。。。
(入力バッファsrc_img
)= 416 x 416 x 3 x 32bit(float) / (18 x 1024) 〜 920 (端数は繰り上がる)
(出力バッファdst_img
)= 102 x 102 x 64 x 32bit / (18/1024) 〜 1181 (端数は繰り上がる)
入出力バッファをなんとか削ればよいということですね。その割には他のハードウェア資源(DSPブロック,LUT)の利用率は1%程度です。。この割合がアンバランスということはFPGAメーカーが意図している回路が設計できていないということですね。
つまりどういうことだ
ソフトウェアでよく書いている作法をそのまま高位合成しても
- とりあえず合成はできる
- 性能が全く出ない。そもそも性能が見積もれないことが多い。。
- ハードウェア量が爆発してしまう。。特に内臓メモリ(BRAM)数。
ハードウェアを意識したコードの修正(リファクタリング)が必要です。次回はリファクタリングしてみましょう。