チラシの裏は意外と白くない

最近忘れっぽくなったので調べたことをチラシの裏に書きます

SystemC基本構文①

第3章 SystemC基本構文の1回目。プロセスまでを勉強。

ファイル構造

特別な規則はないが慣習的に、

SC_MODULE

SC_MODULEはVerilogでいうところのmoduleで、構成部品は

  • モジュール名
  • 入出力ポート宣言
    • 入力sc_in、出力sc_out、入出力sc_inout、sc_port, sc_fifo_in, sc_fifo_out
    • データ型を合わせて宣言する
  • メンバ関数、変数宣言
  • 信号宣言
  • コンストラクタ宣言

プロセス(SC_METHOD, SC_THREAD, SC_CTHREAD)について

  • プロセスの内部記述は順序的に実行され、プロセス自体は並列動作する
  • Verilogでいうところのalways文に相当する
  • プロセス間の接続には変数とsc_signalが使用できる
    • sc_signalで書くとデルタ遅延が入るので、sc_signalを使用するのが一般的

SC_CTHREAD

  • センシティビティリストはclockだけ
  • wait()までの記述を実行してプロセスを停止、次のクロックエッジで再開する
  • reset_signal_is()でリセット信号を定義できる
    • reset信号を検出すると、スレッドの先頭に戻ってwait()までの記述を実行する
    • スレッド内部に明示的にif(reset){ // リセット処理 }を書かなくてよいということ。最初のwait();までにはリセット記述を書く
  • プロセスに登録する関数をcppに書く場合には、module名::関数名という記述にする
  • クロックごとに繰り返し実行する処理本体は無限ループの中に入れる
    • 無限ループの中にwait()をいれないと、sim時間が進まない
      • この現象は4bitカウンタのトライアルで確認した
    • 正確には(?)wait()がなくてもよくて、RGB2YUVにおいてはthread0()の無限ループ内にwait()はない
      • 代わりにテストベンチ側のsource()とsink()にwaitが挿入されている
  • プロセス内部のローカル変数はwaitに入るたびに保持される

SC_CTHREADの記述例は、

void (module名)::(関数名)()
{
    // reset時の挙動

    wait();

    while(true) {
        // 入出力プロトコル // .read(), .write()で、ポート・信号と値をやり取りする
        // 処理本体 // 時間概念のないC/C++アルゴリズム
        // 入出力プロトコル
    }    
}

SC_THREAD

  • クロック以外の信号やイベント型をセンシティビティに指定できる
    • イベント型??
  • SC_CTHREADより高速なため、検証ではこちらを使うのが一般的
  • SC_CTHREADを包含するプロセスだが、高位合成記述はSC_CTHREADを用いることがOSCIの標準記述スタイルになっている
  • SC_CTHREADとは異なり、リセット記述をサポートしていない
    • そのためリセット記述を入れる場合は、goto文を使用する(!)
    • 以下の記述例を参考
      • 必ず最初のセンシティビティでリセット(まあこれはよい)
      • 無限ループが複数サイクルの場合、すべてのwait()の直後にgoto L0;を入れないといけないと思われる
        • だからSC_THREADで合成記述を書かないのか?

SC_THREADの記述例は、

void (module名)::(関数名)()
{
    // reset時の記述
    L0: ~~~~

    wait();

    while(true) {
        if(reset.read() == 1) goto L0;
        // 処理本体
        wait();
    }
}

SC_METHOD

  • センシティビティリストのいずれかのイベントが発生したときに起動し、プロセス全体を実行して終了する
    • SC_CTHREAD, SC_THREADはシミュレーション中1回しか起動されないのだった
      • そのためこれらのプロセスは無限ループを持つが、SC_METHODは無限ループやwaitを持たない
  • プロセスが起動されるたびにローカル変数は初期化されるため、前回起動したときの値を保持できない
    • 保持したい場合staticとしてローカル変数宣言するか、moduleのメンバ変数として外に出しておく
  • SC_METHODは高位合成対象としてスケジューリングされず、そのままRTLに変換される
    • SC_CTHREADやSC_THREADはwait()・wait()間の回路が大きくターゲット周波数で合成できない場合などに、合成ツールがレジスタスライスを挿入する=スケジューリング
    • clockをセンシティビティに指定したSC_METHODでは記述すべてを1cycleに収めろ、という意味になる
      • FF-FF間のランダムロジックがきっちり決まっていれば、SC_METHODで記述可能…という理解で正しい?
      • SC_METHODで書いた回路がタイミングメットしない場合は、スケジューリングNGになる?

dont_initialize()について

ここは教科書でよくわからなかったので、以下の通りSC_CTHREAD, SC_THREAD, SC_METHODを作って実験してみた。

void proc_test::method()
{
    cout << "[METHOD] main sequence" << endl;
}

void proc_test::thread()
{
    // reset
    L0: cout << "[THREAD] reset status" << endl;

    wait();

    while(true){
        if(!reset) goto L0;
        cout << "[THREAD] main sequence" << endl;
        wait();
    }
}

void proc_test::cthread()
{
    // reset
    cout << "[CTHREAD] reset status" << endl;

    wait();

    while(true){
        cout << "[CTHREAD] main sequence" << endl;
        wait();
    }
}

コンストラクタの記述は以下。

    // constructor
    SC_CTOR(proc_test) {
        SC_METHOD(method);
        sensitive << clock.pos();

        SC_THREAD(thread);
        sensitive << clock.pos();

        SC_CTHREAD(cthread, clock.pos());
        reset_signal_is(reset, false);
    }

dont_initializeなし

$ ./run.x 

        SystemC 2.3.3-Accellera --- Mar  8 2020 14:00:56
        Copyright (c) 1996-2018 by all Contributors,
        ALL RIGHTS RESERVED
[METHOD] main sequence
[THREAD] reset status
[METHOD] main sequence
[CTHREAD] reset status
[THREAD] reset status
[METHOD] main sequence
[CTHREAD] main sequence
[THREAD] main sequence
[METHOD] main sequence
[CTHREAD] main sequence
[THREAD] main sequence

Info: /OSCI/SystemC: Simulation stopped by user.

dont_initializeあり

$ ./run.x 

        SystemC 2.3.3-Accellera --- Mar  8 2020 14:00:56
        Copyright (c) 1996-2018 by all Contributors,
        ALL RIGHTS RESERVED
[METHOD] main sequence
[CTHREAD] reset status
[THREAD] reset status
[METHOD] main sequence
[CTHREAD] main sequence
[THREAD] main sequence
[METHOD] main sequence
[CTHREAD] main sequence
[THREAD] main sequence

Info: /OSCI/SystemC: Simulation stopped by user.

図示するとこんな感じか。SC_THREADとSC_METHODはsim開始時に一度呼ばれ(オレンジ)、その後はセンシティビティリストに登録されたイベントに従って起動される(青)。コンストラクタにdont_initialize()を記述しておくと、このsim開始時の起動が抑制される。 SC_CTHREADについてはsim開始時の呼び出しがないので、dont_initialize()を適用する意味がない。

f:id:samurai375:20200327143053j:plain

プロセスまとめ

process SC_CTHREAD SC_THREAD SC_METHOD
用途 高位合成向け 検証環境向け 両方?
sim開始時の呼び出し なし あり あり
再度呼び出し なし なし あり
while,waitの使用 可能 可能 不可
dont_initialize 無効 有効 有効
センシティビティリスト clockのみ指定可能 複数信号を指定可能 複数信号を指定可能
リセット信号 可能 不可 不可