Vengineerの妄想

人生を妄想しています。

Bluespec SystemVerilog : HELLO WORLDを学ぶ(その6)

Verification Engineerの戯言


(その5)の最後のコードからSystemCコードを生成してみましょう!

なお、SystemCコードを生成するには、環境変数(SYSTEMC)にSystemCがインストールされているディレクトリを指定する必要があります。

    % bsc -sim FirstAttempt.bsv
    Elaborated module file created: mkAttempt.ba
    % bsc -systemc -e mkAttempt mkAttempt.ba
    Warning: Unknown position: (S0028)
      Support for BSV-to-SystemC in this release is not complete or has not been
      tested
    Bluesim object reused: mkAttempt.{h,o}
    Bluesim object created: schedule.{h,o}
   SystemC object created: mkAttempt_systemc.{h,o}

メッセージから生成されるSystemCコードはまだ、完璧では内容ですね!
生成されるファイルは、2つ、ソースファイル(mkAttempt_systemc.c)とヘッダファイル(mkAttempt_systemc.h)です。
生成されるファイルは、FirstAttempt.bsvの中で定義したmoduleの名前をベースにしています。
では、まずは、ヘッダーファイル(mkAttempt_systemc.h)を見ていきましょう。

    #ifndef __MKATTEMPT_SYSTEMC_H__
    #define __MKATTEMPT_SYSTEMC_H__

    #include "bluesim_kernel_api.h"
    #include "mkAttempt.h"

    /* SystemC model definition */
    SC_MODULE(mkAttempt) {
 
     /* clock and reset inputs */
     public:
      sc_in<bool > CLK;
      sc_in<bool > RST_N;
 
     /* method ports */
     public:
 
     /* implementation class */
     public:
      bluesim::MOD_mkAttempt *_model_inst;
 
     /* constructor */
     public:
      SC_CTOR(mkAttempt)
        : CLK("CLK"), RST_N("RST_N"), _model_inst(NULL)
      {
    
        SC_METHOD(handle_CLK);
        sensitive << CLK.value_changed();
        dont_initialize();
    
        SC_METHOD(handle_RST_N);
        sensitive << RST_N.value_changed();
      }
 
     /* destructor */
     public:
      ~mkAttempt()
      {
      }
 
     /* simulation callbacks */
     public:
      virtual void start_of_simulation()
	      {
	        bk_wait_for_license();
	        bk_init(false);
	        bk_set_interactive();
	        _model_inst = (bluesim::MOD_mkAttempt *)(bk_get_model_instance());
	      };
      virtual void end_of_simulation()
	      {
	        bk_shutdown();
	      };
 
     /* clock and reset handlers */
     private:
      void handle_CLK();
      void handle_RST_N();
    };

    #endif /* ifndef __MKATTEMPT_SYSTEMC_H__ */

純粋なOSCIベースのSystemCコードではありません。
"bluesim_kernel_api.h"というヘッダファイルをインクルードし、bluesim::というキーワードも使っています。
このSystemCコードはあくまでもシミュレーション用のコードになります。

mkAttemptモジュールは、Verilog HDLコードとCLKとRST_Nの入力ポートがあります。
2つのSC_METHODとシミュレーション用にstart_of_simulationend_of_simulationも定義しています。
(ここでライセンス管理等もやっているようです)

SC_METHODでは、handle_CLK関数がCLKの変化をイベントとし、handle_RST_N関数はRST_Nの変化をイベントとしています。

次にソースコード(mkAttempt_systemc.c)を見ていきましょう。

    #include "bluesim_systemc.h"
    #include "mkAttempt_systemc.h"

    void mkAttempt::handle_CLK()
    {
      static tClock clk = bk_get_clock_by_name("CLK");
  
      /* sample method input ports */
  
      /* update VCD waveforms for ports */
      tTime now = sc_time_stamp().value();
      bk_VCD_combo_update(now);
  
      /* execute schedule */
      tEdgeDirection dir = (CLK->read)() ? POSEDGE : NEGEDGE;
      bk_quit_after_edge(clk, dir, bk_clock_edge_count(clk, dir) + 1llu);
      bk_trigger_clock_edge(clk, dir, now);
      bk_advance(false);
  
      /* update method output ports */
    }

    void mkAttempt::handle_RST_N()
    {
       (_model_inst->reset_RST_N)((RST_N->read)());
    }

handle_CLK関数に関しては、ほどんとbk_xxxというAPIを使っています。
handle_RST_N関数に関しては、実際のモデルへRST_Nポートの値を渡しているだけです。

ということで、生成されるSystemCコードはあくまでもシミュレーション用のコードですので、
内容については深く立ち入らないようにします。

検証、Verification、Bluespec SystemVerilog

P.S
HELLO WORLDを学ぶは、今回で最後です。次回からは「COUNTERを学ぶ」です。