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 and Synthesijer.Scala in HLS-friends 201512

An introduction of Synthesijer and Synthesijer.Scala

  • Login to see the comments

  • Be the first to like this

Synthesijer and Synthesijer.Scala in HLS-friends 201512

  1. 1. Synthesijerの進捗報告とSynthesijerの進捗報告と Synthesijer.Scalaの紹介 1 わさらぼ みよしたけふみ 2015.12.8
  2. 2. Synthesijer とは  JavaプログラムをFPGA上のハードウェアに変換  複雑なアルゴリズムのハードウェア実装を楽に  オブクジェクト指向設計による再利用性の向上  特殊な記法,追加構文はない  ソフトウェアとして実行可能.動作の確認、検証が容易 Open-source  ソフトウェアとして実行可能.動作の確認、検証が容易  書けるプログラムに制限は加える  (動的なnew,再帰は不可など)  HDLモジュールのJavaからのインスタンス生成 (ハード屋に読めるようにJavaをゆがめている…だけ…かも) while(…){ if(...){ 2 if(...){ … }else{ … … } …. } 複雑な状態遷移も,Javaの制御構文を使って楽に設計できる 同じJavaプログラムをソフトウェアとしても FPGA上のハードウェアとしても実行可能
  3. 3. 使ってみる •高位合成ツール「Synthesijer」を使う •http://cellspe.matrix.jp/zerofpga/synthesijer.html •Javaベース高位合成系 Synthesijer による回路モジュール設計例•Javaベース高位合成系 Synthesijer による回路モジュール設計例 •http://www.ritsumei.ac.jp/se/re/izumilab/lecture/15ZyboLedSjr/ •Synthesijer - BC::labs •http://labs.beatcraft.com/ja/index.php?Synthesijer •Synthesijer関連まとめ@Qiita 3 •http://qiita.com/kazunori279/items/4951ca5f6164040878ce
  4. 4. デザインコストは問題!! 4 Ivo Bolsens, “FPGA2032 Roadmap:A Personal Perspective", FPGAs in 2032: Challenges and Opportunities in the next 20 years,” Feb. 2012
  5. 5. Synthesijer オーバービュー Javaコード Javaプログラムの解析Javaコード フロントエンド スケジューリング表を作成 最適化 VHDL/ Verilog HDL コード 中間表現 (S式) ミドルエンド 5 HDL構文の組み立て VHDL/ Verilog HDL コード VHDL/ Verilog HDL コード バックエンド
  6. 6. すごくべたなプログラムにみるコード生成の例 べたなプログラムを用意 public class SimpleProgram{ public int sum(int a, int b, int c,public int sum(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l){ c = a + b; f = d + e; i = g + h; l = j + k; c = c + f; 6 c = c + f; l = l + i; c = c + l; return c; } }
  7. 7. 最適化の例 内部表現 sum_0000: op=METHOD_EXIT, src=, dest=, next=0001 sum_0001: op=METHOD_ENTRY, src=, dest=, next=0002 (name=sum) sum_0002: op=ADD, src=sum_a_0000:INT, sum_b_0001:INT, dest=binary_expr_00012:INT, next=0003 sum_0003: op=ASSIGN, src=binary_expr_00012:INT, dest=sum_c_0002:INT, next=0004 sum_0004: op=ADD, src=sum_d_0003:INT, sum_e_0004:INT, dest=binary_expr_00013:INT, next=0005 sum_0005: op=ASSIGN, src=binary_expr_00013:INT, dest=sum_f_0005:INT, next=0006 sum_0006: op=ADD, src=sum_g_0006:INT, sum_h_0007:INT, dest=binary_expr_00014:INT, next=0007 sum_0007: op=ASSIGN, src=binary_expr_00014:INT, dest=sum_i_0008:INT, next=0008 sum_0008: op=ADD, src=sum_j_0009:INT, sum_k_0010:INT, dest=binary_expr_00015:INT, next=0009 sum_0009: op=ASSIGN, src=binary_expr_00015:INT, dest=sum_l_0011:INT, next=0010 sum_0010: op=ADD, src=sum_c_0002:INT, sum_f_0005:INT, dest=binary_expr_00016:INT, next=0011 sum_0011: op=ASSIGN, src=binary_expr_00016:INT, dest=sum_c_0002:INT, next=0012 sum_0012: op=ADD, src=sum_l_0011:INT, sum_i_0008:INT, dest=binary_expr_00017:INT, next=0013 sum_0013: op=ASSIGN, src=binary_expr_00017:INT, dest=sum_l_0011:INT, next=0014 7 sum_0013: op=ASSIGN, src=binary_expr_00017:INT, dest=sum_l_0011:INT, next=0014 sum_0014: op=ADD, src=sum_c_0002:INT, sum_l_0011:INT, dest=binary_expr_00018:INT, next=0015 sum_0015: op=ASSIGN, src=binary_expr_00018:INT, dest=sum_c_0002:INT, next=0016 sum_0016: op=RETURN, src=sum_c_0002:INT, dest=, next=0000 sum_0017: op=JP, src=, dest=, next=0000
  8. 8. 最適化の例 同時実行可能な命令をセットにする sum_0000: op=METHOD_EXIT, src=, dest=, next=0001 sum_0001: op=METHOD_ENTRY, src=, dest=, next=0002 (name=sum) sum_0002: op=ADD, src=sum_a_0000:INT, sum_b_0001:INT, dest=binary_expr_00012:INT, next=0003 sum_0002: op=ADD, src=sum_d_0003:INT, sum_e_0004:INT, dest=binary_expr_00013:INT, next=0003 sum_0002: op=ADD, src=sum_g_0006:INT, sum_h_0007:INT, dest=binary_expr_00014:INT, next=0003 sum_0002: op=ADD, src=sum_j_0009:INT, sum_k_0010:INT, dest=binary_expr_00015:INT, next=0003 sum_0003: op=ASSIGN, src=binary_expr_00012:INT, dest=sum_c_0002:INT, next=0010 sum_0003: op=ASSIGN, src=binary_expr_00013:INT, dest=sum_f_0005:INT, next=0010 sum_0003: op=ASSIGN, src=binary_expr_00014:INT, dest=sum_i_0008:INT, next=0010 sum_0003: op=ASSIGN, src=binary_expr_00015:INT, dest=sum_l_0011:INT, next=0010 sum_0010: op=ADD, src=sum_c_0002:INT, sum_f_0005:INT, dest=binary_expr_00016:INT, next=0011 sum_0010: op=ADD, src=sum_l_0011:INT, sum_i_0008:INT, dest=binary_expr_00017:INT, next=0011 sum_0011: op=ASSIGN, src=binary_expr_00016:INT, dest=sum_c_0002:INT, next=0014 sum_0011: op=ASSIGN, src=binary_expr_00017:INT, dest=sum_l_0011:INT, next=0014 8 sum_0011: op=ASSIGN, src=binary_expr_00017:INT, dest=sum_l_0011:INT, next=0014 sum_0014: op=ADD, src=sum_c_0002:INT, sum_l_0011:INT, dest=binary_expr_00018:INT, next=0015 sum_0015: op=ASSIGN, src=binary_expr_00018:INT, dest=sum_c_0002:INT, next=0016 sum_0016: op=RETURN, src=sum_c_0002:INT, dest=, next=0000 sum_0017: op=JP, src=, dest=, next=0000
  9. 9. 最適化の例 依存関係にある命令群を専用命令にまとめる sum_0000: op=METHOD_EXIT, src=, dest=, next=0001 sum_0001: op=METHOD_ENTRY, src=, dest=, next=0002 (name=sum) sum_0002: op=ADD, src=sum_a_0000:INT, sum_b_0001:INT, dest=binary_expr_00012:INT, next=0016 sum_0002: op=ADD, src=sum_d_0003:INT, sum_e_0004:INT, dest=binary_expr_00013:INT, next=0016 sum_0002: op=ADD, src=sum_g_0006:INT, sum_h_0007:INT, dest=binary_expr_00014:INT, next=0016 sum_0002: op=ADD, src=sum_j_0009:INT, sum_k_0010:INT, dest=binary_expr_00015:INT, next=0016 sum_0002: op=ASSIGN, src=binary_expr_00012:INT:chain, dest=sum_c_0002:INT, next=0016 sum_0002: op=ASSIGN, src=binary_expr_00013:INT:chain, dest=sum_f_0005:INT, next=0016 sum_0002: op=ASSIGN, src=binary_expr_00014:INT:chain, dest=sum_i_0008:INT, next=0016 sum_0002: op=ASSIGN, src=binary_expr_00015:INT:chain, dest=sum_l_0011:INT, next=0016 sum_0002: op=ADD, src=sum_c_0002:INT:chain, sum_f_0005:INT:chain, dest=binary_expr_00016:INT, sum_0002: op=ADD, src=sum_l_0011:INT:chain, sum_i_0008:INT:chain, dest=binary_expr_00017:INT, sum_0002: op=ASSIGN, src=binary_expr_00016:INT:chain, dest=sum_c_0002:INT, next=0016 9 src=binary_expr_00016:INT:chain, dest=sum_c_0002:INT, next=0016 sum_0002: op=ASSIGN, src=binary_expr_00017:INT:chain, dest=sum_l_0011:INT, next=0016 sum_0002: op=ADD, src=sum_c_0002:INT:chain, sum_l_0011:INT:chain, dest=binary_expr_00018:INT sum_0002: op=ASSIGN, src=binary_expr_00018:INT:chain, dest=sum_c_0002:INT, next=0016 sum_0016: op=RETURN, src=sum_c_0002:INT, dest=, next=0000 sum_0017: op=JP, src=, dest=, next=0000
  10. 10. 内部情報のダンプと利用 内部はS式.S式を外でいじって処理系に戻すことも可 (SEQUENCER sum (SLOT 0 (METHOD_EXIT :next (1)) ) (SLOT 1(SLOT 1 (METHOD_ENTRY :next (2)) ) (SLOT 2 (SET binary_expr_00012 (ADD sum_a_0000 sum_b_0001) :next (16)) (SET binary_expr_00013 (ADD sum_d_0003 sum_e_0004) :next (16)) (SET binary_expr_00014 (ADD sum_g_0006 sum_h_0007) :next (16)) (SET binary_expr_00015 (ADD sum_j_0009 sum_k_0010) :next (16)) (SET sum_c_0002 (ASSIGN binary_expr_00012) :next (16)) ... ... (SET sum_c_0002 (ASSIGN binary_expr_00016) :next (16)) (SET sum_l_0011 (ASSIGN binary_expr_00017) :next (16)) (SET binary_expr_00018 (ADD sum_c_0002 sum_l_0011) :next (16)) 10 (SET binary_expr_00018 (ADD sum_c_0002 sum_l_0011) :next (16)) (SET sum_c_0002 (ASSIGN binary_expr_00018) :next (16)) ) (SLOT 16 (RETURN sum_c_0002 :next (0)) ) (SLOT 17 (JP :next (0)) ) )
  11. 11. 内部情報のダンプと利用 11
  12. 12. 内部情報のダンプと利用 12
  13. 13. Synthesijer はJavaベースなので... オブジェクト指向的プログラミング!! … … … 13
  14. 14. インスタンス生成 クラスのインスタンスを生成/利用できる public class Test002 { public static final int DEFAULT_VALUE = 0x20; ex. sample/test/Test002.javaとsample/test/Test003.java 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 class Test003 { private final Test002 t = new Test002(); 14 public void set(int i, int v){ a[i] = v; } … } public void test(){ t.init(); t.set(0, 100); // 0 <- 100 … } … }
  15. 15. インスタンス生成 クラスのインスタンスを生成/利用できる ex. sample/test/Test002.javaとsample/test/Test003.java Test002 class_t_0000 ( .clk(class_t_0000_clk),.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_adin), .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), 15 … .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), … );
  16. 16. インスタンス生成・拡張モジュール VHDL/Verilog HDLで書いたモジュールのインスタンス化 module hoge( input wire clk, ex. Verilog HDLで書いたhogeをJavaから呼び出す 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, clk reset a_address a_din hoge q 16 input wire func_req, output wire func_busy, output wire [31:0] q ); … endmodule a_we a_oe a_din a_dout func_req func_busy a_length
  17. 17. インスタンス生成・拡張モジュール VHDL/Verilog HDLで書いたモジュールのインスタンス化 class HogeIface extends HDLModule{ ↓のようなJava用のダミーコードを書く … private final HogeIface obj = new HogeIface(); … 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)); private void func(){ obj.a[10] = 100; obj.func(); … a[] 17 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)); } … } func() これはJavaでは使わない,という印
  18. 18. インスタンス生成の例 乱数生成のハードウェアをJavaから使う // xorshift RNG, period 2^128-1 // cf. http://www.jstatsoft.org/v08/i14/paper module xor128 (( input wire clk, input wire reset, output reg [63:0] q ); reg[31:0] x = 123456789, y = 362436069, z = 521288629, w = 88675123; reg[31:0] t; always @(posedge clk) begin q[63:32] <= 32'h0; if(reset == 1'b1) begin x <= 123456789; y <= 362436069; z <= 521288629; w <= 88675123; 18 z <= 521288629; w <= 88675123; end else begin t = x ^ (x << 11); x = y; y = z; z = w; w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); q[31:0] <= w; end end endmodule
  19. 19. インスタンス生成の例 乱数生成のハードウェアをJavaから使う /** * リスト15: XOR128.java * xor128をJavaから利用するためのダミークラス */ import synthesijer.hdl.HDLModule;import synthesijer.hdl.HDLModule; import synthesijer.hdl.HDLPort; import synthesijer.hdl.HDLPrimitiveType; public class XOR128Iface extends HDLModule{ // Javaプログラムのためのダミー変数 // xor128の出力qに相当する public long q; public XOR128Iface(String... args){ // - 実際に使用するモジュール名 19 // - 実際に使用するモジュール名 // - クロック信号名 // - リセット信号名 // の順に指定する. super("xor128", "clk", "reset"); // メンバ変数"q"に相当する64bit幅の出力ポートを生成する newPort("q", HDLPort.DIR.OUT, HDLPrimitiveType.genSignedType(64)); } }
  20. 20. インスタンス生成の例 乱数生成のハードウェアをJavaから使う /** * リスト16: XOR128Test.java * xor128をJavaから利用する例* xor128をJavaから利用する例 */ public class XOR128Test{ // XOR128モジュールのインスタンスを生成 private final XOR128Iface rng = new XOR128Iface(); public boolean test(){ long v = rng.q; // 乱数を読み出す // 処理の例.たとえば1000より大きければ真,とか. if(v > 1000){ 20 if(v > 1000){ return true; }else{ return false; } } }
  21. 21. インスタンス生成の例 乱数生成のハードウェアをJavaから使う 21
  22. 22. HDLモジュールをインスタンスとして使う •ライブラリとしていくつか用意 •UART •FIFO,キャッシュメモリ •AXIマスタ,スレーブ •簡単なI2Cマスタ •音声出力モジュール 22
  23. 23. クラスの継承も可 public class Test010{ public void test(){ int a = 20; int b = 30; int c = 0; library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; int c = 0; c = a & b; c = a | b; c = a ^ b; } } public class Test012 extends Test010{ public void run(){ test(); use IEEE.numeric_std.all; entity Test012 is port ( clk : in std_logic; reset : in std_logic; run_busy : out std_logic; run_req : in std_logic; test_busy : out std_logic; test_req : in std_logic 23 test(); } } ); end Test012; architecture RTL of Test012 is …
  24. 24. クラスの継承も可 public abstract class Test013_A{ abstract public int hoge(); } public class Test013_B extends Test013_A{public class Test013_B extends Test013_A{ public int hoge(){ return 10; } } public class Test013_C extends Test013_A{ public int hoge(){ return 20; } public class Test013{ private final Test013_A obj0 = new Test013_B(); 24 } } private final Test013_A obj0 = new Test013_B(); private final Test013_A obj1 = new Test013_C(); public void test(){ int a = obj0.hoge(); int b = obj1.hoge(); } }
  25. 25. Synthesijer はJavaベースなので... Threadを使って並列化できる … … … 25
  26. 26. スレッドの利用例 JavaではThreadクラスを継承して並列動作を記述 /* * リスト11: ThreadCounter.java * Threadの活用例 */ // JavaではThreadクラスを継承したクラスを作る public class ThreadCounter extends Thread{ public int counter = 0; // Threadの処理はrunメソッドで実装する public void run(){ while(true){ 26 while(true){ // 変数をインクリメントする無限ループ counter++; } } }
  27. 27. スレッドの利用例 JavaではThreadクラスを継承して並列動作を記述 import synthesijer.rt.unsynthesizable; public class ThreadTest{ private final ThreadCounter t0 = new ThreadCounter(); private final ThreadCounter t1 = new ThreadCounter(); public void test(){public void test(){ t0.start(); t1.start(); } // このメソッドはSynthesijerでは無視する @unsynthesizable public static void main(String... args){ ThreadTest t = new ThreadTest(); t.test(); while(true){ System.out.println("t0:" + t.t0.counter); 27 System.out.println("t0:" + t.t0.counter); System.out.println("t1:" + t.t1.counter); try{ Thread.sleep(1); }catch(Exception e){ e.printStackTrace(); } } } }
  28. 28. スレッドの利用例 PCで実行したところ 28
  29. 29. スレッドの利用例 シミュレーションで確認したところ 29
  30. 30. ここまでのまとめ •Synthesijer = Java→VHDL/Verilog HDL変換ツールです •継承とかスレッドとかサポートしてます •HDLなモジュールもクラスにしてインスタンス生成します •内部表現を出力したり,再利用したりできます •しゃべってないけど 30 •再帰呼び出しの実装をしてみたり •もっとJavaっぽいコードのサポートをしたいなあとか
  31. 31. もう一つの開発コスト軽減のアプローチ 31
  32. 32. RTL設計の辛さ  “信号の流れ”を記述する  “処理の流れ”を“信号の流れ”に変換 本質としては  “処理の流れ”を“信号の流れ”に変換  ↔ 書きたいのは“処理の流れ”   たくさんの似たような構造  たくさんの似たような名前 実務的には 32  たくさんの似たような名前   記述の再利用をしたいが難しい
  33. 33. 手軽なFPGA開発のための取り組み  高位合成言語処理系  DSL DSL 33
  34. 34. 高位合成処理系  CやJava,C#などを入力言語とした開発環境  開発コストを小さくできる  生成したHWの質は処理系依存  良いHW生成にはコツが必要  ディレクティブの活用  書き方を考える必要がある 34
  35. 35. DSLベースの設計手法  RTL設計を楽にするためのDSL  実装したいアプリケーション別のDSL  プログラミングモデルに特化したDSL 35
  36. 36. 様々なDSLベースのシステム開発(1) MyHDL (Pythonベース) RTL設計(あるいは少し抽象的なHW設計)を より楽にするためのDSL  MyHDL (Pythonベース)  JHDL (Javaベース)  Chisel (Scalaベース)  PyVerilog (Pythonベース) 36  などなどなど
  37. 37. 様々なDSLベースのシステム開発(2)  Spiral ←Linear Digital Processing 実装したいアプリケーションに特化したDSL  HDL Coder ← 信号処理(Matlab)  Optimus ← ストリーム処理  LINQ ← クエリプロセッシング などなどなど 37   DSLを作るツールも.(たとえば,LMS/Scala)
  38. 38. 様々なDSLベースのシステム開発(3)  Bluespec (並行プログラミング) 使用するプログラミングモデルに特化したDSL  MaxCompiler (データフロープログラミング)  FloPoCo (浮動小数点数パイプライン)  SPGen (パイプライン) などなどなど 38  
  39. 39. 欲しいDSL  Bluespec (並行プログラミング) 使用するプログラミングモデルに特化したDSL  MaxCompiler (データフロープログラミング)  FloPoCo (浮動小数点数パイプライン) などなどなど  状態遷移および各状態での処理設計がやりやすく 39  状態遷移および各状態での処理設計がやりやすく 組み合わせ回路が書きやすい言語
  40. 40. モデル モジュールの設計単位組み合わせ回路. 状態は持たない 出力 40 入力 クロック単位での状態保持 状態遷移マシン
  41. 41. Synthesijer.Scalaの立ち位置 Javaコード Javaプログラムの解析Javaコード フロントエンド スケジューリング表を作成 最適化 VHDL/ Verilog HDL コード 中間表現 (S式) ミドルエンド 41 HDL構文の組み立て VHDL/ Verilog HDL コード VHDL/ Verilog HDL コード バックエンド Scalaで 自分で組立て
  42. 42. はじめてのSynthesijer.scala  Lチカの例 def generate_led() : Module = { val m = new Module("led") val q = m.outP("q") val counter = m.signal(32) def main(args:Array[String]) = { val led = generate_led(5) val sim = generate_sim(led, "led_sim") led.genVHDL() led.genVerilog() sim.genVHDL()val counter = m.signal(32) q <= counter.ref(5) val seq = m.sequencer("main") counter <= (seq.idle, VECTOR_ZERO) val s0 = seq.idle -> seq.add() counter <= s0 * (counter + 1) return m } sim.genVHDL() led.portFor("q").setPinID("M14"); led.portFor("q").setIoAttr("LVCMOS33"); led.sysClk.setPinID("L16"); led.sysClk.setIoAttr("LVCMOS33"); led.sysReset.setPinID("G15"); led.sysReset.setIoAttr("LVCMOS33"); println(led.genUCF()) println(led.genXDC()) } 42 def generate_sim(target:Module, name:String) : SimModule = { val sim = new SimModule(name) val inst = sim.instance(target) val (clk, reset, counter) = sim.system(10) inst.sysClk <= clk inst.sysReset <= reset return sim }
  43. 43. はじめてのSynthesijer.scala 43
  44. 44. ベンディングマシンの例 ¢5 自動販売機 ¢5 ¢10 ドリンク一杯¢20 お釣りは出ません 44 ドリンク お釣りは出ません
  45. 45. RTLでの設計の場合 … type stateType is (NONE, CHARGE_5, CHARGE_10, CHARGE_15, OK) signal state, next_state: stateType := NONE; … case (state) is when NONE => if nickel then next_state <= CHARGE_5; elsif dime then next_state <= CHARGE_10; else next_state <= NONE; end if; when CHARGE_5 => if nickel then next_state <= CHARGE_10; 45 next_state <= CHARGE_10; elsif dime then next_state <= CHARGE_15; else next_state <= NONE; end if; …
  46. 46. ベンディングマシンの例 class VendingMachine(n:String,c:String,r:String) extends Module(n,c,r){ val nickel = inP("nickel") val dime = inP("dime") val rdy = outP("rdy") val seq = sequencer("main")val seq = sequencer("main") val s5,s10,s15,s_ok = seq.add() rdy <= (seq.idle, LOW) rdy <= (s_ok, HIGH) seq.idle -> (nickel, s5) seq.idle -> (dime, s10) s5 -> (nickel,s10) s5 -> (dime, s15) 46 s10 -> (nickel, s15) s10 -> (dime, s_ok) s15 -> (nickel, s_ok) s15 -> (dime, s_ok) s_ok -> seq.idle } val m = new VendingMachine("machine", "clk", "reset") m.genVHDL() m.visuallize_statemachine()
  47. 47. ベンディングマシンのステートマシン 47
  48. 48. Scalaの機能を使った設計効率化の向上  設計資産をメソッドやクラスとして保存,再利用  類似オブジェクトや類似オブジェクトの生成  ループとパタンマッチによる直列化/復元コードの生成 48
  49. 49. 設計資産の再利用 例: デコーダ (7セグメントLEDの点灯) 6 4 0 2 51 49 7 3
  50. 50. 設計資産の再利用 process (data) begin 6 従来のHDLによるRTL設計の場合 begin case (data) is when 0 => segment <= X"7e"; when 1 => segment <= X"30"; … when 9 => segment <= X"79"; when others => null; 4 0 2 51 50 when others => null; end case; end process; 7 3 毎回このパターンを書かないといけない.
  51. 51. 設計資産の再利用 パターンを作るメソッド.回路のレシピ. Synthesijer.scalaを使う場合 def decoder(s:ExprItem, l:List[(Int,Int)], w:Int) = { l.foldRight[ExprItem](value(0,w)){ (a, z) => ?(s == a._1, value(a._2, w), z) } 実データに合わせた回路の生成 51 val tbl = List((0, 0x7e), (1, 0x30), …, (9, 0x79)) segment := decoder(data, tbl, segment.width()) 実データに合わせた回路の生成
  52. 52. 自分なりのパタン,最適化の埋め込みも  組み合わせ回路の段数に応じたFF(状態)の追加,除去 入出力データに対するパタンマッチ 例えば...  入出力データに対するパタンマッチ  よく使うモジュールのテンプレート化  プロトコル処理のテンプレート化 **バイト目が到着まで待って**する **バイトまではメモリに保存 52 **バイトまではメモリに保存 **バイト以降は,そのまま次にフォワード などなど
  53. 53. 自分なりの実装,例 例えば...ANDゲートをLUTじゃなくてMUXで作りたい 53
  54. 54. 自分なりの実装,例 継承とオーバーライドを使って,自然に表現可能 val x0 = inP("x0") val y0 = inP("y0")val y0 = inP("y0") val z0 = outP("z0") val z1 = outP("z1") val z2 = outP("z2") z0 := x0 and y0 val x1c = new CARRY4Sig(x0) val y1c = new CARRY4Sig(y0) 54 val y1c = new CARRY4Sig(y0) z1 := x1c and y1c z2 := z0 or z1
  55. 55. 自分なりの実装,例 例えば...ANDゲートをLUTじゃなくてMUXで作りたい 55
  56. 56. 自分なりの実装,例 例えば...ANDゲートをLUTじゃなくてMUXで作りたい 56
  57. 57. Synthesijer.* Javaコード Javaプログラムの解析Javaコード フロントエンド スケジューリング表を作成 最適化 VHDL/ Verilog HDL コード 中間表現 (S式) ミドルエンド JRubyで 自分で組立て Clojureで 自分で組立て 57 HDL構文の組み立て VHDL/ Verilog HDL コード VHDL/ Verilog HDL コード バックエンド Scalaで 自分で組立て
  58. 58. 使ってみる •高位合成ツール「Synthesijer」を使う •http://cellspe.matrix.jp/zerofpga/synthesijer.html •Javaベース高位合成系 Synthesijer による回路モジュール設計例•Javaベース高位合成系 Synthesijer による回路モジュール設計例 •http://www.ritsumei.ac.jp/se/re/izumilab/lecture/15ZyboLedSjr/ •Synthesijer - BC::labs •http://labs.beatcraft.com/ja/index.php?Synthesijer •Synthesijer関連まとめ@Qiita 58 •http://qiita.com/kazunori279/items/4951ca5f6164040878ce •Synthesijer.Scala関連 •http://wasa-labo.com/wp/?p=320#more-320

×