はじめに
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++モデルの中を見てみましたが、このモデルがどのように呼ばれるのかが、わかりませんね。 どうなんでしょうか。