2つの顔を持つ SystemC(IEEE1666)

SystemC Advent Calendar2012 の 五日目の記事です。
先ずは以下の2つのソースを見てもらったほうが話は早いと思います。
仕様としては、32bitの2つのデータを乗算するという回路です。
※今回のコードは極端に記載してありますのでご了承ください。
 あと、記述が汚い点も。。。使用するなら自己責任で。


  • SystemCモデル(サイクルモデル)
  •  1|#include <systemc.h>
     2|
     3|SC_MODULE( hoge ){
     4|
     5|  sc_in  <bool >        clk;
     6|  sc_in  <bool >        xrst;
     7|  sc_in  <sc_uint<32> > indata1;
     8|  sc_in  <sc_uint<32> > indata2;
     9|  sc_out <sc_uint<64> > outdata;
    10|
    11|  void process();
    12|
    13|  SC_CTOR( hoge )
    14|  {
    15|    SC_CTHREAD( process, clk.pos() );
    16|    reset_signal_is(xrst, false);
    17|  }
    18|};
    19|
    20|void hoge::process(){
    21|  outdata.write(0);
    22|  wait();
    23|
    24|  while (true) {
    25|    outdata.write(indata1.read() * indata2.read());
    26|    wait();
    27|  }
    28|}
  • SystemCモデル(TLM/TLM2.0モデル)
  •  1|#include <systemc.h>
     2|using namespace tlm;
     3|
     4|SC_MODULE( hoge ),tlm_fw_transport_if<> {
     5|
     6|  sc_uint<32> _data1, _data2;
     7|  sc_uint<64> _tmp;
     8|  sc_uint<64> _outdata;
     9|  unsigned long long __tmp;
    10|
    11|  void b_transport(tlm_generic_payload&, sc_time&);
    12|  tlm_sync_enum nb_transport_fw(tlm_generic_payload&, tlm_phase&, sc_time&);
    13|  unsigned int transport_dbg(tlm_generic_payload&);
    14|  bool get_direct_mem_ptr(tlm_generic_payload&, tlm_dmi&);
    15|
    16|  tlm_target_socket<32> target_socket;
    17|
    18|  SC_CTOR( hoge )
    19|    : target_socket("target_socket")
    20|  {
    21|    target_socket.bind( *this );
    22|    _outdata = 0;
    23|  }
    24|};
    25|
    26|inline void hoge::b_transport(tlm_generic_payload& trans, sc_time& delay){
    27|
    28|  unsigned char* ptr  = trans.get_data_ptr();
    29|
    30|  delay += SC_ZERO_TIME;
    31|  if (trans.is_read()) {
    32|    _outdata = _data1 * _data2;
    33|    __tmp = _outdata.to_uint64();
    34|    trans.set_data_ptr(reinterpret_cast<unsigned char*>(&__tmp));
    35|  } else if (trans.is_write()) {
    36|    _tmp = *(reinterpret_cast<unsigned long long *>(ptr)) ;
    37|    _data1 = _tmp.range(310);
    38|    _data2 = _tmp.range(6332);
    39|  }
    40|  trans.set_dmi_allowed(false);
    41|  trans.set_response_status(TLM_OK_RESPONSE );
    42|
    43|}
    44|
    45|inline tlm_sync_enum hoge::nb_transport_fw(tlm_generic_payload& trans, tlm_phase& phase, sc_time&
    46|delay){
    47|  return TLM_COMPLETED;
    48|}
    49|
    50|inline unsigned int hoge::transport_dbg(tlm_generic_payload& trans){
    51|  return 0;
    52|}
    53|
    54|inline bool hoge::get_direct_mem_ptr(tlm_generic_payload& trans, tlm_dmi& dmi){
    55|  return false;
    56|}

クロックがない


まず、一番の大きな違いは「抽象度」の違いだと思います。
最初のコードはクロックドリブン(本記述ではclk信号の立ち上がり)で動作する回路です。
一方、その次に記載しているソースコードは、関数ドリブンで動作しております。
(本記述では、b_transport関数がコールされた時点で動作)
High Level Synthsis(高位合成や動作合成)を行う際のモデル記述は極端に言うと、最初のコードになりま す。
Virtual Platform(仮想環境)といった場合には、後半のコードのイメージになります。
※今回、リセット信号は書いてないだけです。


定義する関数


TLM(主にTLM2.0という場合が多い)モデルと言われるモデルには
必ず定義しないといけない関数があります。
今回は、ターゲット(いわゆるBusなどで言うスレーブ)モデルなので、
上記に記述した関数が最低限必要になります。(Loosely-Timed限定)


SystemC(IEEE1666)は考えて上手く使おう!


SystemCには記述スタイルによって、このように明確に違いがあります。
筆者自身は最初に SystemCを使い場合はサイクルを考えずに機能を記述していく
TLMモデルがいいのかなと思いますが、最初にサイクルモデルを記述される方は
RTL記述のようにならないように何を書かないといけないか考えてみてください。

関連記事

コメントの投稿

非公開コメント

プロフィール

Kocha

Author:Kocha
なんでもチャレンジ!(^o^)/
E-mail
github:Kocha
イベントカレンダー

カレンダー
09 | 2017/10 | 11
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 - - - -
カテゴリ
OVP (4)
最新記事
最新コメント
アーカイブ
リンク
Twitter
アクセス人数