19 #ifndef SC_INCLUDE_DYNAMIC_PROCESSES
20 #define SC_INCLUDE_DYNAMIC_PROCESSES
23 #include <tlm/scc/lwtr/tlm2_lwtr.h>
24 #include <cci_configuration>
25 #include <tlm/scc/tlm_mm.h>
27 #include <chi/chi_tlm.h>
31 #include <unordered_map>
38 using tx_db = ::lwtr::tx_db;
39 using tx_fiber = ::lwtr::tx_fiber;
40 template <
typename BEGIN = ::lwtr::no_data,
typename END = ::lwtr::no_data>
41 using tx_generator = ::lwtr::tx_generator<BEGIN, END>;
42 using tx_handle = ::lwtr::tx_handle;
53 extern bool registered;
63 template <
typename TYPES = chi::chi_protocol_types>
73 cci::cci_param<bool> enableTimedTracing{
"enableTimedTracing",
true};
76 cci::cci_param<bool> enableDmiTracing{
"enableDmiTracing",
false};
86 chi_lwtr(
char const* full_name,
unsigned bus_width,
bool recording_enabled =
true, tx_db* tr_db = tx_db::get_default_db())
87 : enableBlTracing(
"enableBlTracing", recording_enabled)
88 , enableNbTracing(
"enableNbTracing", recording_enabled)
89 , full_name(full_name)
91 , bus_width(bus_width)
94 sc_core::sc_spawn_options opts;
96 opts.dont_initialize();
97 opts.set_sensitivity(&nb_timed_peq.event());
98 sc_core::sc_spawn([
this](){
101 initialize_streams();
105 nbtx_req_handle_map.clear();
106 nbtx_last_req_handle_map.clear();
107 nbtx_resp_handle_map.clear();
108 nbtx_last_resp_handle_map.clear();
109 nbtx_data_handle_map.clear();
110 nbtx_last_data_handle_map.clear();
111 nbtx_ack_handle_map.clear();
112 delete dmi_trInvalidateHandle;
113 delete dmi_trGetHandle;
114 delete dmi_streamHandle;
115 for(
auto* p : nb_trTimedHandle)
delete p;
116 delete nb_streamHandleTimed;
117 for(
auto* p : nb_trHandle)
delete p;
118 delete nb_streamHandle;
119 for(
auto* p : b_trTimedHandle)
delete p;
120 delete b_streamHandleTimed;
121 for(
auto* p : b_trHandle)
delete p;
122 delete b_streamHandle;
136 tlm::tlm_sync_enum
nb_transport_fw(
typename TYPES::tlm_payload_type& trans,
typename TYPES::tlm_phase_type& phase,
137 sc_core::sc_time& delay)
override;
147 tlm::tlm_sync_enum
nb_transport_bw(
typename TYPES::tlm_payload_type& trans,
typename TYPES::tlm_phase_type& phase,
148 sc_core::sc_time& delay)
override;
157 void b_transport(
typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay)
override;
166 void b_snoop(
typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay)
override;
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");
268 if(isRecordingBlockingTxEnabled() && !b_streamHandle) {
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");
276 if(enableTimedTracing.get_value()) {
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);
284 if(isRecordingNonBlockingTxEnabled() && !nb_streamHandle) {
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]");
290 if(enableTimedTracing.get_value()) {
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);
299 if(m_db && enableDmiTracing.get_value() && !dmi_streamHandle) {
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;
316 sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
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());
336 template <
typename TYPES>
338 if(!isRecordingBlockingTxEnabled()) {
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);
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);
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);
401 template <
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);
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);
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);
462 template <
typename TYPES>
464 typename TYPES::tlm_phase_type& phase,
465 sc_core::sc_time& delay) {
466 if(!isRecordingNonBlockingTxEnabled()){
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);
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);
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));
548 template <
typename TYPES>
550 typename TYPES::tlm_phase_type& phase,
551 sc_core::sc_time& delay) {
552 if(!isRecordingNonBlockingTxEnabled()){
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);
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);
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);
633 template <
typename TYPES>
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!");
726 template <
typename TYPES>
728 if(!(m_db && enableDmiTracing.get_value()))
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);
743 template <
typename TYPES>
745 if(!(m_db && enableDmiTracing.get_value())) {
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);
The TLM2 transaction recorder.
bool isRecordingNonBlockingTxEnabled() const
get the current state of transaction recording
tlm::tlm_sync_enum nb_transport_fw(typename TYPES::tlm_payload_type &trans, typename TYPES::tlm_phase_type &phase, sc_core::sc_time &delay) override
The non-blocking forward transport function.
void b_snoop(typename TYPES::tlm_payload_type &trans, sc_core::sc_time &delay) override
The blocking snoop function.
void b_transport(typename TYPES::tlm_payload_type &trans, sc_core::sc_time &delay) override
The blocking transport function.
cci::cci_param< bool > enableNbTracing
the attribute to selectively enable/disable recording of non-blocking protocol tx
tlm::tlm_sync_enum nb_transport_bw(typename TYPES::tlm_payload_type &trans, typename TYPES::tlm_phase_type &phase, sc_core::sc_time &delay) override
The non-blocking backward transport function.
unsigned int transport_dbg(typename TYPES::tlm_payload_type &trans) override
The debug transportfunction.
cci::cci_param< bool > enableBlTracing
the attribute to selectively enable/disable recording of blocking protocol tx
chi_lwtr(char const *full_name, unsigned bus_width, bool recording_enabled=true, tx_db *tr_db=tx_db::get_default_db())
The constructor of the component.
bool isRecordingBlockingTxEnabled() const
get the current state of transaction recording
void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override
The direct memory interface backward function.
bool get_direct_mem_ptr(typename TYPES::tlm_payload_type &trans, tlm::tlm_dmi &dmi_data) override
The direct memory interface forward function.
The TLM transaction extensions recorder registry.
payload_type * allocate()
get a plain tlm_payload_type without extensions
TLM2.0 components modeling CHI.
tlm::tlm_fw_transport_if< TYPES > chi_fw_transport_if
alias declaration for the forward interface
SCC SCV4TLM classes and functions.
The AXI protocol traits class. Since the protocoll defines additional non-ignorable phases a dedicate...
void notify(const TYPE &entry, const sc_core::sc_time &t)
non-blocking push.
boost::optional< TYPE > get_next()
non-blocking get
static tlm_mm & get()
accessor function of the singleton