42template <
typename TYPES = tilelink::tl_protocol_types>
class tlc_recording_payload :
public TYPES::tlm_payload_type {
44 SCVNS scv_tr_handle parent;
47 tlc_recording_payload& operator=(
const typename TYPES::tlm_payload_type& x) {
49 this->set_command(x.get_command());
50 this->set_address(x.get_address());
51 this->set_data_ptr(
nullptr);
52 this->set_data_length(x.get_data_length());
53 this->set_response_status(x.get_response_status());
54 this->set_byte_enable_ptr(
nullptr);
55 this->set_byte_enable_length(x.get_byte_enable_length());
56 this->set_streaming_width(x.get_streaming_width());
59 explicit tlc_recording_payload(tlm::tlm_mm_interface* mm)
60 : TYPES::tlm_payload_type(mm)
81 template <
unsigned int BUSWIDTH = 32,
int N = 1, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
84 template <
unsigned int BUSWIDTH = 32,
int N = 1, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
111 sc_core::sc_attribute<unsigned> rd_response_timeout{
"rd_response_timeout", 0};
113 sc_core::sc_attribute<unsigned> wr_response_timeout{
"wr_response_timeout", 0};
129 tlc_recorder(
const char* name,
unsigned bus_width,
bool recording_enabled =
true,
130 SCVNS scv_tr_db* tr_db = SCVNS scv_tr_db::get_default_db())
136 , fixed_basename(name) {
137 register_extensions();
141 btx_handle_map.clear();
142 nbtx_req_handle_map.clear();
143 nbtx_last_req_handle_map.clear();
144 nbtx_resp_handle_map.clear();
145 nbtx_last_resp_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;
226 unsigned int transport_dbg(
typename TYPES::tlm_payload_type& trans)
override;
242 tlm_utils::peq_with_cb_and_phase<tlc_recorder, recording_types> b_timed_peq;
244 tlm_utils::peq_with_cb_and_phase<tlc_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, REQ = FW, RESP = BW, ACK };
270 SCVNS scv_tr_stream* nb_streamHandle{
nullptr};
272 SCVNS scv_tr_stream* nb_streamHandleTimed{
nullptr};
274 std::array<SCVNS scv_tr_generator<std::string, std::string>*, 2> nb_trHandle{{
nullptr,
nullptr}};
276 std::array<SCVNS scv_tr_generator<>*, 3> nb_trTimedHandle{{
nullptr,
nullptr,
nullptr}};
277 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_req_handle_map;
278 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_last_req_handle_map;
279 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_resp_handle_map;
280 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_last_resp_handle_map;
282 SCVNS scv_tr_stream* dmi_streamHandle{
nullptr};
284 SCVNS scv_tr_generator<>* dmi_trGetHandle{
nullptr};
285 SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>* dmi_trInvalidateHandle{
nullptr};
288 void initialize_streams() {
290 b_streamHandle =
new SCVNS scv_tr_stream((fixed_basename +
"_bl").c_str(),
"[TLM][ace][b]", m_db);
291 b_trHandle[tlm::TLM_READ_COMMAND] =
292 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
"read", *b_streamHandle,
"start_delay",
"end_delay");
293 b_trHandle[tlm::TLM_WRITE_COMMAND] =
294 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
"write", *b_streamHandle,
"start_delay",
"end_delay");
295 b_trHandle[tlm::TLM_IGNORE_COMMAND] =
296 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
"ignore", *b_streamHandle,
"start_delay",
"end_delay");
298 b_streamHandleTimed =
new SCVNS scv_tr_stream((fixed_basename +
"_bl_timed").c_str(),
"[TLM][ace][b][timed]", m_db);
299 b_trTimedHandle[tlm::TLM_READ_COMMAND] =
new SCVNS scv_tr_generator<>(
"read", *b_streamHandleTimed);
300 b_trTimedHandle[tlm::TLM_WRITE_COMMAND] =
new SCVNS scv_tr_generator<>(
"write", *b_streamHandleTimed);
301 b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] =
new SCVNS scv_tr_generator<>(
"ignore", *b_streamHandleTimed);
305 nb_streamHandle =
new SCVNS scv_tr_stream((fixed_basename +
"_nb").c_str(),
"[TLM][ace][nb]", m_db);
307 new SCVNS scv_tr_generator<std::string, std::string>(
"fw", *nb_streamHandle,
"tlm_phase",
"tlm_phase[return_path]");
309 new SCVNS scv_tr_generator<std::string, std::string>(
"bw", *nb_streamHandle,
"tlm_phase",
"tlm_phase[return_path]");
311 nb_streamHandleTimed =
new SCVNS scv_tr_stream((fixed_basename +
"_nb_timed").c_str(),
"[TLM][ace][nb][timed]", m_db);
312 nb_trTimedHandle[FW] =
new SCVNS scv_tr_generator<>(
"request", *nb_streamHandleTimed);
313 nb_trTimedHandle[BW] =
new SCVNS scv_tr_generator<>(
"response", *nb_streamHandleTimed);
314 nb_trTimedHandle[ACK] =
new SCVNS scv_tr_generator<>(
"ack", *nb_streamHandleTimed);
318 dmi_streamHandle =
new SCVNS scv_tr_stream((fixed_basename +
"_dmi").c_str(),
"[TLM][ace][dmi]", m_db);
319 dmi_trGetHandle =
new SCVNS scv_tr_generator<>(
"get", *dmi_streamHandle);
320 dmi_trInvalidateHandle =
321 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
"invalidate", *dmi_streamHandle,
"start_addr",
"end_addr");
330 const std::string fixed_basename;
397 tlm_recording_payload* req{
nullptr};
403 SCVNS scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_core::sc_time_stamp());
407 if(b_streamHandleTimed) {
412 req->id = h.get_id();
413 b_timed_peq.notify(*req, tlm::BEGIN_REQ, delay);
416 auto addr = trans.get_address();
417 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
419 ext->recordBeginTx(h, trans);
422 trans.get_extension(preExt);
423 if(preExt ==
nullptr) {
426 trans.set_auto_extension(preExt);
428 trans.set_extension(preExt);
432 SCVNS scv_tr_handle preTx(preExt->
txHandle);
435 trans.get_extension(preExt);
446 trans.set_address(addr);
447 tlm::scc::scv::record(h, trans);
448 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
450 ext->recordEndTx(h, trans);
452 b_trHandle[trans.get_command()]->end_transaction(h, delay.value(), sc_core::sc_time_stamp());
454 if(b_streamHandleTimed) {
455 b_timed_peq.notify(*req, tlm::END_RESP, delay);
460 tlm_recording_payload* req{
nullptr};
461 if(!b_streamHandleTimed) {
466 SCVNS scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_core::sc_time_stamp());
470 if(b_streamHandleTimed) {
475 req->id = h.get_id();
476 b_timed_peq.notify(*req, tlm::BEGIN_REQ, delay);
479 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
481 ext->recordBeginTx(h, trans);
484 trans.get_extension(preExt);
488 trans.set_auto_extension(preExt);
490 trans.set_extension(preExt);
494 SCVNS scv_tr_handle preTx(preExt->
txHandle);
497 trans.get_extension(preExt);
508 tlm::scc::scv::record(h, trans);
509 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
511 ext->recordEndTx(h, trans);
513 b_trHandle[trans.get_command()]->end_transaction(h, delay.value(), sc_core::sc_time_stamp());
515 if(b_streamHandleTimed) {
516 b_timed_peq.notify(*req, tlm::END_RESP, delay);
546 sc_core::sc_time& delay) {
548 return get_fw_if()->nb_transport_fw(trans, phase, delay);
554 SCVNS scv_tr_handle h = nb_trHandle[FW]->begin_transaction(phase.get_name());
556 trans.get_extension(preExt);
557 if(phase == tlm::BEGIN_REQ && preExt ==
nullptr) {
560 trans.set_auto_extension(preExt);
562 trans.set_extension(preExt);
563 }
else if(preExt !=
nullptr) {
567 sc_assert(preExt !=
nullptr &&
"ERROR on forward path in phase other than tlm::BEGIN_REQ");
571 h.record_attribute(
"delay", delay.to_string());
572 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
574 ext->recordBeginTx(h, trans);
578 if(nb_streamHandleTimed) {
579 tlm_recording_payload* req =
mm::get().allocate();
583 req->is_snoop = phase == tlm::BEGIN_RESP;
584 nb_timed_peq.notify(*req, phase, delay);
589 tlm::tlm_sync_enum status =
get_fw_if()->nb_transport_fw(trans, phase, delay);
593 tlm::scc::scv::record(h, status);
594 h.record_attribute(
"delay[return_path]", delay.to_string());
595 tlm::scc::scv::record(h, trans);
596 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
598 ext->recordEndTx(h, trans);
600 if(status == tlm::TLM_COMPLETED || (phase == tilelink::ACK)) {
602 trans.get_extension(preExt);
613 if(nb_streamHandleTimed) {
614 tlm_recording_payload* req =
mm::get().allocate();
618 nb_timed_peq.notify(*req, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase, delay);
620 }
else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
621 tlm_recording_payload* req =
mm::get().allocate();
625 nb_timed_peq.notify(*req, phase, delay);
628 nb_trHandle[FW]->end_transaction(h, phase.get_name());
634 sc_core::sc_time& delay) {
636 return get_bw_if()->nb_transport_bw(trans, phase, delay);
642 SCVNS scv_tr_handle h = nb_trHandle[BW]->begin_transaction(phase.get_name());
644 trans.get_extension(preExt);
645 if(phase == tlm::BEGIN_REQ && preExt ==
nullptr) {
648 trans.set_auto_extension(preExt);
650 trans.set_extension(preExt);
651 }
else if(preExt !=
nullptr) {
655 sc_assert(preExt !=
nullptr &&
"ERROR on backward path in phase other than tlm::BEGIN_REQ");
659 h.record_attribute(
"delay", delay.to_string());
660 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
662 ext->recordBeginTx(h, trans);
666 if(nb_streamHandleTimed) {
667 tlm_recording_payload* req =
mm::get().allocate();
671 req->is_snoop = phase == tlm::BEGIN_REQ;
672 nb_timed_peq.notify(*req, phase, delay);
677 tlm::tlm_sync_enum status =
get_bw_if()->nb_transport_bw(trans, phase, delay);
681 tlm::scc::scv::record(h, status);
682 h.record_attribute(
"delay[return_path]", delay.to_string());
683 tlm::scc::scv::record(h, trans);
684 for(
auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
686 ext->recordEndTx(h, trans);
688 if(status == tlm::TLM_COMPLETED || (status == tlm::TLM_UPDATED && phase == tilelink::ACK)) {
690 trans.get_extension(preExt);
701 if(nb_streamHandleTimed) {
702 tlm_recording_payload* req =
mm::get().allocate();
706 nb_timed_peq.notify(*req, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase, delay);
708 }
else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
709 tlm_recording_payload* req =
mm::get().allocate();
713 nb_timed_peq.notify(*req, phase, delay);
716 nb_trHandle[BW]->end_transaction(h, phase.get_name());