scc  2024.06
SystemC components library
chi_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 <tlm/scc/tlm_mm.h>
26 #include <array>
27 #include <chi/chi_tlm.h>
28 #include <regex>
29 #include <string>
30 #include <scc/peq.h>
31 #include <unordered_map>
32 #include <vector>
33 
35 namespace chi {
36 namespace lwtr {
37 
38 using tx_db = ::lwtr::tx_db;
39 using tx_fiber = ::lwtr::tx_fiber;
40 template <typename BEGIN = ::lwtr::no_data, typename END = ::lwtr::no_data>
41 using tx_generator = ::lwtr::tx_generator<BEGIN, END>;
42 using tx_handle = ::lwtr::tx_handle;
43 using mm = tlm::scc::tlm_mm<>;
44 using namespace tlm::scc::lwtr;
45 
47  const bool snoop;
48  const bool credit;
49  nb_chi_rec_entry(tlm::scc::tlm_gp_shared_ptr tr,tlm::tlm_phase const ph, uintptr_t const id, tx_handle parent, bool snoop=false, bool credit=false)
50  : nb_rec_entry{tr, ph, id, parent}
51  , snoop(snoop), credit(credit) {}
52 };
53 extern bool registered;
54 
63 template <typename TYPES = chi::chi_protocol_types>
64 class chi_lwtr : public virtual chi::chi_fw_transport_if<TYPES>, public virtual chi::chi_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  chi_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 ~chi_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  nbtx_data_handle_map.clear();
110  nbtx_last_data_handle_map.clear();
111  nbtx_ack_handle_map.clear();
112  delete dmi_trInvalidateHandle;
113  delete dmi_trGetHandle;
114  delete dmi_streamHandle;
115  for(auto* p : nb_trTimedHandle) delete p; // NOLINT
116  delete nb_streamHandleTimed;
117  for(auto* p : nb_trHandle) delete p; // NOLINT
118  delete nb_streamHandle;
119  for(auto* p : b_trTimedHandle) delete p; // NOLINT
120  delete b_streamHandleTimed;
121  for(auto* p : b_trHandle) delete p; // NOLINT
122  delete b_streamHandle;
123  }
124 
125  // TLM-2.0 interface methods for initiator and target sockets, surrounded with
126  // Tx Recording
136  tlm::tlm_sync_enum nb_transport_fw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
137  sc_core::sc_time& delay) override;
147  tlm::tlm_sync_enum nb_transport_bw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
148  sc_core::sc_time& delay) override;
157  void b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) override;
166  void b_snoop(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) override;
174  bool get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) override;
181  void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override;
188  unsigned int transport_dbg(typename TYPES::tlm_payload_type& trans) override;
194  inline bool isRecordingBlockingTxEnabled() const { return m_db && enableBlTracing.get_value(); }
200  inline bool isRecordingNonBlockingTxEnabled() const { return m_db && enableNbTracing.get_value(); }
201 
202 protected:
204  sc_core::sc_port<chi::chi_fw_transport_if<TYPES>> fw_port{"fw_port"};
205 
207  sc_core::sc_port<chi::chi_bw_transport_if<TYPES>> bw_port{"bw_port"};
208 
209 private:
210  std::string const full_name;
212  ::scc::peq<nb_chi_rec_entry> nb_timed_peq;
217  void nbtx_cb();
218  const unsigned bus_width{0};
220  tx_db* m_db{nullptr};
222  ::lwtr::tx_relation_handle pred_succ_hndl{0}, par_chld_hndl{0};
224  tx_fiber* b_streamHandle{nullptr};
226  std::array<tx_generator<sc_core::sc_time, sc_core::sc_time>*, 3> b_trHandle{{nullptr, nullptr, nullptr}};
228  tx_fiber* b_streamHandleTimed{nullptr};
231  std::array<tx_generator<>*, 3> b_trTimedHandle{{nullptr, nullptr, nullptr}};
232 
233  enum DIR { FW, BW, DATA, ACK, CREDIT, REQ = FW, RESP = BW };
234  enum TYPE {
235  READ = tlm::TLM_READ_COMMAND,
236  WRITE = tlm::TLM_WRITE_COMMAND,
237  OTHER = tlm::TLM_IGNORE_COMMAND,
238  SNOOP,
239  NO_OF_TYPES
240  };
242  tx_fiber* nb_streamHandle{nullptr};
244  tx_fiber* nb_streamHandleTimed{nullptr};
246  std::array<tx_generator<std::string, std::string>*, 5> nb_trHandle{{nullptr, nullptr, nullptr, nullptr, nullptr}};
248  std::array<tx_generator<>*, 5> nb_trTimedHandle{{nullptr, nullptr}};
249  std::unordered_map<uint64_t, tx_handle> nbtx_req_handle_map;
250  std::unordered_map<uint64_t, tx_handle> nbtx_last_req_handle_map;
251  std::unordered_map<uint64_t, tx_handle> nbtx_resp_handle_map;
252  std::unordered_map<uint64_t, tx_handle> nbtx_last_resp_handle_map;
253  std::unordered_map<uint64_t, tx_handle> nbtx_data_handle_map;
254  std::unordered_map<uint64_t, tx_handle> nbtx_last_data_handle_map;
255  std::unordered_map<uint64_t, tx_handle> nbtx_ack_handle_map;
257  tx_fiber* dmi_streamHandle{nullptr};
259  tx_generator<>* dmi_trGetHandle{nullptr};
260  tx_generator<sc_dt::uint64, sc_dt::uint64>* dmi_trInvalidateHandle{nullptr};
261 
262 protected:
263  void initialize_streams() {
264  if(m_db) {
265  pred_succ_hndl = m_db->create_relation("PREDECESSOR_SUCCESSOR");
266  par_chld_hndl = m_db->create_relation("PARENT_CHILD");
267  }
268  if(isRecordingBlockingTxEnabled() && !b_streamHandle) {
269  b_streamHandle = new tx_fiber((full_name + "_bl").c_str(), "[TLM][chi][b]", m_db);
270  b_trHandle[tlm::TLM_READ_COMMAND] = new tx_generator<sc_core::sc_time, sc_core::sc_time>(
271  "read", *b_streamHandle, "start_delay", "end_delay");
272  b_trHandle[tlm::TLM_WRITE_COMMAND] = new tx_generator<sc_core::sc_time, sc_core::sc_time>(
273  "write", *b_streamHandle, "start_delay", "end_delay");
274  b_trHandle[tlm::TLM_IGNORE_COMMAND] = new tx_generator<sc_core::sc_time, sc_core::sc_time>(
275  "ignore", *b_streamHandle, "start_delay", "end_delay");
276  if(enableTimedTracing.get_value()) {
277  b_streamHandleTimed =
278  new tx_fiber((full_name + "_bl_timed").c_str(), "[TLM][chi][b][timed]", m_db);
279  b_trTimedHandle[tlm::TLM_READ_COMMAND] = new tx_generator<>("read", *b_streamHandleTimed);
280  b_trTimedHandle[tlm::TLM_WRITE_COMMAND] = new tx_generator<>("write", *b_streamHandleTimed);
281  b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] = new tx_generator<>("ignore", *b_streamHandleTimed);
282  }
283  }
284  if(isRecordingNonBlockingTxEnabled() && !nb_streamHandle) {
285  nb_streamHandle = new tx_fiber((full_name + "_nb").c_str(), "[TLM][chi][nb]", m_db);
286  nb_trHandle[FW] = new tx_generator<std::string, std::string>("fw", *nb_streamHandle, "tlm_phase",
287  "tlm_phase[return_path]");
288  nb_trHandle[BW] = new tx_generator<std::string, std::string>("bw", *nb_streamHandle, "tlm_phase",
289  "tlm_phase[return_path]");
290  if(enableTimedTracing.get_value()) {
291  nb_streamHandleTimed = new tx_fiber((full_name + "_nb_timed").c_str(), "[TLM][chi][nb][timed]", m_db);
292  nb_trTimedHandle[REQ] = new tx_generator<>("request", *nb_streamHandleTimed);
293  nb_trTimedHandle[RESP] = new tx_generator<>("response", *nb_streamHandleTimed);
294  nb_trTimedHandle[DATA] = new tx_generator<>("data", *nb_streamHandleTimed);
295  nb_trTimedHandle[ACK] = new tx_generator<>("ack", *nb_streamHandleTimed);
296  nb_trTimedHandle[CREDIT] = new tx_generator<>("link", *nb_streamHandleTimed);
297  }
298  }
299  if(m_db && enableDmiTracing.get_value() && !dmi_streamHandle) {
300  dmi_streamHandle = new tx_fiber((full_name + "_dmi").c_str(), "[TLM][chi][dmi]", m_db);
301  dmi_trGetHandle = new tx_generator<>("get", *dmi_streamHandle);
302  dmi_trInvalidateHandle = new tx_generator<sc_dt::uint64, sc_dt::uint64>(
303  "invalidate", *dmi_streamHandle, "start_addr", "end_addr");
304  }
305  }
306 
307 private:
308  inline std::string phase2string(const tlm::tlm_phase& p) {
309  std::stringstream ss;
310  ss << p;
311  return ss.str();
312  }
313 };
314 
315 template <unsigned BUSWIDTH=32, typename TYPES = chi::chi_protocol_types, int N = 1,
316  sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
317 class chi_lwtr_recorder : public sc_core::sc_module, public chi_lwtr<TYPES> {
318 public:
321 
322  chi_lwtr_recorder(sc_core::sc_module_name nm, bool recording_enabled = true, tx_db* tr_db = tx_db::get_default_db())
323  : sc_core::sc_module(nm)
324  , chi_lwtr<TYPES>(name(), BUSWIDTH, recording_enabled, tr_db)
325  {
326  is(*this);
327  ts(*this);
328  this->bw_port(ts.get_base_port());
329  this->fw_port(is.get_base_port());
330  }
331 };
333 // implementations of functions
335 
336 template <typename TYPES>
337 void chi_lwtr<TYPES>::b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) {
338  if(!isRecordingBlockingTxEnabled()) {
339  fw_port->b_transport(trans, delay);
340  return;
341  }
342  // Get a handle for the new transaction
343  tx_handle h = b_trHandle[trans.get_command()]->begin_tx(delay);
344  tx_handle htim;
345  /*************************************************************************
346  * do the timed notification
347  *************************************************************************/
348  if(b_streamHandleTimed)
349  htim = b_trTimedHandle[trans.get_command()]->begin_tx_delayed(sc_core::sc_time_stamp()+delay, par_chld_hndl, h);
350 
351  if(registered)
352  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
353  if(extensionRecording) {
354  extensionRecording->recordBeginTx(h, trans);
355  if(htim.is_valid())
356  extensionRecording->recordBeginTx(htim, trans);
357  }
358  link_pred_ext* preExt = nullptr;
359 
360  trans.get_extension(preExt);
361  if(preExt == nullptr) { // we are the first recording this transaction
362  preExt = new link_pred_ext(h, this);
363  if(trans.has_mm())
364  trans.set_auto_extension(preExt);
365  else
366  trans.set_extension(preExt);
367  } else {
368  h.add_relation(pred_succ_hndl, preExt->txHandle);
369  }
370  tx_handle preTx(preExt->txHandle);
371  preExt->txHandle = h;
372  fw_port->b_transport(trans, delay);
373  trans.get_extension(preExt);
374  if(preExt->creator == this) {
375  // clean-up the extension if this is the original creator
376  trans.set_extension(static_cast<link_pred_ext*>(nullptr));
377  if(!trans.has_mm()) {
378  delete preExt;
379  }
380  } else {
381  preExt->txHandle = preTx;
382  }
383 
384  h.record_attribute("trans", trans);
385  if(registered)
386  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
387  if(extensionRecording) {
388  extensionRecording->recordEndTx(h, trans);
389  if(htim.is_active())
390  extensionRecording->recordEndTx(htim, trans);
391  }
392  // End the transaction
393  h.end_tx(delay);
394  // and now the stuff for the timed tx
395  if(htim.is_valid()) {
396  htim.record_attribute("trans", trans);
397  htim.end_tx_delayed(sc_core::sc_time_stamp()+delay);
398  }
399 }
400 
401 template <typename TYPES>
402 void chi_lwtr<TYPES>::b_snoop(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) {
403  if(!b_streamHandleTimed) {
404  bw_port->b_snoop(trans, delay);
405  return;
406  }
407  // Get a handle for the new transaction
408  tx_handle h = b_trHandle[trans.get_command()]->begin_tx(delay);
409  tx_handle htim;
410  /*************************************************************************
411  * do the timed notification
412  *************************************************************************/
413  if(b_streamHandleTimed)
414  htim = b_trTimedHandle[trans.get_command()]->begin_tx_delayed(sc_core::sc_time_stamp()+delay, par_chld_hndl, h);
415 
416  if(registered)
417  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
418  if(extensionRecording) {
419  extensionRecording->recordBeginTx(h, trans);
420  if(htim.is_valid())
421  extensionRecording->recordBeginTx(htim, trans);
422  }
423  link_pred_ext* preExt = nullptr;
424 
425  trans.get_extension(preExt);
426  if(preExt == nullptr) { // we are the first recording this transaction
427  preExt = new link_pred_ext(h, this);
428  trans.set_extension(preExt);
429  } else {
430  h.add_relation(pred_succ_hndl, preExt->txHandle);
431  }
432  tx_handle preTx(preExt->txHandle);
433  preExt->txHandle = h;
434  bw_port->b_snoop(trans, delay);
435  trans.get_extension(preExt);
436  if(preExt->creator == this) {
437  // clean-up the extension if this is the original creator
438  trans.set_extension(static_cast<link_pred_ext*>(nullptr));
439  if(!trans.has_mm())
440  delete preExt;
441  } else {
442  preExt->txHandle = preTx;
443  }
444 
445  h.record_attribute("trans", trans);
446  if(registered)
447  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
448  if(extensionRecording) {
449  extensionRecording->recordEndTx(h, trans);
450  if(htim.is_active())
451  extensionRecording->recordEndTx(htim, trans);
452  }
453  // End the transaction
454  h.end_tx(delay);
455  // and now the stuff for the timed tx
456  if(htim.is_valid()) {
457  htim.record_attribute("trans", trans);
458  htim.end_tx_delayed(sc_core::sc_time_stamp()+delay);
459  }
460 }
461 
462 template <typename TYPES>
463 tlm::tlm_sync_enum chi_lwtr<TYPES>::nb_transport_fw(typename TYPES::tlm_payload_type& trans,
464  typename TYPES::tlm_phase_type& phase,
465  sc_core::sc_time& delay) {
466  if(!isRecordingNonBlockingTxEnabled()){
467  return fw_port->nb_transport_fw(trans, phase, delay);
468  }
469  /*************************************************************************
470  * prepare recording
471  *************************************************************************/
472  // Get a handle for the new transaction
473  tx_handle h = nb_trHandle[FW]->begin_tx(phase2string(phase));
474  link_pred_ext* preExt = nullptr;
475  trans.get_extension(preExt);
476  if((phase == tlm::BEGIN_REQ) && preExt == nullptr) { // we are the first recording this transaction
477  preExt = new link_pred_ext(h, this);
478  if(trans.has_mm())
479  trans.set_auto_extension(preExt);
480  else
481  trans.set_extension(preExt);
482  } else if(preExt != nullptr) {
483  // link handle if we have a predecessor
484  h.add_relation(pred_succ_hndl, preExt->txHandle);
485  } else {
486  sc_assert(preExt != nullptr && "ERROR on forward path in phase other than tlm::BEGIN_REQ");
487  }
488  // update the extension
489  preExt->txHandle = h;
490  h.record_attribute("delay", delay);
491  if(registered)
492  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
493  if(extensionRecording)
494  extensionRecording->recordBeginTx(h, trans);
495  /*************************************************************************
496  * do the timed notification
497  *************************************************************************/
498  if(nb_streamHandleTimed) {
499  nb_chi_rec_entry rec(mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h,
500  (trans.template get_extension<chi::chi_snp_extension>() != nullptr),
501  (phase == tlm::BEGIN_REQ) && (trans.template get_extension<chi::chi_credit_extension>() != nullptr));
502  rec.tr->deep_copy_from(trans);
503  nb_timed_peq.notify(rec, delay);
504  }
505  /*************************************************************************
506  * do the access
507  *************************************************************************/
508  tlm::tlm_sync_enum status = fw_port->nb_transport_fw(trans, phase, delay);
509  /*************************************************************************
510  * handle recording
511  *************************************************************************/
512  h.record_attribute("status", status);
513  h.record_attribute("delay[return_path]", delay);
514  h.record_attribute("trans", trans);
515  if(registered)
516  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
517  if(extensionRecording)
518  extensionRecording->recordEndTx(h, trans);
519  // get the extension and free the memory if it was mine
520  if(status == tlm::TLM_COMPLETED) {
521  // the transaction is finished
522  trans.get_extension(preExt);
523  if(preExt && preExt->creator == this) {
524  trans.set_extension(static_cast<link_pred_ext*>(nullptr));
525  if(!trans.has_mm()) {
526  delete preExt;
527  }
528  }
529  /*************************************************************************
530  * do the timed notification if req. finished here
531  *************************************************************************/
532  if(nb_streamHandleTimed) {
533  nb_chi_rec_entry rec {mm::get().allocate(), (phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase,
534  reinterpret_cast<uint64_t>(&trans), h}; //TODO: check phase
535  rec.tr->deep_copy_from(trans);
536  nb_timed_peq.notify(rec, delay);
537  }
538  } else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
539  nb_chi_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h};
540  rec.tr->deep_copy_from(trans);
541  nb_timed_peq.notify(rec, delay);
542  }
543  // End the transaction
544  nb_trHandle[FW]->end_tx(h, phase2string(phase));
545  return status;
546 }
547 
548 template <typename TYPES>
549 tlm::tlm_sync_enum chi_lwtr<TYPES>::nb_transport_bw(typename TYPES::tlm_payload_type& trans,
550  typename TYPES::tlm_phase_type& phase,
551  sc_core::sc_time& delay) {
552  if(!isRecordingNonBlockingTxEnabled()){
553  return bw_port->nb_transport_bw(trans, phase, delay);
554  }
555  /*************************************************************************
556  * prepare recording
557  *************************************************************************/
558  link_pred_ext* preExt = nullptr;
559  trans.get_extension(preExt);
560  // Get a handle for the new transaction
561  tx_handle h = nb_trHandle[BW]->begin_tx(phase2string(phase));
562  // link handle if we have a predecessor and that's not ourself
563  if(phase == tlm::BEGIN_REQ && preExt == nullptr) { // we are the first recording this transaction
564  preExt = new link_pred_ext(h, this);
565  trans.set_extension(preExt);
566  preExt->txHandle = h;
567  } else if(preExt) {
568  // link handle if we have a predecessor
569  h.add_relation(pred_succ_hndl, preExt->txHandle);
570  // and set the extension handle to this transaction
571  preExt->txHandle = h;
572  } else {
573  sc_assert(preExt != nullptr && "ERROR on backward path in phase other than tlm::BEGIN_REQ");
574  }
575  // and set the extension handle to this transaction
576  h.record_attribute("delay", delay);
577  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
578  if(extensionRecording)
579  extensionRecording->recordBeginTx(h, trans);
580  /*************************************************************************
581  * do the timed notification
582  *************************************************************************/
583  if(nb_streamHandleTimed) {
584  nb_chi_rec_entry rec(mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h,
585  (trans.template get_extension<chi::chi_snp_extension>() != nullptr),
586  (phase == tlm::BEGIN_REQ) && (trans.template get_extension<chi::chi_credit_extension>() != nullptr));
587  rec.tr->deep_copy_from(trans);
588  nb_timed_peq.notify(rec, delay);
589  }
590  /*************************************************************************
591  * do the access
592  *************************************************************************/
593  tlm::tlm_sync_enum status = bw_port->nb_transport_bw(trans, phase, delay);
594  /*************************************************************************
595  * handle recording
596  *************************************************************************/
597  h.record_attribute("status", status);
598  h.record_attribute("delay[return_path]", delay);
599  h.record_attribute("trans", trans);
600  if(registered)
601  for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
602  if(extensionRecording)
603  extensionRecording->recordEndTx(h, trans);
604  // End the transaction
605  nb_trHandle[BW]->end_tx(h, phase2string(phase));
606  // get the extension and free the memory if it was mine
607  if(status == tlm::TLM_COMPLETED) {
608  // the transaction is finished
609  if(preExt && preExt->creator == this) {
610  // clean-up the extension if this is the original creator
611  trans.set_extension(static_cast<link_pred_ext*>(nullptr));
612  if(!trans.has_mm()) {
613  delete preExt;
614  }
615  }
616  /*************************************************************************
617  * do the timed notification if req. finished here
618  *************************************************************************/
619  if(nb_streamHandleTimed) {
620  nb_chi_rec_entry rec {mm::get().allocate(), (phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase,
621  reinterpret_cast<uint64_t>(&trans), h, phase == tlm::BEGIN_REQ};
622  rec.tr->deep_copy_from(trans);
623  nb_timed_peq.notify(rec, delay);
624  }
625  } else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
626  nb_chi_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h, phase == tlm::BEGIN_REQ};
627  rec.tr->deep_copy_from(trans);
628  nb_timed_peq.notify(rec, delay);
629  }
630  return status;
631 }
632 
633 template <typename TYPES>
635  auto opt = nb_timed_peq.get_next();
636  if(opt) {
637  auto& e = opt.get();
638  tx_handle h;
639  // Now process outstanding recordings
640  if(e.credit) {
641  nb_trTimedHandle[CREDIT]->begin_tx().end_tx();
642  } else if(e.ph == tlm::BEGIN_REQ) {
643  h = nb_trTimedHandle[REQ]->begin_tx(par_chld_hndl, e.parent);
644  nbtx_req_handle_map[e.id] = h;
645  } else if(e.ph == tlm::END_REQ) {
646  auto it = nbtx_req_handle_map.find(e.id);
647  if(it != nbtx_req_handle_map.end()) {
648  h = it->second;
649  nbtx_req_handle_map.erase(it);
650  h.record_attribute("trans", *e.tr);
651  h.end_tx();
652  nbtx_last_req_handle_map[e.id] = h;
653  }
654  } else if(e.ph == tlm::BEGIN_RESP) {
655  auto it = nbtx_req_handle_map.find(e.id);
656  if(it != nbtx_req_handle_map.end()) {
657  h = it->second;
658  nbtx_req_handle_map.erase(it);
659  h.record_attribute("trans", *e.tr);
660  h.end_tx();
661  nbtx_last_req_handle_map[e.id] = h;
662  }
663  h = nb_trTimedHandle[RESP]->begin_tx(par_chld_hndl, e.parent);
664  nbtx_resp_handle_map[e.id] = h;
665  it = nbtx_last_req_handle_map.find(e.id);
666  if(it != nbtx_last_req_handle_map.end()) {
667  tx_handle& pred = it->second;
668  h.add_relation(pred_succ_hndl, pred);
669  nbtx_last_req_handle_map.erase(it);
670  } else {
671  it = nbtx_last_resp_handle_map.find(e.id);
672  if(it != nbtx_last_resp_handle_map.end()) {
673  tx_handle& pred = it->second;
674  h.add_relation(pred_succ_hndl, pred);
675  nbtx_last_resp_handle_map.erase(it);
676  }
677  }
678  } else if(e.ph == tlm::END_RESP) {
679  auto it = nbtx_resp_handle_map.find(e.id);
680  if(it != nbtx_resp_handle_map.end()) {
681  h = it->second;
682  nbtx_resp_handle_map.erase(it);
683  h.record_attribute("trans", *e.tr);
684  h.end_tx();
685  }
686  } else if(e.ph == chi::BEGIN_DATA || e.ph == chi::BEGIN_PARTIAL_DATA) {
687  auto it = nbtx_req_handle_map.find(e.id);
688  if(it != nbtx_req_handle_map.end()) {
689  h = it->second;
690  h.end_tx();
691  nbtx_last_req_handle_map[e.id] = h;
692  }
693  h = nb_trTimedHandle[DATA]->begin_tx();
694  h.record_attribute("trans", *e.tr);
695  h.add_relation(par_chld_hndl, e.parent);
696  nbtx_data_handle_map[e.id] = h;
697  it = nbtx_last_data_handle_map.find(e.id);
698  if(it != nbtx_last_data_handle_map.end()) {
699  auto pred = it->second;
700  nbtx_last_data_handle_map.erase(it);
701  h.add_relation(pred_succ_hndl, pred);
702  }
703  } else if(e.ph == chi::END_DATA || e.ph == chi::END_PARTIAL_DATA) {
704  auto it = nbtx_data_handle_map.find(e.id);
705  if(it != nbtx_data_handle_map.end()) {
706  h = it->second;
707  nbtx_data_handle_map.erase(it);
708  h.end_tx();
709  }
710  } else if(e.ph == chi::ACK) {
711  auto it = nbtx_ack_handle_map.find(e.id);
712  if(it == nbtx_ack_handle_map.end()) {
713  auto h = nb_trTimedHandle[ACK]->begin_tx();
714  nbtx_ack_handle_map[e.id] = h;
715  h.add_relation(par_chld_hndl, e.parent);
716  } else {
717  nb_trTimedHandle[ACK]->end_tx(it->second);
718  nbtx_ack_handle_map.erase(it);
719  }
720  } else
721  sc_assert(!"phase not supported!");
722  }
723  return;
724 }
725 
726 template <typename TYPES>
727 bool chi_lwtr<TYPES>::get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) {
728  if(!(m_db && enableDmiTracing.get_value()))
729  return fw_port->get_direct_mem_ptr(trans, dmi_data);
730  tx_handle h = dmi_trGetHandle->begin_tx();
731  bool status = fw_port->get_direct_mem_ptr(trans, dmi_data);
732  h.record_attribute("trans", trans);
733  h.record_attribute("dmi_data", dmi_data);
734  h.end_tx();
735  return status;
736 }
743 template <typename TYPES>
744 void chi_lwtr<TYPES>::invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) {
745  if(!(m_db && enableDmiTracing.get_value())) {
746  bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
747  return;
748  }
749  tx_handle h = dmi_trInvalidateHandle->begin_tx(start_addr);
750  bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
751  dmi_trInvalidateHandle->end_tx(h, end_addr);
752  return;
753 }
760 template <typename TYPES> unsigned int chi_lwtr<TYPES>::transport_dbg(typename TYPES::tlm_payload_type& trans) {
761  return fw_port->transport_dbg(trans);
762 }
763 } // namespace lwtr
764 } // namespace chi
The TLM2 transaction recorder.
Definition: chi_lwtr.h:64
bool isRecordingNonBlockingTxEnabled() const
get the current state of transaction recording
Definition: chi_lwtr.h:200
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: chi_lwtr.h:463
void b_snoop(typename TYPES::tlm_payload_type &trans, sc_core::sc_time &delay) override
The blocking snoop function.
Definition: chi_lwtr.h:402
void b_transport(typename TYPES::tlm_payload_type &trans, sc_core::sc_time &delay) override
The blocking transport function.
Definition: chi_lwtr.h:337
cci::cci_param< bool > enableNbTracing
the attribute to selectively enable/disable recording of non-blocking protocol tx
Definition: chi_lwtr.h:70
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: chi_lwtr.h:549
unsigned int transport_dbg(typename TYPES::tlm_payload_type &trans) override
The debug transportfunction.
Definition: chi_lwtr.h:760
cci::cci_param< bool > enableBlTracing
the attribute to selectively enable/disable recording of blocking protocol tx
Definition: chi_lwtr.h:67
chi_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: chi_lwtr.h:86
bool isRecordingBlockingTxEnabled() const
get the current state of transaction recording
Definition: chi_lwtr.h:194
void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override
The direct memory interface backward function.
Definition: chi_lwtr.h:744
bool get_direct_mem_ptr(typename TYPES::tlm_payload_type &trans, tlm::tlm_dmi &dmi_data) override
The direct memory interface forward function.
Definition: chi_lwtr.h:727
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 CHI.
Definition: chi_tlm.cpp:21
tlm::tlm_fw_transport_if< TYPES > chi_fw_transport_if
alias declaration for the forward interface
Definition: chi_tlm.h:912
SCC SCV4TLM classes and functions.
The AXI protocol traits class. Since the protocoll defines additional non-ignorable phases a dedicate...
Definition: chi_tlm.h:897
Definition: chi_lwtr.h:46
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