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 <axi/checker/axi_protocol.h>
26 #include <tlm/scc/tlm_mm.h>
28 #include <axi/axi_tlm.h>
32 #include <unordered_map>
39 using tx_db = ::lwtr::tx_db;
40 using tx_fiber = ::lwtr::tx_fiber;
41 template <
typename BEGIN = ::lwtr::no_data,
typename END = ::lwtr::no_data>
42 using tx_generator = ::lwtr::tx_generator<BEGIN, END>;
43 using tx_handle = ::lwtr::tx_handle;
53 extern bool registered;
63 template <
typename TYPES = axi::axi_protocol_types>
73 cci::cci_param<bool> enableTimedTracing{
"enableTimedTracing",
true};
76 cci::cci_param<bool> enableDmiTracing{
"enableDmiTracing",
false};
86 ace_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 delete b_streamHandle;
110 for(
auto* p : b_trHandle)
112 delete b_streamHandleTimed;
113 for(
auto* p : b_trTimedHandle)
115 delete nb_streamHandle;
116 for(
auto* p : nb_trHandle)
118 delete nb_streamHandleTimed;
119 for(
auto* p : nb_trTimedHandle)
121 delete dmi_streamHandle;
122 delete dmi_trGetHandle;
123 delete dmi_trInvalidateHandle;
138 tlm::tlm_sync_enum
nb_transport_fw(
typename TYPES::tlm_payload_type& trans,
typename TYPES::tlm_phase_type& phase,
139 sc_core::sc_time& delay)
override;
149 tlm::tlm_sync_enum
nb_transport_bw(
typename TYPES::tlm_payload_type& trans,
typename TYPES::tlm_phase_type& phase,
150 sc_core::sc_time& delay)
override;
159 void b_transport(
typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay)
override;
168 void b_snoop(
typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay)
override;
190 unsigned int transport_dbg(
typename TYPES::tlm_payload_type& trans)
override;
206 sc_core::sc_port<axi::ace_fw_transport_if<TYPES>> fw_port{
"fw_port"};
209 sc_core::sc_port<axi::ace_bw_transport_if<TYPES>> bw_port{
"bw_port"};
212 std::string
const full_name;
220 const unsigned bus_width{0};
222 tx_db* m_db{
nullptr};
224 ::lwtr::tx_relation_handle pred_succ_hndl{0}, par_chld_hndl{0};
226 tx_fiber* b_streamHandle{
nullptr};
228 std::array<tx_generator<sc_core::sc_time, sc_core::sc_time>*, 3> b_trHandle{{
nullptr,
nullptr,
nullptr}};
230 tx_fiber* b_streamHandleTimed{
nullptr};
233 std::array<tx_generator<>*, 3> b_trTimedHandle{{
nullptr,
nullptr,
nullptr}};
235 enum DIR { FW, BW, REQ = FW, RESP = BW, ACK };
237 tx_fiber* nb_streamHandle{
nullptr};
239 tx_fiber* nb_streamHandleTimed{
nullptr};
241 std::array<tx_generator<std::string, std::string>*, 3> nb_trHandle{{
nullptr,
nullptr,
nullptr}};
243 std::array<tx_generator<>*, 3> nb_trTimedHandle{{
nullptr,
nullptr,
nullptr}};
244 std::unordered_map<uint64_t, tx_handle> nbtx_req_handle_map;
245 std::unordered_map<uint64_t, tx_handle> nbtx_last_req_handle_map;
246 std::unordered_map<uint64_t, tx_handle> nbtx_resp_handle_map;
247 std::unordered_map<uint64_t, tx_handle> nbtx_last_resp_handle_map;
249 tx_fiber* dmi_streamHandle{
nullptr};
251 tx_generator<>* dmi_trGetHandle{
nullptr};
252 tx_generator<sc_dt::uint64, sc_dt::uint64>* dmi_trInvalidateHandle{
nullptr};
255 void initialize_streams() {
257 pred_succ_hndl = m_db->create_relation(
"PREDECESSOR_SUCCESSOR");
258 par_chld_hndl = m_db->create_relation(
"PARENT_CHILD");
260 if(isRecordingBlockingTxEnabled() && !b_streamHandle) {
261 b_streamHandle =
new tx_fiber((full_name +
"_bl").c_str(),
"[TLM][ace][b]", m_db);
262 b_trHandle[tlm::TLM_READ_COMMAND] =
new tx_generator<sc_core::sc_time, sc_core::sc_time>(
263 "read", *b_streamHandle,
"start_delay",
"end_delay");
264 b_trHandle[tlm::TLM_WRITE_COMMAND] =
new tx_generator<sc_core::sc_time, sc_core::sc_time>(
265 "write", *b_streamHandle,
"start_delay",
"end_delay");
266 b_trHandle[tlm::TLM_IGNORE_COMMAND] =
new tx_generator<sc_core::sc_time, sc_core::sc_time>(
267 "ignore", *b_streamHandle,
"start_delay",
"end_delay");
268 if(enableTimedTracing.get_value()) {
269 b_streamHandleTimed =
270 new tx_fiber((full_name +
"_bl_timed").c_str(),
"[TLM][ace][b][timed]", m_db);
271 b_trTimedHandle[tlm::TLM_READ_COMMAND] =
new tx_generator<>(
"read", *b_streamHandleTimed);
272 b_trTimedHandle[tlm::TLM_WRITE_COMMAND] =
new tx_generator<>(
"write", *b_streamHandleTimed);
273 b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] =
new tx_generator<>(
"ignore", *b_streamHandleTimed);
276 if(isRecordingNonBlockingTxEnabled() && !nb_streamHandle) {
277 nb_streamHandle =
new tx_fiber((full_name +
"_nb").c_str(),
"[TLM][ace][nb]", m_db);
278 nb_trHandle[FW] =
new tx_generator<std::string, std::string>(
"fw", *nb_streamHandle,
"tlm_phase",
279 "tlm_phase[return_path]");
280 nb_trHandle[BW] =
new tx_generator<std::string, std::string>(
"bw", *nb_streamHandle,
"tlm_phase",
281 "tlm_phase[return_path]");
282 if(enableTimedTracing.get_value()) {
283 nb_streamHandleTimed =
284 new tx_fiber((full_name +
"_nb_timed").c_str(),
"[TLM][ace][nb][timed]", m_db);
285 nb_trTimedHandle[FW] =
new tx_generator<>(
"request", *nb_streamHandleTimed);
286 nb_trTimedHandle[BW] =
new tx_generator<>(
"response", *nb_streamHandleTimed);
287 nb_trTimedHandle[ACK] =
new tx_generator<>(
"ack", *nb_streamHandleTimed);
290 if(m_db && enableDmiTracing.get_value() && !dmi_streamHandle) {
291 dmi_streamHandle =
new tx_fiber((full_name +
"_dmi").c_str(),
"[TLM][ace][dmi]", m_db);
292 dmi_trGetHandle =
new tx_generator<>(
"get", *dmi_streamHandle);
293 dmi_trInvalidateHandle =
new tx_generator<sc_dt::uint64, sc_dt::uint64>(
294 "invalidate", *dmi_streamHandle,
"start_addr",
"end_addr");
303 sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
309 ace_lwtr_recorder(sc_core::sc_module_name nm,
bool recording_enabled =
true, tx_db* tr_db = tx_db::get_default_db())
310 : sc_core::sc_module(nm)
315 this->bw_port(ts.get_base_port());
316 this->fw_port(is.get_base_port());
323 template <
typename TYPES>
325 if(!isRecordingBlockingTxEnabled()) {
326 fw_port->b_transport(trans, delay);
330 tx_handle h = b_trHandle[trans.get_command()]->begin_tx(delay);
335 if(b_streamHandleTimed)
336 htim = b_trTimedHandle[trans.get_command()]->begin_tx_delayed(sc_core::sc_time_stamp()+delay, par_chld_hndl, h);
340 if(extensionRecording) {
341 extensionRecording->recordBeginTx(h, trans);
343 extensionRecording->recordBeginTx(htim, trans);
347 trans.get_extension(preExt);
348 if(preExt ==
nullptr) {
351 trans.set_auto_extension(preExt);
353 trans.set_extension(preExt);
355 h.add_relation(pred_succ_hndl, preExt->txHandle);
357 tx_handle preTx(preExt->txHandle);
358 preExt->txHandle = h;
359 fw_port->b_transport(trans, delay);
360 trans.get_extension(preExt);
361 if(preExt->creator ==
this) {
364 if(!trans.has_mm()) {
368 preExt->txHandle = preTx;
371 h.record_attribute(
"trans", trans);
374 if(extensionRecording) {
375 extensionRecording->recordEndTx(h, trans);
377 extensionRecording->recordEndTx(htim, trans);
382 if(htim.is_valid()) {
383 htim.record_attribute(
"trans", trans);
384 htim.end_tx_delayed(sc_core::sc_time_stamp()+delay);
388 template <
typename TYPES>
390 if(!b_streamHandleTimed) {
391 bw_port->b_snoop(trans, delay);
395 tx_handle h = b_trHandle[trans.get_command()]->begin_tx(delay);
400 if(b_streamHandleTimed)
401 htim = b_trTimedHandle[trans.get_command()]->begin_tx_delayed(sc_core::sc_time_stamp()+delay, par_chld_hndl, h);
405 if(extensionRecording) {
406 extensionRecording->recordBeginTx(h, trans);
408 extensionRecording->recordBeginTx(htim, trans);
412 trans.get_extension(preExt);
413 if(preExt ==
nullptr) {
415 trans.set_extension(preExt);
417 h.add_relation(pred_succ_hndl, preExt->txHandle);
419 tx_handle preTx(preExt->txHandle);
420 preExt->txHandle = h;
421 bw_port->b_snoop(trans, delay);
422 trans.get_extension(preExt);
423 if(preExt->creator ==
this) {
429 preExt->txHandle = preTx;
432 h.record_attribute(
"trans", trans);
435 if(extensionRecording) {
436 extensionRecording->recordEndTx(h, trans);
438 extensionRecording->recordEndTx(htim, trans);
443 if(htim.is_valid()) {
444 htim.record_attribute(
"trans", trans);
445 htim.end_tx_delayed(sc_core::sc_time_stamp()+delay);
449 template <
typename TYPES>
451 typename TYPES::tlm_phase_type& phase,
452 sc_core::sc_time& delay) {
453 if(!isRecordingNonBlockingTxEnabled()){
454 return fw_port->nb_transport_fw(trans, phase, delay);
460 tx_handle h = nb_trHandle[FW]->begin_tx(phase.get_name());
462 trans.get_extension(preExt);
463 if((phase == axi::BEGIN_PARTIAL_REQ || phase == tlm::BEGIN_REQ) && preExt ==
nullptr) {
466 trans.set_auto_extension(preExt);
468 trans.set_extension(preExt);
469 }
else if(preExt !=
nullptr) {
471 h.add_relation(pred_succ_hndl, preExt->txHandle);
473 sc_assert(preExt !=
nullptr &&
"ERROR on forward path in phase other than tlm::BEGIN_REQ");
476 preExt->txHandle = h;
477 h.record_attribute(
"delay", delay);
480 if(extensionRecording)
481 extensionRecording->recordBeginTx(h, trans);
485 if(nb_streamHandleTimed) {
486 nb_ace_rec_entry rec(
mm::get().allocate(), phase,
reinterpret_cast<uint64_t
>(&trans), h, (phase == tlm::BEGIN_RESP || phase == axi::BEGIN_PARTIAL_RESP));
487 rec.tr->deep_copy_from(trans);
488 nb_timed_peq.
notify(rec, delay);
493 if(checker) checker->fw_pre(trans, phase);
494 tlm::tlm_sync_enum status = fw_port->nb_transport_fw(trans, phase, delay);
495 if(checker) checker->fw_post(trans, phase, status);
499 h.record_attribute(
"tlm_sync", status);
500 h.record_attribute(
"delay[return_path]", delay);
501 h.record_attribute(
"trans", trans);
504 if(extensionRecording)
505 extensionRecording->recordEndTx(h, trans);
507 if(status == tlm::TLM_COMPLETED || (phase == axi::ACK)) {
508 trans.get_extension(preExt);
509 if(preExt && preExt->creator ==
this) {
511 if(!trans.has_mm()) {
518 if(nb_streamHandleTimed) {
519 nb_ace_rec_entry rec {
mm::get().
allocate(), phase,
reinterpret_cast<uint64_t
>(&trans), h, (phase == tlm::BEGIN_RESP || phase == axi::BEGIN_PARTIAL_RESP)};
520 rec.tr->deep_copy_from(trans);
521 nb_timed_peq.
notify(rec, delay);
523 }
else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
524 nb_ace_rec_entry rec {
mm::get().
allocate(), phase,
reinterpret_cast<uint64_t
>(&trans), h, (phase == tlm::BEGIN_RESP || phase == axi::BEGIN_PARTIAL_RESP)};
525 rec.tr->deep_copy_from(trans);
526 nb_timed_peq.
notify(rec, delay);
529 nb_trHandle[FW]->end_tx(h, phase.get_name());
533 template <
typename TYPES>
535 typename TYPES::tlm_phase_type& phase,
536 sc_core::sc_time& delay) {
537 if(!isRecordingNonBlockingTxEnabled()){
539 checker->bw_pre(trans, phase);
540 tlm::tlm_sync_enum status = bw_port->nb_transport_bw(trans, phase, delay);
541 checker->bw_post(trans, phase, status);
544 return bw_port->nb_transport_bw(trans, phase, delay);
550 trans.get_extension(preExt);
552 tx_handle h = nb_trHandle[BW]->begin_tx(phase.get_name());
554 if(phase == tlm::BEGIN_REQ && preExt ==
nullptr) {
556 trans.set_extension(preExt);
557 preExt->txHandle = h;
560 h.add_relation(pred_succ_hndl, preExt->txHandle);
562 preExt->txHandle = h;
564 sc_assert(preExt !=
nullptr &&
"ERROR on backward path in phase other than tlm::BEGIN_REQ");
567 h.record_attribute(
"delay", delay);
569 if(extensionRecording)
570 extensionRecording->recordBeginTx(h, trans);
574 if(nb_streamHandleTimed) {
576 rec.tr->deep_copy_from(trans);
577 nb_timed_peq.
notify(rec, delay);
582 if(checker) checker->bw_pre(trans, phase);
583 tlm::tlm_sync_enum status = bw_port->nb_transport_bw(trans, phase, delay);
584 if(checker) checker->bw_post(trans, phase, status);
588 h.record_attribute(
"tlm_sync", status);
589 h.record_attribute(
"delay[return_path]", delay);
590 h.record_attribute(
"trans", trans);
593 if(extensionRecording)
594 extensionRecording->recordEndTx(h, trans);
596 nb_trHandle[BW]->end_tx(h, phase.get_name());
598 if(status == tlm::TLM_COMPLETED || (status == tlm::TLM_UPDATED && phase == axi::ACK)) {
600 if(preExt && preExt->creator ==
this) {
603 if(!trans.has_mm()) {
610 if(nb_streamHandleTimed) {
612 rec.tr->deep_copy_from(trans);
613 nb_timed_peq.
notify(rec, delay);
615 }
else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
617 rec.tr->deep_copy_from(trans);
618 nb_timed_peq.
notify(rec, delay);
623 template <
typename TYPES>
630 if(e.ph == tlm::BEGIN_REQ || e.ph == axi::BEGIN_PARTIAL_REQ) {
631 h = nb_trTimedHandle[REQ]->begin_tx(par_chld_hndl, e.parent);
632 nbtx_req_handle_map[e.id] = h;
633 }
else if(e.ph == tlm::END_REQ || e.ph == axi::END_PARTIAL_REQ) {
634 auto it = nbtx_req_handle_map.find(e.id);
635 if(it != nbtx_req_handle_map.end()) {
637 nbtx_req_handle_map.erase(it);
638 h.record_attribute(
"trans", *e.tr);
640 nbtx_last_req_handle_map[e.id] = h;
642 }
else if(e.ph == tlm::BEGIN_RESP || e.ph == axi::BEGIN_PARTIAL_RESP) {
643 auto it = nbtx_req_handle_map.find(e.id);
644 if(it != nbtx_req_handle_map.end()) {
646 nbtx_req_handle_map.erase(it);
647 h.record_attribute(
"trans", *e.tr);
649 nbtx_last_req_handle_map[e.id] = h;
651 h = nb_trTimedHandle[RESP]->begin_tx(par_chld_hndl, e.parent);
652 nbtx_resp_handle_map[e.id] = h;
653 it = nbtx_last_req_handle_map.find(e.id);
654 if(it != nbtx_last_req_handle_map.end()) {
655 tx_handle& pred = it->second;
656 h.add_relation(pred_succ_hndl, pred);
657 nbtx_last_req_handle_map.erase(it);
659 it = nbtx_last_resp_handle_map.find(e.id);
660 if(it != nbtx_last_resp_handle_map.end()) {
661 tx_handle& pred = it->second;
662 h.add_relation(pred_succ_hndl, pred);
663 nbtx_last_resp_handle_map.erase(it);
666 }
else if(e.ph == tlm::END_RESP || e.ph == axi::END_PARTIAL_RESP) {
667 auto it = nbtx_resp_handle_map.find(e.id);
668 if(it != nbtx_resp_handle_map.end()) {
670 nbtx_resp_handle_map.erase(it);
671 h.record_attribute(
"trans", *e.tr);
673 if(e.ph == axi::END_PARTIAL_RESP) {
674 nbtx_last_resp_handle_map[e.id] = h;
677 }
else if(e.ph == axi::ACK) {
678 h = nb_trTimedHandle[ACK]->begin_tx(par_chld_hndl, e.parent);
679 h.record_attribute(
"trans", *e.tr);
682 sc_assert(!
"phase not supported!");
687 template <
typename TYPES>
689 if(!(m_db && enableDmiTracing.get_value()))
690 return fw_port->get_direct_mem_ptr(trans, dmi_data);
691 tx_handle h = dmi_trGetHandle->begin_tx();
692 bool status = fw_port->get_direct_mem_ptr(trans, dmi_data);
693 h.record_attribute(
"trans", trans);
694 h.record_attribute(
"dmi_data", dmi_data);
704 template <
typename TYPES>
706 if(!(m_db && enableDmiTracing.get_value())) {
707 bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
710 tx_handle h = dmi_trInvalidateHandle->begin_tx(start_addr);
711 bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
712 dmi_trInvalidateHandle->end_tx(h, end_addr);
722 return fw_port->transport_dbg(trans);
The TLM2 transaction recorder.
bool isRecordingBlockingTxEnabled() const
get the current state of transaction recording
ace_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.
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.
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 > enableBlTracing
the attribute to selectively enable/disable recording of blocking protocol tx
bool isRecordingNonBlockingTxEnabled() const
get the current state of transaction recording
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.
void b_snoop(typename TYPES::tlm_payload_type &trans, sc_core::sc_time &delay) override
The blocking snoop function.
unsigned int transport_dbg(typename TYPES::tlm_payload_type &trans) override
The debug transportfunction.
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.
The TLM transaction extensions recorder registry.
payload_type * allocate()
get a plain tlm_payload_type without extensions
static tlm_mm & get()
accessor function of the singleton
TLM2.0 components modeling AHB.
tlm::tlm_fw_transport_if< TYPES > ace_fw_transport_if
alias declaration for the ACE 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