Contenu connexe Similaire à Synthesijer hls 20150116 (6) Plus de Takefumi MIYOSHI (20) Synthesijer hls 201501162. 2
Synthesijer とは
✔ JavaプログラムをFPGA上のハードウェアに変換
✔ 複雑なアルゴリズムのハードウェア実装を楽に
✔ オブクジェクト指向設計による再利用性の向上
✔ 特殊な記法,追加構文はない
✔ ソフトウェアとして実行可能.動作の確認、検証が容易
✔ 書けるプログラムに制限は加える
(動的なnew,再帰は不可など)
Javaコンパイラ
フロントエンド
Synthesijer
エンジン
Javaコンパイラ
バックエンド
合成
配置配線
while(){
if(...){
…
}else{
…
…
}
….
}
複雑な状態遷移も,Javaの制御構文を使って楽に設計できる
同じJavaプログラムをソフトウェアとしても
FPGA上のハードウェアとしても実行可能
Open-source
5. 5
Synthesijer 開発の経緯
✔ 2009年頃 Bluespecに感銘を受ける
✔ 2010年12月頃 高位合成処理系を作ってみたい→Javaベースに
✔ 2011年7月
JavaRockの開発を開始
JavaをVHDLに変換する.1文1ステート→簡単な並列化
✔ 2012(?)年〜2013年
農工大中條研小池さんによるJavaRock-Thrashの開発
種々の最適化の実装など
✔ 2014年
Synthesijerとして名称をあらため開発を再スタート
JavaRock/JavaRock-Thrashの実装を通じた知見の活用
なぜか
16. 16
参考
✔ http://synthesijer.sourceforge.net
✔ リソース一式,クイックスタートガイドなど
✔ http://qiita.com/kazunori279/items/4951ca5f6164040878ce
✔ Synthesijer関連資料まとめ
✔ http://labs.beatcraft.com/ja/index.php?Synthesijer
✔ Altera DE0-nanoでのサンプルの動作手順など
(ビートクラフト様)
✔ http://marsee101.blog19.fc2.com/blog-category-116.html
✔ FPGAの部屋: Synthesijerでラプラシアンフィルタを作ってみた
✔ http://wasa-labo.com/wp/
✔ わさらぼ ブログ – 開発状況,Tipsなど
26. 26
Synthesijer でのHDL生成: 例題
package blink_led;
public class BlinkLED {
public boolean led;
public void run(){
while(true){
led = true;
for(int i = 0; i < 5000000; i++) ;
led = false;
for(int i = 0; i < 5000000; i++) ;
}
}
}
27. 27
Synthesijer でのHDL生成: 大枠
class
entity blink_led_BlinkLED is
port (
clk : in std_logic;
reset : in std_logic;
field_led_output : out std_logic;
field_led_input : in std_logic;
field_led_input_we : in std_logic;
run_req : in std_logic;
run_busy : out std_logic
);
end blink_led_BlinkLED;
class BlinkLED {
public boolean led;
public void run(){
while(true){
…
}
}
}
module
クラス毎にHWモジュールを生成
28. 28
Synthesijer でのHDL生成: スケジュール表
メソッド毎にスケジュール表を生成
run_0000: op=METHOD_EXIT, src=, dest=, next=0001
run_0001: op=METHOD_ENTRY, src=, dest=, next=0002 (name=run)
run_0002: op=JT, src=true:BOOLEAN, dest=, next=0004, 0003
run_0003: op=JP, src=, dest=, next=0023
run_0004: op=ASSIGN, src=true:BOOLEAN, dest=class_led_0000:BOOLEAN, next=0005
run_0005: op=ASSIGN, src=0:INT, dest=run_i_0001:INT, next=0006
run_0006: op=LT, src=run_i_0001:INT, 5000000:INT, dest=binary_expr_00002:BOOLEAN, next=0007
run_0007: op=JT, src=binary_expr_00002:BOOLEAN, dest=, next=0012, 0008
run_0008: op=JP, src=, dest=, next=0013
run_0009: op=ADD, src=run_i_0001:INT, 1:INT, dest=unary_expr_00003:INT, next=0010
run_0010: op=ASSIGN, src=unary_expr_00003:INT, dest=run_i_0001:INT, next=0011
run_0011: op=JP, src=, dest=, next=0006
run_0012: op=JP, src=, dest=, next=0009
run_0013: op=ASSIGN, src=false:BOOLEAN, dest=class_led_0000:BOOLEAN, next=0014
run_0014: op=ASSIGN, src=0:INT, dest=run_i_0004:INT, next=0015
run_0015: op=LT, src=run_i_0004:INT, 5000000:INT, dest=binary_expr_00005:BOOLEAN, next=0016
run_0016: op=JT, src=binary_expr_00005:BOOLEAN, dest=, next=0021, 0017
run_0017: op=JP, src=, dest=, next=0022
run_0018: op=ADD, src=run_i_0004:INT, 1:INT, dest=unary_expr_00006:INT, next=0019
run_0019: op=ASSIGN, src=unary_expr_00006:INT, dest=run_i_0004:INT, next=0020
run_0020: op=JP, src=, dest=, next=0015
run_0021: op=JP, src=, dest=, next=0018
run_0022: op=JP, src=, dest=, next=0002
run_0023: op=JP, src=, dest=, next=0000
30. 30
Synthesijer でのHDL生成: 出力(データ操作)
メソッド毎にスケジュール表を生成 → 文/式相当のデータ操作
run_0000: op=METHOD_EXIT, src=, dest=, next=0001
run_0001: op=METHOD_ENTRY, src=, dest=, next=0002 (name=run)
run_0002: op=JT, src=true:BOOLEAN, dest=, next=0004, 0003
run_0003: op=JP, src=, dest=, next=0023
run_0004: op=ASSIGN, src=true:BOOLEAN, dest=class_led_0000:BOOLEAN, next=0005
run_0005: op=ASSIGN, src=0:INT, dest=run_i_0001:INT, next=0006
run_0006: op=LT, src=run_i_0001:INT, 5000000:INT, dest=binary_expr_00002:BOOLEAN, next=0007
run_0007: op=JT, src=binary_expr_00002:BOOLEAN, dest=, next=0012, 0008
run_0008: op=JP, src=, dest=, next=0013
run_0009: op=ADD, src=run_i_0001:INT, 1:INT, dest=unary_expr_00003:INT, next=0010
run_0010: op=ASSIGN, src=unary_expr_00003:INT, dest=run_i_0001:INT, next=0011
run_0011: op=JP, src=, dest=, next=0006
run_0012: op=JP, src=, dest=, next=0009
run_0013: op=ASSIGN, src=false:BOOLEAN, dest=class_led_0000:BOOLEAN, next=0014
run_0014: op=ASSIGN, src=0:INT, dest=run_i_0004:INT, next=0015
run_0015: op=LT, src=run_i_0004:INT, 5000000:INT, dest=binary_expr_00005:BOOLEAN, next=0016
run_0016: op=JT, src=binary_expr_00005:BOOLEAN, dest=, next=0021, 0017
run_0017: op=JP, src=, dest=, next=0022
run_0018: op=ADD, src=run_i_0004:INT, 1:INT, dest=unary_expr_00006:INT, next=0019
run_0019: op=ASSIGN, src=unary_expr_00006:INT, dest=run_i_0004:INT, next=0020
run_0020: op=JP, src=, dest=, next=0015
run_0021: op=JP, src=, dest=, next=0018
run_0022: op=JP, src=, dest=, next=0002
run_0023: op=JP, src=, dest=, next=0000
31. 31
Synthesijer でのHDL生成: 出力(データ操作)
メソッド毎にスケジュール表を生成 → 文/式相当のデータ操作
run_0000: op=METHOD_EXIT, src=, dest=, next=0001
run_0001: op=METHOD_ENTRY, src=, dest=, next=0002 (name=run)
run_0002: op=JT, src=true:BOOLEAN, dest=, next=0004, 0003
run_0003: op=JP, src=, dest=, next=0023
run_0004: op=ASSIGN, src=true:BOOLEAN, dest=class_led_0000:BOOLEAN, next=0005
run_0005: op=ASSIGN, src=0:INT, dest=run_i_0001:INT, next=0006
run_0006: op=LT, src=run_i_0001:INT, 5000000:INT, dest=binary_expr_00002:BOOLEAN, next=0007
run_0007: op=JT, src=binary_expr_00002:BOOLEAN, dest=, next=0012, 0008
run_0008: op=JP, src=, dest=, next=0013
run_0009: op=ADD, src=run_i_0001:INT, 1:INT, dest=unary_expr_00003:INT, next=0010
run_0010: op=ASSIGN, src=unary_expr_00003:INT, dest=run_i_0001:INT, next=0011
run_0011: op=JP, src=, dest=, next=0006
run_0012: op=JP, src=, dest=, next=0009
run_0013: op=ASSIGN, src=false:BOOLEAN, dest=class_led_0000:BOOLEAN, next=0014
run_0014: op=ASSIGN, src=0:INT, dest=run_i_0004:INT, next=0015
run_0015: op=LT, src=run_i_0004:INT, 5000000:INT, dest=binary_expr_00005:BOOLEAN, next=0016
run_0016: op=JT, src=binary_expr_00005:BOOLEAN, dest=, next=0021, 0017
run_0017: op=JP, src=, dest=, next=0022
run_0018: op=ADD, src=run_i_0004:INT, 1:INT, dest=unary_expr_00006:INT, next=0019
run_0019: op=ASSIGN, src=unary_expr_00006:INT, dest=run_i_0004:INT, next=0020
run_0020: op=JP, src=, dest=, next=0015
run_0021: op=JP, src=, dest=, next=0018
run_0022: op=JP, src=, dest=, next=0002
run_0023: op=JP, src=, dest=, next=0000
...
assign tmp_0010 = run_i_0001 + 32'h00000001;
...
always @(posedge clk) begin
if(reset == 1'b1) begin
run_i_0001 <= 32'h00000000;
end else begin
if (run_method == run_method_S_0004) begin
run_i_0001 <= 32'h00000000;
end else if (run_method == run_method_S_0010) begin
run_i_0001 <= unary_expr_00003;
end
end
end
...
always @(posedge clk) begin
if(reset == 1'b1) begin
unary_expr_00003 <= 0;
end else begin
if (run_method == run_method_S_0009) begin
unary_expr_00003 <= tmp_0010;
end
end
end
...
34. 34
インスタンス生成
クラスのインスタンスを生成/利用できる
public class Test002 {
public static final int DEFAULT_VALUE = 0x20;
public int[] a = new int[128];
public int x, y;
public void init(){
for(int i = 0; i < a.length; i++){
a[i] = 0;
}
}
public void set(int i, int v){
a[i] = v;
}
…
}
ex. sample/test/Test002.javaとsample/test/Test003.java
public class Test003 {
private final Test002 t = new Test002();
public void test(){
t.init();
t.set(0, 100); // 0 <- 100
…
}
…
}
35. 35
インスタンス生成
クラスのインスタンスを生成/利用できる
ex. sample/test/Test002.javaとsample/test/Test003.java
Test002 class_t_0000 (
.clk(class_t_0000_clk),
.reset(class_t_0000_reset),
.a_address(class_t_0000_a_address),
.a_we(class_t_0000_a_we),
.a_oe(class_t_0000_a_oe),
.a_din(class_t_0000_a_din),
.a_dout(class_t_0000_a_dout),
.a_length(class_t_0000_a_length),
…
.set_i(class_t_0000_set_i),
.set_v(class_t_0000_set_v),
…
.init_req(class_t_0000_init_req),
.init_busy(class_t_0000_init_busy),
…
.set_req(class_t_0000_set_req),
.set_busy(class_t_0000_set_busy),
…
);
36. 36
インスタンス生成・拡張モジュール
VHDL/Verilog HDLで書いたモジュールのインスタンス化
module hoge(
input wire clk,
input wire reset,
input signed [31:0] a_address,
input signed [31:0] a_din,
input wire we,
input wire oe,
output signed [31:0] a_dout,
output signed [31:0] a_length,
input wire func_req,
output wire func_busy,
output wire [31:0] q
);
…
endmodule
clk
reset
a_address
a_din
a_we
a_oe
a_din
a_dout
func_req
func_busy
hoge q
ex. Verilog HDLで書いたhogeをJavaから呼び出す
a_length
37. 37
インスタンス生成・拡張モジュール
VHDL/Verilog HDLで書いたモジュールのインスタンス化
class HogeIface extends HDLModule{
int[] a;
void func(){}
public HogeIface(String... args){
newPort("a_address", HDLPort.DIR.IN, genSignedType(32));
newPort("a_din", HDLPort.DIR.IN, genSignedType(32));
newPort("a_we", HDLPort.DIR.IN, genBitType());
newPort("a_oe", HDLPort.DIR.IN, genBitType());
newPort("a_dout", HDLPort.DIR.OUT, genSignedType(32));
newPort("a_length", HDLPort.DIR.OUT, genSignedType(32));
newPort("func_req", HDLPort.DIR.IN, genBitType());
newPort("func_busy", HDLPort.DIR.OUT, genBitType());
newPort("q", HDLPort.DIR.OUT, genVectorType(32), Enum.of(OPTION.EXPORT));
}
…
}
↓のようなJava用のダミーコードを書いて,使う
…
private final HogeIface obj = new
HogeIface();
…
private void func(){
obj.a[10] = 100;
obj.func();
…
a[]
func()
これはJavaでは使わない
42. 42
はじめての Synthesijer.scala
✔ Lチカ
def generate_led() : Module = {
val m = new Module("led")
val q = m.outP("q")
val counter = m.signal(32)
q := counter.ref(5)
val seq = m.sequencer("main")
counter is (VECTOR_ZERO in seq.idle)
val s0 = seq.idle -> seq.add()
counter <= (counter + 1 in s0)
return m
}
def main() = {
val m = generate_led()
m.genVHDL()
}
44. 44
設計資産の再利用
process (data)
begin
case (data) is
when 0 => segment <= X"7e";
when 1 => segment <= X"30";
…
when 9 => segment <= X"79";
when others => null;
end case;
end process;
4
0
2
51
6
7
3
毎回このパターンを書かないといけない.
従来のHDLによるRTL設計の場合
45. 45
設計資産の再利用
def decoder(s:ExprItem, l:List[(Int,Int)], w:Int) = {
l.foldRight(value(0,w)){
(a, z) => ?(s == a._1, value(a._2, w), z)
}
val tbl = List((0, 0x7e), (1, 0x30), …, (9, 0x79))
segment := decoder(data, tbl, segment.width())
パターンを作るメソッド.回路のレシピ.
Synthesijer.scalaを使う場合
実データに合わせた回路の生成