7月17日(火)、7月18日(木)にXilinx本社のセミナルームで、”AutoESLを使用したハイレベルの合成”という題のセミナを受けてきました。

2日間ともお昼の後は眠かったんですが、特に1日目は前の夜がとても蒸し暑く寝苦しかったので、とっても眠く夢心地で聞いていたので、誤解や聞き間違いがあるかもしれませんので、眉につばをつけて御覧ください。

以前、展示会のデモでCatapult C Synthesis のデモを見せてもらったことがあります。その時は、何の回路か忘れましたが、レイテンシとスループットを設定して簡単にいろいろな構成の回路を生成していました。これはとっても素敵なことだと思いました。FPGAを使っていて何が困るかというと、レイテンシを最短に、スループットを最小にしたいという妄想?にとらわれている時に、ぎりぎりのところを狙うとします。このくらいパイプラインしたら、この動作周波数で行けるかな?というギリギリのところを狙った時に、HDLを書いて論理合成、インプリメントするまでは、その回路で行けるかどうかわからないことです。インプリメントして結果を見た時にだめだったとなった時に、色々、ツールのエフォートレベルを変えてみたり、ダメだったら配置制約を加えてクリティカルパスを潰していきます。でも、そういう時は往々にして、他のところがクリティカルパスに新たになってもぐらたたきゲームの用になったりします。そうすると回路を書き換えてパイプライン段数を変更したりしました。データパス系だけだと比較的簡単にパイプラインできることが多いですが、制御系が絡んでいたりするとだと作り直しになったりします。
そこでHigh Level Synthesis(HLS) を使って、お手軽にレイテンシとスループットを設定して変更しながら、色々な回路を生成してもらって、ピッタリの動作周波数で動くものを選べれば簡単なのにと思いました。これは時間と労力が劇的に少なくなるとっても素敵なことです。でもツールの価格が高いという欠点がありました。
AutoESLはVivado のSystem Editon に組み込まれるそうなので、お手軽に使えそうです。期待してセミナに行きました。結論から言うとAutoESLはそういうツールではないようです。C言語からVHDL、Verilog、SystemCを合成してくれますが、お手軽にレイテンシとスループットを設定して回路を生成してくれるツールではないとの説明でした。C言語で書いたアルゴリズムをHDLに変換できるのですが、どのように変換するかはディレクティブで指定するようです。PIPELINEやDATAFLOWなどのディレクティブをCソースコードに付加することによって、最適化するイメージみたいです。XilinxのFPGAに最適化されているようで、RESOURCEというディレクティブでは、BRAMやLUTRAMも選べるようです。セミナをやってみた感じでは、C to HDLの品質をディレクティブを入れていくことによってチューニングして品質を上げていって、品質を上げたことによるリソースの増加を見て落とし所を決めるというイメージでした。これはこれで使いこなせるようになった時は、カリカリにチューニングできそうです。(注:カリカリにチューニング出来るというのは、適切な部分にディレクティブを入れていくと、どんどん早くなってチューニングが進む様子のことを書きました。HDLで適切に書けば、その方が性能が上がるのは言うまでもないことだと思います)
一番良いと思ったのは、データ型でビット幅を自由に選べて、C++でしたら飽和演算のタイプも指定できることです。固定小数点型もあります。これで演算途中のビット精度を自由に決めることができるので、演算がたくさんある場合のFPGAのリソース量をコントロールしやすいと思います。
AutoESLは、プロセッサで実行しているCコードを手軽にハードウェアにオフロードするという用途にピッタリなのではないか?と思いました。PLB、FSL、AXIスレーブ、マスタ、ストリームバスも選択すれば簡単に接続できるようです。
非常に制限も少なく使いやすいのですが、例えば、3X3の画像用のラプラシアンフィルタなどでは、HDLでやっている方法では作りづらいのではないか?と思いました。
例えば、”画像のエッジ検出6(3X3での方式の検討)”でラプラシアンフィルタをVHDLで書いたのですが、この場合には、画像の2ラインをBRAMにバッファして現在のピクセルとクロック遅れのピクセルを集めてきてラプラシアンフィルタを構成していました。これをCで書くことはなかなか難しいのではないか?ということです。Cで書くとすると、どうしても画像データを入れておく部分は配列にする必要があります。(malloc()禁止です)配列にするとメモリにマップされるので、DDRなどのSDRAMに領域が大きいためマップされることになると思います。ラプラシアンフィルタの演算要素を取ってくるために配列をReadすると、DDR SDRAMに3x3要素のデータを取りに行く事になると思われます。この方法ではDDR SDRAMのメモリ負荷が増え、場合によっては帯域が足りなくなることが考えられます。この程度の画像の演算ではローカルにピクセルデータを持っている方が、メモリ帯域の面からもベターだと思われます。つまり、ラプラシアンフィルタのアルゴリズムをAutoESLで書いて、それにデータを入れる部分はHDLで書いた方が我々の用途には合っていると思われます。
適材適所でツールを使用するといった方法が良いのでは?と思います。スループットを求め、小さなメモリ帯域でプロセッサをほとんど使用しない場合は、前に書いたような構成にしたいと思います。またプロセッサでほとんど処理をしていて、もっと早い処理を望む場合はAutoESLが使うことが最も適していると思われます。使用したいバスを自動生成しながらZynqのPL部にオフロードします。更にハードウェアにオフロードした部分をディレクティブを指定してチューニングすることが出来ます。
今の私の用途では、主要なブロックはEDKでIPを使用して構成して、独自の部分はAXI4バスプロトコルを独自に構成してインターフェースします。それにつながる独自アルゴリズムの部分をCで書いてAutoESLでHDLにコンパイルしてもらいます。この様に作るのが一番だと今のところは思っています。(注:AutoESLでは、あくまでソフトウェアで書けるように書くのが良いと思っています。色々なバッファを入れるためにテクニックを使ってCで書くのは本末転倒になる可能性があるのではないでしょうか? 普通にCで書けないのであれば、HDLを使うか、IPを使えば良いのでは?と思います。アルゴリズムをソフトウェアの浮動小数点(ハードでも出来ると思いますが)とハードウェアに最適化するための固定小数点、飽和演算をifdef で切り替えてお手軽にシミュレーション出来るのは魅力的です)
最後に、AutoESLの吐いたVHDL, Verilogはわかり易かったです。HDLに落としてからでも、もしかしたらそれでデバックできるのではないでしょうか?

最後にも付け足しておきますが、講師の方には本当に申し訳なかったですが、夢心地で聞いていたので間違っているかもしれません。もし間違っているというご指摘がありましたら、コメント欄でお知らせください。