©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コンセプト1
FPGAの設計を楽しみましょう!
●
使い慣れた言語で楽して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の結果から
単なるステートマシンの
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
14フラット化
関数を使い回ししても、複製しない
hoge foo0 bar0
hoge_top
foo1 bar1
15メモリマップの一元化
全ての関数のメモリを一元化する
●
Cソースと同じようにメモリに支配されたモジュール群ができあがる
⇒ 全てのモジュールのメモリが一元化される
関数ごとにメモリを持つほうが処理が効果的では?
●
関数ごとに配列メモリとか持ってしまうとI/Fが複雑になる
●
メモリの問題解決は上位のメモリ・コントローラで解決すればよい
16Synverll
最適化っておいしい?
高位合成処理の結果って難しい
●
最適化されたくないんですが
やってみよう・・・
将来のお話し・・・
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;
20Synverll
動かしてみる
やってよう・・・
●
想定しているソースコード
●
PC上で開発するときは・・・
●
実行方法
●
生成物
●
制約は?
●
ライブラリは?
将来のお話し・・・
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生成物・その1
Verilog HDLモジュール
hoge_top.v
hoge.v
foo0.v
foo1.v
bar0.v
bar1.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 Memory
input [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 Singal
input [31:0] __base_buffer,
input [15:0] __args_xpos,
input [15:0] __args_ypos,
// Call Singal
// Result Singal
output reg __func_result
);
制御信号
メモリー
インターフェース
引数
戻り値
26生成物・その3
メモリマップ
一元化された
 メモリマップが
   出力される。
======================================================================
Memory Map
======================================================================
[GLOBAL/LOCAL] [MEMORY NAME] [ADDRESS] [SIZE]
GLOBAL @jpeg_ptr 00000000 4
GLOBAL @APP0info 00000004 18
<<<中略>>>
GLOBAL @CbAC_HT 00000808 768
@DCT %datalong 00000b08 256
GLOBAL @DU_DCT 00000c08 128
GLOBAL @zigzag 00000c88 64
GLOBAL @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/Write
AXI4 Lite Slave
将来
半精度、単精度、倍精度を準備したい。
32bitアーキテクチャなので倍精度は後回し。
LLVM Standard Library
よく使用するものから対応していく。
32Synverll
将来にむけて
将来のお話し
●
処理単位でVerilog HDL化
●
ストリーム対応は?
●
パイプライン化
●
アクセラレート
●
シミュレーション
●
OpenCVアクセラレート
●
ロードマップ
33処理単位でVerilog HDL化
全てのソースコードを一括して高位合成処理しようとは考えていない
例えば、次のような流れの回路を作るようなことを想定している・・・
hoge_0
FIFO
hoge_1
FIFO FIFO
34処理単位でCソースをVerilog HDL化
ソースを分割してSynverllにかける
void hoge_0(...)
{
...
}
void hoge_1(...)
{
...
}
void main()
{
...
hoge_0(...);
hoge_1(...);
...
}
main.c hoge0.c hoge1.c
35ストリームの対応は?
ストリーム構想
●
将来、対応するかも・・・
●
ただし、制約が付くだろう。
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 SOURCE
hoge(buf);
#else
hoge.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 SOURCE
hoge(buf);
#else
hoge.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ライブラリ
41ひょっとして、LLVM-IRの高位合成処理系?
実はできます・・・
LLVM-IRの高位合成処理として使ってみたい!
⇒ オープンソースなのでご自由に改変してくださいませ!
42楽して開発したいよ
FPGAは規模も大きいし、これにプロセッサまで付いたら・・・
とにかく開発工数が多くて面倒!
好きな言語で好きなエディタ使って、好きなツール使って、
楽にシステム開発したいよ。
出力コードが気に入らないなら修正すればいいんじゃないの?
HDL変換する参考のコード程度でも良いかな?
                           以上っす。

Synverll