Vivado HLSで簡単な高位合成を行ってみました。
少々クセが強そうな感じです。
チュートリアル
Vivado HLSを起動し、Create new projectをクリックして新規HLSプロジェクトを作成する。
Project nameにプロジェクトの名前、Locationに保存先を指定しNextをクリックする。
そのままでNextをクリックする。
次もそのままでNextをクリックする。
…をクリックしてボードファイルを設定する。
ボードファイルを設定したら、Finishをクリックする。数秒でプロジェクトが作成される。
プロジェクト作成画面のProject→New Sourceをクリックしてソースファイルを追加する。
ソースファイル(ここではtest.cpp)が追加された。このソースファイルに回路記述を書いていく。
ソース例は以下のような感じ。
#include <ap_int.h>
void test(
ap_uint<32>
data_in,
ap_uint<32>
*data_out
)
{
*data_out
= data_in;
}
ap_int.hをインクルードすればap_uint<n>で幅nの信号を表現できる。
引数のap_uint<n>がin(式の右辺)、ap_uint<n> *がout(式の左辺)となる。
例はdata_inをdata_outに出力するだけ。
ソースを開いて右側のDirectiveタグを開く。
変数名をダブルクリックでインターフェースを決めることができる。
Project→Project Settings をクリックしてSynthesisのTopFunctionを先ほど作成したソースの関数を設定する。
Solution→Run C Synthesis→Active Solutionをクリックし高位合成する。
高位合成が終わると回路規模などが確認できる。
Solution→Export RTLをクリックする。
OKをクリックするとIPが作成される。
プロジェクト/solution名/impl/ipに作成されたIPが入っている。
メモ
staticもしくはグローバル変数にすれば前回回路動作時の値を保持し続けられる。これらはRESETプラグマ(#pragma
HLS RESET
variable=”変数名”)でap_reset時に値を初期化させることができる。逆に初期化したくないならRESETプラグマにoffオプションをつける(#pragma
HLS RESET variable=”変数名” off)と初期化しない。
よくよくC言語的に考えたらstaticかグローバル変数は前回関数終了時点での値のままなわけで、当たり前といえば当たり前である。
ap_resetの極性はSolution
SettingsのGeneralにAddでconfig_rtlを追加してreset levelを選択することでローアクティブかハイアクティブかを設定可能。ちなみにデフォはハイアクティブ。ローアクティブにするとap_rst_nと信号名にnがつくようになる。
回路に高位合成で作成したIPを仕込み、VivadoでLaunch
SDKでXilinx
SDKを起動するとcアプリ用のドライバ(x<ip名>.h)を自動生成してくれる。
そのドライバの中にデータ型がu64で定義されたものが出てくることがある。そのままだと多分エラーになる。どっかでtypedef
long long u64;と追記しu64をlong
longと定義してやれば問題なく動く。
多分bit幅が32bitより大きく64bit以下の場合はu64で定義されるっぽい。それより大きい幅は複数のu32で構成された構造体で定義されるっぽい。
Vivadoでデザインに配置済のIPをHLSにて編集するとき、Synthesisした時点でVivado側で自動でIPの変更を検知して更新するかどうか聞いてくるようになるが、HLSでExport
RTLを行ってからIPの更新をしたほうが良い。SynthesisしただけでExport
RTL
せずIPを更新しようとするとエラーが出る。また、たまにVivadoがIPの変更を自動で検知しないことがあるが、IPのrepositoryをrefresh(Settings→IP→Repository→Reflesh
Allをクリック)してやると変更が検知される。
0 件のコメント:
コメントを投稿