はじめに
Bluespec SystemVerilogの例題の中を調べてみるシリーズの(その2)
例題
smoke_test という例題の中を調べます。
Verilog HDL Simulator を実行
いったん、clean します。
make clean
smoke_test_verilog ターゲットを実行します。
make smoke_test_verilog Checking Verilog generation bsc -no-show-timestamps -no-show-version -verilog FibOne.bsv Verilog file created: mkFibOne.v Checking Verilog simulation bsc -no-show-timestamps -no-show-version -vsim iverilog -e mkFibOne -o mkFibOne.vexe mkFibOne.v /home/vengineer/home/src/bsc/inst/lib/exec/bsc_build_vsim_iverilog: 204: iverilog: not found ERROR: cannot compile Verilog files make: *** [Makefile:77: smoke_test_verilog] Error 127
iverilog が無いので、apt で install 後、再度、実行
make smoke_test_verilog Checking Verilog generation bsc -no-show-timestamps -no-show-version -verilog FibOne.bsv Verilog file created: mkFibOne.v Checking Verilog simulation bsc -no-show-timestamps -no-show-version -vsim iverilog -e mkFibOne -o mkFibOne.vexe mkFibOne.v Verilog binary file created: mkFibOne.vexe ./mkFibOne.vexe > smoke_test_verilog.out Comparing result of Bluespec Simulation Some simulator specific difference expected diff mkFibOne.out.expected smoke_test_verilog.out Bluespec installation looks OK
生成されたファイルを確認します。
ls FibOne.bo FibOne.bsv Makefile mkFibOne.out.expected mkFibOne.v mkFibOne.vexe smoke_test_verilog.out
最初の bsc コマンドの実行では、
bsc -no-show-timestamps -no-show-version -verilog FibOne.bsv
- FibOne.bo
- mkFibOne.v
が生成されました。
-sim の時は、
- FibOne.bo
- mkFibOne.ba
が生成されたので、FibOne.bo は中間データのようですね。
プログラム (mkFibOne.vexe) を実行します。
./mkFibOne.vexe > smoke_test_verilog.out
smoke_test_verilog.out と期待値ファイル mkFibOne.out.expected を diffコマンドで比較します。
生成された SystemVerilog コード
生成された SystemVerilog コード (mkFibOne.v) は、下記のようになっています。
// // Generated by Bluespec Compiler // // // Ports: // Name I/O size props // CLK I 1 clock // RST_N I 1 reset // // No combinational paths from inputs to outputs // // `ifdef BSV_ASSIGNMENT_DELAY `else `define BSV_ASSIGNMENT_DELAY `endif `ifdef BSV_POSITIVE_RESET `define BSV_RESET_VALUE 1'b1 `define BSV_RESET_EDGE posedge `else `define BSV_RESET_VALUE 1'b0 `define BSV_RESET_EDGE negedge `endif``` module mkFibOne(CLK, RST_N); input CLK; input RST_N; // register next_fib_inst reg [31 : 0] next_fib_inst; wire [31 : 0] next_fib_inst$D_IN; wire next_fib_inst$EN; // register this_fib_inst reg [31 : 0] this_fib_inst; wire [31 : 0] this_fib_inst$D_IN; wire this_fib_inst$EN; // register next_fib_inst assign next_fib_inst$D_IN = this_fib_inst + next_fib_inst ; assign next_fib_inst$EN = 1'd1 ; // register this_fib_inst assign this_fib_inst$D_IN = next_fib_inst ; assign this_fib_inst$EN = 1'd1 ; // handling of inlined registers always@(posedge CLK) begin if (RST_N == `BSV_RESET_VALUE) begin next_fib_inst <= `BSV_ASSIGNMENT_DELAY 32'd1; this_fib_inst <= `BSV_ASSIGNMENT_DELAY 32'd0; end else begin if (next_fib_inst$EN) next_fib_inst <= `BSV_ASSIGNMENT_DELAY next_fib_inst$D_IN; if (this_fib_inst$EN) this_fib_inst <= `BSV_ASSIGNMENT_DELAY this_fib_inst$D_IN; end end // synopsys translate_off `ifdef BSV_NO_INITIAL_BLOCKS `else // not BSV_NO_INITIAL_BLOCKS initial begin next_fib_inst = 32'hAAAAAAAA; this_fib_inst = 32'hAAAAAAAA; end `endif // BSV_NO_INITIAL_BLOCKS // synopsys translate_on // handling of system tasks // synopsys translate_off always@(negedge CLK) begin #0; if (RST_N != `BSV_RESET_VALUE) $display("%0d", $signed(this_fib_inst)); if (RST_N != `BSV_RESET_VALUE) if ((this_fib_inst ^ 32'h80000000) > 32'h80002710) $finish(32'd0); end // synopsys translate_on endmodule // mkFibOne
クロックとリセットが追加されています。
module mkFibOne(CLK, RST_N); input CLK; input RST_N;
// register containing the current Fibonacci value Reg#(int) this_fib(); // interface instantiation mkReg#(0) this_fib_inst(this_fib); // module instantiation // register containing the next Fibonacci value Reg#(int) next_fib(); mkReg#(1) next_fib_inst(next_fib);
の部分が下記のようになりました。
// register next_fib_inst reg [31 : 0] next_fib_inst; wire [31 : 0] next_fib_inst$D_IN; wire next_fib_inst$EN; // register this_fib_inst reg [31 : 0] this_fib_inst; wire [31 : 0] this_fib_inst$D_IN; wire this_fib_inst$EN;
Bluespec Systemverilog の ruleの部分
rule fib; // predicate condition always true, so omitted this_fib <= next_fib; next_fib <= this_fib + next_fib; // note that this uses stale this_fib $display("%0d", this_fib); if ( this_fib > 10000 ) $finish(0) ; endrule: fib
は、下記のようになりました。CLK同期の回路になるようです
// register next_fib_inst assign next_fib_inst$D_IN = this_fib_inst + next_fib_inst ; assign next_fib_inst$EN = 1'd1 ; // register this_fib_inst assign this_fib_inst$D_IN = next_fib_inst ; assign this_fib_inst$EN = 1'd1 ; // handling of inlined registers always@(posedge CLK) begin if (RST_N == `BSV_RESET_VALUE) begin next_fib_inst <= `BSV_ASSIGNMENT_DELAY 32'd1; this_fib_inst <= `BSV_ASSIGNMENT_DELAY 32'd0; end else begin if (next_fib_inst$EN) next_fib_inst <= `BSV_ASSIGNMENT_DELAY next_fib_inst$D_IN; if (this_fib_inst$EN) this_fib_inst <= `BSV_ASSIGNMENT_DELAY this_fib_inst$D_IN; end end
下記は synopsys translate off になっている部分です。初期値の部分と$displayと$finish部分です。後半は、CLKの立下りエッジになっています。
// synopsys translate_off `ifdef BSV_NO_INITIAL_BLOCKS `else // not BSV_NO_INITIAL_BLOCKS initial begin next_fib_inst = 32'hAAAAAAAA; this_fib_inst = 32'hAAAAAAAA; end `endif // BSV_NO_INITIAL_BLOCKS // synopsys translate_on // handling of system tasks // synopsys translate_off always@(negedge CLK) begin #0; if (RST_N != `BSV_RESET_VALUE) $display("%0d", $signed(this_fib_inst)); if (RST_N != `BSV_RESET_VALUE) if ((this_fib_inst ^ 32'h80000000) > 32'h80002710) $finish(32'd0); end // synopsys translate_on
おわりに
次回は、smoke_test_bluesim で生成されたC++モデルについてみてみます。