Verification Engineerの戯言
昨日に続き、SimplTLInitiator_DMIクラスについてです。
SimpleTLInitiator1_DMIクラスのrunメソッドは、次のようになっています。
生成したトランザクションがDMI内のアドレスかどうかを調べ、DMI内のアドレスであれば、
DMIで処理し、そうでないときはsocketに対して、nb_transportメソッドを実行し、
外部へのトランザクションを発生します。
void run() { transaction_type trans; phase_type phase; sc_core::sc_time t; while (initTransaction(trans)) { phase = tlm::BEGIN_REQ; t = sc_core::SC_ZERO_TIME; // Check if the address is covered by our DMI region if ( (trans.get_address() >= mDMIData.dmi_start_address) && (trans.get_address() <= mDMIData.dmi_end_address) ) { ここは、DMIのコードなので後ほど、 } else { switch (socket->nb_transport(trans, phase, t)) { case tlm::TLM_COMPLETED: wait(t); break; case tlm::TLM_ACCEPTED: case tlm::TLM_UPDATED: wait(mEndEvent); break; case tlm::TLM_REJECTED: default: assert(0); exit(1); }; // Acquire DMI pointer if we get the hint: if (trans.get_dmi_allowed()) { dmi_type tmp; dmi_mode_type tmp_mode; tmp_mode.type = tlm::tlm_dmi_mode::WRITE; if ( socket->get_direct_mem_ptr(trans.get_address(), tmp_mode, tmp) && (tmp_mode.type != tlm::tlm_dmi_mode::READ)) { mDMIData = tmp; } } } } sc_core::sc_stop(); wait(); }initTransactionメソッドでトランザクションを生成します。
生成したトランザクションがDMI内のアドレスかどうかを調べ、DMI内のアドレスであれば、
DMIで処理し、そうでないときはsocketに対して、nb_transportメソッドを実行し、
外部へのトランザクションを発生します。
nb_transportメソッドの戻り値によってアクションが変わります。
tlm::TLM_COMPLETEDであれば、t時間ウエイトします。
tlm::TLM_ACCEPTEDあるいはtlm::TLM_UPDATEDであれば、mEndEventが発生するまでウエイトします。
mEndEventをnotifyするのは、ターゲット側から呼び出されるnb_transportメソッドです。
tlm::TLM_COMPLETEDであれば、t時間ウエイトします。
tlm::TLM_ACCEPTEDあるいはtlm::TLM_UPDATEDであれば、mEndEventが発生するまでウエイトします。
mEndEventをnotifyするのは、ターゲット側から呼び出されるnb_transportメソッドです。
tlm::TLM_REJECTEDの場合は、アサートし、シミュレーションは終了します。
このコードは、Loosely-timed coding styleのイニシエータソケットの戻り値に対するコードになるようです。
次に引数のtransからDMIができるかどうか(trans.get_dmi_allowed())をチェックし、
YesのときはDMIのためのメモリポインタをソケットのget_direct_mem_ptrメソッドで獲得します。
なぜこのようにするかというと、最初からDMIをサポートするかどうかわからないので、最初の1回目のトランザクションの結果で
DMIがサポートしているかどうかを知ることができるからだと思います。
YesのときはDMIのためのメモリポインタをソケットのget_direct_mem_ptrメソッドで獲得します。
なぜこのようにするかというと、最初からDMIをサポートするかどうかわからないので、最初の1回目のトランザクションの結果で
DMIがサポートしているかどうかを知ることができるからだと思います。
トランザクションがDMIのアドレス内のときは次のように処理を行います。
その後、アクセスに必要な時間、ウエイトします。
trans.set_response_status(tlm::TLM_OK_RESPONSE); sc_dt::uint64 tmp = trans.get_address() - mDMIData.dmi_start_address; assert(hasHostEndianness(mDMIData.endianness)); if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { *(unsigned int*)&mDMIData.dmi_ptr[tmp] = mData; } else { mData = *(unsigned int*)&mDMIData.dmi_ptr[tmp]; } if (trans.get_command() == tlm::TLM_WRITE_COMMAND) { wait(mDMIData.write_latency); } else { wait(mDMIData.read_latency); }DMIのデータポインタを使って直接ターゲット内のメモリにアクセスします。
その後、アクセスに必要な時間、ウエイトします。