197 unsigned int transport_dbg(
typename TYPES::tlm_payload_type& trans)
override;
213 sc_core::sc_port<chi::chi_fw_transport_if<TYPES>>
fw_port{
"fw_port"};
216 sc_core::sc_port<chi::chi_bw_transport_if<TYPES>>
bw_port{
"bw_port"};
219 std::string
const full_name;
227 const unsigned bus_width{0};
229 tx_db* m_db{
nullptr};
231 ::lwtr::tx_relation_handle pred_succ_hndl{0}, par_chld_hndl{0};
233 tx_fiber* b_streamHandle{
nullptr};
235 std::array<tx_generator<sc_core::sc_time, sc_core::sc_time>*, 3> b_trHandle{{
nullptr,
nullptr,
nullptr}};
237 tx_fiber* b_streamHandleTimed{
nullptr};
240 std::array<tx_generator<>*, 3> b_trTimedHandle{{
nullptr,
nullptr,
nullptr}};
242 enum DIR { FW, BW, DATA, ACK, CREDIT, REQ = FW, RESP = BW };
243 enum TYPE { READ = tlm::TLM_READ_COMMAND, WRITE = tlm::TLM_WRITE_COMMAND, OTHER = tlm::TLM_IGNORE_COMMAND, SNOOP, NO_OF_TYPES };
245 tx_fiber* nb_streamHandle{
nullptr};
247 tx_fiber* nb_streamHandleTimed{
nullptr};
249 std::array<tx_generator<std::string, std::string>*, 5> nb_trHandle{{
nullptr,
nullptr,
nullptr,
nullptr,
nullptr}};
251 std::array<tx_generator<>*, 5> nb_trTimedHandle{{
nullptr,
nullptr}};
252 std::unordered_map<uint64_t, tx_handle> nbtx_req_handle_map;
253 std::unordered_map<uint64_t, tx_handle> nbtx_last_req_handle_map;
254 std::unordered_map<uint64_t, tx_handle> nbtx_resp_handle_map;
255 std::unordered_map<uint64_t, tx_handle> nbtx_last_resp_handle_map;
256 std::unordered_map<uint64_t, tx_handle> nbtx_data_handle_map;
257 std::unordered_map<uint64_t, tx_handle> nbtx_last_data_handle_map;
258 std::unordered_map<uint64_t, tx_handle> nbtx_ack_handle_map;
260 tx_fiber* dmi_streamHandle{
nullptr};
262 tx_generator<>* dmi_trGetHandle{
nullptr};
263 tx_generator<sc_dt::uint64, sc_dt::uint64>* dmi_trInvalidateHandle{
nullptr};
266 void initialize_streams() {
268 pred_succ_hndl = m_db->create_relation(
"PREDECESSOR_SUCCESSOR");
269 par_chld_hndl = m_db->create_relation(
"PARENT_CHILD");
272 b_streamHandle =
new tx_fiber((full_name +
"_bl").c_str(),
"[TLM][chi][b]", m_db);
273 b_trHandle[tlm::TLM_READ_COMMAND] =
274 new tx_generator<sc_core::sc_time, sc_core::sc_time>(
"read", *b_streamHandle,
"start_delay",
"end_delay");
275 b_trHandle[tlm::TLM_WRITE_COMMAND] =
276 new tx_generator<sc_core::sc_time, sc_core::sc_time>(
"write", *b_streamHandle,
"start_delay",
"end_delay");
277 b_trHandle[tlm::TLM_IGNORE_COMMAND] =
278 new tx_generator<sc_core::sc_time, sc_core::sc_time>(
"ignore", *b_streamHandle,
"start_delay",
"end_delay");
280 b_streamHandleTimed =
new tx_fiber((full_name +
"_bl_timed").c_str(),
"[TLM][chi][b][timed]", m_db);
281 b_trTimedHandle[tlm::TLM_READ_COMMAND] =
new tx_generator<>(
"read", *b_streamHandleTimed);
282 b_trTimedHandle[tlm::TLM_WRITE_COMMAND] =
new tx_generator<>(
"write", *b_streamHandleTimed);
283 b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] =
new tx_generator<>(
"ignore", *b_streamHandleTimed);
287 nb_streamHandle =
new tx_fiber((full_name +
"_nb").c_str(),
"[TLM][chi][nb]", m_db);
288 nb_trHandle[FW] =
new tx_generator<std::string, std::string>(
"fw", *nb_streamHandle,
"tlm_phase",
"tlm_phase[return_path]");
289 nb_trHandle[BW] =
new tx_generator<std::string, std::string>(
"bw", *nb_streamHandle,
"tlm_phase",
"tlm_phase[return_path]");
291 nb_streamHandleTimed =
new tx_fiber((full_name +
"_nb_timed").c_str(),
"[TLM][chi][nb][timed]", m_db);
292 nb_trTimedHandle[REQ] =
new tx_generator<>(
"request", *nb_streamHandleTimed);
293 nb_trTimedHandle[RESP] =
new tx_generator<>(
"response", *nb_streamHandleTimed);
294 nb_trTimedHandle[DATA] =
new tx_generator<>(
"data", *nb_streamHandleTimed);
295 nb_trTimedHandle[ACK] =
new tx_generator<>(
"ack", *nb_streamHandleTimed);
296 nb_trTimedHandle[CREDIT] =
new tx_generator<>(
"link", *nb_streamHandleTimed);
300 dmi_streamHandle =
new tx_fiber((full_name +
"_dmi").c_str(),
"[TLM][chi][dmi]", m_db);
301 dmi_trGetHandle =
new tx_generator<>(
"get", *dmi_streamHandle);
302 dmi_trInvalidateHandle =
303 new tx_generator<sc_dt::uint64, sc_dt::uint64>(
"invalidate", *dmi_streamHandle,
"start_addr",
"end_addr");
308 inline std::string phase2string(
const tlm::tlm_phase& p) {
309 std::stringstream ss;
315template <
unsigned BUSWIDTH = 32,
typename TYPES = chi::chi_protocol_types,
int N = 1,
316 sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
317class chi_lwtr_recorder :
public sc_core::sc_module,
public chi_lwtr<TYPES> {
322 chi_lwtr_recorder(sc_core::sc_module_name nm,
bool recording_enabled =
true, tx_db* tr_db = tx_db::get_default_db())
323 : sc_core::sc_module(nm)
327 this->
bw_port(ts.get_base_port());
328 this->
fw_port(is.get_base_port());
337 fw_port->b_transport(trans, delay);
341 tx_handle h = b_trHandle[trans.get_command()]->begin_tx(delay);
346 if(b_streamHandleTimed)
347 htim = b_trTimedHandle[trans.get_command()]->begin_tx_delayed(sc_core::sc_time_stamp() + delay, par_chld_hndl, h);
350 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
351 if(extensionRecording) {
352 extensionRecording->recordBeginTx(h, trans);
354 extensionRecording->recordBeginTx(htim, trans);
358 trans.get_extension(preExt);
359 if(preExt ==
nullptr) {
362 trans.set_auto_extension(preExt);
364 trans.set_extension(preExt);
366 h.add_relation(pred_succ_hndl, preExt->txHandle);
368 tx_handle preTx(preExt->txHandle);
369 preExt->txHandle = h;
370 fw_port->b_transport(trans, delay);
371 trans.get_extension(preExt);
372 if(preExt->creator ==
this) {
375 if(!trans.has_mm()) {
379 preExt->txHandle = preTx;
382 h.record_attribute(
"trans", trans);
384 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
385 if(extensionRecording) {
386 extensionRecording->recordEndTx(h, trans);
388 extensionRecording->recordEndTx(htim, trans);
393 if(htim.is_valid()) {
394 htim.record_attribute(
"trans", trans);
395 htim.end_tx_delayed(sc_core::sc_time_stamp() + delay);
400 if(!b_streamHandleTimed) {
401 bw_port->b_snoop(trans, delay);
405 tx_handle h = b_trHandle[trans.get_command()]->begin_tx(delay);
410 if(b_streamHandleTimed)
411 htim = b_trTimedHandle[trans.get_command()]->begin_tx_delayed(sc_core::sc_time_stamp() + delay, par_chld_hndl, h);
414 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
415 if(extensionRecording) {
416 extensionRecording->recordBeginTx(h, trans);
418 extensionRecording->recordBeginTx(htim, trans);
422 trans.get_extension(preExt);
423 if(preExt ==
nullptr) {
425 trans.set_extension(preExt);
427 h.add_relation(pred_succ_hndl, preExt->txHandle);
429 tx_handle preTx(preExt->txHandle);
430 preExt->txHandle = h;
431 bw_port->b_snoop(trans, delay);
432 trans.get_extension(preExt);
433 if(preExt->creator ==
this) {
439 preExt->txHandle = preTx;
442 h.record_attribute(
"trans", trans);
444 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
445 if(extensionRecording) {
446 extensionRecording->recordEndTx(h, trans);
448 extensionRecording->recordEndTx(htim, trans);
453 if(htim.is_valid()) {
454 htim.record_attribute(
"trans", trans);
455 htim.end_tx_delayed(sc_core::sc_time_stamp() + delay);
459template <
typename TYPES>
461 sc_core::sc_time& delay) {
463 return fw_port->nb_transport_fw(trans, phase, delay);
469 tx_handle h = nb_trHandle[FW]->begin_tx(phase2string(phase));
471 trans.get_extension(preExt);
472 if((phase == tlm::BEGIN_REQ) && preExt ==
nullptr) {
475 trans.set_auto_extension(preExt);
477 trans.set_extension(preExt);
478 }
else if(preExt !=
nullptr) {
480 h.add_relation(pred_succ_hndl, preExt->txHandle);
482 sc_assert(preExt !=
nullptr &&
"ERROR on forward path in phase other than tlm::BEGIN_REQ");
485 preExt->txHandle = h;
486 h.record_attribute(
"delay", delay);
488 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
489 if(extensionRecording)
490 extensionRecording->recordBeginTx(h, trans);
494 if(nb_streamHandleTimed) {
496 (trans.template get_extension<chi::chi_snp_extension>() !=
nullptr),
497 (phase == tlm::BEGIN_REQ) && has_credit(trans));
498 rec.tr->deep_copy_from(trans);
499 nb_timed_peq.notify(rec, delay);
504 tlm::tlm_sync_enum status =
fw_port->nb_transport_fw(trans, phase, delay);
508 h.record_attribute(
"status", status);
509 h.record_attribute(
"delay[return_path]", delay);
510 h.record_attribute(
"trans", trans);
512 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
513 if(extensionRecording)
514 extensionRecording->recordEndTx(h, trans);
516 if(status == tlm::TLM_COMPLETED) {
518 trans.get_extension(preExt);
519 if(preExt && preExt->creator ==
this) {
521 if(!trans.has_mm()) {
528 if(nb_streamHandleTimed) {
530 reinterpret_cast<uint64_t
>(&trans), h};
531 rec.tr->deep_copy_from(trans);
532 nb_timed_peq.notify(rec, delay);
534 }
else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
536 rec.tr->deep_copy_from(trans);
537 nb_timed_peq.notify(rec, delay);
540 nb_trHandle[FW]->end_tx(h, phase2string(phase));
544template <
typename TYPES>
546 sc_core::sc_time& delay) {
548 return bw_port->nb_transport_bw(trans, phase, delay);
554 trans.get_extension(preExt);
556 tx_handle h = nb_trHandle[BW]->begin_tx(phase2string(phase));
558 if(phase == tlm::BEGIN_REQ && preExt ==
nullptr) {
560 trans.set_extension(preExt);
561 preExt->txHandle = h;
564 h.add_relation(pred_succ_hndl, preExt->txHandle);
566 preExt->txHandle = h;
568 sc_assert(preExt !=
nullptr &&
"ERROR on backward path in phase other than tlm::BEGIN_REQ");
571 h.record_attribute(
"delay", delay);
572 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
573 if(extensionRecording)
574 extensionRecording->recordBeginTx(h, trans);
578 if(nb_streamHandleTimed) {
580 (trans.template get_extension<chi::chi_snp_extension>() !=
nullptr),
581 (phase == tlm::BEGIN_REQ) && has_credit(trans));
582 rec.tr->deep_copy_from(trans);
583 nb_timed_peq.notify(rec, delay);
588 tlm::tlm_sync_enum status =
bw_port->nb_transport_bw(trans, phase, delay);
592 h.record_attribute(
"status", status);
593 h.record_attribute(
"delay[return_path]", delay);
594 h.record_attribute(
"trans", trans);
596 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
597 if(extensionRecording)
598 extensionRecording->recordEndTx(h, trans);
600 nb_trHandle[BW]->end_tx(h, phase2string(phase));
602 if(status == tlm::TLM_COMPLETED) {
604 if(preExt && preExt->creator ==
this) {
607 if(!trans.has_mm()) {
614 if(nb_streamHandleTimed) {
616 reinterpret_cast<uint64_t
>(&trans), h, phase == tlm::BEGIN_REQ};
617 rec.tr->deep_copy_from(trans);
618 nb_timed_peq.notify(rec, delay);
620 }
else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
622 rec.tr->deep_copy_from(trans);
623 nb_timed_peq.notify(rec, delay);
628template <
typename TYPES>
void chi_lwtr<TYPES>::nbtx_cb() {
635 nb_trTimedHandle[CREDIT]->begin_tx().end_tx();
636 }
else if(e.ph == tlm::BEGIN_REQ) {
637 h = nb_trTimedHandle[REQ]->begin_tx(par_chld_hndl, e.parent);
638 nbtx_req_handle_map[e.id] = h;
639 }
else if(e.ph == tlm::END_REQ) {
640 auto it = nbtx_req_handle_map.find(e.id);
641 if(it != nbtx_req_handle_map.end()) {
643 nbtx_req_handle_map.erase(it);
644 h.record_attribute(
"trans", *e.tr);
646 nbtx_last_req_handle_map[e.id] = h;
648 }
else if(e.ph == tlm::BEGIN_RESP) {
649 auto it = nbtx_req_handle_map.find(e.id);
650 if(it != nbtx_req_handle_map.end()) {
652 nbtx_req_handle_map.erase(it);
653 h.record_attribute(
"trans", *e.tr);
655 nbtx_last_req_handle_map[e.id] = h;
657 h = nb_trTimedHandle[RESP]->begin_tx(par_chld_hndl, e.parent);
658 nbtx_resp_handle_map[e.id] = h;
659 it = nbtx_last_req_handle_map.find(e.id);
660 if(it != nbtx_last_req_handle_map.end()) {
661 tx_handle& pred = it->second;
662 h.add_relation(pred_succ_hndl, pred);
663 nbtx_last_req_handle_map.erase(it);
665 it = nbtx_last_resp_handle_map.find(e.id);
666 if(it != nbtx_last_resp_handle_map.end()) {
667 tx_handle& pred = it->second;
668 h.add_relation(pred_succ_hndl, pred);
669 nbtx_last_resp_handle_map.erase(it);
672 }
else if(e.ph == tlm::END_RESP) {
673 auto it = nbtx_resp_handle_map.find(e.id);
674 if(it != nbtx_resp_handle_map.end()) {
676 nbtx_resp_handle_map.erase(it);
677 h.record_attribute(
"trans", *e.tr);
680 }
else if(e.ph == chi::BEGIN_DATA || e.ph == chi::BEGIN_PARTIAL_DATA) {
681 auto it = nbtx_req_handle_map.find(e.id);
682 if(it != nbtx_req_handle_map.end()) {
685 nbtx_last_req_handle_map[e.id] = h;
687 h = nb_trTimedHandle[DATA]->begin_tx();
688 h.record_attribute(
"trans", *e.tr);
689 h.add_relation(par_chld_hndl, e.parent);
690 nbtx_data_handle_map[e.id] = h;
691 it = nbtx_last_data_handle_map.find(e.id);
692 if(it != nbtx_last_data_handle_map.end()) {
693 auto pred = it->second;
694 nbtx_last_data_handle_map.erase(it);
695 h.add_relation(pred_succ_hndl, pred);
697 }
else if(e.ph == chi::END_DATA || e.ph == chi::END_PARTIAL_DATA) {
698 auto it = nbtx_data_handle_map.find(e.id);
699 if(it != nbtx_data_handle_map.end()) {
701 nbtx_data_handle_map.erase(it);
704 }
else if(e.ph == chi::ACK) {
705 auto it = nbtx_ack_handle_map.find(e.id);
706 if(it == nbtx_ack_handle_map.end()) {
707 auto h = nb_trTimedHandle[ACK]->begin_tx();
708 nbtx_ack_handle_map[e.id] = h;
709 h.add_relation(par_chld_hndl, e.parent);
711 nb_trTimedHandle[ACK]->end_tx(it->second);
712 nbtx_ack_handle_map.erase(it);
715 sc_assert(!
"phase not supported!");
722 return fw_port->get_direct_mem_ptr(trans, dmi_data);
723 tx_handle h = dmi_trGetHandle->begin_tx();
724 bool status =
fw_port->get_direct_mem_ptr(trans, dmi_data);
725 h.record_attribute(
"trans", trans);
726 h.record_attribute(
"dmi_data", dmi_data);
738 bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
741 tx_handle h = dmi_trInvalidateHandle->begin_tx(start_addr);
742 bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
743 dmi_trInvalidateHandle->end_tx(h, end_addr);
753 return fw_port->transport_dbg(trans);