181 unsigned int transport_dbg(
typename TYPES::tlm_payload_type& trans)
override;
200 void record_nb_tx(
typename TYPES::tlm_payload_type&,
const typename TYPES::tlm_phase_type&, sc_core::sc_time, SCVNS scv_tr_handle);
201 const unsigned bus_width{0};
203 SCVNS scv_tr_db* m_db{
nullptr};
205 SCVNS scv_tr_stream* b_streamHandle{
nullptr};
207 std::array<SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>*, 3> b_trHandle{{
nullptr,
nullptr,
nullptr}};
209 SCVNS scv_tr_stream* b_streamHandleTimed{
nullptr};
212 std::array<SCVNS scv_tr_generator<>*, 3> b_trTimedHandle{{
nullptr,
nullptr,
nullptr}};
214 enum DIR { FW, BW, REQ = FW, RESP = BW };
216 SCVNS scv_tr_stream* nb_streamHandle{
nullptr};
218 SCVNS scv_tr_stream* nb_streamHandleTimed{
nullptr};
220 std::array<SCVNS scv_tr_generator<std::string, std::string>*, 2> nb_trHandle{{
nullptr,
nullptr}};
222 std::array<SCVNS scv_tr_generator<>*, 2> nb_trTimedHandle{{
nullptr,
nullptr}};
223 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_req_handle_map;
224 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_last_req_handle_map;
225 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_resp_handle_map;
226 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_last_resp_handle_map;
228 SCVNS scv_tr_stream* dmi_streamHandle{
nullptr};
230 SCVNS scv_tr_generator<>* dmi_trGetHandle{
nullptr};
231 SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>* dmi_trInvalidateHandle{
nullptr};
234 void initialize_streams() {
236 b_streamHandle =
new SCVNS scv_tr_stream((fixed_basename +
"_bl").c_str(),
"[TLM][axi][b]", m_db);
237 b_trHandle[tlm::TLM_READ_COMMAND] =
238 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
"read", *b_streamHandle,
"start_delay",
"end_delay");
239 b_trHandle[tlm::TLM_WRITE_COMMAND] =
240 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
"write", *b_streamHandle,
"start_delay",
"end_delay");
241 b_trHandle[tlm::TLM_IGNORE_COMMAND] =
242 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
"ignore", *b_streamHandle,
"start_delay",
"end_delay");
244 b_streamHandleTimed =
new SCVNS scv_tr_stream((fixed_basename +
"_bl_timed").c_str(),
"[TLM][axi][b][timed]", m_db);
245 b_trTimedHandle[tlm::TLM_READ_COMMAND] =
new SCVNS scv_tr_generator<>(
"read", *b_streamHandleTimed);
246 b_trTimedHandle[tlm::TLM_WRITE_COMMAND] =
new SCVNS scv_tr_generator<>(
"write", *b_streamHandleTimed);
247 b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] =
new SCVNS scv_tr_generator<>(
"ignore", *b_streamHandleTimed);
251 nb_streamHandle =
new SCVNS scv_tr_stream((fixed_basename +
"_nb").c_str(),
"[TLM][axi][nb]", m_db);
253 new SCVNS scv_tr_generator<std::string, std::string>(
"fw", *nb_streamHandle,
"tlm_phase",
"tlm_phase[return_path]");
255 new SCVNS scv_tr_generator<std::string, std::string>(
"bw", *nb_streamHandle,
"tlm_phase",
"tlm_phase[return_path]");
257 nb_streamHandleTimed =
new SCVNS scv_tr_stream((fixed_basename +
"_nb_timed").c_str(),
"[TLM][axi][nb][timed]", m_db);
258 nb_trTimedHandle[FW] =
new SCVNS scv_tr_generator<>(
"request", *nb_streamHandleTimed);
259 nb_trTimedHandle[BW] =
new SCVNS scv_tr_generator<>(
"response", *nb_streamHandleTimed);
263 dmi_streamHandle =
new SCVNS scv_tr_stream((fixed_basename +
"_dmi").c_str(),
"[TLM][axi][dmi]", m_db);
264 dmi_trGetHandle =
new SCVNS scv_tr_generator<>(
"get", *dmi_streamHandle);
265 dmi_trInvalidateHandle =
266 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
"invalidate", *dmi_streamHandle,
"start_addr",
"end_addr");
269 checker =
new axi::checker::axi_protocol(fixed_basename, bus_width / 8, rd_response_timeout.get_value(),
270 wr_response_timeout.get_value());
275 const std::string fixed_basename;
276 axi::checker::checker_if<TYPES>* checker{
nullptr};
277 inline std::string phase2string(
const tlm::tlm_phase& p) {
278 std::stringstream ss;
294 SCVNS scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_core::sc_time_stamp());
298 SCVNS scv_tr_handle bh;
299 if(b_streamHandleTimed) {
300 bh = b_trTimedHandle[trans.get_command()]->begin_transaction(sc_core::sc_time_stamp() + delay);
304 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
306 ext->recordBeginTx(h, trans);
309 trans.get_extension(preExt);
310 if(preExt ==
nullptr) {
313 trans.set_auto_extension(preExt);
315 trans.set_extension(preExt);
319 SCVNS scv_tr_handle preTx(preExt->
txHandle);
322 trans.get_extension(preExt);
333 tlm::scc::scv::record(h, trans);
334 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
336 ext->recordEndTx(h, trans);
338 b_trHandle[trans.get_command()]->end_transaction(h, delay.value(), sc_core::sc_time_stamp());
341 tlm::scc::scv::record(h, trans);
342 b_trTimedHandle[trans.get_command()]->end_transaction(bh, sc_core::sc_time_stamp() + delay);
346template <
typename TYPES>
348 sc_core::sc_time& delay) {
351 checker->fw_pre(trans, phase);
352 tlm::tlm_sync_enum status =
get_fw_if()->nb_transport_fw(trans, phase, delay);
353 checker->fw_post(trans, phase, status);
356 return get_fw_if()->nb_transport_fw(trans, phase, delay);
362 SCVNS scv_tr_handle h = nb_trHandle[FW]->begin_transaction(phase2string(phase));
364 trans.get_extension(preExt);
365 if((phase == axi::BEGIN_PARTIAL_REQ || phase == tlm::BEGIN_REQ) && preExt ==
nullptr) {
368 trans.set_auto_extension(preExt);
370 trans.set_extension(preExt);
371 }
else if(preExt !=
nullptr) {
375 sc_assert(preExt !=
nullptr &&
"ERROR on forward path in phase other than tlm::BEGIN_REQ");
379 h.record_attribute(
"delay", delay.to_string());
380 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
382 ext->recordBeginTx(h, trans);
386 if(nb_streamHandleTimed) {
387 record_nb_tx(trans, phase, delay, h);
393 checker->fw_pre(trans, phase);
394 tlm::tlm_sync_enum status =
get_fw_if()->nb_transport_fw(trans, phase, delay);
396 checker->fw_post(trans, phase, status);
400 tlm::scc::scv::record(h, status);
401 h.record_attribute(
"delay[return_path]", delay.to_string());
402 tlm::scc::scv::record(h, trans);
403 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
405 ext->recordEndTx(h, trans);
407 if(status == tlm::TLM_COMPLETED || (status == tlm::TLM_ACCEPTED && phase == tlm::END_RESP)) {
409 trans.get_extension(preExt);
420 if(nb_streamHandleTimed) {
421 record_nb_tx(trans, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase, delay, h);
423 }
else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
424 record_nb_tx(trans, phase, delay, h);
427 nb_trHandle[FW]->end_transaction(h, phase2string(phase));
431template <
typename TYPES>
433 sc_core::sc_time& delay) {
436 checker->bw_pre(trans, phase);
437 tlm::tlm_sync_enum status =
get_bw_if()->nb_transport_bw(trans, phase, delay);
438 checker->bw_post(trans, phase, status);
441 return get_bw_if()->nb_transport_bw(trans, phase, delay);
447 SCVNS scv_tr_handle h = nb_trHandle[BW]->begin_transaction(phase2string(phase));
449 trans.get_extension(preExt);
450 if(phase == tlm::BEGIN_REQ && preExt ==
nullptr) {
453 trans.set_auto_extension(preExt);
455 trans.set_extension(preExt);
456 }
else if(preExt !=
nullptr) {
460 sc_assert(preExt !=
nullptr &&
"ERROR on backward path in phase other than tlm::BEGIN_REQ");
464 h.record_attribute(
"delay", delay.to_string());
465 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
467 ext->recordBeginTx(h, trans);
471 if(nb_streamHandleTimed) {
472 record_nb_tx(trans, phase, delay, h);
478 checker->bw_pre(trans, phase);
479 tlm::tlm_sync_enum status =
get_bw_if()->nb_transport_bw(trans, phase, delay);
481 checker->bw_post(trans, phase, status);
485 tlm::scc::scv::record(h, status);
486 h.record_attribute(
"delay[return_path]", delay.to_string());
487 tlm::scc::scv::record(h, trans);
488 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
490 ext->recordEndTx(h, trans);
492 if(status == tlm::TLM_COMPLETED || (status == tlm::TLM_UPDATED && phase == tlm::END_RESP)) {
494 trans.get_extension(preExt);
505 if(nb_streamHandleTimed) {
506 record_nb_tx(trans, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase, delay, h);
508 }
else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
509 record_nb_tx(trans, phase, delay, h);
512 nb_trHandle[BW]->end_transaction(h, phase2string(phase));
516template <
typename TYPES>
517void axi_recorder<TYPES>::record_nb_tx(
typename TYPES::tlm_payload_type& trans,
const typename TYPES::tlm_phase_type& phase,
518 sc_core::sc_time delay, SCVNS scv_tr_handle parent) {
519 SCVNS scv_tr_handle h;
521 auto t = sc_core::sc_time_stamp() + delay;
522 auto id =
reinterpret_cast<uintptr_t
>(&trans);
523 if(phase == tlm::BEGIN_REQ || phase == axi::BEGIN_PARTIAL_REQ) {
524 h = nb_trTimedHandle[REQ]->begin_transaction(t);
525 tlm::scc::scv::record(h, trans);
527 nbtx_req_handle_map[id] = h;
528 }
else if(phase == tlm::END_REQ || phase == axi::END_PARTIAL_REQ) {
529 auto it = nbtx_req_handle_map.find(
id);
530 if(it != nbtx_req_handle_map.end()) {
532 nbtx_req_handle_map.erase(it);
533 h.end_transaction(t);
534 nbtx_last_req_handle_map[id] = h;
536 }
else if(phase == tlm::BEGIN_RESP || phase == axi::BEGIN_PARTIAL_RESP) {
537 auto it = nbtx_req_handle_map.find(
id);
538 if(it != nbtx_req_handle_map.end()) {
540 nbtx_req_handle_map.erase(it);
541 h.end_transaction(t);
542 nbtx_last_req_handle_map[id] = h;
544 h = nb_trTimedHandle[RESP]->begin_transaction(t);
545 tlm::scc::scv::record(h, trans);
547 nbtx_resp_handle_map[id] = h;
548 it = nbtx_last_req_handle_map.find(
id);
549 if(it != nbtx_last_req_handle_map.end()) {
550 SCVNS scv_tr_handle& pred = it->second;
552 nbtx_last_req_handle_map.erase(it);
554 it = nbtx_last_resp_handle_map.find(
id);
555 if(it != nbtx_last_resp_handle_map.end()) {
556 SCVNS scv_tr_handle& pred = it->second;
558 nbtx_last_resp_handle_map.erase(it);
561 }
else if(phase == tlm::END_RESP || phase == axi::END_PARTIAL_RESP) {
562 auto it = nbtx_resp_handle_map.find(
id);
563 if(it != nbtx_resp_handle_map.end()) {
565 nbtx_resp_handle_map.erase(it);
566 h.end_transaction(t);
567 if(phase == axi::END_PARTIAL_RESP) {
568 nbtx_last_resp_handle_map[id] = h;
572 sc_assert(!
"phase not supported!");
578 return get_fw_if()->get_direct_mem_ptr(trans, dmi_data);
579 else if(!dmi_streamHandle)
580 initialize_streams();
581 SCVNS scv_tr_handle h = dmi_trGetHandle->begin_transaction();
582 bool status =
get_fw_if()->get_direct_mem_ptr(trans, dmi_data);
583 tlm::scc::scv::record(h, trans);
584 tlm::scc::scv::record(h, dmi_data);
596 get_bw_if()->invalidate_direct_mem_ptr(start_addr, end_addr);
598 }
else if(!dmi_streamHandle)
599 initialize_streams();
600 SCVNS scv_tr_handle h = dmi_trInvalidateHandle->begin_transaction(start_addr);
601 get_bw_if()->invalidate_direct_mem_ptr(start_addr, end_addr);
602 dmi_trInvalidateHandle->end_transaction(h, end_addr);
612 unsigned int count =
get_fw_if()->transport_dbg(trans);