186 unsigned int transport_dbg(
typename TYPES::tlm_payload_type& trans)
override;
202 sc_core::sc_port<axi::ace_fw_transport_if<TYPES>>
fw_port{
"fw_port"};
205 sc_core::sc_port<axi::ace_bw_transport_if<TYPES>>
bw_port{
"bw_port"};
208 std::string
const full_name;
216 const unsigned bus_width{0};
218 tx_db* m_db{
nullptr};
220 ::lwtr::tx_relation_handle pred_succ_hndl{0}, par_chld_hndl{0};
222 tx_fiber* b_streamHandle{
nullptr};
224 std::array<tx_generator<sc_core::sc_time, sc_core::sc_time>*, 3> b_trHandle{{
nullptr,
nullptr,
nullptr}};
226 tx_fiber* b_streamHandleTimed{
nullptr};
229 std::array<tx_generator<>*, 3> b_trTimedHandle{{
nullptr,
nullptr,
nullptr}};
231 enum DIR { FW, BW, REQ = FW, RESP = BW, ACK };
233 tx_fiber* nb_streamHandle{
nullptr};
235 tx_fiber* nb_streamHandleTimed{
nullptr};
237 std::array<tx_generator<std::string, std::string>*, 3> nb_trHandle{{
nullptr,
nullptr,
nullptr}};
239 std::array<tx_generator<>*, 3> nb_trTimedHandle{{
nullptr,
nullptr,
nullptr}};
240 std::unordered_map<uint64_t, tx_handle> nbtx_req_handle_map;
241 std::unordered_map<uint64_t, tx_handle> nbtx_last_req_handle_map;
242 std::unordered_map<uint64_t, tx_handle> nbtx_resp_handle_map;
243 std::unordered_map<uint64_t, tx_handle> nbtx_last_resp_handle_map;
245 tx_fiber* dmi_streamHandle{
nullptr};
247 tx_generator<>* dmi_trGetHandle{
nullptr};
248 tx_generator<sc_dt::uint64, sc_dt::uint64>* dmi_trInvalidateHandle{
nullptr};
251 void initialize_streams() {
253 pred_succ_hndl = m_db->create_relation(
"PREDECESSOR_SUCCESSOR");
254 par_chld_hndl = m_db->create_relation(
"PARENT_CHILD");
257 b_streamHandle =
new tx_fiber((full_name +
"_bl").c_str(),
"[TLM][ace][b]", m_db);
258 b_trHandle[tlm::TLM_READ_COMMAND] =
259 new tx_generator<sc_core::sc_time, sc_core::sc_time>(
"read", *b_streamHandle,
"start_delay",
"end_delay");
260 b_trHandle[tlm::TLM_WRITE_COMMAND] =
261 new tx_generator<sc_core::sc_time, sc_core::sc_time>(
"write", *b_streamHandle,
"start_delay",
"end_delay");
262 b_trHandle[tlm::TLM_IGNORE_COMMAND] =
263 new tx_generator<sc_core::sc_time, sc_core::sc_time>(
"ignore", *b_streamHandle,
"start_delay",
"end_delay");
265 b_streamHandleTimed =
new tx_fiber((full_name +
"_bl_timed").c_str(),
"[TLM][ace][b][timed]", m_db);
266 b_trTimedHandle[tlm::TLM_READ_COMMAND] =
new tx_generator<>(
"read", *b_streamHandleTimed);
267 b_trTimedHandle[tlm::TLM_WRITE_COMMAND] =
new tx_generator<>(
"write", *b_streamHandleTimed);
268 b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] =
new tx_generator<>(
"ignore", *b_streamHandleTimed);
272 nb_streamHandle =
new tx_fiber((full_name +
"_nb").c_str(),
"[TLM][ace][nb]", m_db);
273 nb_trHandle[FW] =
new tx_generator<std::string, std::string>(
"fw", *nb_streamHandle,
"tlm_phase",
"tlm_phase[return_path]");
274 nb_trHandle[BW] =
new tx_generator<std::string, std::string>(
"bw", *nb_streamHandle,
"tlm_phase",
"tlm_phase[return_path]");
276 nb_streamHandleTimed =
new tx_fiber((full_name +
"_nb_timed").c_str(),
"[TLM][ace][nb][timed]", m_db);
277 nb_trTimedHandle[FW] =
new tx_generator<>(
"request", *nb_streamHandleTimed);
278 nb_trTimedHandle[BW] =
new tx_generator<>(
"response", *nb_streamHandleTimed);
279 nb_trTimedHandle[ACK] =
new tx_generator<>(
"ack", *nb_streamHandleTimed);
283 dmi_streamHandle =
new tx_fiber((full_name +
"_dmi").c_str(),
"[TLM][ace][dmi]", m_db);
284 dmi_trGetHandle =
new tx_generator<>(
"get", *dmi_streamHandle);
285 dmi_trInvalidateHandle =
286 new tx_generator<sc_dt::uint64, sc_dt::uint64>(
"invalidate", *dmi_streamHandle,
"start_addr",
"end_addr");
291 axi::checker::checker_if<TYPES>* checker{
nullptr};
294template <
unsigned BUSWIDTH = 32,
typename TYPES = axi::axi_protocol_types,
int N = 1,
295 sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
296class ace_lwtr_recorder :
public sc_core::sc_module,
public ace_lwtr<TYPES> {
301 ace_lwtr_recorder(sc_core::sc_module_name nm,
bool recording_enabled =
true, tx_db* tr_db = tx_db::get_default_db())
302 : sc_core::sc_module(nm)
306 this->
bw_port(ts.get_base_port());
307 this->
fw_port(is.get_base_port());
316 fw_port->b_transport(trans, delay);
320 tx_handle h = b_trHandle[trans.get_command()]->begin_tx(delay);
325 if(b_streamHandleTimed)
326 htim = b_trTimedHandle[trans.get_command()]->begin_tx_delayed(sc_core::sc_time_stamp() + delay, par_chld_hndl, h);
329 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
330 if(extensionRecording) {
331 extensionRecording->recordBeginTx(h, trans);
333 extensionRecording->recordBeginTx(htim, trans);
337 trans.get_extension(preExt);
338 if(preExt ==
nullptr) {
341 trans.set_auto_extension(preExt);
343 trans.set_extension(preExt);
345 h.add_relation(pred_succ_hndl, preExt->txHandle);
347 tx_handle preTx(preExt->txHandle);
348 preExt->txHandle = h;
349 fw_port->b_transport(trans, delay);
350 trans.get_extension(preExt);
351 if(preExt->creator ==
this) {
354 if(!trans.has_mm()) {
358 preExt->txHandle = preTx;
361 h.record_attribute(
"trans", trans);
363 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
364 if(extensionRecording) {
365 extensionRecording->recordEndTx(h, trans);
367 extensionRecording->recordEndTx(htim, trans);
372 if(htim.is_valid()) {
373 htim.record_attribute(
"trans", trans);
374 htim.end_tx_delayed(sc_core::sc_time_stamp() + delay);
379 if(!b_streamHandleTimed) {
380 bw_port->b_snoop(trans, delay);
384 tx_handle h = b_trHandle[trans.get_command()]->begin_tx(delay);
389 if(b_streamHandleTimed)
390 htim = b_trTimedHandle[trans.get_command()]->begin_tx_delayed(sc_core::sc_time_stamp() + delay, par_chld_hndl, h);
393 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
394 if(extensionRecording) {
395 extensionRecording->recordBeginTx(h, trans);
397 extensionRecording->recordBeginTx(htim, trans);
401 trans.get_extension(preExt);
402 if(preExt ==
nullptr) {
404 trans.set_extension(preExt);
406 h.add_relation(pred_succ_hndl, preExt->txHandle);
408 tx_handle preTx(preExt->txHandle);
409 preExt->txHandle = h;
410 bw_port->b_snoop(trans, delay);
411 trans.get_extension(preExt);
412 if(preExt->creator ==
this) {
418 preExt->txHandle = preTx;
421 h.record_attribute(
"trans", trans);
423 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
424 if(extensionRecording) {
425 extensionRecording->recordEndTx(h, trans);
427 extensionRecording->recordEndTx(htim, trans);
432 if(htim.is_valid()) {
433 htim.record_attribute(
"trans", trans);
434 htim.end_tx_delayed(sc_core::sc_time_stamp() + delay);
438template <
typename TYPES>
440 sc_core::sc_time& delay) {
442 return fw_port->nb_transport_fw(trans, phase, delay);
448 tx_handle h = nb_trHandle[FW]->begin_tx(phase.get_name());
450 trans.get_extension(preExt);
451 if((phase == axi::BEGIN_PARTIAL_REQ || phase == tlm::BEGIN_REQ) && preExt ==
nullptr) {
454 trans.set_auto_extension(preExt);
456 trans.set_extension(preExt);
457 }
else if(preExt !=
nullptr) {
459 h.add_relation(pred_succ_hndl, preExt->txHandle);
461 sc_assert(preExt !=
nullptr &&
"ERROR on forward path in phase other than tlm::BEGIN_REQ");
464 preExt->txHandle = h;
465 h.record_attribute(
"delay", delay);
467 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
468 if(extensionRecording)
469 extensionRecording->recordBeginTx(h, trans);
473 if(nb_streamHandleTimed) {
475 (phase == tlm::BEGIN_RESP || phase == axi::BEGIN_PARTIAL_RESP));
476 rec.tr->deep_copy_from(trans);
477 nb_timed_peq.notify(rec, delay);
483 checker->fw_pre(trans, phase);
484 tlm::tlm_sync_enum status =
fw_port->nb_transport_fw(trans, phase, delay);
486 checker->fw_post(trans, phase, status);
490 h.record_attribute(
"tlm_sync", status);
491 h.record_attribute(
"delay[return_path]", delay);
492 h.record_attribute(
"trans", trans);
494 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
495 if(extensionRecording)
496 extensionRecording->recordEndTx(h, trans);
498 if(status == tlm::TLM_COMPLETED || (phase == axi::ACK)) {
499 trans.get_extension(preExt);
500 if(preExt && preExt->creator ==
this) {
502 if(!trans.has_mm()) {
509 if(nb_streamHandleTimed) {
511 (phase == tlm::BEGIN_RESP || phase == axi::BEGIN_PARTIAL_RESP)};
512 rec.tr->deep_copy_from(trans);
513 nb_timed_peq.notify(rec, delay);
515 }
else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
517 (phase == tlm::BEGIN_RESP || phase == axi::BEGIN_PARTIAL_RESP)};
518 rec.tr->deep_copy_from(trans);
519 nb_timed_peq.notify(rec, delay);
522 nb_trHandle[FW]->end_tx(h, phase.get_name());
526template <
typename TYPES>
528 sc_core::sc_time& delay) {
531 checker->bw_pre(trans, phase);
532 tlm::tlm_sync_enum status =
bw_port->nb_transport_bw(trans, phase, delay);
533 checker->bw_post(trans, phase, status);
536 return bw_port->nb_transport_bw(trans, phase, delay);
542 trans.get_extension(preExt);
544 tx_handle h = nb_trHandle[BW]->begin_tx(phase.get_name());
546 if(phase == tlm::BEGIN_REQ && preExt ==
nullptr) {
548 trans.set_extension(preExt);
549 preExt->txHandle = h;
552 h.add_relation(pred_succ_hndl, preExt->txHandle);
554 preExt->txHandle = h;
556 sc_assert(preExt !=
nullptr &&
"ERROR on backward path in phase other than tlm::BEGIN_REQ");
559 h.record_attribute(
"delay", delay);
560 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
561 if(extensionRecording)
562 extensionRecording->recordBeginTx(h, trans);
566 if(nb_streamHandleTimed) {
568 rec.tr->deep_copy_from(trans);
569 nb_timed_peq.notify(rec, delay);
575 checker->bw_pre(trans, phase);
576 tlm::tlm_sync_enum status =
bw_port->nb_transport_bw(trans, phase, delay);
578 checker->bw_post(trans, phase, status);
582 h.record_attribute(
"tlm_sync", status);
583 h.record_attribute(
"delay[return_path]", delay);
584 h.record_attribute(
"trans", trans);
586 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
587 if(extensionRecording)
588 extensionRecording->recordEndTx(h, trans);
590 nb_trHandle[BW]->end_tx(h, phase.get_name());
592 if(status == tlm::TLM_COMPLETED || (status == tlm::TLM_UPDATED && phase == axi::ACK)) {
594 if(preExt && preExt->creator ==
this) {
597 if(!trans.has_mm()) {
604 if(nb_streamHandleTimed) {
606 rec.tr->deep_copy_from(trans);
607 nb_timed_peq.notify(rec, delay);
609 }
else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
611 rec.tr->deep_copy_from(trans);
612 nb_timed_peq.notify(rec, delay);
617template <
typename TYPES>
void ace_lwtr<TYPES>::nbtx_cb() {
623 if(e.ph == tlm::BEGIN_REQ || e.ph == axi::BEGIN_PARTIAL_REQ) {
624 h = nb_trTimedHandle[REQ]->begin_tx(par_chld_hndl, e.parent);
625 nbtx_req_handle_map[e.id] = h;
626 }
else if(e.ph == tlm::END_REQ || e.ph == axi::END_PARTIAL_REQ) {
627 auto it = nbtx_req_handle_map.find(e.id);
628 if(it != nbtx_req_handle_map.end()) {
630 nbtx_req_handle_map.erase(it);
631 h.record_attribute(
"trans", *e.tr);
633 nbtx_last_req_handle_map[e.id] = h;
635 }
else if(e.ph == tlm::BEGIN_RESP || e.ph == axi::BEGIN_PARTIAL_RESP) {
636 auto it = nbtx_req_handle_map.find(e.id);
637 if(it != nbtx_req_handle_map.end()) {
639 nbtx_req_handle_map.erase(it);
640 h.record_attribute(
"trans", *e.tr);
642 nbtx_last_req_handle_map[e.id] = h;
644 h = nb_trTimedHandle[RESP]->begin_tx(par_chld_hndl, e.parent);
645 nbtx_resp_handle_map[e.id] = h;
646 it = nbtx_last_req_handle_map.find(e.id);
647 if(it != nbtx_last_req_handle_map.end()) {
648 tx_handle& pred = it->second;
649 h.add_relation(pred_succ_hndl, pred);
650 nbtx_last_req_handle_map.erase(it);
652 it = nbtx_last_resp_handle_map.find(e.id);
653 if(it != nbtx_last_resp_handle_map.end()) {
654 tx_handle& pred = it->second;
655 h.add_relation(pred_succ_hndl, pred);
656 nbtx_last_resp_handle_map.erase(it);
659 }
else if(e.ph == tlm::END_RESP || e.ph == axi::END_PARTIAL_RESP) {
660 auto it = nbtx_resp_handle_map.find(e.id);
661 if(it != nbtx_resp_handle_map.end()) {
663 nbtx_resp_handle_map.erase(it);
664 h.record_attribute(
"trans", *e.tr);
666 if(e.ph == axi::END_PARTIAL_RESP) {
667 nbtx_last_resp_handle_map[e.id] = h;
670 }
else if(e.ph == axi::ACK) {
671 h = nb_trTimedHandle[ACK]->begin_tx(par_chld_hndl, e.parent);
672 h.record_attribute(
"trans", *e.tr);
675 sc_assert(!
"phase not supported!");
682 return fw_port->get_direct_mem_ptr(trans, dmi_data);
683 tx_handle h = dmi_trGetHandle->begin_tx();
684 bool status =
fw_port->get_direct_mem_ptr(trans, dmi_data);
685 h.record_attribute(
"trans", trans);
686 h.record_attribute(
"dmi_data", dmi_data);
698 bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
701 tx_handle h = dmi_trInvalidateHandle->begin_tx(start_addr);
702 bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
703 dmi_trInvalidateHandle->end_tx(h, end_addr);
713 return fw_port->transport_dbg(trans);