Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Synthesijer hls 20150116

5,166 views

Published on

Synthesijer and Synthesijer.Scala

Published in: Engineering
  • Be the first to comment

Synthesijer hls 20150116

  1. 1. Synthesijer @高位合成友の会 わさらぼ 三好 健文 2015.01.16
  2. 2. 2 Synthesijer とは ✔ JavaプログラムをFPGA上のハードウェアに変換 ✔ 複雑なアルゴリズムのハードウェア実装を楽に ✔ オブクジェクト指向設計による再利用性の向上 ✔ 特殊な記法,追加構文はない ✔ ソフトウェアとして実行可能.動作の確認、検証が容易 ✔ 書けるプログラムに制限は加える (動的なnew,再帰は不可など) Javaコンパイラ フロントエンド Synthesijer エンジン Javaコンパイラ バックエンド 合成 配置配線 while(){ if(...){ … }else{ … … } …. } 複雑な状態遷移も,Javaの制御構文を使って楽に設計できる 同じJavaプログラムをソフトウェアとしても FPGA上のハードウェアとしても実行可能 Open-source
  3. 3. 3 サンプル1: グラフィクス表示 ✔ 90度位相ずれしたサインカーブをSWで描画
  4. 4. 4 FPGAでの実行例 ✔ 90度位相ずれしたサインカーブを実機で確認
  5. 5. 5 Synthesijer 開発の経緯 ✔ 2009年頃 Bluespecに感銘を受ける ✔ 2010年12月頃 高位合成処理系を作ってみたい→Javaベースに ✔ 2011年7月 JavaRockの開発を開始 JavaをVHDLに変換する.1文1ステート→簡単な並列化 ✔ 2012(?)年〜2013年 農工大中條研小池さんによるJavaRock-Thrashの開発 種々の最適化の実装など ✔ 2014年 Synthesijerとして名称をあらため開発を再スタート JavaRock/JavaRock-Thrashの実装を通じた知見の活用 なぜか
  6. 6. 6 Synthesijer クイックスタート
  7. 7. 7 クイックスタート 1/8 (1) バイナリパッケージをダウンロードします http://synthesijer.sourceforge.net なるべく日付の新しいものをDLしてください ダウンロードページに遷移します ✔ JDK7が必要です. ✔ Eclipseを使って開発してみます.
  8. 8. 8 クイックスタート 2/8 (2) Eclipseでプロジェクトを作ります
  9. 9. 9 クイックスタート 3/8 (3) libフォルダを作ってDLしたJARをコピー,ビルドパスに追加する DLしたJARをD&Dでコピー ビルドパスに追加 準備完了!!
  10. 10. 10 クイックスタート 4/8 (4) Javaのクラスを作る クラス生成ダイアログ
  11. 11. 11 クイックスタート 5/8 (5) 間隔をおいて変数ledをtrue/falseするプログラムを書く Lチカに相当する変数 適当なウェイト 点滅 自動コンパイルが裏で動くので,Javaコードとしての正しさは 即座にチェックされる
  12. 12. 12 クイックスタート 6/8 (6) Synthesijerを使ってJavaコードをHDLに変換 実行 中間生成物 VHDL/Verilog HDL
  13. 13. 13 クイックスタート 7/8 (7) ISEで合成,配置配線 生成したモジュールの インスタンスを生成 トップのHDLと UCFは別途用意
  14. 14. 14 クイックスタート 8/8 (8) FPGAをコンフィギュレーションして動作を確認
  15. 15. 15 補足 ✔ 配列(= ブロックRAM)やVHDL/Verilogライブラリ: synthesijer_lib_yyyymmdd.zip ✔ サンプル: synthesijer_samples_yyyymmdd.zip
  16. 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など
  17. 17. 17 Synthesijer とは? 
  18. 18. 18 高位合成処理系に何を求めるか? ✔ 記述コストの軽減 ✔ 高抽象度の表現方法を利用したい ✔ 言語習得にコストをかけたくない ✔ 動作検証/デバッグ効率の向上 ✔ 短時間で動作を確認したい ✔ 見通しよく,手軽なデバッグをしたい ✔ FPGAのパフォーマンスの活用 ✔ 粗粒度,細粒度の並列性の活用 ✔ IPコアや内部機能ユニットを活用したい ✔ 設計空間の探索
  19. 19. 19 Synthesijer ✔ クラスによるオブジェクト指向設計言語  ← HWのモジュール設計との親和性は高そう ✔ 言語仕様で並列処理をサポート ✔ Thread,wait-notify ✔ (Cと違い)明示的なポインタの扱いが不要 ✔ 言語の想定するメモリ構造から解放され得るかも ✔ 動的な振る舞いは厄介そう Javaベースの高位合成処理系
  20. 20. 20 Synthesijer 設計基本方針 ✔ JavaプログラムをそのままHDL→HW化 ✔ 追加構文,データ型は導入しない ✔ 使える記述には制限を導入 HDLで書けることをすべてJavaで書けるようにするではない Javaで書けることををすべてHDL(HW)にするではない Javaとして実行可能なプログラムをHWにする ≒ フェッチのないJavaプロセッサをHDLで直接生成する
  21. 21. 21 3つの開発パタン (1) Javaによるモジュールだけでシステムを構成 (2) HDLによるモジュールを部品として利用.全体管理はJavaで記述 = 既存IPコア,FPGAの性能を活用 (3) Javaによるモジュールを部品として利用.全体管理はHDLで記述 = 複雑なアルゴリズムをSWプログラマに書いてもらう.SW資産の活用 (1)Javaでシステムを構成 (2)Java + HDL記述の部品 (3)HDL + Java記述の部品
  22. 22. 22 最近よく実装しているパタン FIFO 実行 ステージ FIFO 実行 ステージ FIFO スループット T [bps] 実行 ステージ FIFO 実行 ステージ FIFO 実行 ステージ FIFO 実行 ステージ FIFO ここを Javaで書く
  23. 23. 23 FPGAにキラーアプリはないの定理 Florent de Dinechin, "Building Custom Arithmetic Operators with the FloPoCo Generator”, http://www.hipeac.net/conference/berlin/tutorial/flopoco なんとかして開発スピードを速くしたい
  24. 24. 24 SynthesijerのHDL生成方法
  25. 25. 25 Synthesijer でのHDL生成 Javaコード グローバルテーブルの作成 スケジュール表の作成 最適化 出力 VHDL/ Verilog HDL コード Javaコード VHDL/ Verilog HDL コード
  26. 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. 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. 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
  29. 29. 29 Synthesijer でのHDL生成: 出力(状態遷移) メソッド毎にスケジュール表を生成 → 状態遷移機械
  30. 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. 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 ...
  32. 32. 32 最適化 ✔ メモリ書き込みアクセスのパック ✔ 基本ブロック内の細粒度並列化 ✔ メモリ読み込みのアドレス指定のステート最適化 ✔ 演算のチェイニング 今実装しているもの もうすぐ実装するもの ≒ スケジュール表ベースでサイズを小さくすること
  33. 33. 33 SynthesijerはJavaベースなので... オブジェクト指向的プログラミング!! … … …
  34. 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. 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. 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. 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では使わない
  38. 38. 38 インスタンス生成・拡張モジュール VHDL/Verilog HDLで書いたモジュールのインスタンス化 @SynthesijerNativeInterface("hoge") class HogeIface extends HDLModule{ int[] a; void func(){} public HogeIface(String... args){ newPort("q", HDLPort.DIR.OUT, genVectorType(32), Enum.of(OPTION.EXPORT)); } } 将来的にはこんな感じにすっきりさせたい これはJavaでは使わない
  39. 39. 39 +α Synthesijer.scala
  40. 40. 40 Synthesijer.scala ✔ Javaで全部書けない...とはいえ ✔ もう普通のHDL(= VHDL/Verilog HDL)は書きたくない ✔ たくさんの似たような名前の変数の定義 ✔ リセット,パルス信号をもとに戻すの忘れる ✔ などなど ✔ 制御構造とデータ処理が同じ,な設計モデルはいやだ ✔ 記述の再利用をしたい ✔ データ処理とデータ代入をわけたい もっと高級なRTL設計言語があればいい
  41. 41. 41 Synthesijer.scala とは ✔ Synthesijerのバックエンドを使ってScala“で”HDLを書く ✔ signal, port: 状態を変更可能なオブジェクト ✔ expr: 副作用なしの式 ✔ sequencer: 状態遷移機械 ✔ module: モジュール全体 ✔ 上記のオブジェクトをScalaでインスタンス化.つなぎ合わせる.
  42. 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() }
  43. 43. 43 設計資産の再利用 例: デコーダ (7セグメントLEDの点灯) 4 0 2 51 6 7 3
  44. 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. 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を使う場合 実データに合わせた回路の生成
  46. 46. 46 Synthesijer.Scalaについて詳細 http://www.slideshare.net/miyox/synthesijerscala-prosym-2015
  47. 47. 47 自分なりのパタン,最適化の埋め込みも ✔ 組み合わせ回路の段数に応じたFF(状態)の追加,除去 ✔ 入出力データに対するパタンマッチ ✔ よく使うモジュールのテンプレート化 例えば... などなど
  48. 48. 48 今後のSynthesijer
  49. 49. 49 ロードマップ 手続き型言語的 基本演算,操作 整数プリミ ティブ型変 数の利用 算術,論理, シフト演算 (除算・剰 余算以外) 制御構文 (分岐,ルー プ) メソッド呼び 出し 除算・剰余 算 浮動小数点 数演算 オブジェクト指向 的インスンタンス 協調 finalでのイ ンスタンス の生成 インスタン スメソッドの 呼び出し インスタン ス変数への リードアク セス インスタン ス変数への ライトアクセ ス インスタン ス間での配 列読み書き のサポート インスタン スの配列, 配列の配列 のサポート コンストラク タのサポー ト インスタン スのチェイ ンアクセス 並列化 パフォーマンス 基本ブロッ ク内自動並 列化 Threadに よる明示的 な処理の並 列化をサ ポート ループ内パ イプライニ ング ライブラリ 整数プリミ ティブ変数 の配列 AXI接続用 のコンポー ネントライブ ラリの提供 Stringクラ スのサポー ト ユーザビリティ コマンドライ ンでのコン パイル HDLモ ジュールと のバイン ディング機 構 FPGA合成 ツールとの 連携,統一 的な開発フ ローの提供 スケジュー リング可視 化ツール HDL生成ラ イブラリを 活用した DSLの提供 2014年7月 2014年12月 2015年3月 2015年6月
  50. 50. 50 今後挑戦したいこと ✔ メソッドのパイプライン化 ✔ I/Oストリームへの対応 ✔ コンストラクタに対応 ✔ コンパイル時のJavaプログラム実行 ✔ lambda式対応 ✔ Streamへの対応
  51. 51. 51 Synthesijer http://synthesijer.sourceforge.net/

×