このところ、Synthesijer を試してみたりして高位合成ツールを使っているが、基礎的な理解が足りないと感じている。
Vivado HLSも”
Vivado のライセンス”で書いたが、Activation Based Licenses では、Vivado HLS Evaluation License のライセンス期限が365日になっていたので、1年間評価で使えるはずだ。
Vivado HLSの教科書は、”
Vivado Design Suite ユーザー ガイド 高位合成 UG902 (v2014.1) 2014 年 4 月 2 日”とする。
このユーザーズガイドには、最初に”高位合成の理解”という項目があって、コード例を用いて高位合成の基本的なプロセスを説明してくれている。
コード例を下に引用する。
int foo(char x, char a, char b, char c) {
char y;
y = x*a+b+c;
return y;
}
Cの関数 foo は、3つの演算がある関数だ。Vivado HLSでCからHDLに合成されるとクロック周波数やFPGAの種類やグレードによって、何クロックで処理できるか不定だそうだが、7ページの”図 1‐1 : スケジュー リ ングおよびバインデ ィ ングの例”では、2クロックで処理されている。a, x, b の * と + を1クロックで処理して、最後の c を次のクロックで加算している。クロック周波数が低いか、FPGAの種類やグレードが速ければ1クロックになるそうだ。
最初のクロックの乗算 + 加算は DSP48 でできるそうだ。パイプライン化しなければ、同じ DSP48 リソースを次のクロックで使用することもできるのだろう?下に図を示す。
7ページの”図 1‐1 : スケジュー リ ングおよびバインデ ィ ングの例”を参照した。
次の例は、”制御ロジックの抽出とインプ リメ ンテーシ ョン、 および I/O ポー トのインプリメンテーシ ョン”を説明するためのコード例だそうだ。コード例を下に引用する。
void foo(int in[3], char a, char b, char c, int out[3]) {
int x,y;
for(int i = 0; i < 3; i++) {
x = in[i];
y = a*x + b + c;
out[i] = y;
}
}
今度は、入力の1つが配列になって、関数内部でも配列の内容を使用して、ループで順次演算を行っている。
Vivado HLSでは、配列はデフォルトで BlockRAM に合成されるそうだ。ポートに書いてあると BlockRAM へのインターフェース信号が合成されるそうだ。
9ページの”図 1‐2 : 抽出と IO ポー ト シーケンスの制御”では、4ステート (C0, C1, C2, C3) のステートマシンを回しながら演算を行う様子が書いてある。
C0ステートでは、使い回しのできる b + c を行う。
C1ステートでは、BlockRAMから配列データを読み出すためにアドレスとチップ・イネーブルを出力する。
C2ステートで BlockRAMからデータが出てくるのでラッチする。(ここでもクロック周波数が低ければ後段の乗算 + 加算を実行できるはずだ。つまり1クロック少なくなり得る)
C3ステートでは、a と BlockRAM から Read された配列データを乗算し、b + c の結果と加算する。
C0ステートを実行してから C1 ~ C3 を3回繰り返せば、この関数の演算は終了となる。
何も directive を指定しないと、そうなるらしい。UNROLL directive を指定すると、for ループを展開してfor 内部の演算器を3倍にして、for 内部の処理を3回繰り返す代わりに1回のみで演算が終了するだろう。(依存関係が無いから。)
9ページの”図 1‐2 : 抽出と IO ポー ト シーケンスの制御”を引用
わかりやすい資料だと思う。これを読んで、試しながらブログに書いてみたい。
- 2015年01月06日 05:26 |
- Vivado HLS
-
| トラックバック:0
-
| コメント:0