スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

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 !!!

関連記事

コメントの投稿

非公開コメント

プロフィール

Kocha

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

カレンダー
08 | 2017/09 | 10
- - - - - 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
アクセス人数
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。