Vengineerの妄想(準備期間)

人生は短いけど、長いです。人生を楽しみましょう!

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

はじめに

Bluespec SystemVerilogの例題の中を調べてみるシリーズの(その3)

今回は、smoke_test_bluesim で生成されたC++モデルの中をみてみます。

生成されたC++モデル

生成されたC++モデルのファイルは、下記のようになっています。

  • mkFibOne.cxx
  • mkFibOne.h
  • model_mkFibOne.cxx
  • model_mkFibOne.h

mkFibOneがFibOneのC++モデルで、model_mkFibOne がテストベンチのC++モデルっぽいです。

mkFibOne

ヘッダファイル (mkFibOne.h)

/*
 * Generated by Bluespec Compiler
 * 
 */

/* Generation options: */
#ifndef __mkFibOne_h__
#define __mkFibOne_h__

#include "bluesim_types.h"
#include "bs_module.h"
#include "bluesim_primitives.h"
#include "bs_vcd.h"

ここまでがヘッダファイル。

Module クラスを継承する MOD_mkFibOne クラス

/* Class declaration for the mkFibOne module */
class MOD_mkFibOne : public Module {

クロック

 /* Clock handles */
 private:
  tClock __clk_handle_0;
 
 /* Clock gate handles */
 public:
  tUInt8 *clk_gate[0];

インスタンスのパラメータ。今回は無いようです。

 /* Instantiation parameters */
 public:

内部ステータス。ここでは、next_fib_inst と this_fib_inst

 /* Module state */
 public:
  MOD_Reg<tUInt32> INST_next_fib_inst;
  MOD_Reg<tUInt32> INST_this_fib_inst;

コンストラク

 /* Constructor */
 public:
  MOD_mkFibOne(tSimStateHdl simHdl, char const *name, Module *parent);

シンボル初期化関数

 /* Symbol init methods */
 private:
  void init_symbols_0();

リセット信号

 /* Reset signal definitions */
 private:
  tUInt8 PORT_RST_N;

ポート

 /* Port definitions */
 public:

 /* Publicly accessible definitions */
 public:
 
 /* Local definitions */
 private:

リセット信号とリセット関数

 /* Rules */
 public:
  void RL_fib();
 
 /* Methods */
 public:
 
 /* Reset routines */
 public:
  void reset_RST_N(tUInt8 ARG_rst_in);
 
 /* Static handles to reset routines */
 public:
 
 /* Pointers to reset fns in parent module for asserting output resets */
 private:
 
 /* Functions for the parent module to register its reset fns */
 public:

クロック関数

 /* Functions to set the elaborated clock id */
 public:
  void set_clk_0(char const *s);
 
 /* State dumping routine */
 public:
  void dump_state(unsigned int indent);

VCDダンプ関連

 /* VCD dumping routines */
 public:
  unsigned int dump_VCD_defs(unsigned int levels);
  void dump_VCD(tVCDDumpType dt, unsigned int levels, MOD_mkFibOne &backing);
  void vcd_defs(tVCDDumpType dt, MOD_mkFibOne &backing);
  void vcd_prims(tVCDDumpType dt, MOD_mkFibOne &backing);
};

#endif /* ifndef __mkFibOne_h__ */

コンストラクタの中でinit_symbols_0関数が呼ばれています。

MOD_mkFibOne::MOD_mkFibOne(tSimStateHdl simHdl, char const *name, Module *parent)
  : Module(simHdl, name, parent),
    __clk_handle_0(BAD_CLOCK_HANDLE),
    INST_next_fib_inst(simHdl, "next_fib_inst", this, 32u, 1u, (tUInt8)0u),
    INST_this_fib_inst(simHdl, "this_fib_inst", this, 32u, 0u, (tUInt8)0u),
    PORT_RST_N((tUInt8)1u)
{
  symbol_count = 3u;
  symbols = new tSym[symbol_count];
  init_symbols_0();
}

next_fib_inst, RL_fib, this_fib_inst を登録。next_fib_inst, this_fib_instはレジスタ、RL_fibはルール

/* Symbol init fns */

void MOD_mkFibOne::init_symbols_0()
{
  init_symbol(&symbols[0u], "next_fib_inst", SYM_MODULE, &INST_next_fib_inst);
  init_symbol(&symbols[1u], "RL_fib", SYM_RULE);
  init_symbol(&symbols[2u], "this_fib_inst", SYM_MODULE, &INST_this_fib_inst);
}

リセット関数 (reset_RST_N)

/* Reset routines */

void MOD_mkFibOne::reset_RST_N(tUInt8 ARG_rst_in)
{
  PORT_RST_N = ARG_rst_in;
  INST_this_fib_inst.reset_RST(ARG_rst_in);
  INST_next_fib_inst.reset_RST(ARG_rst_in);
}

VCDファイル関連

/* State dumping routine */
void MOD_mkFibOne::dump_state(unsigned int indent)
{
  printf("%*s%s:\n", indent, "", inst_name);
  INST_next_fib_inst.dump_state(indent + 2u);
  INST_this_fib_inst.dump_state(indent + 2u);
}


/* VCD dumping routines */

unsigned int MOD_mkFibOne::dump_VCD_defs(unsigned int levels)
{
  vcd_write_scope_start(sim_hdl, inst_name);
  vcd_num = vcd_reserve_ids(sim_hdl, 3u);
  unsigned int num = vcd_num;
  for (unsigned int clk = 0u; clk < bk_num_clocks(sim_hdl); ++clk)
    vcd_add_clock_def(sim_hdl, this, bk_clock_name(sim_hdl, clk), bk_clock_vcd_num(sim_hdl, clk));
  vcd_write_def(sim_hdl, bk_clock_vcd_num(sim_hdl, __clk_handle_0), "CLK", 1u);
  vcd_write_def(sim_hdl, num++, "RST_N", 1u);
  num = INST_next_fib_inst.dump_VCD_defs(num);
  num = INST_this_fib_inst.dump_VCD_defs(num);
  vcd_write_scope_end(sim_hdl);
  return num;
}

void MOD_mkFibOne::dump_VCD(tVCDDumpType dt, unsigned int levels, MOD_mkFibOne &backing)
{
  vcd_defs(dt, backing);
  vcd_prims(dt, backing);
}

void MOD_mkFibOne::vcd_defs(tVCDDumpType dt, MOD_mkFibOne &backing)
{
  unsigned int num = vcd_num;
  if (dt == VCD_DUMP_XS)
  {
    vcd_write_x(sim_hdl, num++, 1u);
  }
  else
    if (dt == VCD_DUMP_CHANGES)
    {
      if ((backing.PORT_RST_N) != PORT_RST_N)
      {
    vcd_write_val(sim_hdl, num, PORT_RST_N, 1u);
    backing.PORT_RST_N = PORT_RST_N;
      }
      ++num;
    }
    else
    {
      vcd_write_val(sim_hdl, num++, PORT_RST_N, 1u);
      backing.PORT_RST_N = PORT_RST_N;
    }
}

void MOD_mkFibOne::vcd_prims(tVCDDumpType dt, MOD_mkFibOne &backing)
{
  INST_next_fib_inst.dump_VCD(dt, backing.INST_next_fib_inst);
  INST_this_fib_inst.dump_VCD(dt, backing.INST_this_fib_inst);
}

rule の部分

/* Rule actions */

void MOD_mkFibOne::RL_fib()
{
  tUInt32 DEF_this_fib_inst_PLUS_next_fib_inst___d3;
  tUInt8 DEF_NOT_this_fib_inst_SLE_10000___d6;
  tUInt32 DEF_b__h131;
  tUInt32 DEF_b__h163;
  tUInt32 DEF_signed_this_fib_inst___d4;

ここまでは変数の宣言。

  • METH_read() が信号の値のリード
  • METH_write() が信号の値のライト
  • primSEL8 で比較
  DEF_b__h163 = INST_this_fib_inst.METH_read();
  DEF_signed_this_fib_inst___d4 = DEF_b__h163;
  DEF_b__h131 = INST_next_fib_inst.METH_read();
  DEF_NOT_this_fib_inst_SLE_10000___d6 = !primSLE8(1u, 32u, (tUInt32)(DEF_b__h163), 32u, 10000u);
  DEF_this_fib_inst_PLUS_next_fib_inst___d3 = DEF_b__h163 + DEF_b__h131;
  INST_this_fib_inst.METH_write(DEF_b__h131);
  INST_next_fib_inst.METH_write(DEF_this_fib_inst_PLUS_next_fib_inst___d3);

下記の部分は、$display と $finish の部分のようです。

  • $display => dollar_display
  • $finish => dollar_finish
if (!(PORT_RST_N == (tUInt8)0u))
  {
    dollar_display(sim_hdl, this, "s,-32", &__str_literal_1, DEF_signed_this_fib_inst___d4);
    if (DEF_NOT_this_fib_inst_SLE_10000___d6)
      dollar_finish(sim_hdl, "32", 0u);
  }
}

おわりに

生成されたC++モデルの中を見てみましたが、このモデルがどのように呼ばれるのかが、わかりませんね。 どうなんでしょうか。