Verification Engineerの戯言
今回と次回では、SimpleLTTarget1/2について説明します。
SimpleBusに接続するターゲットとしては、
unit_test/tlm/common/include/modelsディレクトリに次の6つが用意されています。
必要な次の3つのメソッドです。
で受信トランザクションからアドレス、コマンド、データポインタを獲得します。
get_commandメソッドの戻り値がtlm::TLM_WRITE_COMMANDのときは、ライトなので、
get_data_ptrメソッドで獲得したデータを内部メモリ(mMem[address])にストアし、引数tに10(SC_NS)を設定します。
tlm::TLM_READ_COMMANDのときは、リードなので内部メモリ(mMem[address])の値をdataにロードし、
引数tに100(SC_NS)を代入します。引数tに代入した値は、トランザクションを送信してきたイニシエータに渡され、
イニシエータ内でウエイトする時間として使われます。
その後に、set_response_stateコマンドでステータスとしてtlm::TLM_OK_RESPONSEを設定します。
最後にset_dmi_allowedメソッドでDMIが使えることを設定し、tlm::TLM_COMPLETEDを戻り値とします。
イニシエータでは、この戻り値を受けて処理をします。ちなみに次のコードは、'''SimpleLTInitiator1クラスの部分です。
unit_test/tlm/common/include/modelsディレクトリに次の6つが用意されています。
SimpleLTTarget1 SimpleLTTarget2SimpleLTTarget1クラスは、tlm::tlm_fw_nb_transport_ifクラスを継承しますので、
必要な次の3つのメソッドです。
sync_enum_type nb_transport(transaction_type& trans, phase_type& phase, sc_core::sc_time& t); unsigned int transport_dbg(tlm::tlm_debug_payload& r); bool get_direct_mem_ptr(const sc_dt::uint64& address, dmi_mode_type& dmi_mode, tlm::tlm_dmi& dmi_data);まずは、nb_transportメソッドです。
sync_enum_type nb_transport(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) { assert(phase == tlm::BEGIN_REQ); sc_dt::uint64 address = trans.get_address(); assert(address < 400); unsigned int& data = *reinterpret_cast<unsigned int*>(trans.get_data_ptr()); if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { std::cout << name() << ": Received write request: A = 0x" << std::hex << (unsigned int)address << ", D = 0x" << data << std::dec << " @ " << sc_core::sc_time_stamp() << std::endl; *reinterpret_cast<unsigned int*>(&mMem[address]) = data; t += sc_core::sc_time(10, sc_core::SC_NS); } else { std::cout << name() << ": Received read request: A = 0x" << std::hex << (unsigned int)address << std::dec << " @ " << sc_core::sc_time_stamp() << std::endl; data = *reinterpret_cast<unsigned int*>(&mMem[address]); t += sc_core::sc_time(100, sc_core::SC_NS); } trans.set_response_status(tlm::TLM_OK_RESPONSE); trans.set_dmi_allowed(true); // LT target // - always return true // - not necessary to update phase (if true is returned) return tlm::TLM_COMPLETED; }引数transに対して、get_addressメソッド、get_commandメソッド、get_data_ptrメソッド、
で受信トランザクションからアドレス、コマンド、データポインタを獲得します。
get_commandメソッドの戻り値がtlm::TLM_WRITE_COMMANDのときは、ライトなので、
get_data_ptrメソッドで獲得したデータを内部メモリ(mMem[address])にストアし、引数tに10(SC_NS)を設定します。
tlm::TLM_READ_COMMANDのときは、リードなので内部メモリ(mMem[address])の値をdataにロードし、
引数tに100(SC_NS)を代入します。引数tに代入した値は、トランザクションを送信してきたイニシエータに渡され、
イニシエータ内でウエイトする時間として使われます。
その後に、set_response_stateコマンドでステータスとしてtlm::TLM_OK_RESPONSEを設定します。
最後にset_dmi_allowedメソッドでDMIが使えることを設定し、tlm::TLM_COMPLETEDを戻り値とします。
イニシエータでは、この戻り値を受けて処理をします。ちなみに次のコードは、'''SimpleLTInitiator1クラスの部分です。
switch (socket->nb_transport(trans, phase, t)) { case tlm::TLM_COMPLETED: wait(t); break;引数tに設定した時間、イニシエータでウエイト(wait(t))します。
次に、transport_dbgメソッドです。このメソッドは、デバッグ用です。
戻り値は、アクセスしたバイト数です。
unsigned int transport_dbg(tlm::tlm_debug_payload& r) { if (r.address >= 400) return 0; unsigned int tmp = (int)r.address; unsigned int num_bytes; if (tmp + r.num_bytes >= 400) { num_bytes = 400 - tmp; } else { num_bytes = r.num_bytes; } if (r.do_read) { for (unsigned int i = 0; i < num_bytes; ++i) { r.data[i] = mMem[i + tmp]; } } else { for (unsigned int i = 0; i < num_bytes; ++i) { mMem[i + tmp] = r.data[i]; } } return num_bytes; }transport_dbgメソッドでは、最大400バイトまでリード/ライトできるようになっています。
戻り値は、アクセスしたバイト数です。
途中ですが、今日はここまで。