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
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
static tlm_mm & get()
accessor function of the singleton