Learn SystemC with Examples #6 (Signal: read and write~Buffer)

Signal: read and write

https://www.learnsystemc.com/basic/signal_readwrite

sc_signalとは

  1. プリミティブチャネルであり、電気信号を運ぶワイヤーをモデリングするために使う
  2. evaluate-update方式を使う。これにより、同時read/writeのふるまいが一意になる。現在の値と新しい値を維持する。
  3. write() メソッドは現在の値と新しい値が異なるときにupdateリクエストを出す。
  4. sc_signal_inout_if<T> インタフェースがある。

コンストラク

  1. sc_signal()
    • ベースクラスの sc_prim_channel(sc_gen_unique_name("signal")) 呼び出し
  2. sc_signal(const char* name_)
    • ベースクラスの sc_prim_channel(name_) 呼び出し

メンバ関数

  1. T& read() or operator const T& ()
    • 現在の値の参照を返す。信号の状態を変化させない。
  2. void write(const T&)
    • 次デルタ時刻に値を更新する。
  3. operator=
    • write() と等価
  4. sc_event& default_event(), sc_event& value_changed_event()
    • 値が変化したときのイベントの参照を返す。
  5. bool event()
    • 同一シミュレーション時刻の直前のデルタ時刻のupdateフェーズでちょうど値の更新が行われた場合のみ true

sc_fifoとの比較

  1. sc_signal のスロット数は1
  2. sc_signal は現在の値と新しい値が異なる場合のみupdateリクエストをトリガーする
  3. sc_signal の read は値を削除しない。

executionフェーズ以外のsc_signalについて

  1. 初期値をエラボレーション中に書き込める
  2. sc_mainからエラボレーション中あるいはシミュレーション停止中に書き込める。sc_startの呼び出し前でも呼び出し後でも可能。

補注:要するにVerilogでのノンブロッキング代入と同じ。

Signal: detect event

https://www.learnsystemc.com/basic/signal_event

  1. sc_event& default_event(), sc_event& value_changed_event()
    • value-changed eventの参照を返す。
  2. bool event()
    • 同一シミュレーション時刻の直前のデルタ時刻のupdateフェーズでちょうど値の更新が行われた場合のみ true

Signal: many writers

https://www.learnsystemc.com/basic/signal_many_writer

sc_signalのクラス定義
template <class T, sc_writer_policy WRITER_POLICY = SC_ONE_WRITER> class sc_signal: public sc_signal_inout_if<T>, public sc_prim_channel {}

  1. WRITER_POLICY == SC_ONE_WRITER の場合、複数のプロセスから信号が書き込まれるとエラー
  2. WRITER_POLICY == SC_MANY_WRITERS の場合、
    • 複数のプロセスが同時に信号に書き込むとエラーになる
    • 異なるデルタ時刻であれば異なるプロセスが書き込むことは可能

デフォルトはSC_ONE_WRITER。
読み込みは同一時刻か異なる時刻かにかかわらず複数のプロセスからread可能。

補注:
サンプルコード中、writer2() スレッドの s1.write(v); のコメントアウトを有効化すると以下のようにランタイムエラーになる。
信号s1に対して複数のドライバが存在するためである。
一方、s2に対する複数ドライバは SC_MANY_WRITERS 指定によりエラーにならない。
s2でも同時書き込みが発生するとエラーになるが、writer2内で同時書き込みが起こらないようデルタ遅延が挿入されているためエラーは起きない。
同時書き込みが起きてもエラーにならない別の機構については次のチャプターで紹介されている。

Error: (E115) sc_signal<T> cannot have more than one driver:
 signal `consumers.signal_0' (sc_signal)
 first driver `consumers.writer1' (sc_thread_process)
 second driver `consumers.writer2' (sc_thread_process)
In file: ../../../src/sysc/communication/sc_signal.cpp:67
In process: consumers.writer2 @ 0 s

Resolved Signal

https://www.learnsystemc.com/basic/resolved_signal

Resolved signalとは、sc_signal_resolved 型あるいは sc_signal_rv 型のオブジェクトである。
sc_signal との違いは、resolved signalは複数のプロセスからの同時書き込みを許容し、チャネル内で衝突を解決する点である。

  1. sc_signal_resolved はプリミティブチャネルであり、sc_signalの派生クラスである。
  2. sc_signal_rv はリミティブチャネルであり、sc_signalの派生クラスである。
    • sc_signal_rv は sc_signal_resolved と似ている。
    • 違いはテンプレート引数。クラス定義は以下の通り。
      • class sc_signal_resolved: public sc_signal<sc_dt::sc_logic,SC_MANY_WRITERS>
      • template <int W> class sc_signal_rv: public sc_signal<sc_dt::sc_lv<W>,SC_MANY_WRITERS>

解決テーブルは以下の通り。補注:Verilogwireと同じ。

  | 0 | 1 | Z | X |
0 | 0 | X | 0 | X |
1 | X | 1 | 1 | X |
Z | 0 | 1 | Z | X |
X | X | X | X | X |

sc_signal<bool>

https://www.learnsystemc.com/basic/signal_bool

sc_signal_in_if<bool> と sc_signal_in_if<sc_dt::sc_logic>は追加のメンバ関数を持つ。

  1. posedge_event(), negedge_event()
    • 値が変化し、新しい値が 1/0 の時にいつでも通知を出すイベントの参照を返す
  2. posedge(), negedge()
    • 直前のデルタ時刻で値が更新され、新しい値が 1/0 の時にtrueを返し、そうでなければfalseを返す。

Buffer

https://www.learnsystemc.com/basic/buffer

sc_bufferはプリミティブチャネルであり、sc_signalの派生クラスである。
sc_signalとの違いはvalue-changed eventが値の書き込みが行われたときに発生する点である。

  1. sc_signal の場合、現在の値が1で1が書き込まれたとき、 イベントはトリガーされない。
  2. sc_buffer の場合、現在の値が1で1が書き込まれたとき、 イベントはトリガーされる。