ふと気になったのでChiselのBlackboxで複数のファイルから構成されたVerilogのRTLを指定できるのかを試してみた。
Blackboxのおさらい
Chiselには既存のVerilog-HDLのRTLをModule
に組み込む方法としてBlackbox
が存在している。
これを使用することでChiselのモジュールのクラス名と一致するRTLのモジュールをChiselのモジュールでインスタンスして使うことが可能だ。
簡単に使い方をおさらいしておく。
- Verilog-HDLのRTL(Test.v)
module Test ( input in, output out ); assign out = in; endmodule
上記のTestモジュールを含むファイルをChiselのプロジェクトの以下の場所に保存しておく。
- src/main/resources/Test.v
TestモジュールをChiselのモジュール内でインスタンスして使う場合にはBlackbox
を継承したクラスを作成してそのクラスを通常のモジュールと同様にインスタンスすればいい。
- Testを使用するChiselモジュール
class Test extends Blackbox with HasBlackBoxResource { val io = IO(new Bundle { val in = Input(Bool()) val out = Output(Bool()) }) // setResourceにファイルを指定することで、シミュレーション実行時に"Test.v"が // テストの実行時に使用されるようになる。 setResource("/Test.v") // "/"が無いとエラー } class Top extends Module { val io = IO(new Bundle { val in = Input(Bool()) val out = Output(Bool()) }) // Blackboxで作成したラッパークラスをインスタンス val m_test = Module(new Test) // 通常のモジュールと同様に接続 m_test.io.in := io.in io.out := m_test.io.out }
Blackboxで指定するモジュールが複数のファイルで構成される場合
FPGAで使用するようなRAM推定のファイルならひとつのファイルにひとつのモジュールが書かれていることが多いので、setResource
に指定するファイルは自ずと一つになる。
では、既存の資産を流用するケースで複数のRTLファイルから構成されるモジュールをBlackbox
モジュールに指定してChiselのモジュール内で使用するにはどうればいいのだろうか?ということを考えたことが無かったので試してみた。
文章で書くといまいちイメージしにくいかもしれないが例えば以下のような感じのことを指している。
- a.sv : module aが実装されている
- b.sv : module bが実装されている
というケースに於いて、モジュール"a"/"b"が以下のように階層化されているような場合だ。
- a.svのモジュール"a"
module a ( input in, output out ); b b (.in(in), .out(out)); endmodule : a
- b.svのモジュール"b"
module b ( input in, output out ); assign out = in; endmodule : b
この場合にモジュール"a"をChiselのBlackbox
に指定した際に"a.sv"/"b.sv"の2つのファイルが必要になるのだが、setResource
の指定はどうすればいいかについて幾つか試してみる。
まずは"a.sv"のみを指定。
class a extends BlackBox with HasBlackBoxResource { val io = IO(new Bundle { val in = Input(Bool()) val out = Output(Bool()) }) setResource("/a.sv") } class BlackBoxTop extends Module { val io = IO(new Bundle { val in = Input(Bool()) val out = Output(Bool()) }) val m_a = Module(new a) m_a.io.in := io.in io.out := m_a.io.out }
テストを作ってverilatorで上記のモジュールをテストすると以下のようにエラーが発生する。エラーの中身はモジュール"b"が実装されているファイルが見つからない、という内容だ。
Total FIRRTL Compile Time: 465.0 ms cd /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop && verilator --cc BlackBoxTop.v --assert -Wno-fatal -Wno-WIDTH -Wno-STMTDLY -O1 --top-module BlackBoxTop +define+TOP_TYPE=VBlackBoxTop +define+PRINTF_COND=!BlackBoxTop.reset +define+STOP_COND=!BlackBoxTop.reset -CFLAGS "-Wno-undefined-bool-conversion -O1 -DTOP_TYPE=VBlackBoxTop -DVL_USER_FINISH -include VBlackBoxTop.h" -Mdir /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop -f /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop/firrtl_black_box_resource_files.f --exe /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop/BlackBoxTop-harness.cpp --trace %Error: /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop/a.sv:7: Cannot find file containing module: b %Error: /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop/a.sv:7: This may be because there's no search path specified with -I<dir>. %Error: /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop/a.sv:7: Looked in: %Error: /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop/a.sv:7: b %Error: /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop/a.sv:7: b.v %Error: /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop/a.sv:7: b.sv %Error: /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop/a.sv:7: /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop/b %Error: /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop/a.sv:7: /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop/b.v %Error: /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop/a.sv:7: /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop/b.sv %Error: Exiting due to 9 error(s) %Error: Command Failed /usr/local/bin/verilator_bin --cc BlackBoxTop.v --assert -Wno-fatal -Wno-WIDTH -Wno-STMTDLY -O1 --top-module BlackBoxTop \+define\+TOP_TYPE\=VBlackBoxTop \+define\+PRINTF_COND\=\!BlackBoxTop.reset \+define\+STOP_COND\=\!BlackBoxTop.reset -CFLAGS -Wno-undefined-bool-conversion\ -O1\ -DTOP_TYPE\=VBlackBoxTop\ -DVL_USER_FINISH\ -include\ VBlackBoxTop.h -Mdir /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop -f /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop/firrtl_black_box_resource_files.f --exe /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop/BlackBoxTop-harness.cpp --trace
Chiselのテストフレームワークのシミュレータのバックエンドとしてverilatorを指定した場合に、モジュール内にsetResource
が使用されると、シミュレーションの実行ディレクトリに"firrtl_black_box_resource_files.f"というファイルが出来ており、この中にsetResource
で指定したファイルのパスが記載され、モジュールの解決が行われる仕組みになっており、今回のケースだと"a.sv"のみが指定されたため、ファイルが見つからないということになっている。
ここまで書くともう察した方もいるだろうが、解決方法は単純で必要なファイルを全てsetResource
を使って指定してやればOKだ。
先ほどのモジュール"a"の場合はBlackbox
を継承したクラスの実装は以下のようになる。
class a extends BlackBox with HasBlackBoxResource { val io = IO(new Bundle { val in = Input(Bool()) val out = Output(Bool()) }) setResource("/a.sv") setResource("/b.sv") // "b.sv"も追加する }
この状態でテストを再度実行すると以下のようにVerilatorのエラーは発生せずにシミュレーションが開始される。
Total FIRRTL Compile Time: 425.4 ms cd /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop && verilator --cc BlackBoxTop.v --assert -Wno-fatal -Wno-WIDTH -Wno-STMTDLY -O1 --top-module BlackBoxTop +define+TOP_TYPE=VBlackBoxTop +define+PRINTF_COND=!BlackBoxTop.reset +define+STOP_COND=!BlackBoxTop.reset -CFLAGS "-Wno-undefined-bool-conversion -O1 -DTOP_TYPE=VBlackBoxTop -DVL_USER_FINISH -include VBlackBoxTop.h" -Mdir /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop -f /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop/firrtl_black_box_resource_files.f --exe /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop/BlackBoxTop-harness.cpp --trace make: ディレクトリ '/home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop' に入ります g++ -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVL_PRINTF=printf -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TRACE=1 -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -Wno-shadow -Wno-undefined-bool-conversion -O1 -DTOP_TYPE=VBlackBoxTop -DVL_USER_FINISH -include VBlackBoxTop.h -c -o BlackBoxTop-harness.o /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop/BlackBoxTop-harness.cpp g++ -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVL_PRINTF=printf -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TRACE=1 -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -Wno-shadow -Wno-undefined-bool-conversion -O1 -DTOP_TYPE=VBlackBoxTop -DVL_USER_FINISH -include VBlackBoxTop.h -c -o verilated.o /usr/local/share/verilator/include/verilated.cpp g++ -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVL_PRINTF=printf -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TRACE=1 -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -Wno-shadow -Wno-undefined-bool-conversion -O1 -DTOP_TYPE=VBlackBoxTop -DVL_USER_FINISH -include VBlackBoxTop.h -c -o verilated_vcd_c.o /usr/local/share/verilator/include/verilated_vcd_c.cpp /usr/bin/perl /usr/local/share/verilator/bin/verilator_includer -DVL_INCLUDE_OPT=include VBlackBoxTop.cpp > VBlackBoxTop__ALLcls.cpp /usr/bin/perl /usr/local/share/verilator/bin/verilator_includer -DVL_INCLUDE_OPT=include VBlackBoxTop__Trace.cpp VBlackBoxTop__Syms.cpp VBlackBoxTop__Trace__Slow.cpp > VBlackBoxTop__ALLsup.cpp g++ -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVL_PRINTF=printf -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TRACE=1 -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -Wno-shadow -Wno-undefined-bool-conversion -O1 -DTOP_TYPE=VBlackBoxTop -DVL_USER_FINISH -include VBlackBoxTop.h -c -o VBlackBoxTop__ALLcls.o VBlackBoxTop__ALLcls.cpp g++ -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVL_PRINTF=printf -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TRACE=1 -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -Wno-shadow -Wno-undefined-bool-conversion -O1 -DTOP_TYPE=VBlackBoxTop -DVL_USER_FINISH -include VBlackBoxTop.h -c -o VBlackBoxTop__ALLsup.o VBlackBoxTop__ALLsup.cpp Archiving VBlackBoxTop__ALL.a ... ar r VBlackBoxTop__ALL.a VBlackBoxTop__ALLcls.o VBlackBoxTop__ALLsup.o ar: VBlackBoxTop__ALL.a を作成しています ranlib VBlackBoxTop__ALL.a g++ BlackBoxTop-harness.o verilated.o verilated_vcd_c.o VBlackBoxTop__ALL.a -o VBlackBoxTop -lm -lstdc++ make: ディレクトリ '/home/diningyo/prj/study/2000_chisel/500_learning-chisel3/test_run_dir/BlackboxTop' から出ます sim start on diningyo-pc at Mon Oct 7 23:48:19 2019 inChannelName: 00011230.in outChannelName: 00011230.out cmdChannelName: 00011230.cmd STARTING test_run_dir/BlackboxTop/VBlackBoxTop
ということで、Chiselのテストフレームワーク経由で複数のファイルからなるRTLをブラックボックス化して使う際には必要なファイルを全てsetResource
で列挙すればOKだった。
setResource
を何個も列挙するのはめんどくさいので、以下のような感じでSeq
とかに適当に入れてforeach
とかで処理するのが良いと思う。
class a extends BlackBox with HasBlackBoxResource { val io = IO(new Bundle { val in = Input(Bool()) val out = Output(Bool()) }) val rtlList = Seq("a.sv", "b.sv") rtlList.foreach( f => setResource(s"/$f")) }
ということで、複数のRTLファイルから構成されるVerilog-HDLのモジュールをBlackbox
化して使う方法でした。