Vengineerの妄想

人生を妄想しています。

Bluespec SystemVerilog の例題の中を調べる(その2)

はじめに

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++モデルについてみてみます。