bambooflow Note

b_transport

最終更新:

bambooflow

- view
メンバー限定 登録/ログイン

TLM-2.0 b_transportについて



b_transportについて

void b_transport( tlm_generic_payload& , sc_time& )

b_transportはイニシエータからターゲットにデータ転送するときに使用するI/Fの関数。
b_transportはtlm_blocking_transport_ifの純粋仮想関数。
tlm_fw_transport_ifはこのtlm_blocking_transport_ifを継承しているので、tlm_fw_transport_ifを使ってインターフェースを準備するにはb_transportの定義が必要となる。
ブロッキングなので、b_transportではwait記述が可能。もちろんなくてもかまわない。
第1引数tlm_generic_payloadは共通のトランザクション。
第2引数sc_time& はタイミングアノテーション用。
LTモデルでは、sc_timeはSC_ZERO_TIMEを渡す。


LTモデルのb_transportの簡単な記述例(時間無し)

ターゲット側で、レジスタを用意して、アドレス指定してRead/Writeアクセス。
イニシエータ側はアドレスを指定してデータを書き込み、そのあと同じアドレスに対してデータを読み込む。

基本的なアクセスは以下のような感じになる。
  1. イニシエータ側でb_transportを呼ぶ
  2. ターゲット側に実装されたb_transportが処理される
  3. ターゲット側は最後にresponse_statusを設定してイニシエータに戻す(return)
  4. イニシエータはresponse_statusをみて正しく処理されたか確認する

ターゲット側

// メンバ変数
  enum { REG_MAX_SIZE=256 };       // レジスタのサイズ
  unsigned int Reg[REG_MAX_SIZE];  // レジスタを用意
 
void b_transport( tlm::tlm_generic_payload &trans, sc_time &time )
{
  // アドレス取得
  unsigned int address = static_cast<unsigned int>(trans.get_address());
  // データポインタ
  unsigned int *data_ptr = reinterpret_cast<unsigned int*>(trans.get_data_ptr());
 
  // unsigned int data_length = trans.get_data_length();
  // unsigned int streaming_width = get_streaming_width();
  // unsigned char* byte_enable_ptr = get_byte_enable_ptr();
  // unsigned int byte_enable_length = get_byte_enable_length();
  // bool dmi = is_dmi_allowed();
 
  unsigned int idx = address/4;
  if (idx < REG_MAX_SIZE) {
    if (trans.is_read()) {  // TLM_READ_COMMAND
      // Read動作
      *data_ptr = Reg[idx];
 
      //wait( 10, SC_US );
      trans.set_response_status( tlm::TLM_OK_RESPONSE ); // アクセスOK
    }
    else if (trans.is_write()) {  // TLM_WRITE_COMMAND
      // Write動作
      Reg[idx] = *data_ptr;
 
      //wait( 15, SC_US );
      trans.set_response_status( tlm::TLM_OK_RESPONSE ); // アクセスOK
    }
    else { // TLM_IGNORE_COMMAND
      trans.set_response_status( tlm::TLM_COMMAND_ERROR_RESPONSE ); // アクセスERROR
    }
  }
  else {
    cout << " Address Error: " << "addr=" << hex << address
         << " (MAX_SIZE=" << REG_MAX_SIZE << ")" << endl;
    trans.set_response_status( tlm::TLM_ADDRESS_ERROR_RESPONSE  ); // アドレス指定エラー
  }
}
 

イニシエータ側

void thread0()
{
  unsigned int addr = 0x100;
  {  // 書き込み動作
    unsigned int data = 0x1234;  // 適当な値
 
    tlm::tlm_generic_payload* trans = new tlm::tlm_generic_payload;
    sc_time time = SC_ZERO_TIME;
 
    // データ書き込み設定
    trans->set_address( addr );
    trans->set_data_ptr( reinterpret_cast<unsigned char*>(&data) );
    trans->set_data_length( 4 );   // byte
    trans->set_write();  // set_command( tlm::TLM_WRITE_COMMAND );
 
    i_socket->b_transport( *trans, time );
 
    if (trans->is_response_ok()) {
       cout << "Initiator::Write Access OK" << endl;
       cout << "  Write Data=0x" << hex << data << endl;
    }
    else if (trans->is_response_error()) {
       cout << "Initiator::Write Access ERROR" << endl;
    }
 
    delete trans;
  }
  {  // 読み込み動作
    unsigned int data;
 
    tlm::tlm_generic_payload* trans = new tlm::tlm_generic_payload;
    sc_time time = SC_ZERO_TIME;
 
    // データ読み込み設定
    trans->set_address( addr );
    trans->set_data_ptr( reinterpret_cast<unsigned char*>(&data) );
    trans->set_data_length( 4 );   // byte
    trans->set_read();  // set_command( tlm::TLM_READ_COMMAND );
 
    i_socket->b_transport( *trans, time );
 
    if (trans->is_response_ok()) {
       cout << "Initiator::Read Access OK" << endl;
       cout << "  Read Data=0x" << hex << data << endl;
    }
    else if (trans->is_response_error()) {
       cout << "Initiator::Read Access ERROR" << endl;
    }
 
    delete trans;
  }
}
 

注意点

ここでの記述例は、イニシエータではthreadの関数から直接ソケットのb_transport()関数を呼んだり、ターゲットではb_transport関数内で直接処理を記述したりしている。
今回は説明のために直接記述しているが、本来これは、よくない記述。
コーディングルールにのっとるなら、通信部分と機能記述を分離しなければならない。
分離には継承とvirtual =0を駆使するとできる。
記事メニュー
ウィキ募集バナー