[SystemC][TLM2] ST,ARM,Cadenceからの提案


STMicroelectronics, ARM and Cadence Improve Tool and Model Interoperability With Three Joint Contributions to Accellera Systems Initiative


ということで、さっそくダウンロード。
「introduction.pdf」に色々書いてあります。

  • Wire (Interrupt, reset, ...) Modeling in VP
    tlm_wireということで、bool型、TLM-1ベースでの実装を提案

  • Register & Memory Inspection API
    scireg APIにて、Register & Memory定義

  • System Address Map API
    transportdbginvalidatedirectmemptr()を使って制御。


下2つは SCMLと仲良くして欲しいな。


実際の動かしはまだ後日。

[SystemC][TLM] SystemC-2.3からの追加:gp_option

SystemC-2.3(TLM2.0)からの追加機能として「gp_option」があります。
詳しい変更としては、こちらの資料を見たらわかり易いと思います。


20130623_gp_option.png

DMIDebug(transport_dbg) の payload dataについて、
使用、未使用の許可が可能です。

20130623_gp_option2.png 20130623_gp_option3.png

Response status に関しては、欲しいと思っていたので、
ありがたいです。

TLMモデルからSystemCモデルへの7つの課題

Merry Christmas!!!


SystemC Advent Calendar2012 の 最後の記事です。


今回は、クリスマスプレゼントということで問題提起だけにしたいと思います。
っと言っても大した事ではないのですが。


では、本題です。
2つの顔を持つ SystemC(IEEE1666) というように
SystemCでは幅広い範囲の抽象度で記述することができます。
それではそれぞれのモデルを再度は以下のような感じになります。


モデリング例


  • Cycleモデル
  •  1|#include <stdlib.h>
     2|#include <vector>
     3|using namespace std;
     4|
     5|#include <systemc.h>
     6|
     7|SC_MODULE( hoge ) {
     8|
     9|  sc_in  <bool >        clk;
    10|  sc_in  <bool >        xrst;
    11|  sc_in  <bool >        ce;
    12|  sc_in  <bool >        we;
    13|  sc_in  <sc_uint<10> > address;
    14|  sc_in  <sc_uint<32> > wdata;
    15|  sc_out <sc_uint<32> > rdata;
    16|
    17|  vector<unsigned int>  mem;
    18|  unsigned int          mem_size;
    19|
    20|  void process();
    21|  void write(unsigned intunsigned int);
    22|  unsigned int read(unsigned int);
    23|
    24|  SC_CTOR( hoge )
    25|    :  clk("clk"), xrst("xrst"), ce("ce"), we("we")
    26|     , address("address"), wdata("wdata"), rdata("rdata")
    27|  {
    28|    SC_THREAD(process);
    29|      sensitive << clk.pos();
    30|      async_reset_signal_is(xrst, false);
    31|    // Size Of Memory 32bit x 256word
    32|    mem_size = 0x100;
    33|    mem.resize(mem_size);
    34|    for(unsigned int i=0; i<mem_size; i++){ mem[i] = 0; }
    35|  }
    36|};
    37|
    38|inline void hoge::process(){
    39|  rdata.write(0);
    40|  wait();
    41|
    42|  while (true) {
    43|    if ((ce.read() == 1)) {
    44|      unsigned int _adrs = address.read() >> 2;
    45|      if (we.read() == 1) {
    46|        unsigned int _data = wdata.read();
    47|        write(_adrs, _data);
    48|      } else {
    49|        rdata = read(_adrs);
    50|      }
    51|    } else {
    52|      wait();
    53|    }
    54|  }
    55|}
    56|
    57|inline void hoge::write(unsigned int _adrs, unsigned int _data){
    58|  mem[_adrs] = _data;
    59|  wait();
    60|}
    61|
    62|inline unsigned int hoge::read(unsigned int _adrs){
    63|  wait();
    64|  wait();
    65|  return mem[_adrs];
    66|}
  • モデルの実行波形
  • 20121225_waves.png
  • TLMモデル
  •  1|#include <stdlib.h>
     2|#include <vector>
     3|using namespace std;
     4|
     5|#include <systemc.h>
     6|#include <tlm.h>
     7|#include "tlm_utils/simple_target_socket.h"
     8|using namespace tlm;
     9|
    10|SC_MODULE( hoge ) {
    11|
    12|  tlm_utils::simple_target_socket<hoge, 32> target_socket;
    13|
    14|  vector<unsigned int> mem;
    15|  unsigned int         mem_size;
    16|
    17|  void my_b_transport(tlm_generic_payload&, sc_time&);
    18|  void write(unsigned intunsigned int);
    19|  unsigned int read(unsigned int);
    20|
    21|  SC_CTOR( hoge )
    22|    : target_socket("target_socket")
    23|  {
    24|
    25|    target_socket.register_b_transport(this, &hoge::my_b_transport);
    26|
    27|    // Size Of Memory 32bit x 256word
    28|    mem_size = 0x100;
    29|    mem.resize(mem_size);
    30|    for(unsigned int i=0; i<mem_size; i++){ mem[i] = 0; }
    31|  }
    32|};
    33|
    34|inline void hoge::my_b_transport(tlm_generic_payload& trans, sc_time& delay){
    35|
    36|  sc_dt::uint64  adr  = trans.get_address() >> 2;
    37|  unsigned char* ptr  = trans.get_data_ptr();
    38|  unsigned int   len  = trans.get_data_length();
    39|  unsigned int   _tmp;
    40|
    41|  if (trans.is_read()) {
    42|    delay += sc_time(30SC_NS);
    43|    _tmp = read(adr);
    44|    memcpy(ptr, &_tmp, len);
    45|  } else if (trans.is_write()) {
    46|    delay += sc_time(10SC_NS);
    47|    memcpy( &_tmp, ptr, len);
    48|    write(adr, _tmp);
    49|  } else {
    50|    delay += SC_ZERO_TIME;
    51|  }
    52|  trans.set_dmi_allowed(false);
    53|  trans.set_response_status( tlm::TLM_OK_RESPONSE );
    54|}
    55|
    56|inline void hoge::write(unsigned int _adrs, unsigned int _data){
    57|  mem[_adrs] = _data;
    58|}
    59|
    60|inline unsigned int hoge::read(unsigned int _adrs){
    61|  return mem[_adrs];
    62|}

差分はなにか?


例えば、 #define で記述するような場合はこんな感じです。

  1|#include <stdlib.h>
  2|#include <vector>
  3|using namespace std;
  4|
  5|#include <systemc.h>
  6|//###################################################################//
  7|//# 1.Include
  8|//###################################################################//
  9|#ifdef TLM
 10|  #include "tlm_utils/simple_target_socket.h"
 11|  using namespace tlm;
 12|#endif
 13|//###################################################################//
 14|
 15|SC_MODULE( hoge ) {
 16|
 17|//###################################################################//
 18|//# 2.Interface
 19|//###################################################################//
 20|#ifdef TLM
 21|  tlm_utils::simple_target_socket<hoge, 32> target_socket;
 22|#else
 23|  sc_in  <bool >        clk;
 24|  sc_in  <bool >        xrst;
 25|  sc_in  <bool >        ce;
 26|  sc_in  <bool >        we;
 27|  sc_in  <sc_uint<10> > address;
 28|  sc_in  <sc_uint<32> > wdata;
 29|  sc_out <sc_uint<32> > rdata;
 30|#endif
 31|//###################################################################//
 32|
 33|  vector<unsigned int> mem;
 34|  unsigned int         mem_size;
 35|
 36|//###################################################################//
 37|//# 3.process関数
 38|//###################################################################//
 39|#ifdef TLM
 40|  void my_b_transport(tlm_generic_payload&, sc_time&);
 41|#else
 42|  void process();
 43|#endif
 44|  void write(unsigned intunsigned int);
 45|  unsigned int read(unsigned int);
 46|//###################################################################//
 47|
 48|  SC_CTOR( hoge )
 49|//###################################################################//
 50|//# 4.初期化リスト
 51|//###################################################################//
 52|#ifdef TLM
 53|    : target_socket("target_socket")
 54|#else
 55|    :  clk("clk"), xrst("xrst"), ce("ce"), we("we")
 56|     , address("address"), wdata("wdata"), rdata("rdata")
 57|#endif
 58|//###################################################################//
 59|  {
 60|
 61|//###################################################################//
 62|//# 5.process起動条件
 63|//###################################################################//
 64|#ifdef TLM
 65|    target_socket.register_b_transport(this, &hoge::my_b_transport);
 66|#else
 67|    SC_THREAD(process);
 68|      sensitive << clk.pos();
 69|      async_reset_signal_is(xrst, false);
 70|#endif
 71|//###################################################################//
 72|    // Size Of Memory 32bit x 256word
 73|    mem_size = 0x100;
 74|    mem.resize(mem_size);
 75|    for(unsigned int i=0; i<mem_size; i++){ mem[i] = 0; }
 76|  }
 77|};
 78|
 79|//###################################################################//
 80|//# 6.process(処理)
 81|//###################################################################//
 82|#ifdef TLM
 83|inline void hoge::my_b_transport(tlm_generic_payload& trans, sc_time& delay){
 84|
 85|  sc_dt::uint64  adr  = trans.get_address() >> 2;
 86|  unsigned char* ptr  = trans.get_data_ptr();
 87|  unsigned int   len  = trans.get_data_length();
 88|  unsigned int   _tmp;
 89|
 90|  if (trans.is_read()) {
 91|    delay += sc_time(30SC_NS);
 92|    _tmp = read(adr);
 93|    memcpy(ptr, &_tmp, len);
 94|  } else if (trans.is_write()) {
 95|    delay += sc_time(10SC_NS);
 96|    memcpy( &_tmp, ptr, len);
 97|    write(adr, _tmp);
 98|  } else {
 99|    delay += SC_ZERO_TIME;
100|  }
101|  trans.set_dmi_allowed(false);
102|  trans.set_response_status( tlm::TLM_OK_RESPONSE );
103|}
104|#else
105|inline void hoge::process(){
106|  rdata.write(0);
107|  wait();
108|
109|  while (true) {
110|    if ((ce.read() == 1)) {
111|      unsigned int _adrs = address.read() >> 2;
112|      if (we.read() == 1) {
113|        unsigned int _data = wdata.read();
114|        write(_adrs, _data);
115|      } else {
116|        rdata = read(_adrs);
117|      }
118|    } else {
119|      wait();
120|    }
121|  }
122|}
123|#endif
124|//###################################################################//
125|
126|inline void hoge::write(unsigned int _adrs, unsigned int _data){
127|  mem[_adrs] = _data;
128|//###################################################################//
129|//# 7.タイミング
130|//###################################################################//
131|#ifndef TLM
132|  wait();
133|#endif
134|//###################################################################//
135|}
136|
137|inline unsigned int hoge::read(unsigned int _adrs){
138|//###################################################################//
139|//# 7.タイミング
140|//###################################################################//
141|#ifndef TLM
142|  wait();
143|  wait();
144|#endif
145|//###################################################################//
146|  return mem[_adrs];
147|}

まとめ


理想的な設計フローとして、TLMモデルから SystemCモデルにする場合に課題点についてでした。 ただ、これらの課題は簡単に解決するものもあるし、更に追求していくともっと壁があると思います(笑)

  • 課題点
  • 1. Include
    2. Interface
    3. process関数
    4. 初期化リスト
    5. process起動条件
    6. process(処理)
    7. Timing

TLM2.0 Socketの種類を把握して有効に使おう

SystemC Advent Calendar2012 の 24日目の記事です。
今回は、TLM2.0モデルのインターフェースになる Socket についてです。


Socketとは何か?


TLM2.0のコアインターフェース(トランスポート、DMI、デバッグトランスポート)の関数呼び出しを提供し、それらのインターフェースをグループ化してポートよりも使いやすくしたもの。


Socketを使う利点


  • TLM2.0のコアインターフェース(トランスポート、DMI、デバッグトランスポート)をまとめて利用できる。
  • 1回の記述でフォワードパスとバックワードパスとを接続できる。
  • コンパイラによる接続チェックがサポートされている。
  • バス幅をパラメータとして指定できる。
  • ソケットを使用せず、ポートのみでコアインターフェースを利用することは推奨しない(相互運用性)

Socketの種類


様々なソケットを用意されています。
これは、用途に応じて使い分けると良いと思います。

クラス コールバック関数の登録 マルチポート b⇔nb変換 タグ付き
tlm_initiator_socket × - ×
tlm_target_socket × × ×
以下、tlm_utilsにて提供
simple_initiator_socket × - ×
simple_initiator_socket_tagged × -
simple_target_socket × ×
simple_target_socket_tagged ×
passthrough_target_socket × × ×
passthrough_target_socket_tagged × ×
multi_passthrough_initiator_socket -
multi_passthrough_target_socket ×
※b⇔nb変換:ブロッキングAPIとノンブロッキングAPIの自動変換


標準Socketよりは tlm_utilsのほうがオススメ


サンプルとして、ターゲット(スレーブ)側の動作について記載します。
※あくまでサンプルなので、自己責任でお願いします。


  • tlm_target_socketを使う記述例
  •  1|#include <stdlib.h>
     2|#include <vector>
     3|using namespace std;
     4|
     5|#include <systemc.h>
     6|#include <tlm.h>
     7|using namespace tlm;
     8|
     9|SC_MODULE( hoge ),tlm_fw_transport_if<> {
    10|
    11|  vector<unsigned int> mem;
    12|  unsigned int         mem_size;
    13|
    14|  void b_transport(tlm_generic_payload&, sc_time&);
    15|  tlm_sync_enum nb_transport_fw(tlm_generic_payload&, tlm_phase&, sc_time&);
    16|  unsigned int transport_dbg(tlm_generic_payload&);
    17|  bool get_direct_mem_ptr(tlm_generic_payload&, tlm_dmi&);
    18|
    19|  tlm_target_socket<32> target_socket;
    20|
    21|  SC_CTOR( hoge )
    22|    : target_socket("target_socket")
    23|  {
    24|    target_socket.bind( *this );
    25|    mem_size = 0x1000;
    26|    mem.resize(mem_size);
    27|    for(unsigned int i=0; i<mem_size; i++){ mem[i] = 0; }
    28|  }
    29|};
    30|
    31|inline void hoge::b_transport(tlm_generic_payload& trans, sc_time& delay){
    32|
    33|  sc_dt::uint64  adr  = trans.get_address() / 4;
    34|  unsigned char* ptr  = trans.get_data_ptr();
    35|  unsigned int   len  = trans.get_data_length();
    36|  unsigned char* byt  = trans.get_byte_enable_ptr();
    37|  unsigned int   blen = trans.get_byte_enable_length();
    38|  unsigned int   wid  = trans.get_streaming_width();
    39|
    40|  delay += SC_ZERO_TIME;
    41|
    42|  if ( adr >= sc_dt::uint64(mem_size) ) {
    43|    trans.set_response_status( tlm::TLM_ADDRESS_ERROR_RESPONSE );
    44|    return;
    45|  }
    46|  if ( wid < len ) {
    47|    trans.set_response_status( tlm::TLM_BURST_ERROR_RESPONSE );
    48|    return;
    49|  }
    50|
    51|  if (trans.is_read()) {
    52|   if ( byt != 0 ) {
    53|     for ( unsigned int i = 0; i < len; i++ )
    54|       if ( byt[i % blen] == TLM_BYTE_ENABLED ) {
    55|         ptr[i] = (mem[adr+i/4] >> ((i&3)*8)) & 0xFF;
    56|       }
    57|   } else {
    58|     memcpy(ptr, &mem[adr], len);
    59|   }
    60|  } else if (trans.is_write()) {
    61|   if ( byt != 0 ) {
    62|     for ( unsigned int i = 0; i < len; i++ )
    63|       if ( byt[i % blen] == TLM_BYTE_ENABLED ) {
    64|         unsigned char temp[4];
    65|         memcpy (temp, &mem[adr+i/4], 4);
    66|         memcpy (&temp[i&3], &ptr[i], 1);
    67|         memcpy (&mem[adr+i/4], temp, 4);
    68|       }
    69|   } else {
    70|     memcpy( &mem[adr], ptr, len);
    71|   }
    72|  }
    73|  trans.set_dmi_allowed(false);
    74|  trans.set_response_status( tlm::TLM_OK_RESPONSE );
    75|
    76|}
    77|
    78|inline tlm_sync_enum hoge::nb_transport_fw(tlm_generic_payload& trans, tlm_phase& phase, sc_time&
    79|delay){
    80|  return tlm::TLM_COMPLETED;
    81|}
    82|
    83|inline unsigned int hoge::transport_dbg(tlm_generic_payload& trans){
    84|  return 0;
    85|}
    86|
    87|inline bool hoge::get_direct_mem_ptr(tlm_generic_payload& trans, tlm_dmi& dmi){
    88|  return false;
    89|}


  • simple_target_socketを使う記述例
  •  1|#include <stdlib.h>
     2|#include <vector>
     3|using namespace std;
     4|
     5|#include <systemc.h>
     6|#include <tlm.h>
     7|#include "tlm_utils/simple_target_socket.h"
     8|using namespace tlm;
     9|
    10|SC_MODULE( hoge ) {
    11|
    12|  vector<unsigned int> mem;
    13|  unsigned int         mem_size;
    14|
    15|  void my_b_transport(tlm_generic_payload&, sc_time&);
    16|
    17|  tlm_utils::simple_target_socket<hoge, 32> target_socket;
    18|
    19|  SC_CTOR( hoge )
    20|    : target_socket("target_socket")
    21|  {
    22|
    23|    target_socket.register_b_transport(this, &hoge::my_b_transport);
    24|
    25|    mem_size = 0x1000;
    26|    mem.resize(mem_size);
    27|    for(unsigned int i=0; i<mem_size; i++){ mem[i] = 0; }
    28|  }
    29|};
    30|
    31|inline void hoge::my_b_transport(tlm_generic_payload& trans, sc_time& delay){
    32|
    33|  sc_dt::uint64  adr  = trans.get_address() / 4;
    34|  unsigned char* ptr  = trans.get_data_ptr();
    35|  unsigned int   len  = trans.get_data_length();
    36|  unsigned char* byt  = trans.get_byte_enable_ptr();
    37|  unsigned int   blen = trans.get_byte_enable_length();
    38|  unsigned int   wid  = trans.get_streaming_width();
    39|
    40|  delay += SC_ZERO_TIME;
    41|
    42|  if ( adr >= sc_dt::uint64(mem_size) ) {
    43|    trans.set_response_status( tlm::TLM_ADDRESS_ERROR_RESPONSE );
    44|    return;
    45|  }
    46|  if ( wid < len ) {
    47|    trans.set_response_status( tlm::TLM_BURST_ERROR_RESPONSE );
    48|    return;
    49|  }
    50|
    51|  if (trans.is_read()) {
    52|   if ( byt != 0 ) {
    53|     for ( unsigned int i = 0; i < len; i++ )
    54|       if ( byt[i % blen] == TLM_BYTE_ENABLED ) {
    55|         ptr[i] = (mem[adr+i/4] >> ((i&3)*8)) & 0xFF;
    56|       }
    57|   } else {
    58|     memcpy(ptr, &mem[adr], len);
    59|   }
    60|  } else if (trans.is_write()) {
    61|   if ( byt != 0 ) {
    62|     for ( unsigned int i = 0; i < len; i++ )
    63|       if ( byt[i % blen] == TLM_BYTE_ENABLED ) {
    64|         unsigned char temp[4];
    65|         memcpy (temp, &mem[adr+i/4], 4);
    66|         memcpy (&temp[i&3], &ptr[i], 1);
    67|         memcpy (&mem[adr+i/4], temp, 4);
    68|       }
    69|   } else {
    70|     memcpy( &mem[adr], ptr, len);
    71|   }
    72|  }
    73|  trans.set_dmi_allowed(false);
    74|  trans.set_response_status( tlm::TLM_OK_RESPONSE );
    75|
    76|}

コメント


記述としては、極端すぎるような感じもしますが上記のような感じです。
simple_initiator/target_socketを使い方やメリットとしては、

  • tlm_utilsのヘッダーファイルを includeする必要がある。
  • tlm_fw_transport_if などの継承が要らない。
  • 必要なものだけ登録(例えば、register_b_transport)すれば良い。

などがあると思います。
個人的には、記述する際にはこちらのほうが色々とお得かと思います。


いよいよ明日で最後となります。
最後は、「TLMモデルからSystemCモデルに」ついてです。
Merry Christmas Eve !!!

TLM2.0:テンポラリデカップリング記述(Quantum Keeper)

前回のblogにて、シミュレーションを高速化するために
Direct Memory Interface(DMI)を使うという話でしたが、
高速化の手法として「テンポラリデカップリング」を使う方法もあります。

ある期間(set_global_quantum)を設けて、一気に wait(sync)することで、
wait(シミュレーション時間の経過)の回数を少なくするというものです。

Initiator;quantum期間を指定


31|    SC_CTOR( lt_initiator )
32|        : initiator_socket("initiator_socket")
33|    {
34|        SC_THREAD( process );
35|        initiator_socket.bind( *this );
36|#ifdef QUANTUM
37|        m_quantumkeeper.set_global_quantum(sc_time(100,SC_US));
38|        m_quantumkeeper.reset();
39|#endif
40|    }

Initiator:通信後(例:b_transport)に時間更新判断


101|    sc_time delay = SC_ZERO_TIME;
102|#ifdef QUANTUM
103|    delay = m_quantumkeeper.get_local_time();
104|#endif
105|
106|    initiator_socket->b_transport(*trans, delay);
107|
108|    if(trans->get_response_status() != tlm::TLM_OK_RESPONSE) {
109|        sc_stop();
110|    }
111|    
112|#ifdef QUANTUM
113|    m_quantumkeeper.set(delay);
114|    if (m_quantumkeeper.need_sync()) {
115|        std::cout << "Syncing..." << std::endl;
116|        m_quantumkeeper.sync();
117|    }
118|#else
119|    wait(delay);
120|#endif

こちらもシミュレーション時間は測定してものの
少しの時間しか流れないシミュレーションは特に差分は見えなかったです。
■シミュレーション概要
latency = 10 ns
total simulation time = 200us
■シミュレーション結果
 ○ Timing anotation(毎回waitを実行())
  real 0m0.148s
  user 0m0.072s
  sys  0m0.032s

 ○ Quantum time(global_qantum:1us)
  real 0m0.144s
  user 0m0.068s
  sys  0m0.036s
  
 ○ Quantum time(global_qantum:2us)
  real 0m0.137s
  user 0m0.084s
  sys  0m0.016s
  
 ○ Quantum time(global_qantum:5us)
  real 0m0.138s
  user 0m0.064s
  sys  0m0.032s
  
 ○ Quantum time(global_qantum:10us)
  real 0m0.149s
  user 0m0.084s
  sys  0m0.024s
今回のソースはこちらのGitHubのほうに置いてあります。
GitHub:systems/tutor_test/007_tlm2_quantum
プロフィール

Kocha

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

カレンダー
10 | 2017/11 | 12
- - - 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 - -
カテゴリ
OVP (4)
最新記事
最新コメント
アーカイブ
リンク
Twitter
アクセス人数