scc  2024.06
SystemC components library
axi_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 #include <tlm/scc/lwtr/tlm2_lwtr.h>
20 #include <cci_configuration>
21 #include <axi/checker/axi_protocol.h>
22 #include <tlm/scc/tlm_mm.h>
23 #include <array>
24 #include <axi/axi_tlm.h>
25 #include <regex>
26 #include <string>
27 #include <scc/peq.h>
28 #include <unordered_map>
29 #include <vector>
30 
32 namespace axi {
33 namespace lwtr {
34 
35 using tx_db = ::lwtr::tx_db;
36 using tx_fiber = ::lwtr::tx_fiber;
37 template <typename BEGIN = ::lwtr::no_data, typename END = ::lwtr::no_data>
38 using tx_generator = ::lwtr::tx_generator<BEGIN, END>;
39 using tx_handle = ::lwtr::tx_handle;
40 using mm = tlm::scc::tlm_mm<>;
41 using namespace tlm::scc::lwtr;
42 
43 extern bool registered;
44 
53 template <typename TYPES = axi::axi_protocol_types>
54 class axi_lwtr : public virtual axi::axi_fw_transport_if<TYPES>, public virtual axi::axi_bw_transport_if<TYPES> {
55 public:
57  cci::cci_param<bool> enableBlTracing;
58 
60  cci::cci_param<bool> enableNbTracing;
61 
63  cci::cci_param<bool> enableTimedTracing{"enableTimedTracing", true};
64 
66  cci::cci_param<bool> enableDmiTracing{"enableDmiTracing", false};
67 
69  cci::cci_param<bool> enableProtocolChecker{"enableProtocolChecker", false};
70 
71  cci::cci_param<unsigned> rd_response_timeout{"rd_response_timeout", 0};
72 
73  cci::cci_param<unsigned> wr_response_timeout{"wr_response_timeout", 0};
74 
83  axi_lwtr(char const* full_name, unsigned bus_width, bool recording_enabled = true, tx_db* tr_db = tx_db::get_default_db())
84  : enableBlTracing("enableBlTracing", recording_enabled)
85  , enableNbTracing("enableNbTracing", recording_enabled)
86  , full_name(full_name)
87  , nb_timed_peq()
88  , bus_width(bus_width)
89  , m_db(tr_db)
90  {
91  sc_core::sc_spawn_options opts;
92  opts.spawn_method();
93  opts.dont_initialize();
94  opts.set_sensitivity(&nb_timed_peq.event());
95  sc_core::sc_spawn([this](){nbtx_cb();}, nullptr, &opts);
96  initialize_streams();
97  }
98 
99  virtual ~axi_lwtr() override {
100  nbtx_req_handle_map.clear();
101  nbtx_last_req_handle_map.clear();
102  nbtx_resp_handle_map.clear();
103  nbtx_last_resp_handle_map.clear();
104  delete checker;
105  delete dmi_trInvalidateHandle;
106  delete dmi_trGetHandle;
107  delete dmi_streamHandle;
108  for(auto* p : nb_trTimedHandle) delete p; // NOLINT
109  delete nb_streamHandleTimed;
110  for(auto* p : nb_trHandle) delete p; // NOLINT
111  delete nb_streamHandle;
112  for(auto* p : b_trTimedHandle) delete p; // NOLINT
113  delete b_streamHandleTimed;
114  for(auto* p : b_trHandle) delete p; // NOLINT
115  delete b_streamHandle;
116  }
117 
118  // TLM-2.0 interface methods for initiator and target sockets, surrounded with
119  // Tx Recording
129  tlm::tlm_sync_enum nb_transport_fw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
130  sc_core::sc_time& delay) override;
140  tlm::tlm_sync_enum nb_transport_bw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
141  sc_core::sc_time& delay) override;
150  void b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) override;
158  bool get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) override;
165  void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override;
172  unsigned int transport_dbg(typename TYPES::tlm_payload_type& trans) override;
178  inline bool isRecordingBlockingTxEnabled() const { return m_db && enableBlTracing.get_value(); }
184  inline bool isRecordingNonBlockingTxEnabled() const { return m_db && enableNbTracing.get_value(); }
185 
186 protected:
188  sc_core::sc_port<axi::axi_fw_transport_if<TYPES>> fw_port{"fw_port"};
189 
191  sc_core::sc_port<axi::axi_bw_transport_if<TYPES>> bw_port{"bw_port"};
192 
193 private:
194  std::string const full_name;
196  ::scc::peq<nb_rec_entry> nb_timed_peq;
201  void nbtx_cb();
202  const unsigned bus_width{0};
204  tx_db* m_db{nullptr};
206  ::lwtr::tx_relation_handle pred_succ_hndl{0}, par_chld_hndl{0};
208  tx_fiber* b_streamHandle{nullptr};
210  std::array<tx_generator<sc_core::sc_time, sc_core::sc_time>*, 3> b_trHandle{{nullptr, nullptr, nullptr}};
212  tx_fiber* b_streamHandleTimed{nullptr};
215  std::array<tx_generator<>*, 3> b_trTimedHandle{{nullptr, nullptr, nullptr}};
216 
217  enum DIR { FW, BW, REQ = FW, RESP = BW };
219  tx_fiber* nb_streamHandle{nullptr};
221  tx_fiber* nb_streamHandleTimed{nullptr};
223  std::array<tx_generator<std::string, std::string>*, 2> nb_trHandle{{nullptr, nullptr}};
225  std::array<tx_generator<>*, 2> nb_trTimedHandle{{nullptr, nullptr}};
226  std::unordered_map<uint64_t, tx_handle> nbtx_req_handle_map;
227  std::unordered_map<uint64_t, tx_handle> nbtx_last_req_handle_map;
228  std::unordered_map<uint64_t, tx_handle> nbtx_resp_handle_map;
229  std::unordered_map<uint64_t, tx_handle> nbtx_last_resp_handle_map;
231  tx_fiber* dmi_streamHandle{nullptr};
233  tx_generator<>* dmi_trGetHandle{nullptr};
234  tx_generator<sc_dt::uint64, sc_dt::uint64>* dmi_trInvalidateHandle{nullptr};
235 
236 protected:
237  void initialize_streams() {
238  if(m_db) {
239  pred_succ_hndl = m_db->create_relation("PREDECESSOR_SUCCESSOR");
240  par_chld_hndl = m_db->create_relation("PARENT_CHILD");
241  }
242  if(isRecordingBlockingTxEnabled() && !b_streamHandle) {
243  b_streamHandle = new tx_fiber((full_name + "_bl").c_str(), "[TLM][axi][b]", m_db);
244  b_trHandle[tlm::TLM_READ_COMMAND] = new tx_generator<sc_core::sc_time, sc_core::sc_time>(
245  "read", *b_streamHandle, "start_delay", "end_delay");
246  b_trHandle[tlm::TLM_WRITE_COMMAND] = new tx_generator<sc_core::sc_time, sc_core::sc_time>(
247  "write", *b_streamHandle, "start_delay", "end_delay");
248  b_trHandle[tlm::TLM_IGNORE_COMMAND] = new tx_generator<sc_core::sc_time, sc_core::sc_time>(
249  "ignore", *b_streamHandle, "start_delay", "end_delay");
250  if(enableTimedTracing.get_value()) {
251  b_streamHandleTimed =
252  new tx_fiber((full_name + "_bl_timed").c_str(), "[TLM][axi][b][timed]", m_db);
253  b_trTimedHandle[tlm::TLM_READ_COMMAND] = new tx_generator<>("read", *b_streamHandleTimed);
254  b_trTimedHandle[tlm::TLM_WRITE_COMMAND] = new tx_generator<>("write", *b_streamHandleTimed);
255  b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] = new tx_generator<>("ignore", *b_streamHandleTimed);
256  }
257  }
258  if(isRecordingNonBlockingTxEnabled() && !nb_streamHandle) {
259  nb_streamHandle = new tx_fiber((full_name + "_nb").c_str(), "[TLM][axi][nb]", m_db);
260  nb_trHandle[FW] = new tx_generator<std::string, std::string>("fw", *nb_streamHandle, "tlm_phase",
261  "tlm_phase[return_path]");
262  nb_trHandle[BW] = new tx_generator<std::string, std::string>("bw", *nb_streamHandle, "tlm_phase",
263  "tlm_phase[return_path]");
264  if(enableTimedTracing.get_value()) {
265  nb_streamHandleTimed =
266  new tx_fiber((full_name + "_nb_timed").c_str(), "[TLM][axi][nb][timed]", m_db);
267  nb_trTimedHandle[FW] = new tx_generator<>("request", *nb_streamHandleTimed);
268  nb_trTimedHandle[BW] = new tx_generator<>("response", *nb_streamHandleTimed);
269  }
270  }
271  if(m_db && enableDmiTracing.get_value() && !dmi_streamHandle) {
272  dmi_streamHandle = new tx_fiber((full_name + "_dmi").c_str(), "[TLM][axi][dmi]", m_db);
273  dmi_trGetHandle = new tx_generator<>("get", *dmi_streamHandle);
274  dmi_trInvalidateHandle = new tx_generator<sc_dt::uint64, sc_dt::uint64>(
275  "invalidate", *dmi_streamHandle, "start_addr", "end_addr");
276  }
277  if(enableProtocolChecker.get_value()) {
278  checker=new axi::checker::axi_protocol(full_name, bus_width/8, rd_response_timeout.get_value(), wr_response_timeout.get_value());
279  }
280  }
281 
282 private:
283  axi::checker::checker_if<TYPES>* checker{nullptr};
284 };
285 
286 template <unsigned BUSWIDTH=32, typename TYPES = axi::axi_protocol_types, int N = 1,
287  sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
288 class axi_lwtr_recorder : public sc_core::sc_module, public axi_lwtr<TYPES> {
289 public:
292 
293  axi_lwtr_recorder(sc_core::sc_module_name nm, bool recording_enabled = true, tx_db* tr_db = tx_db::get_default_db())
294  : sc_core::sc_module(nm)
295  , axi_lwtr<TYPES>(name(), BUSWIDTH, recording_enabled, tr_db)
296  {
297  is(*this);
298  ts(*this);
299  this->bw_port(ts.get_base_port());
300  this->fw_port(is.get_base_port());
301  }
302 };
304 // implementations of functions
306 
307 template <typename TYPES>
308 void axi_lwtr<TYPES>::b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) {
309  if(!isRecordingBlockingTxEnabled()) {
310  fw_port->b_transport(trans, delay);
311  return;
312  }
313  // Get a handle for the new transaction
314  tx_handle h = b_trHandle[trans.get_command()]->begin_tx(delay);
315  tx_handle htim;
316  /*************************************************************************
317  * do the timed notification
318  *************************************************************************/
319  if(b_streamHandleTimed)
320  htim = b_trTimedHandle[trans.get_command()]->begin_tx_delayed(sc_core::sc_time_stamp()+delay, par_chld_hndl, h);
321 
322  if(registered)
323  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
324  if(extensionRecording) {
325  extensionRecording->recordBeginTx(h, trans);
326  if(htim.is_valid())
327  extensionRecording->recordBeginTx(htim, trans);
328  }
329  link_pred_ext* preExt = nullptr;
330 
331  trans.get_extension(preExt);
332  if(preExt == nullptr) { // we are the first recording this transaction
333  preExt = new link_pred_ext(h, this);
334  if(trans.has_mm())
335  trans.set_auto_extension(preExt);
336  else
337  trans.set_extension(preExt);
338  } else {
339  h.add_relation(pred_succ_hndl, preExt->txHandle);
340  }
341  tx_handle preTx{preExt->txHandle};
342  preExt->txHandle = h;
343  fw_port->b_transport(trans, delay);
344  trans.get_extension(preExt);
345  if(preExt->creator == this) {
346  // clean-up the extension if this is the original creator
347  trans.set_extension(static_cast<link_pred_ext*>(nullptr));
348  if(!trans.has_mm()) {
349  delete preExt;
350  }
351  } else {
352  preExt->txHandle = preTx;
353  }
354 
355  h.record_attribute("trans", trans);
356  if(registered)
357  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
358  if(extensionRecording) {
359  extensionRecording->recordEndTx(h, trans);
360  if(htim.is_active())
361  extensionRecording->recordEndTx(htim, trans);
362  }
363  // End the transaction
364  h.end_tx(delay);
365  // and now the stuff for the timed tx
366  if(htim.is_valid()) {
367  htim.record_attribute("trans", trans);
368  htim.end_tx_delayed(sc_core::sc_time_stamp()+delay);
369  }
370 }
371 
372 template <typename TYPES>
373 tlm::tlm_sync_enum axi_lwtr<TYPES>::nb_transport_fw(typename TYPES::tlm_payload_type& trans,
374  typename TYPES::tlm_phase_type& phase,
375  sc_core::sc_time& delay) {
376  if(!isRecordingNonBlockingTxEnabled()){
377  if(checker){
378  checker->fw_pre(trans, phase);
379  tlm::tlm_sync_enum status = fw_port->nb_transport_fw(trans, phase, delay);
380  checker->fw_post(trans, phase, status);
381  return status;
382  } else
383  return fw_port->nb_transport_fw(trans, phase, delay);
384  }
385  /*************************************************************************
386  * prepare recording
387  *************************************************************************/
388  // Get a handle for the new transaction
389  tx_handle h = nb_trHandle[FW]->begin_tx(phase.get_name());
390  link_pred_ext* preExt = nullptr;
391  trans.get_extension(preExt);
392  if((phase == axi::BEGIN_PARTIAL_REQ || phase == tlm::BEGIN_REQ) && preExt == nullptr) { // we are the first recording this transaction
393  preExt = new link_pred_ext(h, this);
394  if(trans.has_mm())
395  trans.set_auto_extension(preExt);
396  else
397  trans.set_extension(preExt);
398  } else if(preExt != nullptr) {
399  // link handle if we have a predecessor
400  h.add_relation(pred_succ_hndl, preExt->txHandle);
401  } else {
402  sc_assert(preExt != nullptr && "ERROR on forward path in phase other than tlm::BEGIN_REQ");
403  }
404  // update the extension
405  preExt->txHandle = h;
406  h.record_attribute("delay", delay);
407  if(registered)
408  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
409  if(extensionRecording)
410  extensionRecording->recordBeginTx(h, trans);
411  /*************************************************************************
412  * do the timed notification
413  *************************************************************************/
414  if(nb_streamHandleTimed) {
415  nb_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h};
416  rec.tr->deep_copy_from(trans);
417  nb_timed_peq.notify(rec, delay);
418  }
419  /*************************************************************************
420  * do the access
421  *************************************************************************/
422  if(checker) checker->fw_pre(trans, phase);
423  tlm::tlm_sync_enum status = fw_port->nb_transport_fw(trans, phase, delay);
424  if(checker) checker->fw_post(trans, phase, status);
425  /*************************************************************************
426  * handle recording
427  *************************************************************************/
428  h.record_attribute("tlm_sync", status);
429  h.record_attribute("delay[return_path]", delay);
430  h.record_attribute("trans", trans);
431  if(registered)
432  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
433  if(extensionRecording)
434  extensionRecording->recordEndTx(h, trans);
435  // get the extension and free the memory if it was mine
436  if(status == tlm::TLM_COMPLETED || (status == tlm::TLM_ACCEPTED && phase == tlm::END_RESP)) {
437  trans.get_extension(preExt);
438  if(preExt && preExt->creator == this) {
439  trans.set_extension(static_cast<link_pred_ext*>(nullptr));
440  if(!trans.has_mm()) {
441  delete preExt;
442  }
443  }
444  /*************************************************************************
445  * do the timed notification if req. finished here
446  *************************************************************************/
447  if(nb_streamHandleTimed) {
448  nb_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h};
449  rec.tr->deep_copy_from(trans);
450  nb_timed_peq.notify(rec, delay);
451  }
452  } else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
453  nb_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h};
454  rec.tr->deep_copy_from(trans);
455  nb_timed_peq.notify(rec, delay);
456  }
457  // End the transaction
458  nb_trHandle[FW]->end_tx(h, phase.get_name());
459  return status;
460 }
461 
462 template <typename TYPES>
463 tlm::tlm_sync_enum axi_lwtr<TYPES>::nb_transport_bw(typename TYPES::tlm_payload_type& trans,
464  typename TYPES::tlm_phase_type& phase,
465  sc_core::sc_time& delay) {
466  if(!isRecordingNonBlockingTxEnabled()){
467  if(checker) {
468  checker->bw_pre(trans, phase);
469  tlm::tlm_sync_enum status = bw_port->nb_transport_bw(trans, phase, delay);
470  checker->bw_post(trans, phase, status);
471  return status;
472  } else
473  return bw_port->nb_transport_bw(trans, phase, delay);
474  }
475  /*************************************************************************
476  * prepare recording
477  *************************************************************************/
478  link_pred_ext* preExt = nullptr;
479  trans.get_extension(preExt);
480  // Get a handle for the new transaction
481  tx_handle h = nb_trHandle[BW]->begin_tx(phase.get_name());
482  // link handle if we have a predecessor and that's not ourself
483  if(phase == tlm::BEGIN_REQ && preExt == nullptr) { // we are the first recording this transaction
484  preExt = new link_pred_ext(h, this);
485  trans.set_extension(preExt);
486  preExt->txHandle = h;
487  } else if(preExt) {
488  // link handle if we have a predecessor
489  h.add_relation(pred_succ_hndl, preExt->txHandle);
490  // and set the extension handle to this transaction
491  preExt->txHandle = h;
492  } else {
493  sc_assert(preExt != nullptr && "ERROR on backward path in phase other than tlm::BEGIN_REQ");
494  }
495  // and set the extension handle to this transaction
496  h.record_attribute("delay", delay);
497  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
498  if(extensionRecording)
499  extensionRecording->recordBeginTx(h, trans);
500  /*************************************************************************
501  * do the timed notification
502  *************************************************************************/
503  if(nb_streamHandleTimed) {
504  nb_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h};
505  rec.tr->deep_copy_from(trans);
506  nb_timed_peq.notify(rec, delay);
507  }
508  /*************************************************************************
509  * do the access
510  *************************************************************************/
511  if(checker) checker->bw_pre(trans, phase);
512  tlm::tlm_sync_enum status = bw_port->nb_transport_bw(trans, phase, delay);
513  if(checker) checker->bw_post(trans, phase, status);
514  /*************************************************************************
515  * handle recording
516  *************************************************************************/
517  h.record_attribute("tlm_sync", status);
518  h.record_attribute("delay[return_path]", delay);
519  h.record_attribute("trans", trans);
520  if(registered)
521  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
522  if(extensionRecording)
523  extensionRecording->recordEndTx(h, trans);
524  // End the transaction
525  nb_trHandle[BW]->end_tx(h, phase.get_name());
526  // get the extension and free the memory if it was mine
527  if(status == tlm::TLM_COMPLETED || (status == tlm::TLM_UPDATED && phase == tlm::END_RESP)) {
528  // the transaction is finished
529  if(preExt && preExt->creator == this) {
530  // clean-up the extension if this is the original creator
531  trans.set_extension(static_cast<link_pred_ext*>(nullptr));
532  if(!trans.has_mm()) {
533  delete preExt;
534  }
535  }
536  /*************************************************************************
537  * do the timed notification if req. finished here
538  *************************************************************************/
539  if(nb_streamHandleTimed) {
540  nb_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h};
541  rec.tr->deep_copy_from(trans);
542  nb_timed_peq.notify(rec, delay);
543  }
544  } else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
545  nb_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h};
546  rec.tr->deep_copy_from(trans);
547  nb_timed_peq.notify(rec, delay);
548  }
549  return status;
550 }
551 
552 template <typename TYPES>
554  auto opt = nb_timed_peq.get_next();
555  if(opt) {
556  auto& e = opt.get();
557  tx_handle h;
558  // Now process outstanding recordings
559  if(e.ph == tlm::BEGIN_REQ || e.ph == axi::BEGIN_PARTIAL_REQ) {
560  h = nb_trTimedHandle[REQ]->begin_tx(par_chld_hndl, e.parent);
561  nbtx_req_handle_map[e.id] = h;
562  } else if(e.ph == tlm::END_REQ || e.ph == axi::END_PARTIAL_REQ) {
563  auto it = nbtx_req_handle_map.find(e.id);
564  if(it != nbtx_req_handle_map.end()) {
565  h = it->second;
566  nbtx_req_handle_map.erase(it);
567  h.record_attribute("trans", *e.tr);
568  h.end_tx();
569  nbtx_last_req_handle_map[e.id] = h;
570  }
571  } else if(e.ph == tlm::BEGIN_RESP || e.ph == axi::BEGIN_PARTIAL_RESP) {
572  auto it = nbtx_req_handle_map.find(e.id);
573  if(it != nbtx_req_handle_map.end()) {
574  h = it->second;
575  nbtx_req_handle_map.erase(it);
576  h.record_attribute("trans", *e.tr);
577  h.end_tx();
578  nbtx_last_req_handle_map[e.id] = h;
579  }
580  h = nb_trTimedHandle[RESP]->begin_tx(par_chld_hndl, e.parent);
581  nbtx_resp_handle_map[e.id] = h;
582  it = nbtx_last_req_handle_map.find(e.id);
583  if(it != nbtx_last_req_handle_map.end()) {
584  tx_handle& pred = it->second;
585  h.add_relation(pred_succ_hndl, pred);
586  nbtx_last_req_handle_map.erase(it);
587  } else {
588  it = nbtx_last_resp_handle_map.find(e.id);
589  if(it != nbtx_last_resp_handle_map.end()) {
590  tx_handle& pred = it->second;
591  h.add_relation(pred_succ_hndl, pred);
592  nbtx_last_resp_handle_map.erase(it);
593  }
594  }
595  } else if(e.ph == tlm::END_RESP || e.ph == axi::END_PARTIAL_RESP) {
596  auto it = nbtx_resp_handle_map.find(e.id);
597  if(it != nbtx_resp_handle_map.end()) {
598  h = it->second;
599  h.record_attribute("trans", *e.tr);
600  nbtx_resp_handle_map.erase(it);
601  h.end_tx();
602  if(e.ph == axi::END_PARTIAL_RESP) {
603  nbtx_last_resp_handle_map[e.id] = h;
604  }
605  }
606  } else
607  sc_assert(!"phase not supported!");
608  }
609  return;
610 }
611 
612 template <typename TYPES>
613 bool axi_lwtr<TYPES>::get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) {
614  if(!(m_db && enableDmiTracing.get_value()))
615  return fw_port->get_direct_mem_ptr(trans, dmi_data);
616  tx_handle h = dmi_trGetHandle->begin_tx();
617  bool status = fw_port->get_direct_mem_ptr(trans, dmi_data);
618  h.record_attribute("trans", trans);
619  h.record_attribute("dmi_data", dmi_data);
620  h.end_tx();
621  return status;
622 }
629 template <typename TYPES>
630 void axi_lwtr<TYPES>::invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) {
631  if(!(m_db && enableDmiTracing.get_value())) {
632  bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
633  return;
634  }
635  tx_handle h = dmi_trInvalidateHandle->begin_tx(start_addr);
636  bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
637  dmi_trInvalidateHandle->end_tx(h, end_addr);
638  return;
639 }
646 template <typename TYPES> unsigned int axi_lwtr<TYPES>::transport_dbg(typename TYPES::tlm_payload_type& trans) {
647  return fw_port->transport_dbg(trans);
648 }
649 } // namespace lwtr
650 } // namespace axi
The TLM2 transaction recorder.
Definition: axi_lwtr.h:54
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: axi_lwtr.h:373
bool isRecordingNonBlockingTxEnabled() const
get the current state of transaction recording
Definition: axi_lwtr.h:184
void b_transport(typename TYPES::tlm_payload_type &trans, sc_core::sc_time &delay) override
The blocking transport function.
Definition: axi_lwtr.h:308
axi_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: axi_lwtr.h:83
bool get_direct_mem_ptr(typename TYPES::tlm_payload_type &trans, tlm::tlm_dmi &dmi_data) override
The direct memory interface forward function.
Definition: axi_lwtr.h:613
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: axi_lwtr.h:463
void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override
The direct memory interface backward function.
Definition: axi_lwtr.h:630
cci::cci_param< bool > enableNbTracing
the attribute to selectively enable/disable recording of non-blocking protocol tx
Definition: axi_lwtr.h:60
bool isRecordingBlockingTxEnabled() const
get the current state of transaction recording
Definition: axi_lwtr.h:178
cci::cci_param< bool > enableBlTracing
the attribute to selectively enable/disable recording of blocking protocol tx
Definition: axi_lwtr.h:57
unsigned int transport_dbg(typename TYPES::tlm_payload_type &trans) override
The debug transportfunction.
Definition: axi_lwtr.h:646
The TLM transaction extensions recorder registry.
payload_type * allocate()
get a plain tlm_payload_type without extensions
Definition: tlm_mm.h:185
TLM2.0 components modeling AHB.
Definition: axi_initiator.h:30
tlm::tlm_bw_transport_if< TYPES > axi_bw_transport_if
alias declaration for the backward interface:
Definition: axi_tlm.h:956
tlm::tlm_fw_transport_if< TYPES > axi_fw_transport_if
alias declaration for the forward interface
Definition: axi_tlm.h:954
SCC SCV4TLM classes and functions.
The AXI protocol traits class. Since the protocoll defines additional non-ignorable phases a dedicate...
Definition: axi_tlm.h:920
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
a tlm memory manager
Definition: tlm_mm.h:285
static tlm_mm & get()
accessor function of the singleton
Definition: tlm_mm.h:293