19#ifndef SC_INCLUDE_DYNAMIC_PROCESSES
20#define SC_INCLUDE_DYNAMIC_PROCESSES
24#include <cci_configuration>
25#include <chi/chi_tlm.h>
28#include <tlm/scc/scv/tlm_recorder.h>
29#include <tlm/scc/scv/tlm_recording_extension.h>
30#include <tlm_utils/peq_with_cb_and_phase.h>
31#include <unordered_map>
38#define SCVNS ::scv_tr::
46inline bool has_credit(chi::chi_protocol_types::tlm_payload_type& trans) {
47 return trans.get_extension<chi::chi_credit_extension<chi::credit_type_e::REQ>>() ||
48 trans.get_extension<chi::chi_credit_extension<chi::credit_type_e::RESP>>() ||
49 trans.get_extension<chi::chi_credit_extension<chi::credit_type_e::DATA>>();
53bool register_extensions();
63template <
typename TYPES = chi::chi_protocol_types>
66 template <
unsigned int BUSWIDTH = 32,
int N = 1, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
69 template <
unsigned int BUSWIDTH = 32,
int N = 1, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
88 virtual tlm::tlm_fw_transport_if<TYPES>*
get_fw_if() = 0;
91 virtual tlm::tlm_bw_transport_if<TYPES>*
get_bw_if() = 0;
101 chi_trx_recorder(
const char* name,
bool recording_enabled =
true, SCVNS scv_tr_db* tr_db = SCVNS scv_tr_db::get_default_db())
105 , fixed_basename(name) {
106 register_extensions();
110 btx_handle_map.clear();
111 nbtx_req_handle_map.clear();
112 nbtx_last_req_handle_map.clear();
113 nbtx_resp_handle_map.clear();
114 nbtx_last_resp_handle_map.clear();
115 nbtx_data_handle_map.clear();
116 nbtx_last_data_handle_map.clear();
117 nbtx_ack_handle_map.clear();
119 delete b_streamHandle;
120 for(
auto* p : b_trHandle)
122 delete b_streamHandleTimed;
123 for(
auto* p : b_trTimedHandle)
125 delete nb_streamHandle;
126 for(
auto* p : nb_trHandle)
128 delete nb_streamHandleTimed;
129 for(
auto* p : nb_trTimedHandle)
131 delete dmi_streamHandle;
132 delete dmi_trGetHandle;
133 delete dmi_trInvalidateHandle;
147 tlm::tlm_sync_enum
nb_transport_fw(
typename TYPES::tlm_payload_type& trans,
typename TYPES::tlm_phase_type& phase,
148 sc_core::sc_time& delay)
override;
158 tlm::tlm_sync_enum
nb_transport_bw(
typename TYPES::tlm_payload_type& trans,
typename TYPES::tlm_phase_type& phase,
159 sc_core::sc_time& delay)
override;
168 void b_transport(
typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay)
override;
177 void b_snoop(
typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay)
override;
185 bool get_direct_mem_ptr(
typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data)
override;
199 unsigned int transport_dbg(
typename TYPES::tlm_payload_type& trans)
override;
214 void record_nb_timed(
typename TYPES::tlm_payload_type& rec_parts,
const typename TYPES::tlm_phase_type& phase,
215 sc_core::sc_time
const& ts, SCVNS scv_tr_handle parent,
bool is_credit);
217 SCVNS scv_tr_db* m_db{
nullptr};
219 SCVNS scv_tr_stream* b_streamHandle{
nullptr};
221 std::array<SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>*, 3> b_trHandle{{
nullptr,
nullptr,
nullptr}};
223 SCVNS scv_tr_stream* b_streamHandleTimed{
nullptr};
226 std::array<SCVNS scv_tr_generator<>*, 3> b_trTimedHandle{{
nullptr,
nullptr,
nullptr}};
227 std::unordered_map<uint64_t, SCVNS scv_tr_handle> btx_handle_map;
229 enum DIR { FW, BW, DATA, ACK, CREDIT, REQ = FW, RESP = BW };
230 enum TYPE { READ = tlm::TLM_READ_COMMAND, WRITE = tlm::TLM_WRITE_COMMAND, OTHER = tlm::TLM_IGNORE_COMMAND, SNOOP, NO_OF_TYPES };
232 SCVNS scv_tr_stream* nb_streamHandle{
nullptr};
234 SCVNS scv_tr_stream* nb_streamHandleTimed{
nullptr};
236 std::array<SCVNS scv_tr_generator<std::string, std::string>*, 2> nb_trHandle{{
nullptr,
nullptr}};
238 std::array<SCVNS scv_tr_generator<>*, 5> nb_trTimedHandle{{
nullptr,
nullptr,
nullptr,
nullptr,
nullptr}};
239 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_req_handle_map;
240 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_last_req_handle_map;
241 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_resp_handle_map;
242 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_last_resp_handle_map;
243 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_data_handle_map;
244 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_last_data_handle_map;
245 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_ack_handle_map;
247 SCVNS scv_tr_stream* dmi_streamHandle{
nullptr};
249 SCVNS scv_tr_generator<>* dmi_trGetHandle{
nullptr};
250 SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>* dmi_trInvalidateHandle{
nullptr};
253 void initialize_streams() {
255 b_streamHandle =
new SCVNS scv_tr_stream((fixed_basename +
"_bl").c_str(),
"[TLM][chi][b]", m_db);
256 b_trHandle[tlm::TLM_READ_COMMAND] =
257 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
"read", *b_streamHandle,
"start_delay",
"end_delay");
258 b_trHandle[tlm::TLM_WRITE_COMMAND] =
259 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
"write", *b_streamHandle,
"start_delay",
"end_delay");
260 b_trHandle[tlm::TLM_IGNORE_COMMAND] =
261 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
"ignore", *b_streamHandle,
"start_delay",
"end_delay");
263 b_streamHandleTimed =
new SCVNS scv_tr_stream((fixed_basename +
"_bl_timed").c_str(),
"[TLM][chi][b][timed]", m_db);
264 b_trTimedHandle[tlm::TLM_READ_COMMAND] =
new SCVNS scv_tr_generator<>(
"read", *b_streamHandleTimed);
265 b_trTimedHandle[tlm::TLM_WRITE_COMMAND] =
new SCVNS scv_tr_generator<>(
"write", *b_streamHandleTimed);
266 b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] =
new SCVNS scv_tr_generator<>(
"ignore", *b_streamHandleTimed);
270 nb_streamHandle =
new SCVNS scv_tr_stream((fixed_basename +
"_nb").c_str(),
"[TLM][chi][nb]", m_db);
272 new SCVNS scv_tr_generator<std::string, std::string>(
"fw", *nb_streamHandle,
"tlm_phase",
"tlm_phase[return_path]");
274 new SCVNS scv_tr_generator<std::string, std::string>(
"bw", *nb_streamHandle,
"tlm_phase",
"tlm_phase[return_path]");
276 nb_streamHandleTimed =
new SCVNS scv_tr_stream((fixed_basename +
"_nb_timed").c_str(),
"[TLM][chi][nb][timed]", m_db);
277 nb_trTimedHandle[REQ] =
new SCVNS scv_tr_generator<>(
"request", *nb_streamHandleTimed);
278 nb_trTimedHandle[RESP] =
new SCVNS scv_tr_generator<>(
"response", *nb_streamHandleTimed);
279 nb_trTimedHandle[DATA] =
new SCVNS scv_tr_generator<>(
"data", *nb_streamHandleTimed);
280 nb_trTimedHandle[ACK] =
new SCVNS scv_tr_generator<>(
"ack", *nb_streamHandleTimed);
281 nb_trTimedHandle[CREDIT] =
new SCVNS scv_tr_generator<>(
"link", *nb_streamHandleTimed);
285 dmi_streamHandle =
new SCVNS scv_tr_stream((fixed_basename +
"_dmi").c_str(),
"[TLM][ace][dmi]", m_db);
286 dmi_trGetHandle =
new SCVNS scv_tr_generator<>(
"get", *dmi_streamHandle,
"trans",
"dmi_data");
287 dmi_trInvalidateHandle =
288 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
"invalidate", *dmi_streamHandle,
"start_addr",
"end_addr");
293 const std::string fixed_basename;
295 inline std::string phase2string(
const tlm::tlm_phase& p) {
296 std::stringstream ss;
312 SCVNS scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_core::sc_time_stamp());
317 SCVNS scv_tr_handle bh;
318 if(b_streamHandleTimed) {
319 bh = b_trTimedHandle[
static_cast<unsigned>(trans.get_command())]->begin_transaction(sc_core::sc_time_stamp() + delay);
323 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
325 ext->recordBeginTx(h, trans);
328 trans.get_extension(preExt);
329 if(preExt ==
nullptr) {
331 trans.set_extension(preExt);
335 SCVNS scv_tr_handle preTx(preExt->
txHandle);
338 trans.get_extension(preExt);
345 tlm::scc::scv::record(h, trans);
346 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
348 ext->recordEndTx(h, trans);
350 b_trHandle[trans.get_command()]->end_transaction(h, delay.value(), sc_core::sc_time_stamp());
352 if(b_streamHandleTimed) {
353 tlm::scc::scv::record(bh, trans);
354 b_trTimedHandle[
static_cast<unsigned>(trans.get_command())]->end_transaction(bh, sc_core::sc_time_stamp() + delay);
359 if(!b_streamHandleTimed) {
364 SCVNS scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_core::sc_time_stamp());
368 SCVNS scv_tr_handle bh;
369 if(b_streamHandleTimed) {
370 bh = b_trTimedHandle[
static_cast<unsigned>(trans.get_command())]->begin_transaction(sc_core::sc_time_stamp() + delay);
374 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
376 ext->recordBeginTx(h, trans);
379 trans.get_extension(preExt);
382 trans.set_extension(preExt);
386 SCVNS scv_tr_handle preTx(preExt->
txHandle);
389 trans.get_extension(preExt);
397 tlm::scc::scv::record(h, trans);
398 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
400 ext->recordEndTx(h, trans);
402 b_trHandle[trans.get_command()]->end_transaction(h, delay.value());
404 if(b_streamHandleTimed) {
405 tlm::scc::scv::record(bh, trans);
406 b_trTimedHandle[
static_cast<unsigned>(trans.get_command())]->end_transaction(bh, sc_core::sc_time_stamp() + delay);
410template <
typename TYPES>
412 sc_core::sc_time& delay) {
414 return get_fw_if()->nb_transport_fw(trans, phase, delay);
419 bool is_snoop = (trans.template get_extension<chi::chi_snp_extension>() !=
nullptr);
420 SCVNS scv_tr_handle h = nb_trHandle[FW]->begin_transaction(phase2string(phase));
422 trans.get_extension(preExt);
423 if(phase == tlm::BEGIN_REQ && preExt ==
nullptr) {
425 trans.set_extension(preExt);
426 }
else if(preExt !=
nullptr) {
430 sc_assert(preExt !=
nullptr &&
"ERROR on forward path in phase other than tlm::BEGIN_REQ");
434 h.record_attribute(
"delay", delay.to_string());
435 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
437 ext->recordBeginTx(h, trans);
441 if(nb_streamHandleTimed) {
442 record_nb_timed(trans, phase, delay, h, (phase == tlm::BEGIN_REQ && has_credit(trans)));
447 tlm::tlm_sync_enum status =
get_fw_if()->nb_transport_fw(trans, phase, delay);
451 tlm::scc::scv::record(h, status);
452 h.record_attribute(
"delay[return_path]", delay.to_string());
453 tlm::scc::scv::record(h, trans);
454 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
456 ext->recordEndTx(h, trans);
458 if(status == tlm::TLM_COMPLETED) {
460 trans.get_extension(preExt);
468 if(nb_streamHandleTimed) {
469 record_nb_timed(trans, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase, delay, h,
470 (phase == tlm::BEGIN_REQ && has_credit(trans)));
472 }
else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
473 record_nb_timed(trans, phase, delay, h, (phase == tlm::BEGIN_REQ && has_credit(trans)));
476 nb_trHandle[FW]->end_transaction(h, phase2string(phase));
480template <
typename TYPES>
482 sc_core::sc_time& delay) {
484 return get_bw_if()->nb_transport_bw(trans, phase, delay);
489 bool is_snoop = (trans.template get_extension<chi::chi_snp_extension>() !=
nullptr);
490 SCVNS scv_tr_handle h = nb_trHandle[BW]->begin_transaction(phase2string(phase));
492 trans.get_extension(preExt);
493 if(phase == tlm::BEGIN_REQ && preExt ==
nullptr) {
495 trans.set_extension(preExt);
496 }
else if(preExt !=
nullptr) {
500 sc_assert(preExt !=
nullptr &&
"ERROR on backward path in phase other than tlm::BEGIN_REQ");
504 h.record_attribute(
"delay", delay.to_string());
505 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
507 ext->recordBeginTx(h, trans);
511 if(nb_streamHandleTimed) {
512 record_nb_timed(trans, phase, delay, h, (phase == tlm::BEGIN_REQ && has_credit(trans)));
517 tlm::tlm_sync_enum status =
get_bw_if()->nb_transport_bw(trans, phase, delay);
521 tlm::scc::scv::record(h, status);
522 h.record_attribute(
"delay[return_path]", delay.to_string());
523 tlm::scc::scv::record(h, trans);
524 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
526 ext->recordEndTx(h, trans);
528 if(status == tlm::TLM_COMPLETED) {
530 trans.get_extension(preExt);
538 if(nb_streamHandleTimed) {
539 record_nb_timed(trans, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase, delay, h,
540 (phase == tlm::BEGIN_REQ && has_credit(trans)));
542 }
else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
543 record_nb_timed(trans, phase, delay, h, (phase == tlm::BEGIN_REQ && has_credit(trans)));
546 nb_trHandle[BW]->end_transaction(h, phase2string(phase));
550template <
typename TYPES>
551void chi_trx_recorder<TYPES>::record_nb_timed(
typename TYPES::tlm_payload_type& trans,
const typename TYPES::tlm_phase_type& phase,
552 sc_core::sc_time
const& delay, SCVNS scv_tr_handle parent,
bool is_credit) {
553 SCVNS scv_tr_handle h;
554 std::unordered_map<uint64_t, SCVNS scv_tr_handle>::iterator it;
555 auto t = delay + sc_core::sc_time_stamp();
556 auto id =
reinterpret_cast<uintptr_t
>(&trans);
559 if(phase == tlm::BEGIN_REQ) {
560 h = nb_trTimedHandle[CREDIT]->begin_transaction(t);
562 nbtx_req_handle_map[id] = h;
564 it = nbtx_req_handle_map.find(
id);
565 if(it != nbtx_req_handle_map.end()) {
566 it->second.end_transaction(t);
567 nbtx_req_handle_map.erase(it);
570 }
else if(phase == tlm::BEGIN_REQ) {
571 h = nb_trTimedHandle[REQ]->begin_transaction(t);
572 tlm::scc::scv::record(h, trans);
574 nbtx_req_handle_map[id] = h;
575 nbtx_last_req_handle_map[id] = h;
576 }
else if(phase == tlm::END_REQ) {
577 it = nbtx_req_handle_map.find(
id);
578 if(it != nbtx_req_handle_map.end()) {
579 it->second.end_transaction(t);
580 nbtx_req_handle_map.erase(it);
582 }
else if(phase == tlm::BEGIN_RESP) {
583 it = nbtx_req_handle_map.find(
id);
584 if(it != nbtx_req_handle_map.end()) {
585 it->second.end_transaction(t);
586 nbtx_req_handle_map.erase(it);
588 h = nb_trTimedHandle[RESP]->begin_transaction();
589 tlm::scc::scv::record(h, trans);
591 nbtx_resp_handle_map[id] = h;
592 it = nbtx_last_req_handle_map.find(
id);
593 if(it != nbtx_last_req_handle_map.end()) {
594 SCVNS scv_tr_handle pred = it->second;
595 nbtx_last_req_handle_map.erase(it);
598 it = nbtx_last_resp_handle_map.find(
id);
599 if(it != nbtx_last_resp_handle_map.end()) {
600 SCVNS scv_tr_handle pred = it->second;
601 nbtx_last_resp_handle_map.erase(it);
605 }
else if(phase == tlm::END_RESP) {
606 it = nbtx_resp_handle_map.find(
id);
607 if(it != nbtx_resp_handle_map.end()) {
609 nbtx_resp_handle_map.erase(it);
610 h.end_transaction(t);
612 it = nbtx_req_handle_map.find(
id);
613 if(it != nbtx_req_handle_map.end()) {
615 nbtx_req_handle_map.erase(it);
616 h.end_transaction(t);
619 }
else if(phase == chi::BEGIN_DATA || phase == chi::BEGIN_PARTIAL_DATA) {
620 it = nbtx_req_handle_map.find(
id);
621 if(it != nbtx_req_handle_map.end()) {
623 h.end_transaction(t);
624 nbtx_last_req_handle_map[id] = h;
626 h = nb_trTimedHandle[DATA]->begin_transaction();
627 tlm::scc::scv::record(h, trans);
629 nbtx_data_handle_map[id] = h;
630 it = nbtx_last_data_handle_map.find(
id);
631 if(it != nbtx_last_data_handle_map.end()) {
632 SCVNS scv_tr_handle pred = it->second;
633 nbtx_last_data_handle_map.erase(it);
636 }
else if(phase == chi::END_DATA || phase == chi::END_PARTIAL_DATA) {
637 it = nbtx_data_handle_map.find(
id);
638 if(it != nbtx_data_handle_map.end()) {
640 nbtx_data_handle_map.erase(it);
641 h.end_transaction(t);
643 }
else if(phase == chi::ACK) {
644 it = nbtx_ack_handle_map.find(
id);
645 if(it == nbtx_ack_handle_map.end()) {
646 auto h = nb_trTimedHandle[ACK]->begin_transaction(t);
647 nbtx_ack_handle_map[id] = h;
650 it->second.end_transaction(t);
651 nbtx_ack_handle_map.erase(it);
654 sc_assert(!
"phase not supported!");
657template <
typename TYPES>
660 return get_fw_if()->get_direct_mem_ptr(trans, dmi_data);
661 else if(!dmi_streamHandle)
662 initialize_streams();
663 SCVNS scv_tr_handle h = dmi_trGetHandle->begin_transaction();
664 bool status =
get_fw_if()->get_direct_mem_ptr(trans, dmi_data);
665 tlm::scc::scv::record(h, trans);
666 tlm::scc::scv::record(h, dmi_data);
678 get_bw_if()->invalidate_direct_mem_ptr(start_addr, end_addr);
680 }
else if(!dmi_streamHandle)
681 initialize_streams();
682 SCVNS scv_tr_handle h = dmi_trInvalidateHandle->begin_transaction(start_addr);
683 get_bw_if()->invalidate_direct_mem_ptr(start_addr, end_addr);
684 dmi_trInvalidateHandle->end_transaction(h, end_addr);
694 unsigned int count =
get_fw_if()->transport_dbg(trans);
The TLM2 transaction recorder.
cci::cci_param< bool > enableDmiTracing
the attribute to selectively enable/disable DMI recording
virtual tlm::tlm_bw_transport_if< TYPES > * get_bw_if()=0
the port where bw accesses are forwarded to
void b_snoop(typename TYPES::tlm_payload_type &trans, sc_core::sc_time &delay) override
The blocking snoop function.
virtual tlm::tlm_fw_transport_if< TYPES > * get_fw_if()=0
the port where fw accesses are forwarded to
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.
cci::cci_param< bool > enableNbTracing
the attribute to selectively enable/disable recording of non-blocking protocol tx
void b_transport(typename TYPES::tlm_payload_type &trans, sc_core::sc_time &delay) override
The blocking transport function.
void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override
The direct memory interface backward function.
cci::cci_param< bool > enableTrDbgTracing
the attribute to selectively enable/disable transport dbg recording
cci::cci_param< bool > enableTimedTracing
the attribute to selectively enable/disable timed recording
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.
cci::cci_param< bool > enableBlTracing
the attribute to selectively enable/disable recording of blocking protocol tx
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.
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