Synverll
-
Upload
hidemi-ishihara -
Category
Technology
-
view
709 -
download
0
Transcript of Synverll
©2015, Hidemi Ishihara, All rights reserved.
2015年12月 8日
高位合成友の会@ドワンゴSynverll
AQUAXIS TECHNOLOGYひでみ@hidemi_ishihara
2Synverll
最初はSynverllのご紹介から・・・
● Synverllとは● Synverllを作り始めた経緯● コンセプト● いまさらC言語?
処理方法のお話し・・・高位合成の結果って難しい・・・やってみよう・・・将来のお話し・・・
Vivado HLS WebPACK Editionでましたね
みんな、これ使えばええやん。
3Synverllとは
Synthesis for Verilog HDL using LLVM を略してみた。
● 読み方は「シンバール」
● LLVMを使用したCソースをVerilog HDLに変換する高位合成処理です。
4Synverllを作り始めた経緯
実は冬コミネタ(C89:三日目メ-13a:AQUAXIS)
● CソースをVerilog HDL手動トランスレートするのが面倒になってきた。● 前々、LLVMでなんとかならないかと思ってた。● 本当はひっそり、こっそり、開発するつもりだった。● 研究開発でも、プロダクトでもないです。
あくまで趣味です。
5コンセプト1FPGAの設計を楽しみましょう!
● 使い慣れた言語で楽してFPGAを設計したい● 出力されたRTLが気に入らなければ使わなければ良い!
● 強力な最適化エンジンを積んでいるわけではない。● 強力な最適化エンジンを開発するつもりもない。● あくまでLLVMでコンパイルして、Verilog HDLを出力するだけ。
なので、すごいRTLが出来上がるわけがない。
6コンセプト2「関数=モジュール」
● 関数=モジュールで出力されれば、気に入らないRTLを修正できるかも!● その代わり、I/Fはどの関数も同一になるように定義
Cソースで書いても、RTLで書いても一緒 ⇒ RTLで書かなくても良い⇒ 順次処理は向いている
最適化を期待するコード ⇒ 結果を見なければわからない⇒ 難しいソースコードがそうなってしまう ⇒ RTLが修正できたらいいなぁ
7コンセプト他アクセラレータIP● 何らかのバスにぶら下がるアクセラレータ的なモジュールになることを
想定している。
32bitアーキテクチャ● 32bitアーキテクチャを周到したステートマシンになる
8いまさらC言語を?世の中の高位合成処理はJavaやPythonが流行っているのに・・・
● なぜならば、私がJavaやPythonを使えないから・・・何度か挑戦したがなかなか、覚えられない・・・⇒ 使えてたらSynthesijer、PyCoRAMを使ってる。
● LegUpは?⇒ フリーなんだけど、出力されたRTLがALTERA教だったから。
9Synverll
好きな言語で楽して 開発したいよね。
処理方法のお話し・・・
● 展開方法● スケジューリング● 依存性のある処理● 関数のフラット化● メモリマップの一元化
高位合成の結果って難しい・・・やってみよう・・・将来のお話し・・・
10展開方法Cソースを関数単位で分解
● Synverllはひとつのファイルしか処理できません。
● Cソースを関数単位で分解し、関数をLLVMでコンパイルする。
● ここで-O3の最適化をかけます。● あくまで、LLVMでCソースをコンパ
イルするだけ・・・● そして、LLVM-IRの結果から単なるステートマシンのVerilog HDL化する。
hoge.c
LLVM LLVM LLVM
foo1.cfoo0.c foo2.c
foo1.llfoo0.ll foo2.ll
合成処理
foo1.vfoo0.v foo2.v
関数単位で分解
11スケジューリング
例えば、右のようにLLVM-IRが出力されたとする。合計、6ステップだが、m,n,oは同時に、x,yは同時に実行するよう配置する。つまり、3ステップでzが出力される。
m = a + b;n = c + d;o = e + f;x = m + n;y = m + o;z = x + y;
同時に実行して良い
同時に実行して良い同時に実行できない
LLVM-IRからVerilog HDLの段階で最適化を行う
● 依存性のない処理はどんどん、同時実行にする。
12依存性のある処理依存性のある処理とは
● 追い抜きが発生したら困る処理
foo0(...);foo1(...);
こういった場合、foo0とfoo1は関係無い関数に見える。しかし、もしかしたら、関数の中でメモリ操作をしているかもしれない。(どれくらい深いところでやっているかはわからない)
そうすると、メモリのアクセス順番によって結果が変わってしまう。追い抜きがかからないように必ず、foo0の後にfoo1を処理するようにスケジューリングを組む。
13関数のフラット化関数のフラット化とは
● Cソースでは階層構造で組み立てても、フラット展開する
⇒ Cの関数は同一時間に 同時に動作しないでしょう。 ⇒ つまり、スレッドは 意識していない。
void hoge(...){...foo_0(...);...foo_1(...);foo_1(...);
}
void foo_0(...){bar_0(...);...
}
void foo_1(...){bar_1(...);...
}
module top()hoge u_hoge();
foo_0 u_foo_0(); foo_1 u_foo_1();
bar_0 u_bar_0(); bar_1 u_bar_1();endmodule;
Cソースコード
Verilog HDL
15メモリマップの一元化全ての関数のメモリを一元化する
● Cソースと同じようにメモリに支配されたモジュール群ができあがる⇒ 全てのモジュールのメモリが一元化される
関数ごとにメモリを持つほうが処理が効果的では?
● 関数ごとに配列メモリとか持ってしまうとI/Fが複雑になる● メモリの問題解決は上位のメモリ・コントローラで解決すればよい
17最適化されたくないんですが・・・最適化の弊害・その1
● foo()が居なくなった
int foo( int x , int y ){
int ret;ret = x * y;return ret;
}
int hoge(...){
int a, b, c, d;int m, n;int z;
m = foo( a , b );n = foo( c , d );
z = m * n;}
int hoge(...){
int a, b, c, d;z = a * b * c * d;
}
18最適化されたくないんですが・・・最適化の弊害・その2
● foo()が居なくなった
int bar( int x , int y ){
xとyで複雑な計算;return 結果;
}
int foo( int x , int y ){
int ret;ret = x * y;return ret;
}
int hoge(...){
int a, b, c, d;int m, n;int z;
m = foo( a , b );n = foo( c , d );
z = bar( m , n );;}
int hoge(...){
int a, b, c, d;int m;int z;
m = a * b;n = c * d;
z = bar( m , n );}
barは残っている
19最適化されたくないんですが・・・最適化の弊害・その3
最適化したら・・・げげっ!100ステップのステートマシンになってしまった(苦笑)
この処理は時間がかかってもいい処理なんだけど、ループにしてよ。コンパイラはそんなことにはお構いなく、最適化してしまいます。将来、関数単位で最適化レベルを調整できるようにするつもり・・・
for(a=0;a<10;a++){for(b=0;b<10;b++){
c[a*10+b] = a * b;}
}
c[0] = 0 * 0;c[1] = 0 * 1;・・・c[98] = 9 * 8;c[99] = 9 * 9;
21こんなソースコードを想定しているhoge.c
void hoge(...){...foo_0(...);...foo_1(...);foo_1(...);
}
void bar_0(...){
...}
void foo_0(...){
...bar_0(...);...
}
void bar_1(...){
...}
void foo_1(...){
...bar_1(...);...
}
Synverllはひとつのファイルしか処理しない
22PC上で開発するときは・・・別のソースコードからhoge()を呼び出して使って検証する
% gcc -o main hoge.c main.c% ./main
void main(){
...
hoge(...);
...}
void hoge(...){...foo_0(...);...foo_1(...);foo_1(...);
}
main.c hoge.c
23実行方法Synverllビルド
% git clone git://github.com/aquaxis/synverll.git% cd synverll% make
実行方法
% ./synverll hoge.c
24生成物・その1Verilog HDLモジュールhoge_top.v
hoge.vfoo0.vfoo1.vbar0.vbar1.v
hoge.v foo0.v bar0.v
hoge_top.v
foo1.v bar1.v
25生成物・その2モジュール module RGB2YCbCr(
input __func_clock,input __func_reset,input __func_start,output reg __func_done,output reg __func_ready,
// Global Memoryinput [31:0] __gm_base,output reg __gm_req,output reg __gm_rnw,input __gm_done,output reg [31:0] __gm_adrs,output reg [1:0] __gm_leng,input [31:0] __gm_di,output reg [31:0] __gm_do,
// Memory Singalinput [31:0] __base_buffer,input [15:0] __args_xpos,input [15:0] __args_ypos,// Call Singal// Result Singaloutput reg __func_result
);
制御信号
メモリーインターフェース
引数
戻り値
26生成物・その3メモリマップ
一元化された メモリマップが 出力される。
======================================================================Memory Map======================================================================[GLOBAL/LOCAL] [MEMORY NAME] [ADDRESS] [SIZE]GLOBAL @jpeg_ptr 00000000 4GLOBAL @APP0info 00000004 18<<<中略>>>GLOBAL @CbAC_HT 00000808 768@DCT %datalong 00000b08 256GLOBAL @DU_DCT 00000c08 128GLOBAL @zigzag 00000c88 64GLOBAL @DU 00000cc8 128@process_DU %calc_data 00000d48 4@process_DU %1 00000d4c 4<<<中略>>>@process_DU %7 00000d64 4@process_DU %8 00000d68 4<<<中略>>>@main_encoder %DCY 00000ef4 2@main_encoder %DCCb 00000ef8 2@main_encoder %DCCr 00000efc 2@main_encoder %DU 00000f00 64@create_jpeg %fillbits 00000f40 3======================================================================
27こんなことができるtempはFPGA内部メモリ、bufはFPGA外部メモリとすることができる
void hoge(char *buf){
int i;char temp[10];
for(i=0;i<10;i++){tmep[i] = ...;
}
for(i=0;i<10;i++){buf[i] = temp[i];
}}
void main(){
char buf[10];
...
hoge(buf);
...}
main.c hoge.c
28構成イメージ
hoge foo0 bar0
hoge_top
foo1 bar1
reg ctrl DMA ctrl memory
CPU memory
バス
CPUサイド
FPGAサイド 一元化された内部メモリ
外部メモリ
29制約は?たくさんあってまとまってない!
まずは私が書くCソースが神ソースコードである。
昔、System CをVerilog HDL化しようとして挫折した。結局、自分のソースコードしか展開できないから、放置した。今回は、C言語にしたので、制約は少なくなるはず・・・
3032bitアーキテクチャ4Byteアライメント4Byteアライメントでないメモリアクセスはデータがバグる。
例えば、こんな構造体
struct foo{char a;short b;
} S_FOO;
struct hoge{foo[10];
} S_HOGE;
31ライブラリは?現状 32bit除算器AXI4 Master Read/WriteAXI4 Lite Slave
将来半精度、単精度、倍精度を準備したい。32bitアーキテクチャなので倍精度は後回し。
LLVM Standard Libraryよく使用するものから対応していく。
32Synverll
将来にむけて
将来のお話し
● 処理単位でVerilog HDL化● ストリーム対応は?● パイプライン化● アクセラレート● シミュレーション● OpenCVアクセラレート● ロードマップ
33処理単位でVerilog HDL化全てのソースコードを一括して高位合成処理しようとは考えていない
例えば、次のような流れの回路を作るようなことを想定している・・・
hoge_0FIFO
hoge_1FIFO FIFO
34処理単位でCソースをVerilog HDL化ソースを分割してSynverllにかける
void hoge_0(...){
...}
void hoge_1(...){
...}
void main(){
...
hoge_0(...);hoge_1(...);
...}
main.c hoge0.c hoge1.c
36パイプライン化パイプライン構想処理依存しない関数であれば、関数単位でのパイプライン化又は同時実行を検討している。
int foo(int a, int b){ int c; c = a * b;
return c;}
hoge (){ int a0,a1,a2;
int b0,b1,b2;int c0,c1,c2;
...
c0 = foo(a0, b0);c1 = foo(a1, b1);c2 = foo(a2, b2);
}
37アクセラレートmain関数はCPUで稼動させ、hoge関数をFPGAでアクセラレートする
void main(){
char buf[10];
...
#ifdef SOURCEhoge(buf);
#elsehoge.buf = buf;while(!hoge.ready);hoge.start = 1;while(!hoge.ready);hoge.start = 0;while(!hoge.done);
#endif
...}
38Cテストアプリを使ってシミュレーションしたいシミュレーション構想Cソースで使ったテストアプリを そのまま、使って 実機シミュレーションしたい!
テストベンチをもう一度、 書くのなんて嫌だ!
シミュレータなんて遅いから嫌だ!
void main(){
char buf[10];
...
#ifdef SOURCEhoge(buf);
#elsehoge.buf = buf;while(!hoge.ready);hoge.start = 1;while(!hoge.ready);hoge.start = 0;while(!hoge.done);
#endif
...}
39OpenCVアクセラレータアクセラレーション構想OpenCV関数のうち、C APIとなっている関数で自分が良く使うものをH/Wアクセラレータとしてライブラリ化して、Cソースの書き方でパイプライン化するようにしたい。
cvAdd(dst=B, src=A);cvSub(dst=C, src=B);...
cvAddとcvSubのポインタが連動していれば、パイプライン化発動!
cvAdd_cvSub(dst=C, src=A); とか・・・
p.s.ただし、フォーマットはcvMatに限定するかも・・・
40ロードマップ全てはコミケの当選に委ねられている
全体的に
ライブラリ的に
最適化的に
12/31 '16/3末 '16/7末 '16/9末 '16/12/31
もし、夏コミに当選したらここでV2.0にする
ベータ版 Cテスト対応
浮動小数点
関数単位での最適化
OpenCVライブラリ