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>
32#include <cci_configuration>
38#define SCVNS ::scv_tr::
46bool register_extensions();
56template <
typename TYPES = chi::chi_protocol_types>
60 template <
unsigned int BUSWIDTH = 32,
int N = 1, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
63 template <
unsigned int BUSWIDTH = 32,
int N = 1, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
82 virtual tlm::tlm_fw_transport_if<TYPES>*
get_fw_if() = 0;
85 virtual tlm::tlm_bw_transport_if<TYPES>*
get_bw_if() = 0;
96 SCVNS scv_tr_db* tr_db = SCVNS scv_tr_db::get_default_db())
100 , fixed_basename(name) {
101 register_extensions();
105 btx_handle_map.clear();
106 nbtx_req_handle_map.clear();
107 nbtx_last_req_handle_map.clear();
108 nbtx_resp_handle_map.clear();
109 nbtx_last_resp_handle_map.clear();
110 nbtx_data_handle_map.clear();
111 nbtx_last_data_handle_map.clear();
112 nbtx_ack_handle_map.clear();
114 delete b_streamHandle;
115 for(
auto* p : b_trHandle)
117 delete b_streamHandleTimed;
118 for(
auto* p : b_trTimedHandle)
120 delete nb_streamHandle;
121 for(
auto* p : nb_trHandle)
123 delete nb_streamHandleTimed;
124 for(
auto* p : nb_trTimedHandle)
126 delete dmi_streamHandle;
127 delete dmi_trGetHandle;
128 delete dmi_trInvalidateHandle;
142 tlm::tlm_sync_enum
nb_transport_fw(
typename TYPES::tlm_payload_type& trans,
typename TYPES::tlm_phase_type& phase,
143 sc_core::sc_time& delay)
override;
153 tlm::tlm_sync_enum
nb_transport_bw(
typename TYPES::tlm_payload_type& trans,
typename TYPES::tlm_phase_type& phase,
154 sc_core::sc_time& delay)
override;
163 void b_transport(
typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay)
override;
172 void b_snoop(
typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay)
override;
180 bool get_direct_mem_ptr(
typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data)
override;
194 unsigned int transport_dbg(
typename TYPES::tlm_payload_type& trans)
override;
209 void record_nb_timed(
typename TYPES::tlm_payload_type& rec_parts,
const typename TYPES::tlm_phase_type& phase, sc_core::sc_time
const& ts, SCVNS scv_tr_handle parent,
bool is_credit);
211 SCVNS scv_tr_db* m_db{
nullptr};
213 SCVNS scv_tr_stream* b_streamHandle{
nullptr};
215 std::array<SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>*, 3> b_trHandle{{
nullptr,
nullptr,
nullptr}};
217 SCVNS scv_tr_stream* b_streamHandleTimed{
nullptr};
220 std::array<SCVNS scv_tr_generator<>*, 3> b_trTimedHandle{{
nullptr,
nullptr,
nullptr}};
221 std::unordered_map<uint64_t, SCVNS scv_tr_handle> btx_handle_map;
223 enum DIR { FW, BW, DATA, ACK, CREDIT, REQ = FW, RESP = BW };
225 READ = tlm::TLM_READ_COMMAND,
226 WRITE = tlm::TLM_WRITE_COMMAND,
227 OTHER = tlm::TLM_IGNORE_COMMAND,
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] =
new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
257 "read", *b_streamHandle,
"start_delay",
"end_delay");
258 b_trHandle[tlm::TLM_WRITE_COMMAND] =
new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
259 "write", *b_streamHandle,
"start_delay",
"end_delay");
260 b_trHandle[tlm::TLM_IGNORE_COMMAND] =
new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
261 "ignore", *b_streamHandle,
"start_delay",
"end_delay");
263 b_streamHandleTimed =
264 new SCVNS scv_tr_stream((fixed_basename +
"_bl_timed").c_str(),
"[TLM][chi][b][timed]", m_db);
265 b_trTimedHandle[tlm::TLM_READ_COMMAND] =
new SCVNS scv_tr_generator<>(
"read", *b_streamHandleTimed);
266 b_trTimedHandle[tlm::TLM_WRITE_COMMAND] =
new SCVNS scv_tr_generator<>(
"write", *b_streamHandleTimed);
267 b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] =
new SCVNS scv_tr_generator<>(
"ignore", *b_streamHandleTimed);
271 nb_streamHandle =
new SCVNS scv_tr_stream((fixed_basename +
"_nb").c_str(),
"[TLM][chi][nb]", m_db);
272 nb_trHandle[FW] =
new SCVNS scv_tr_generator<std::string, std::string>(
"fw", *nb_streamHandle,
"tlm_phase",
273 "tlm_phase[return_path]");
274 nb_trHandle[BW] =
new SCVNS scv_tr_generator<std::string, std::string>(
"bw", *nb_streamHandle,
"tlm_phase",
275 "tlm_phase[return_path]");
277 nb_streamHandleTimed =
278 new SCVNS scv_tr_stream((fixed_basename +
"_nb_timed").c_str(),
"[TLM][chi][nb][timed]", m_db);
279 nb_trTimedHandle[REQ] =
new SCVNS scv_tr_generator<>(
"request", *nb_streamHandleTimed);
280 nb_trTimedHandle[RESP] =
new SCVNS scv_tr_generator<>(
"response", *nb_streamHandleTimed);
281 nb_trTimedHandle[DATA] =
new SCVNS scv_tr_generator<>(
"data", *nb_streamHandleTimed);
282 nb_trTimedHandle[ACK] =
new SCVNS scv_tr_generator<>(
"ack", *nb_streamHandleTimed);
283 nb_trTimedHandle[CREDIT] =
new SCVNS scv_tr_generator<>(
"link", *nb_streamHandleTimed);
287 dmi_streamHandle =
new SCVNS scv_tr_stream((fixed_basename +
"_dmi").c_str(),
"[TLM][ace][dmi]", m_db);
288 dmi_trGetHandle =
new SCVNS scv_tr_generator<>(
"get", *dmi_streamHandle,
"trans",
"dmi_data");
289 dmi_trInvalidateHandle =
new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
290 "invalidate", *dmi_streamHandle,
"start_addr",
"end_addr");
295 const std::string fixed_basename;
297 inline std::string phase2string(
const tlm::tlm_phase& p) {
298 std::stringstream ss;
308template <
typename TYPES>
315 SCVNS scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_core::sc_time_stamp());
320 SCVNS scv_tr_handle bh;
321 if(b_streamHandleTimed) {
322 bh = b_trTimedHandle[
static_cast<unsigned>(trans.get_command())]->begin_transaction(sc_core::sc_time_stamp() + delay);
326 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
328 ext->recordBeginTx(h, trans);
331 trans.get_extension(preExt);
332 if(preExt ==
nullptr) {
334 trans.set_extension(preExt);
338 SCVNS scv_tr_handle preTx(preExt->
txHandle);
341 trans.get_extension(preExt);
348 tlm::scc::scv::record(h, trans);
349 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
351 ext->recordEndTx(h, trans);
353 b_trHandle[trans.get_command()]->end_transaction(h, delay.value(), sc_core::sc_time_stamp());
355 if(b_streamHandleTimed) {
356 tlm::scc::scv::record(bh, trans);
357 b_trTimedHandle[
static_cast<unsigned>(trans.get_command())]->end_transaction(bh, sc_core::sc_time_stamp()+ delay);
361template <
typename TYPES>
363 if(!b_streamHandleTimed) {
368 SCVNS scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_core::sc_time_stamp());
372 SCVNS scv_tr_handle bh;
373 if(b_streamHandleTimed) {
374 bh = b_trTimedHandle[
static_cast<unsigned>(trans.get_command())]->begin_transaction(sc_core::sc_time_stamp() + delay);
378 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
380 ext->recordBeginTx(h, trans);
383 trans.get_extension(preExt);
386 trans.set_extension(preExt);
390 SCVNS scv_tr_handle preTx(preExt->
txHandle);
393 trans.get_extension(preExt);
401 tlm::scc::scv::record(h, trans);
402 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
404 ext->recordEndTx(h, trans);
406 b_trHandle[trans.get_command()]->end_transaction(h, delay.value());
408 if(b_streamHandleTimed) {
409 tlm::scc::scv::record(bh, trans);
410 b_trTimedHandle[
static_cast<unsigned>(trans.get_command())]->end_transaction(bh, sc_core::sc_time_stamp()+ delay);
414template <
typename TYPES>
416 typename TYPES::tlm_phase_type& phase,
417 sc_core::sc_time& delay) {
419 return get_fw_if()->nb_transport_fw(trans, phase, delay);
424 bool is_snoop = (trans.template get_extension<chi::chi_snp_extension>() !=
nullptr);
425 SCVNS scv_tr_handle h = nb_trHandle[FW]->begin_transaction(phase2string(phase));
427 trans.get_extension(preExt);
428 if(phase == tlm::BEGIN_REQ && preExt ==
nullptr) {
430 trans.set_extension(preExt);
431 }
else if(preExt !=
nullptr) {
435 sc_assert(preExt !=
nullptr &&
"ERROR on forward path in phase other than tlm::BEGIN_REQ");
439 h.record_attribute(
"delay", delay.to_string());
440 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
442 ext->recordBeginTx(h, trans);
447 trans.get_extension(chi_ext);
448 if(nb_streamHandleTimed) {
449 record_nb_timed(trans, phase, delay, h, (phase == tlm::BEGIN_REQ && chi_ext !=
nullptr));
454 tlm::tlm_sync_enum status =
get_fw_if()->nb_transport_fw(trans, phase, delay);
458 tlm::scc::scv::record(h, status);
459 h.record_attribute(
"delay[return_path]", delay.to_string());
460 tlm::scc::scv::record(h, trans);
461 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
463 ext->recordEndTx(h, trans);
465 if(status == tlm::TLM_COMPLETED) {
467 trans.get_extension(preExt);
475 if(nb_streamHandleTimed) {
476 record_nb_timed(trans, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase,delay, h, (phase == tlm::BEGIN_REQ && chi_ext !=
nullptr));
478 }
else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
479 record_nb_timed(trans, phase, delay, h, (phase == tlm::BEGIN_REQ && chi_ext !=
nullptr));
482 nb_trHandle[FW]->end_transaction(h, phase2string(phase));
486template <
typename TYPES>
488 typename TYPES::tlm_phase_type& phase,
489 sc_core::sc_time& delay) {
491 return get_bw_if()->nb_transport_bw(trans, phase, delay);
496 bool is_snoop = (trans.template get_extension<chi::chi_snp_extension>() !=
nullptr);
497 SCVNS scv_tr_handle h = nb_trHandle[BW]->begin_transaction(phase2string(phase));
499 trans.get_extension(preExt);
500 if(phase == tlm::BEGIN_REQ && preExt ==
nullptr) {
502 trans.set_extension(preExt);
503 }
else if(preExt !=
nullptr) {
507 sc_assert(preExt !=
nullptr &&
"ERROR on backward path in phase other than tlm::BEGIN_REQ");
511 h.record_attribute(
"delay", delay.to_string());
512 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
514 ext->recordBeginTx(h, trans);
519 trans.get_extension(chi_ext);
520 if(nb_streamHandleTimed) {
521 record_nb_timed(trans, phase, delay, h, (phase == tlm::BEGIN_REQ && chi_ext !=
nullptr));
526 tlm::tlm_sync_enum status =
get_bw_if()->nb_transport_bw(trans, phase, delay);
530 tlm::scc::scv::record(h, status);
531 h.record_attribute(
"delay[return_path]", delay.to_string());
532 tlm::scc::scv::record(h, trans);
533 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
535 ext->recordEndTx(h, trans);
537 if(status == tlm::TLM_COMPLETED) {
539 trans.get_extension(preExt);
547 if(nb_streamHandleTimed) {
548 record_nb_timed(trans, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase, delay, h, (phase == tlm::BEGIN_REQ && chi_ext !=
nullptr));
550 }
else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
551 record_nb_timed(trans, phase, delay, h, (phase == tlm::BEGIN_REQ && chi_ext !=
nullptr));
555 nb_trHandle[BW]->end_transaction(h, phase2string(phase));
559template <
typename TYPES>
560void chi_trx_recorder<TYPES>::record_nb_timed(
typename TYPES::tlm_payload_type& trans,
const typename TYPES::tlm_phase_type& phase, sc_core::sc_time
const& delay, SCVNS scv_tr_handle parent,
bool is_credit) {
561 SCVNS scv_tr_handle h;
562 std::unordered_map<uint64_t, SCVNS scv_tr_handle>::iterator it;
563 auto t = delay+sc_core::sc_time_stamp();
564 auto id =
reinterpret_cast<uintptr_t
>(&trans);
567 if(phase == tlm::BEGIN_REQ) {
568 h = nb_trTimedHandle[CREDIT]->begin_transaction(t);
570 nbtx_req_handle_map[id] = h;
572 it = nbtx_req_handle_map.find(
id);
573 if(it != nbtx_req_handle_map.end()) {
574 it->second.end_transaction(t);
575 nbtx_req_handle_map.erase(it);
578 }
else if(phase == tlm::BEGIN_REQ) {
579 h = nb_trTimedHandle[REQ]->begin_transaction(t);
580 tlm::scc::scv::record(h, trans);
582 nbtx_req_handle_map[id] = h;
583 nbtx_last_req_handle_map[id] = h;
584 }
else if(phase == tlm::END_REQ) {
585 it = nbtx_req_handle_map.find(
id);
586 if(it != nbtx_req_handle_map.end()) {
587 it->second.end_transaction(t);
588 nbtx_req_handle_map.erase(it);
590 }
else if(phase == tlm::BEGIN_RESP) {
591 it = nbtx_req_handle_map.find(
id);
592 if(it != nbtx_req_handle_map.end()) {
593 it->second.end_transaction(t);
594 nbtx_req_handle_map.erase(it);
596 h = nb_trTimedHandle[RESP]->begin_transaction();
597 tlm::scc::scv::record(h, trans);
599 nbtx_resp_handle_map[id] = h;
600 it = nbtx_last_req_handle_map.find(
id);
601 if(it != nbtx_last_req_handle_map.end()) {
602 SCVNS scv_tr_handle pred = it->second;
603 nbtx_last_req_handle_map.erase(it);
606 it = nbtx_last_resp_handle_map.find(
id);
607 if(it != nbtx_last_resp_handle_map.end()) {
608 SCVNS scv_tr_handle pred = it->second;
609 nbtx_last_resp_handle_map.erase(it);
613 }
else if(phase == tlm::END_RESP) {
614 it = nbtx_resp_handle_map.find(
id);
615 if(it != nbtx_resp_handle_map.end()) {
617 nbtx_resp_handle_map.erase(it);
618 h.end_transaction(t);
620 it = nbtx_req_handle_map.find(
id);
621 if(it != nbtx_req_handle_map.end()) {
623 nbtx_req_handle_map.erase(it);
624 h.end_transaction(t);
627 }
else if(phase == chi::BEGIN_DATA || phase == chi::BEGIN_PARTIAL_DATA) {
628 it = nbtx_req_handle_map.find(
id);
629 if(it != nbtx_req_handle_map.end()) {
631 h.end_transaction(t);
632 nbtx_last_req_handle_map[id] = h;
634 h = nb_trTimedHandle[DATA]->begin_transaction();
635 tlm::scc::scv::record(h, trans);
637 nbtx_data_handle_map[id] = h;
638 it = nbtx_last_data_handle_map.find(
id);
639 if(it != nbtx_last_data_handle_map.end()) {
640 SCVNS scv_tr_handle pred = it->second;
641 nbtx_last_data_handle_map.erase(it);
644 }
else if(phase == chi::END_DATA || phase == chi::END_PARTIAL_DATA) {
645 it = nbtx_data_handle_map.find(
id);
646 if(it != nbtx_data_handle_map.end()) {
648 nbtx_data_handle_map.erase(it);
649 h.end_transaction(t);
651 }
else if(phase == chi::ACK) {
652 it = nbtx_ack_handle_map.find(
id);
653 if(it == nbtx_ack_handle_map.end()) {
654 auto h = nb_trTimedHandle[ACK]->begin_transaction(t);
655 nbtx_ack_handle_map[id] = h;
658 it->second.end_transaction(t);
659 nbtx_ack_handle_map.erase(it);
662 sc_assert(!
"phase not supported!");
665template <
typename TYPES>
668 return get_fw_if()->get_direct_mem_ptr(trans, dmi_data);
669 else if(!dmi_streamHandle)
670 initialize_streams();
671 SCVNS scv_tr_handle h = dmi_trGetHandle->begin_transaction();
672 bool status =
get_fw_if()->get_direct_mem_ptr(trans, dmi_data);
673 tlm::scc::scv::record(h, trans);
674 tlm::scc::scv::record(h, dmi_data);
684template <
typename TYPES>
687 get_bw_if()->invalidate_direct_mem_ptr(start_addr, end_addr);
689 }
else if(!dmi_streamHandle)
690 initialize_streams();
691 SCVNS scv_tr_handle h = dmi_trInvalidateHandle->begin_transaction(start_addr);
692 get_bw_if()->invalidate_direct_mem_ptr(start_addr, end_addr);
693 dmi_trInvalidateHandle->end_transaction(h, end_addr);
703 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