19 #ifndef SC_INCLUDE_DYNAMIC_PROCESSES
20 #define SC_INCLUDE_DYNAMIC_PROCESSES
24 #include <chi/chi_tlm.h>
27 #include <tlm/scc/scv/tlm_recorder.h>
28 #include <tlm/scc/scv/tlm_recording_extension.h>
29 #include <tlm_utils/peq_with_cb_and_phase.h>
30 #include <unordered_map>
37 bool register_extensions();
42 template <
typename TYPES = chi::chi_protocol_types>
class chi_recording_payload :
public TYPES::tlm_payload_type {
44 SCVNS scv_tr_handle parent;
48 bool is_credit{
false};
51 this->set_command(x.get_command());
52 this->set_address(x.get_address());
53 this->set_data_ptr(
nullptr);
54 this->set_data_length(0);
55 this->set_response_status(x.get_response_status());
56 this->set_byte_enable_ptr(
nullptr);
57 this->set_byte_enable_length(0);
58 this->set_streaming_width(x.get_streaming_width());
62 : TYPES::tlm_payload_type(mm)
68 using tlm_phase_type =
typename TYPES::tlm_phase_type;
80 template <
typename TYPES = chi::chi_protocol_types>
84 template <
unsigned int BUSWIDTH = 32,
int N = 1, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
87 template <
unsigned int BUSWIDTH = 32,
int N = 1, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
112 virtual tlm::tlm_fw_transport_if<TYPES>*
get_fw_if() = 0;
115 virtual tlm::tlm_bw_transport_if<TYPES>*
get_bw_if() = 0;
126 SCVNS scv_tr_db* tr_db = SCVNS scv_tr_db::get_default_db())
132 , fixed_basename(name) {
133 register_extensions();
137 btx_handle_map.clear();
138 nbtx_req_handle_map.clear();
139 nbtx_last_req_handle_map.clear();
140 nbtx_resp_handle_map.clear();
141 nbtx_last_resp_handle_map.clear();
142 nbtx_data_handle_map.clear();
143 nbtx_last_data_handle_map.clear();
144 nbtx_ack_handle_map.clear();
146 delete b_streamHandle;
147 for(
auto* p : b_trHandle)
149 delete b_streamHandleTimed;
150 for(
auto* p : b_trTimedHandle)
152 delete nb_streamHandle;
153 for(
auto* p : nb_trHandle)
155 delete nb_streamHandleTimed;
156 for(
auto* p : nb_trTimedHandle)
158 delete dmi_streamHandle;
159 delete dmi_trGetHandle;
160 delete dmi_trInvalidateHandle;
174 tlm::tlm_sync_enum
nb_transport_fw(
typename TYPES::tlm_payload_type& trans,
typename TYPES::tlm_phase_type& phase,
175 sc_core::sc_time& delay)
override;
185 tlm::tlm_sync_enum
nb_transport_bw(
typename TYPES::tlm_payload_type& trans,
typename TYPES::tlm_phase_type& phase,
186 sc_core::sc_time& delay)
override;
195 void b_transport(
typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay)
override;
204 void b_snoop(
typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay)
override;
212 bool get_direct_mem_ptr(
typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data)
override;
226 unsigned int transport_dbg(
typename TYPES::tlm_payload_type& trans)
override;
242 tlm_utils::peq_with_cb_and_phase<chi_trx_recorder, recording_types> b_timed_peq;
244 tlm_utils::peq_with_cb_and_phase<chi_trx_recorder, recording_types> nb_timed_peq;
249 void btx_cb(tlm_recording_payload& rec_parts,
const typename TYPES::tlm_phase_type& phase);
254 void nbtx_cb(tlm_recording_payload& rec_parts,
const typename TYPES::tlm_phase_type& phase);
256 SCVNS scv_tr_db* m_db{
nullptr};
258 SCVNS scv_tr_stream* b_streamHandle{
nullptr};
260 std::array<SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>*, 3> b_trHandle{{
nullptr,
nullptr,
nullptr}};
262 SCVNS scv_tr_stream* b_streamHandleTimed{
nullptr};
265 std::array<SCVNS scv_tr_generator<>*, 3> b_trTimedHandle{{
nullptr,
nullptr,
nullptr}};
266 std::unordered_map<uint64_t, SCVNS scv_tr_handle> btx_handle_map;
268 enum DIR { FW, BW, DATA, ACK, CREDIT, REQ = FW, RESP = BW };
270 READ = tlm::TLM_READ_COMMAND,
271 WRITE = tlm::TLM_WRITE_COMMAND,
272 OTHER = tlm::TLM_IGNORE_COMMAND,
277 SCVNS scv_tr_stream* nb_streamHandle{
nullptr};
279 SCVNS scv_tr_stream* nb_streamHandleTimed{
nullptr};
281 std::array<SCVNS scv_tr_generator<std::string, std::string>*, 2> nb_trHandle{{
nullptr,
nullptr}};
283 std::array<SCVNS scv_tr_generator<>*, 5> nb_trTimedHandle{{
nullptr,
nullptr,
nullptr,
nullptr,
nullptr}};
284 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_req_handle_map;
285 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_last_req_handle_map;
286 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_resp_handle_map;
287 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_last_resp_handle_map;
288 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_data_handle_map;
289 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_last_data_handle_map;
290 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_ack_handle_map;
292 SCVNS scv_tr_stream* dmi_streamHandle{
nullptr};
294 SCVNS scv_tr_generator<>* dmi_trGetHandle{
nullptr};
295 SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>* dmi_trInvalidateHandle{
nullptr};
298 void initialize_streams() {
300 b_streamHandle =
new SCVNS scv_tr_stream((fixed_basename +
"_bl").c_str(),
"[TLM][chi][b]", m_db);
301 b_trHandle[tlm::TLM_READ_COMMAND] =
new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
302 "read", *b_streamHandle,
"start_delay",
"end_delay");
303 b_trHandle[tlm::TLM_WRITE_COMMAND] =
new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
304 "write", *b_streamHandle,
"start_delay",
"end_delay");
305 b_trHandle[tlm::TLM_IGNORE_COMMAND] =
new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
306 "ignore", *b_streamHandle,
"start_delay",
"end_delay");
308 b_streamHandleTimed =
309 new SCVNS scv_tr_stream((fixed_basename +
"_bl_timed").c_str(),
"[TLM][chi][b][timed]", m_db);
310 b_trTimedHandle[tlm::TLM_READ_COMMAND] =
new SCVNS scv_tr_generator<>(
"read", *b_streamHandleTimed);
311 b_trTimedHandle[tlm::TLM_WRITE_COMMAND] =
new SCVNS scv_tr_generator<>(
"write", *b_streamHandleTimed);
312 b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] =
new SCVNS scv_tr_generator<>(
"ignore", *b_streamHandleTimed);
316 nb_streamHandle =
new SCVNS scv_tr_stream((fixed_basename +
"_nb").c_str(),
"[TLM][chi][nb]", m_db);
317 nb_trHandle[FW] =
new SCVNS scv_tr_generator<std::string, std::string>(
"fw", *nb_streamHandle,
"tlm_phase",
318 "tlm_phase[return_path]");
319 nb_trHandle[BW] =
new SCVNS scv_tr_generator<std::string, std::string>(
"bw", *nb_streamHandle,
"tlm_phase",
320 "tlm_phase[return_path]");
322 nb_streamHandleTimed =
323 new SCVNS scv_tr_stream((fixed_basename +
"_nb_timed").c_str(),
"[TLM][chi][nb][timed]", m_db);
324 nb_trTimedHandle[REQ] =
new SCVNS scv_tr_generator<>(
"request", *nb_streamHandleTimed);
325 nb_trTimedHandle[RESP] =
new SCVNS scv_tr_generator<>(
"response", *nb_streamHandleTimed);
326 nb_trTimedHandle[DATA] =
new SCVNS scv_tr_generator<>(
"data", *nb_streamHandleTimed);
327 nb_trTimedHandle[ACK] =
new SCVNS scv_tr_generator<>(
"ack", *nb_streamHandleTimed);
328 nb_trTimedHandle[CREDIT] =
new SCVNS scv_tr_generator<>(
"link", *nb_streamHandleTimed);
332 dmi_streamHandle =
new SCVNS scv_tr_stream((fixed_basename +
"_dmi").c_str(),
"[TLM][ace][dmi]", m_db);
333 dmi_trGetHandle =
new SCVNS scv_tr_generator<>(
"get", *dmi_streamHandle,
"trans",
"dmi_data");
334 dmi_trInvalidateHandle =
new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
335 "invalidate", *dmi_streamHandle,
"start_addr",
"end_addr");
340 const std::string fixed_basename;
342 inline std::string phase2string(
const tlm::tlm_phase& p) {
343 std::stringstream ss;
353 template <
typename TYPES>
356 if(!isRecordingBlockingTxEnabled()) {
357 get_fw_if()->b_transport(trans, delay);
361 SCVNS scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_core::sc_time_stamp());
366 if(b_streamHandleTimed) {
367 req = mm::get().allocate();
371 req->id = h.get_id();
372 b_timed_peq.notify(*req, tlm::BEGIN_REQ, delay);
377 ext->recordBeginTx(h, trans);
380 trans.get_extension(preExt);
381 if(preExt ==
nullptr) {
383 trans.set_extension(preExt);
387 SCVNS scv_tr_handle preTx(preExt->
txHandle);
389 get_fw_if()->b_transport(trans, delay);
390 trans.get_extension(preExt);
397 tlm::scc::scv::record(h, trans);
400 ext->recordEndTx(h, trans);
402 b_trHandle[trans.get_command()]->end_transaction(h, delay.value(), sc_core::sc_time_stamp());
404 if(b_streamHandleTimed) {
405 b_timed_peq.notify(*req, tlm::END_RESP, delay);
409 template <
typename TYPES>
412 if(!b_streamHandleTimed) {
413 get_fw_if()->b_transport(trans, delay);
417 SCVNS scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_core::sc_time_stamp());
421 if(b_streamHandleTimed) {
422 req = mm::get().allocate();
426 req->id = h.get_id();
427 b_timed_peq.notify(*req, tlm::BEGIN_REQ, delay);
432 ext->recordBeginTx(h, trans);
435 trans.get_extension(preExt);
438 trans.set_extension(preExt);
442 SCVNS scv_tr_handle preTx(preExt->
txHandle);
444 get_fw_if()->b_transport(trans, delay);
445 trans.get_extension(preExt);
453 tlm::scc::scv::record(h, trans);
456 ext->recordEndTx(h, trans);
458 b_trHandle[trans.get_command()]->end_transaction(h, delay.value());
460 if(b_streamHandleTimed) {
461 b_timed_peq.notify(*req, tlm::END_RESP, delay);
465 template <
typename TYPES>
467 SCVNS scv_tr_handle h;
470 case tlm::BEGIN_REQ: {
471 h = b_trTimedHandle[rec_parts.get_command()]->begin_transaction();
473 btx_handle_map[rec_parts.id] = h;
475 case tlm::END_RESP: {
476 auto it = btx_handle_map.find(rec_parts.id);
477 sc_assert(it != btx_handle_map.end());
479 btx_handle_map.erase(it);
480 tlm::scc::scv::record(h, rec_parts);
485 sc_assert(!
"phase not supported!");
490 template <
typename TYPES>
492 typename TYPES::tlm_phase_type& phase,
493 sc_core::sc_time& delay) {
495 return get_fw_if()->nb_transport_fw(trans, phase, delay);
500 bool is_snoop = (trans.template get_extension<chi::chi_snp_extension>() !=
nullptr);
501 SCVNS scv_tr_handle h = nb_trHandle[FW]->begin_transaction(phase2string(phase));
503 trans.get_extension(preExt);
504 if(phase == tlm::BEGIN_REQ && preExt ==
nullptr) {
506 trans.set_extension(preExt);
507 }
else if(preExt !=
nullptr) {
511 sc_assert(preExt !=
nullptr &&
"ERROR on forward path in phase other than tlm::BEGIN_REQ");
515 h.record_attribute(
"delay", delay.to_string());
518 ext->recordBeginTx(h, trans);
522 if(nb_streamHandleTimed) {
527 req->is_snoop = is_snoop;
528 req->is_data = (phase == chi::BEGIN_DATA || chi::BEGIN_PARTIAL_DATA);
530 trans.get_extension(ext);
531 req->is_credit = (phase == tlm::BEGIN_REQ && ext !=
nullptr);
532 nb_timed_peq.notify(*req, phase, delay);
537 tlm::tlm_sync_enum status = get_fw_if()->nb_transport_fw(trans, phase, delay);
541 tlm::scc::scv::record(h, status);
542 h.record_attribute(
"delay[return_path]", delay.to_string());
543 tlm::scc::scv::record(h, trans);
546 ext->recordEndTx(h, trans);
548 if(status == tlm::TLM_COMPLETED) {
550 trans.get_extension(preExt);
558 if(nb_streamHandleTimed) {
563 nb_timed_peq.notify(*req, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase,
566 }
else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
571 nb_timed_peq.notify(*req, phase, delay);
574 nb_trHandle[FW]->end_transaction(h, phase2string(phase));
578 template <
typename TYPES>
580 typename TYPES::tlm_phase_type& phase,
581 sc_core::sc_time& delay) {
583 return get_bw_if()->nb_transport_bw(trans, phase, delay);
588 bool is_snoop = (trans.template get_extension<chi::chi_snp_extension>() !=
nullptr);
589 SCVNS scv_tr_handle h = nb_trHandle[BW]->begin_transaction(phase2string(phase));
591 trans.get_extension(preExt);
592 if(phase == tlm::BEGIN_REQ && preExt ==
nullptr) {
594 trans.set_extension(preExt);
595 }
else if(preExt !=
nullptr) {
599 sc_assert(preExt !=
nullptr &&
"ERROR on backward path in phase other than tlm::BEGIN_REQ");
603 h.record_attribute(
"delay", delay.to_string());
606 ext->recordBeginTx(h, trans);
610 if(nb_streamHandleTimed) {
615 req->is_snoop = is_snoop;
616 req->is_data = (phase == chi::BEGIN_DATA || chi::BEGIN_PARTIAL_DATA);
618 trans.get_extension(ext);
619 req->is_credit = (phase == tlm::BEGIN_REQ && ext !=
nullptr);
620 nb_timed_peq.notify(*req, phase, delay);
625 tlm::tlm_sync_enum status = get_bw_if()->nb_transport_bw(trans, phase, delay);
629 tlm::scc::scv::record(h, status);
630 h.record_attribute(
"delay[return_path]", delay.to_string());
631 tlm::scc::scv::record(h, trans);
634 ext->recordEndTx(h, trans);
636 if(status == tlm::TLM_COMPLETED) {
638 trans.get_extension(preExt);
646 if(nb_streamHandleTimed) {
651 nb_timed_peq.notify(*req, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase,
654 }
else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
659 nb_timed_peq.notify(*req, phase, delay);
662 nb_trHandle[BW]->end_transaction(h, phase2string(phase));
666 template <
typename TYPES>
668 SCVNS scv_tr_handle h;
669 std::unordered_map<uint64_t, SCVNS scv_tr_handle>::iterator it;
671 if(rec_parts.is_credit) {
672 nb_trTimedHandle[CREDIT]->begin_transaction().end_transaction();
673 }
else if(phase == tlm::BEGIN_REQ) {
674 h = nb_trTimedHandle[REQ]->begin_transaction();
675 tlm::scc::scv::record(h, rec_parts);
677 nbtx_req_handle_map[rec_parts.id] = h;
678 nbtx_last_req_handle_map[rec_parts.id] = h;
679 }
else if(phase == tlm::END_REQ) {
680 it = nbtx_req_handle_map.find(rec_parts.id);
681 if(it != nbtx_req_handle_map.end()) {
682 it->second.end_transaction();
683 nbtx_req_handle_map.erase(it);
685 }
else if(phase == tlm::BEGIN_RESP) {
686 it = nbtx_req_handle_map.find(rec_parts.id);
687 if(it != nbtx_req_handle_map.end()) {
688 it->second.end_transaction();
689 nbtx_req_handle_map.erase(it);
691 h = nb_trTimedHandle[RESP]->begin_transaction();
692 tlm::scc::scv::record(h, rec_parts);
694 nbtx_resp_handle_map[rec_parts.id] = h;
695 it = nbtx_last_req_handle_map.find(rec_parts.id);
696 if(it != nbtx_last_req_handle_map.end()) {
697 SCVNS scv_tr_handle pred = it->second;
698 nbtx_last_req_handle_map.erase(it);
701 it = nbtx_last_resp_handle_map.find(rec_parts.id);
702 if(it != nbtx_last_resp_handle_map.end()) {
703 SCVNS scv_tr_handle pred = it->second;
704 nbtx_last_resp_handle_map.erase(it);
708 }
else if(phase == tlm::END_RESP) {
709 it = nbtx_resp_handle_map.find(rec_parts.id);
710 if(it != nbtx_resp_handle_map.end()) {
712 nbtx_resp_handle_map.erase(it);
715 it = nbtx_req_handle_map.find(rec_parts.id);
716 if(it != nbtx_req_handle_map.end()) {
718 nbtx_req_handle_map.erase(it);
722 }
else if(phase == chi::BEGIN_DATA || phase == chi::BEGIN_PARTIAL_DATA) {
723 it = nbtx_req_handle_map.find(rec_parts.id);
724 if(it != nbtx_req_handle_map.end()) {
727 nbtx_last_req_handle_map[rec_parts.id] = h;
729 h = nb_trTimedHandle[DATA]->begin_transaction();
730 tlm::scc::scv::record(h, rec_parts);
732 nbtx_data_handle_map[rec_parts.id] = h;
733 it = nbtx_last_data_handle_map.find(rec_parts.id);
734 if(it != nbtx_last_data_handle_map.end()) {
735 SCVNS scv_tr_handle pred = it->second;
736 nbtx_last_data_handle_map.erase(it);
739 }
else if(phase == chi::END_DATA || phase == chi::END_PARTIAL_DATA) {
740 it = nbtx_data_handle_map.find(rec_parts.id);
741 if(it != nbtx_data_handle_map.end()) {
743 nbtx_data_handle_map.erase(it);
746 }
else if(phase == chi::ACK) {
747 it = nbtx_ack_handle_map.find(rec_parts.id);
748 if(it == nbtx_ack_handle_map.end()) {
749 auto h = nb_trTimedHandle[ACK]->begin_transaction();
750 nbtx_ack_handle_map[rec_parts.id] = h;
753 nb_trTimedHandle[ACK]->end_transaction(it->second);
754 nbtx_ack_handle_map.erase(it);
757 sc_assert(!
"phase not supported!");
762 template <
typename TYPES>
764 if(!(m_db && enableDmiTracing.value))
765 return get_fw_if()->get_direct_mem_ptr(trans, dmi_data);
766 else if(!dmi_streamHandle)
767 initialize_streams();
768 SCVNS scv_tr_handle h = dmi_trGetHandle->begin_transaction();
769 bool status = get_fw_if()->get_direct_mem_ptr(trans, dmi_data);
770 tlm::scc::scv::record(h, trans);
771 tlm::scc::scv::record(h, dmi_data);
781 template <
typename TYPES>
783 if(!(m_db && enableDmiTracing.value)) {
784 get_bw_if()->invalidate_direct_mem_ptr(start_addr, end_addr);
786 }
else if(!dmi_streamHandle)
787 initialize_streams();
788 SCVNS scv_tr_handle h = dmi_trInvalidateHandle->begin_transaction(start_addr);
789 get_bw_if()->invalidate_direct_mem_ptr(start_addr, end_addr);
790 dmi_trInvalidateHandle->end_transaction(h, end_addr);
800 unsigned int count = get_fw_if()->transport_dbg(trans);
The TLM2 transaction recorder.
void b_snoop(typename TYPES::tlm_payload_type &trans, sc_core::sc_time &delay) override
The blocking snoop function.
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.
bool get_direct_mem_ptr(typename TYPES::tlm_payload_type &trans, tlm::tlm_dmi &dmi_data) override
The direct memory interface forward function.
void b_transport(typename TYPES::tlm_payload_type &trans, sc_core::sc_time &delay) override
The blocking transport function.
virtual tlm::tlm_fw_transport_if< TYPES > * get_fw_if()=0
the port where fw accesses are forwarded to
void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override
The direct memory interface backward function.
sc_core::sc_attribute< bool > enableTimedTracing
the attribute to selectively enable/disable timed recording
sc_core::sc_attribute< bool > enableNbTracing
the attribute to selectively enable/disable recording of non-blocking protocol tx
virtual tlm::tlm_bw_transport_if< TYPES > * get_bw_if()=0
the port where bw accesses are forwarded to
unsigned int transport_dbg(typename TYPES::tlm_payload_type &trans) override
The debug transportfunction.
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.
sc_core::sc_attribute< bool > enableBlTracing
the attribute to selectively enable/disable recording of blocking protocol tx
sc_core::sc_attribute< bool > enableTrDbgTracing
the attribute to selectively enable/disable transport dbg recording
bool isRecordingBlockingTxEnabled() const
get the current state of transaction recording
bool isRecordingNonBlockingTxEnabled() const
get the current state of transaction recording
chi_trx_recorder(const char *name, bool recording_enabled=true, SCVNS scv_tr_db *tr_db=SCVNS scv_tr_db::get_default_db())
The constructor of the component.
sc_core::sc_attribute< bool > enableDmiTracing
the attribute to selectively enable/disable DMI recording
the class to hold the information to be recorded on the timed streams
The TLM transaction extensions recorder registry.
generic payload extension class holding the handle of the last recorded SCV transaction
SCVNS scv_tr_handle txHandle
accessor to the SCV transaction handle.
void * get_creator()
accessor to the owner, the property is read only.
TLM2.0 components modeling CHI.
tlm::tlm_fw_transport_if< TYPES > chi_fw_transport_if
alias declaration for the forward interface
const char * rel_str(tx_rel rel)
cast the tx_rel enum to a string