scc  2022.4.0
SystemC components library
ace_lwtr.h
1 /*
2  * Copyright 2023 Arteris IP
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #ifndef SC_INCLUDE_DYNAMIC_PROCESSES
20 #define SC_INCLUDE_DYNAMIC_PROCESSES
21 #endif
22 
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>
27 #include <array>
28 #include <axi/axi_tlm.h>
29 #include <regex>
30 #include <string>
31 #include <scc/peq.h>
32 #include <unordered_map>
33 #include <vector>
34 
36 namespace axi {
37 namespace lwtr {
38 
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;
44 using mm = tlm::scc::tlm_mm<>;
45 using namespace tlm::scc::lwtr;
46 
48  bool snoop;
49  nb_ace_rec_entry(tlm::scc::tlm_gp_shared_ptr tr,tlm::tlm_phase const ph, uintptr_t const id, tx_handle parent, bool snoop)
50  : nb_rec_entry{tr, ph, id, parent}
51  , snoop(snoop) {}
52 };
53 extern bool registered;
54 
63 template <typename TYPES = axi::axi_protocol_types>
64 class ace_lwtr : public virtual axi::ace_fw_transport_if<TYPES>, public virtual axi::ace_bw_transport_if<TYPES> {
65 public:
67  cci::cci_param<bool> enableBlTracing;
68 
70  cci::cci_param<bool> enableNbTracing;
71 
73  cci::cci_param<bool> enableTimedTracing{"enableTimedTracing", true};
74 
76  cci::cci_param<bool> enableDmiTracing{"enableDmiTracing", false};
77 
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)
90  , nb_timed_peq()
91  , bus_width(bus_width)
92  , m_db(tr_db)
93  {
94  sc_core::sc_spawn_options opts;
95  opts.spawn_method();
96  opts.dont_initialize();
97  opts.set_sensitivity(&nb_timed_peq.event());
98  sc_core::sc_spawn([this](){
99  nbtx_cb();
100  }, nullptr, &opts);
101  initialize_streams();
102  }
103 
104  virtual ~ace_lwtr() override {
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)
111  delete p; // NOLINT
112  delete b_streamHandleTimed;
113  for(auto* p : b_trTimedHandle)
114  delete p; // NOLINT
115  delete nb_streamHandle;
116  for(auto* p : nb_trHandle)
117  delete p; // NOLINT
118  delete nb_streamHandleTimed;
119  for(auto* p : nb_trTimedHandle)
120  delete p; // NOLINT
121  delete dmi_streamHandle;
122  delete dmi_trGetHandle;
123  delete dmi_trInvalidateHandle;
124  delete checker;
125  }
126 
127  // TLM-2.0 interface methods for initiator and target sockets, surrounded with
128  // Tx Recording
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;
176  bool get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) override;
183  void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override;
190  unsigned int transport_dbg(typename TYPES::tlm_payload_type& trans) override;
196  inline bool isRecordingBlockingTxEnabled() const { return m_db && enableBlTracing.get_value(); }
202  inline bool isRecordingNonBlockingTxEnabled() const { return m_db && enableNbTracing.get_value(); }
203 
204 protected:
206  sc_core::sc_port<axi::ace_fw_transport_if<TYPES>> fw_port{"fw_port"};
207 
209  sc_core::sc_port<axi::ace_bw_transport_if<TYPES>> bw_port{"bw_port"};
210 
211 private:
212  std::string const full_name;
214  ::scc::peq<nb_ace_rec_entry> nb_timed_peq;
219  void nbtx_cb();
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}};
234 
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};
253 
254 protected:
255  void initialize_streams() {
256  if(m_db) {
257  pred_succ_hndl = m_db->create_relation("PREDECESSOR_SUCCESSOR");
258  par_chld_hndl = m_db->create_relation("PARENT_CHILD");
259  }
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);
274  }
275  }
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);
288  }
289  }
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");
295  }
296  }
297 
298 private:
299  axi::checker::checker_if<TYPES>* checker{nullptr};
300 };
301 
302 template <unsigned BUSWIDTH=32, typename TYPES = axi::axi_protocol_types, int N = 1,
303  sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
304 class ace_lwtr_recorder : public sc_core::sc_module, public ace_lwtr<TYPES> {
305 public:
308 
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)
311  , ace_lwtr<TYPES>(name(), BUSWIDTH, recording_enabled, tr_db)
312  {
313  is(*this);
314  ts(*this);
315  this->bw_port(ts.get_base_port());
316  this->fw_port(is.get_base_port());
317  }
318 };
320 // implementations of functions
322 
323 template <typename TYPES>
324 void ace_lwtr<TYPES>::b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) {
325  if(!isRecordingBlockingTxEnabled()) {
326  fw_port->b_transport(trans, delay);
327  return;
328  }
329  // Get a handle for the new transaction
330  tx_handle h = b_trHandle[trans.get_command()]->begin_tx(delay);
331  tx_handle htim;
332  /*************************************************************************
333  * do the timed notification
334  *************************************************************************/
335  if(b_streamHandleTimed)
336  htim = b_trTimedHandle[trans.get_command()]->begin_tx_delayed(sc_core::sc_time_stamp()+delay, par_chld_hndl, h);
337 
338  if(registered)
339  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
340  if(extensionRecording) {
341  extensionRecording->recordBeginTx(h, trans);
342  if(htim.is_valid())
343  extensionRecording->recordBeginTx(htim, trans);
344  }
345  link_pred_ext* preExt = nullptr;
346 
347  trans.get_extension(preExt);
348  if(preExt == nullptr) { // we are the first recording this transaction
349  preExt = new link_pred_ext(h, this);
350  if(trans.has_mm())
351  trans.set_auto_extension(preExt);
352  else
353  trans.set_extension(preExt);
354  } else {
355  h.add_relation(pred_succ_hndl, preExt->txHandle);
356  }
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) {
362  // clean-up the extension if this is the original creator
363  trans.set_extension(static_cast<link_pred_ext*>(nullptr));
364  if(!trans.has_mm()) {
365  delete preExt;
366  }
367  } else {
368  preExt->txHandle = preTx;
369  }
370 
371  h.record_attribute("trans", trans);
372  if(registered)
373  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
374  if(extensionRecording) {
375  extensionRecording->recordEndTx(h, trans);
376  if(htim.is_active())
377  extensionRecording->recordEndTx(htim, trans);
378  }
379  // End the transaction
380  h.end_tx(delay);
381  // and now the stuff for the timed tx
382  if(htim.is_valid()) {
383  htim.record_attribute("trans", trans);
384  htim.end_tx_delayed(sc_core::sc_time_stamp()+delay);
385  }
386 }
387 
388 template <typename TYPES>
389 void ace_lwtr<TYPES>::b_snoop(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) {
390  if(!b_streamHandleTimed) {
391  bw_port->b_snoop(trans, delay);
392  return;
393  }
394  // Get a handle for the new transaction
395  tx_handle h = b_trHandle[trans.get_command()]->begin_tx(delay);
396  tx_handle htim;
397  /*************************************************************************
398  * do the timed notification
399  *************************************************************************/
400  if(b_streamHandleTimed)
401  htim = b_trTimedHandle[trans.get_command()]->begin_tx_delayed(sc_core::sc_time_stamp()+delay, par_chld_hndl, h);
402 
403  if(registered)
404  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
405  if(extensionRecording) {
406  extensionRecording->recordBeginTx(h, trans);
407  if(htim.is_valid())
408  extensionRecording->recordBeginTx(htim, trans);
409  }
410  link_pred_ext* preExt = nullptr;
411 
412  trans.get_extension(preExt);
413  if(preExt == nullptr) { // we are the first recording this transaction
414  preExt = new link_pred_ext(h, this);
415  trans.set_extension(preExt);
416  } else {
417  h.add_relation(pred_succ_hndl, preExt->txHandle);
418  }
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) {
424  // clean-up the extension if this is the original creator
425  trans.set_extension(static_cast<link_pred_ext*>(nullptr));
426  if(!trans.has_mm())
427  delete preExt;
428  } else {
429  preExt->txHandle = preTx;
430  }
431 
432  h.record_attribute("trans", trans);
433  if(registered)
434  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
435  if(extensionRecording) {
436  extensionRecording->recordEndTx(h, trans);
437  if(htim.is_active())
438  extensionRecording->recordEndTx(htim, trans);
439  }
440  // End the transaction
441  h.end_tx(delay);
442  // and now the stuff for the timed tx
443  if(htim.is_valid()) {
444  htim.record_attribute("trans", trans);
445  htim.end_tx_delayed(sc_core::sc_time_stamp()+delay);
446  }
447 }
448 
449 template <typename TYPES>
450 tlm::tlm_sync_enum ace_lwtr<TYPES>::nb_transport_fw(typename TYPES::tlm_payload_type& trans,
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);
455  }
456  /*************************************************************************
457  * prepare recording
458  *************************************************************************/
459  // Get a handle for the new transaction
460  tx_handle h = nb_trHandle[FW]->begin_tx(phase.get_name());
461  link_pred_ext* preExt = nullptr;
462  trans.get_extension(preExt);
463  if((phase == axi::BEGIN_PARTIAL_REQ || phase == tlm::BEGIN_REQ) && preExt == nullptr) { // we are the first recording this transaction
464  preExt = new link_pred_ext(h, this);
465  if(trans.has_mm())
466  trans.set_auto_extension(preExt);
467  else
468  trans.set_extension(preExt);
469  } else if(preExt != nullptr) {
470  // link handle if we have a predecessor
471  h.add_relation(pred_succ_hndl, preExt->txHandle);
472  } else {
473  sc_assert(preExt != nullptr && "ERROR on forward path in phase other than tlm::BEGIN_REQ");
474  }
475  // update the extension
476  preExt->txHandle = h;
477  h.record_attribute("delay", delay);
478  if(registered)
479  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
480  if(extensionRecording)
481  extensionRecording->recordBeginTx(h, trans);
482  /*************************************************************************
483  * do the timed notification
484  *************************************************************************/
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);
489  }
490  /*************************************************************************
491  * do the access
492  *************************************************************************/
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);
496  /*************************************************************************
497  * handle recording
498  *************************************************************************/
499  h.record_attribute("tlm_sync", status);
500  h.record_attribute("delay[return_path]", delay);
501  h.record_attribute("trans", trans);
502  if(registered)
503  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
504  if(extensionRecording)
505  extensionRecording->recordEndTx(h, trans);
506  // get the extension and free the memory if it was mine
507  if(status == tlm::TLM_COMPLETED || (phase == axi::ACK)) {
508  trans.get_extension(preExt);
509  if(preExt && preExt->creator == this) {
510  trans.set_extension(static_cast<link_pred_ext*>(nullptr));
511  if(!trans.has_mm()) {
512  delete preExt;
513  }
514  }
515  /*************************************************************************
516  * do the timed notification if req. finished here
517  *************************************************************************/
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);
522  }
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);
527  }
528  // End the transaction
529  nb_trHandle[FW]->end_tx(h, phase.get_name());
530  return status;
531 }
532 
533 template <typename TYPES>
534 tlm::tlm_sync_enum ace_lwtr<TYPES>::nb_transport_bw(typename TYPES::tlm_payload_type& trans,
535  typename TYPES::tlm_phase_type& phase,
536  sc_core::sc_time& delay) {
537  if(!isRecordingNonBlockingTxEnabled()){
538  if(checker) {
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);
542  return status;
543  } else
544  return bw_port->nb_transport_bw(trans, phase, delay);
545  }
546  /*************************************************************************
547  * prepare recording
548  *************************************************************************/
549  link_pred_ext* preExt = nullptr;
550  trans.get_extension(preExt);
551  // Get a handle for the new transaction
552  tx_handle h = nb_trHandle[BW]->begin_tx(phase.get_name());
553  // link handle if we have a predecessor and that's not ourself
554  if(phase == tlm::BEGIN_REQ && preExt == nullptr) { // we are the first recording this transaction
555  preExt = new link_pred_ext(h, this);
556  trans.set_extension(preExt);
557  preExt->txHandle = h;
558  } else if(preExt) {
559  // link handle if we have a predecessor
560  h.add_relation(pred_succ_hndl, preExt->txHandle);
561  // and set the extension handle to this transaction
562  preExt->txHandle = h;
563  } else {
564  sc_assert(preExt != nullptr && "ERROR on backward path in phase other than tlm::BEGIN_REQ");
565  }
566  // and set the extension handle to this transaction
567  h.record_attribute("delay", delay);
568  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
569  if(extensionRecording)
570  extensionRecording->recordBeginTx(h, trans);
571  /*************************************************************************
572  * do the timed notification
573  *************************************************************************/
574  if(nb_streamHandleTimed) {
575  nb_ace_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h, phase == tlm::BEGIN_REQ};
576  rec.tr->deep_copy_from(trans);
577  nb_timed_peq.notify(rec, delay);
578  }
579  /*************************************************************************
580  * do the access
581  *************************************************************************/
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);
585  /*************************************************************************
586  * handle recording
587  *************************************************************************/
588  h.record_attribute("tlm_sync", status);
589  h.record_attribute("delay[return_path]", delay);
590  h.record_attribute("trans", trans);
591  if(registered)
592  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
593  if(extensionRecording)
594  extensionRecording->recordEndTx(h, trans);
595  // End the transaction
596  nb_trHandle[BW]->end_tx(h, phase.get_name());
597  // get the extension and free the memory if it was mine
598  if(status == tlm::TLM_COMPLETED || (status == tlm::TLM_UPDATED && phase == axi::ACK)) {
599  // the transaction is finished
600  if(preExt && preExt->creator == this) {
601  // clean-up the extension if this is the original creator
602  trans.set_extension(static_cast<link_pred_ext*>(nullptr));
603  if(!trans.has_mm()) {
604  delete preExt;
605  }
606  }
607  /*************************************************************************
608  * do the timed notification if req. finished here
609  *************************************************************************/
610  if(nb_streamHandleTimed) {
611  nb_ace_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h, phase == tlm::BEGIN_REQ};
612  rec.tr->deep_copy_from(trans);
613  nb_timed_peq.notify(rec, delay);
614  }
615  } else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
616  nb_ace_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h, phase == tlm::BEGIN_REQ};
617  rec.tr->deep_copy_from(trans);
618  nb_timed_peq.notify(rec, delay);
619  }
620  return status;
621 }
622 
623 template <typename TYPES>
625  auto opt = nb_timed_peq.get_next();
626  if(opt) {
627  auto& e = opt.get();
628  tx_handle h;
629  // Now process outstanding recordings
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()) {
636  h = it->second;
637  nbtx_req_handle_map.erase(it);
638  h.record_attribute("trans", *e.tr);
639  h.end_tx();
640  nbtx_last_req_handle_map[e.id] = h;
641  }
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()) {
645  h = it->second;
646  nbtx_req_handle_map.erase(it);
647  h.record_attribute("trans", *e.tr);
648  h.end_tx();
649  nbtx_last_req_handle_map[e.id] = h;
650  }
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);
658  } else {
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);
664  }
665  }
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()) {
669  h = it->second;
670  nbtx_resp_handle_map.erase(it);
671  h.record_attribute("trans", *e.tr);
672  h.end_tx();
673  if(e.ph == axi::END_PARTIAL_RESP) {
674  nbtx_last_resp_handle_map[e.id] = h;
675  }
676  }
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);
680  h.end_tx();
681  } else
682  sc_assert(!"phase not supported!");
683  }
684  return;
685 }
686 
687 template <typename TYPES>
688 bool ace_lwtr<TYPES>::get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) {
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);
695  h.end_tx();
696  return status;
697 }
704 template <typename TYPES>
705 void ace_lwtr<TYPES>::invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) {
706  if(!(m_db && enableDmiTracing.get_value())) {
707  bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
708  return;
709  }
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);
713  return;
714 }
721 template <typename TYPES> unsigned int ace_lwtr<TYPES>::transport_dbg(typename TYPES::tlm_payload_type& trans) {
722  return fw_port->transport_dbg(trans);
723 }
724 } // namespace lwtr
725 } // namespace axi
The TLM2 transaction recorder.
Definition: ace_lwtr.h:64
bool isRecordingBlockingTxEnabled() const
get the current state of transaction recording
Definition: ace_lwtr.h:196
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.
Definition: ace_lwtr.h:86
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.
Definition: ace_lwtr.h:450
bool get_direct_mem_ptr(typename TYPES::tlm_payload_type &trans, tlm::tlm_dmi &dmi_data) override
The direct memory interface forward function.
Definition: ace_lwtr.h:688
cci::cci_param< bool > enableBlTracing
the attribute to selectively enable/disable recording of blocking protocol tx
Definition: ace_lwtr.h:67
bool isRecordingNonBlockingTxEnabled() const
get the current state of transaction recording
Definition: ace_lwtr.h:202
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.
Definition: ace_lwtr.h:534
void b_snoop(typename TYPES::tlm_payload_type &trans, sc_core::sc_time &delay) override
The blocking snoop function.
Definition: ace_lwtr.h:389
unsigned int transport_dbg(typename TYPES::tlm_payload_type &trans) override
The debug transportfunction.
Definition: ace_lwtr.h:721
cci::cci_param< bool > enableNbTracing
the attribute to selectively enable/disable recording of non-blocking protocol tx
Definition: ace_lwtr.h:70
void b_transport(typename TYPES::tlm_payload_type &trans, sc_core::sc_time &delay) override
The blocking transport function.
Definition: ace_lwtr.h:324
void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override
The direct memory interface backward function.
Definition: ace_lwtr.h:705
The TLM transaction extensions recorder registry.
a tlm memory manager
Definition: tlm_mm.h:161
payload_type * allocate()
get a plain tlm_payload_type without extensions
Definition: tlm_mm.h:228
static tlm_mm & get()
accessor function of the singleton
Definition: tlm_mm.h:222
TLM2.0 components modeling AHB.
Definition: axi_initiator.h:30
tlm::tlm_fw_transport_if< TYPES > ace_fw_transport_if
alias declaration for the ACE forward interface
Definition: axi_tlm.h:920
SCC SCV4TLM classes and functions.
The AXI protocol traits class. Since the protocoll defines additional non-ignorable phases a dedicate...
Definition: axi_tlm.h:890
Definition: ace_lwtr.h:47
priority event queue
Definition: peq.h:41
void notify(const TYPE &entry, const sc_core::sc_time &t)
non-blocking push.
Definition: peq.h:77
boost::optional< TYPE > get_next()
non-blocking get
Definition: peq.h:111
Definition: tlm2_lwtr.h:65