188 unsigned int transport_dbg(
typename TYPES::tlm_payload_type& trans)
override;
204 sc_core::sc_port<chi::chi_fw_transport_if<TYPES>>
fw_port{
"fw_port"};
207 sc_core::sc_port<chi::chi_bw_transport_if<TYPES>>
bw_port{
"bw_port"};
210 std::string
const full_name;
218 const unsigned bus_width{0};
220 tx_db* m_db{
nullptr};
222 ::lwtr::tx_relation_handle pred_succ_hndl{0}, par_chld_hndl{0};
224 tx_fiber* b_streamHandle{
nullptr};
226 std::array<tx_generator<sc_core::sc_time, sc_core::sc_time>*, 3> b_trHandle{{
nullptr,
nullptr,
nullptr}};
228 tx_fiber* b_streamHandleTimed{
nullptr};
231 std::array<tx_generator<>*, 3> b_trTimedHandle{{
nullptr,
nullptr,
nullptr}};
233 enum DIR { FW, BW, DATA, ACK, CREDIT, REQ = FW, RESP = BW };
235 READ = tlm::TLM_READ_COMMAND,
236 WRITE = tlm::TLM_WRITE_COMMAND,
237 OTHER = tlm::TLM_IGNORE_COMMAND,
242 tx_fiber* nb_streamHandle{
nullptr};
244 tx_fiber* nb_streamHandleTimed{
nullptr};
246 std::array<tx_generator<std::string, std::string>*, 5> nb_trHandle{{
nullptr,
nullptr,
nullptr,
nullptr,
nullptr}};
248 std::array<tx_generator<>*, 5> nb_trTimedHandle{{
nullptr,
nullptr}};
249 std::unordered_map<uint64_t, tx_handle> nbtx_req_handle_map;
250 std::unordered_map<uint64_t, tx_handle> nbtx_last_req_handle_map;
251 std::unordered_map<uint64_t, tx_handle> nbtx_resp_handle_map;
252 std::unordered_map<uint64_t, tx_handle> nbtx_last_resp_handle_map;
253 std::unordered_map<uint64_t, tx_handle> nbtx_data_handle_map;
254 std::unordered_map<uint64_t, tx_handle> nbtx_last_data_handle_map;
255 std::unordered_map<uint64_t, tx_handle> nbtx_ack_handle_map;
257 tx_fiber* dmi_streamHandle{
nullptr};
259 tx_generator<>* dmi_trGetHandle{
nullptr};
260 tx_generator<sc_dt::uint64, sc_dt::uint64>* dmi_trInvalidateHandle{
nullptr};
263 void initialize_streams() {
265 pred_succ_hndl = m_db->create_relation(
"PREDECESSOR_SUCCESSOR");
266 par_chld_hndl = m_db->create_relation(
"PARENT_CHILD");
269 b_streamHandle =
new tx_fiber((full_name +
"_bl").c_str(),
"[TLM][chi][b]", m_db);
270 b_trHandle[tlm::TLM_READ_COMMAND] =
new tx_generator<sc_core::sc_time, sc_core::sc_time>(
271 "read", *b_streamHandle,
"start_delay",
"end_delay");
272 b_trHandle[tlm::TLM_WRITE_COMMAND] =
new tx_generator<sc_core::sc_time, sc_core::sc_time>(
273 "write", *b_streamHandle,
"start_delay",
"end_delay");
274 b_trHandle[tlm::TLM_IGNORE_COMMAND] =
new tx_generator<sc_core::sc_time, sc_core::sc_time>(
275 "ignore", *b_streamHandle,
"start_delay",
"end_delay");
277 b_streamHandleTimed =
278 new tx_fiber((full_name +
"_bl_timed").c_str(),
"[TLM][chi][b][timed]", m_db);
279 b_trTimedHandle[tlm::TLM_READ_COMMAND] =
new tx_generator<>(
"read", *b_streamHandleTimed);
280 b_trTimedHandle[tlm::TLM_WRITE_COMMAND] =
new tx_generator<>(
"write", *b_streamHandleTimed);
281 b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] =
new tx_generator<>(
"ignore", *b_streamHandleTimed);
285 nb_streamHandle =
new tx_fiber((full_name +
"_nb").c_str(),
"[TLM][chi][nb]", m_db);
286 nb_trHandle[FW] =
new tx_generator<std::string, std::string>(
"fw", *nb_streamHandle,
"tlm_phase",
287 "tlm_phase[return_path]");
288 nb_trHandle[BW] =
new tx_generator<std::string, std::string>(
"bw", *nb_streamHandle,
"tlm_phase",
289 "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 =
new tx_generator<sc_dt::uint64, sc_dt::uint64>(
303 "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)
328 this->
bw_port(ts.get_base_port());
329 this->
fw_port(is.get_base_port());
336template <
typename TYPES>
339 fw_port->b_transport(trans, delay);
343 tx_handle h = b_trHandle[trans.get_command()]->begin_tx(delay);
348 if(b_streamHandleTimed)
349 htim = b_trTimedHandle[trans.get_command()]->begin_tx_delayed(sc_core::sc_time_stamp()+delay, par_chld_hndl, h);
352 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
353 if(extensionRecording) {
354 extensionRecording->recordBeginTx(h, trans);
356 extensionRecording->recordBeginTx(htim, trans);
360 trans.get_extension(preExt);
361 if(preExt ==
nullptr) {
364 trans.set_auto_extension(preExt);
366 trans.set_extension(preExt);
368 h.add_relation(pred_succ_hndl, preExt->txHandle);
370 tx_handle preTx(preExt->txHandle);
371 preExt->txHandle = h;
372 fw_port->b_transport(trans, delay);
373 trans.get_extension(preExt);
374 if(preExt->creator ==
this) {
377 if(!trans.has_mm()) {
381 preExt->txHandle = preTx;
384 h.record_attribute(
"trans", trans);
386 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
387 if(extensionRecording) {
388 extensionRecording->recordEndTx(h, trans);
390 extensionRecording->recordEndTx(htim, trans);
395 if(htim.is_valid()) {
396 htim.record_attribute(
"trans", trans);
397 htim.end_tx_delayed(sc_core::sc_time_stamp()+delay);
401template <
typename TYPES>
403 if(!b_streamHandleTimed) {
404 bw_port->b_snoop(trans, delay);
408 tx_handle h = b_trHandle[trans.get_command()]->begin_tx(delay);
413 if(b_streamHandleTimed)
414 htim = b_trTimedHandle[trans.get_command()]->begin_tx_delayed(sc_core::sc_time_stamp()+delay, par_chld_hndl, h);
417 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
418 if(extensionRecording) {
419 extensionRecording->recordBeginTx(h, trans);
421 extensionRecording->recordBeginTx(htim, trans);
425 trans.get_extension(preExt);
426 if(preExt ==
nullptr) {
428 trans.set_extension(preExt);
430 h.add_relation(pred_succ_hndl, preExt->txHandle);
432 tx_handle preTx(preExt->txHandle);
433 preExt->txHandle = h;
434 bw_port->b_snoop(trans, delay);
435 trans.get_extension(preExt);
436 if(preExt->creator ==
this) {
442 preExt->txHandle = preTx;
445 h.record_attribute(
"trans", trans);
447 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
448 if(extensionRecording) {
449 extensionRecording->recordEndTx(h, trans);
451 extensionRecording->recordEndTx(htim, trans);
456 if(htim.is_valid()) {
457 htim.record_attribute(
"trans", trans);
458 htim.end_tx_delayed(sc_core::sc_time_stamp()+delay);
462template <
typename TYPES>
464 typename TYPES::tlm_phase_type& phase,
465 sc_core::sc_time& delay) {
467 return fw_port->nb_transport_fw(trans, phase, delay);
473 tx_handle h = nb_trHandle[FW]->begin_tx(phase2string(phase));
475 trans.get_extension(preExt);
476 if((phase == tlm::BEGIN_REQ) && preExt ==
nullptr) {
479 trans.set_auto_extension(preExt);
481 trans.set_extension(preExt);
482 }
else if(preExt !=
nullptr) {
484 h.add_relation(pred_succ_hndl, preExt->txHandle);
486 sc_assert(preExt !=
nullptr &&
"ERROR on forward path in phase other than tlm::BEGIN_REQ");
489 preExt->txHandle = h;
490 h.record_attribute(
"delay", delay);
492 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
493 if(extensionRecording)
494 extensionRecording->recordBeginTx(h, trans);
498 if(nb_streamHandleTimed) {
500 (trans.template get_extension<chi::chi_snp_extension>() !=
nullptr),
501 (phase == tlm::BEGIN_REQ) && (trans.template get_extension<chi::chi_credit_extension>() !=
nullptr));
502 rec.tr->deep_copy_from(trans);
503 nb_timed_peq.notify(rec, delay);
508 tlm::tlm_sync_enum status =
fw_port->nb_transport_fw(trans, phase, delay);
512 h.record_attribute(
"status", status);
513 h.record_attribute(
"delay[return_path]", delay);
514 h.record_attribute(
"trans", trans);
516 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
517 if(extensionRecording)
518 extensionRecording->recordEndTx(h, trans);
520 if(status == tlm::TLM_COMPLETED) {
522 trans.get_extension(preExt);
523 if(preExt && preExt->creator ==
this) {
525 if(!trans.has_mm()) {
532 if(nb_streamHandleTimed) {
534 reinterpret_cast<uint64_t
>(&trans), h};
535 rec.tr->deep_copy_from(trans);
536 nb_timed_peq.notify(rec, delay);
538 }
else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
540 rec.tr->deep_copy_from(trans);
541 nb_timed_peq.notify(rec, delay);
544 nb_trHandle[FW]->end_tx(h, phase2string(phase));
548template <
typename TYPES>
550 typename TYPES::tlm_phase_type& phase,
551 sc_core::sc_time& delay) {
553 return bw_port->nb_transport_bw(trans, phase, delay);
559 trans.get_extension(preExt);
561 tx_handle h = nb_trHandle[BW]->begin_tx(phase2string(phase));
563 if(phase == tlm::BEGIN_REQ && preExt ==
nullptr) {
565 trans.set_extension(preExt);
566 preExt->txHandle = h;
569 h.add_relation(pred_succ_hndl, preExt->txHandle);
571 preExt->txHandle = h;
573 sc_assert(preExt !=
nullptr &&
"ERROR on backward path in phase other than tlm::BEGIN_REQ");
576 h.record_attribute(
"delay", delay);
577 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
578 if(extensionRecording)
579 extensionRecording->recordBeginTx(h, trans);
583 if(nb_streamHandleTimed) {
585 (trans.template get_extension<chi::chi_snp_extension>() !=
nullptr),
586 (phase == tlm::BEGIN_REQ) && (trans.template get_extension<chi::chi_credit_extension>() !=
nullptr));
587 rec.tr->deep_copy_from(trans);
588 nb_timed_peq.notify(rec, delay);
593 tlm::tlm_sync_enum status =
bw_port->nb_transport_bw(trans, phase, delay);
597 h.record_attribute(
"status", status);
598 h.record_attribute(
"delay[return_path]", delay);
599 h.record_attribute(
"trans", trans);
601 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
602 if(extensionRecording)
603 extensionRecording->recordEndTx(h, trans);
605 nb_trHandle[BW]->end_tx(h, phase2string(phase));
607 if(status == tlm::TLM_COMPLETED) {
609 if(preExt && preExt->creator ==
this) {
612 if(!trans.has_mm()) {
619 if(nb_streamHandleTimed) {
621 reinterpret_cast<uint64_t
>(&trans), h, phase == tlm::BEGIN_REQ};
622 rec.tr->deep_copy_from(trans);
623 nb_timed_peq.notify(rec, delay);
625 }
else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
627 rec.tr->deep_copy_from(trans);
628 nb_timed_peq.notify(rec, delay);
633template <
typename TYPES>
634void chi_lwtr<TYPES>::nbtx_cb() {
641 nb_trTimedHandle[CREDIT]->begin_tx().end_tx();
642 }
else if(e.ph == tlm::BEGIN_REQ) {
643 h = nb_trTimedHandle[REQ]->begin_tx(par_chld_hndl, e.parent);
644 nbtx_req_handle_map[e.id] = h;
645 }
else if(e.ph == tlm::END_REQ) {
646 auto it = nbtx_req_handle_map.find(e.id);
647 if(it != nbtx_req_handle_map.end()) {
649 nbtx_req_handle_map.erase(it);
650 h.record_attribute(
"trans", *e.tr);
652 nbtx_last_req_handle_map[e.id] = h;
654 }
else if(e.ph == tlm::BEGIN_RESP) {
655 auto it = nbtx_req_handle_map.find(e.id);
656 if(it != nbtx_req_handle_map.end()) {
658 nbtx_req_handle_map.erase(it);
659 h.record_attribute(
"trans", *e.tr);
661 nbtx_last_req_handle_map[e.id] = h;
663 h = nb_trTimedHandle[RESP]->begin_tx(par_chld_hndl, e.parent);
664 nbtx_resp_handle_map[e.id] = h;
665 it = nbtx_last_req_handle_map.find(e.id);
666 if(it != nbtx_last_req_handle_map.end()) {
667 tx_handle& pred = it->second;
668 h.add_relation(pred_succ_hndl, pred);
669 nbtx_last_req_handle_map.erase(it);
671 it = nbtx_last_resp_handle_map.find(e.id);
672 if(it != nbtx_last_resp_handle_map.end()) {
673 tx_handle& pred = it->second;
674 h.add_relation(pred_succ_hndl, pred);
675 nbtx_last_resp_handle_map.erase(it);
678 }
else if(e.ph == tlm::END_RESP) {
679 auto it = nbtx_resp_handle_map.find(e.id);
680 if(it != nbtx_resp_handle_map.end()) {
682 nbtx_resp_handle_map.erase(it);
683 h.record_attribute(
"trans", *e.tr);
686 }
else if(e.ph == chi::BEGIN_DATA || e.ph == chi::BEGIN_PARTIAL_DATA) {
687 auto it = nbtx_req_handle_map.find(e.id);
688 if(it != nbtx_req_handle_map.end()) {
691 nbtx_last_req_handle_map[e.id] = h;
693 h = nb_trTimedHandle[DATA]->begin_tx();
694 h.record_attribute(
"trans", *e.tr);
695 h.add_relation(par_chld_hndl, e.parent);
696 nbtx_data_handle_map[e.id] = h;
697 it = nbtx_last_data_handle_map.find(e.id);
698 if(it != nbtx_last_data_handle_map.end()) {
699 auto pred = it->second;
700 nbtx_last_data_handle_map.erase(it);
701 h.add_relation(pred_succ_hndl, pred);
703 }
else if(e.ph == chi::END_DATA || e.ph == chi::END_PARTIAL_DATA) {
704 auto it = nbtx_data_handle_map.find(e.id);
705 if(it != nbtx_data_handle_map.end()) {
707 nbtx_data_handle_map.erase(it);
710 }
else if(e.ph == chi::ACK) {
711 auto it = nbtx_ack_handle_map.find(e.id);
712 if(it == nbtx_ack_handle_map.end()) {
713 auto h = nb_trTimedHandle[ACK]->begin_tx();
714 nbtx_ack_handle_map[e.id] = h;
715 h.add_relation(par_chld_hndl, e.parent);
717 nb_trTimedHandle[ACK]->end_tx(it->second);
718 nbtx_ack_handle_map.erase(it);
721 sc_assert(!
"phase not supported!");
726template <
typename TYPES>
729 return fw_port->get_direct_mem_ptr(trans, dmi_data);
730 tx_handle h = dmi_trGetHandle->begin_tx();
731 bool status =
fw_port->get_direct_mem_ptr(trans, dmi_data);
732 h.record_attribute(
"trans", trans);
733 h.record_attribute(
"dmi_data", dmi_data);
743template <
typename TYPES>
746 bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
749 tx_handle h = dmi_trInvalidateHandle->begin_tx(start_addr);
750 bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
751 dmi_trInvalidateHandle->end_tx(h, end_addr);
761 return fw_port->transport_dbg(trans);