scc  2022.4.0
SystemC components library
tlm_recorder.h
1 /*******************************************************************************
2  * Copyright 2016-2022 MINRES Technologies GmbH
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 #ifndef TLM2_RECORDER_H_
18 #define TLM2_RECORDER_H_
19 
20 #include "tlm_extension_recording_registry.h"
21 #include "tlm_recording_extension.h"
22 #include <array>
23 #include <regex>
24 #include <sstream>
25 #include <string>
26 #include <sysc/kernel/sc_dynamic_processes.h>
27 #include <tlm/scc/tlm_mm.h>
28 #include <tlm>
29 #include <tlm_utils/peq_with_cb_and_phase.h>
30 #include <unordered_map>
31 
33 namespace tlm {
35 namespace scc {
37 namespace scv {
38 
39 void record(SCVNS scv_tr_handle&, tlm::tlm_generic_payload&);
40 void record(SCVNS scv_tr_handle&, tlm::tlm_phase&);
41 void record(SCVNS scv_tr_handle&, tlm::tlm_sync_enum);
42 void record(SCVNS scv_tr_handle&, tlm::tlm_dmi&);
43 
44 namespace impl {
45 template <typename TYPES = tlm::tlm_base_protocol_types> class tlm_recording_payload : public TYPES::tlm_payload_type {
46 public:
47  SCVNS scv_tr_handle parent;
48  uint64_t id;
49  tlm_recording_payload& operator=(const typename TYPES::tlm_payload_type& x) {
50  id = reinterpret_cast<uintptr_t>(&x);
51  this->set_command(x.get_command());
52  this->set_address(x.get_address());
53  this->set_data_ptr(nullptr);
54  this->set_data_length(x.get_data_length());
55  this->set_response_status(x.get_response_status());
56  this->set_byte_enable_ptr(nullptr);
57  this->set_byte_enable_length(x.get_byte_enable_length());
58  this->set_streaming_width(x.get_streaming_width());
59  return (*this);
60  }
61  explicit tlm_recording_payload(tlm::tlm_mm_interface* mm)
62  : TYPES::tlm_payload_type(mm)
63  , parent()
64  , id(0) {}
65 };
66 template <typename TYPES = tlm::tlm_base_protocol_types> struct tlm_recording_types {
68  using tlm_phase_type = typename TYPES::tlm_phase_type;
69 };
70 
71 } // namespace impl
80 template <typename TYPES = tlm::tlm_base_protocol_types>
81 class tlm_recorder : public virtual tlm::tlm_fw_transport_if<TYPES>, public virtual tlm::tlm_bw_transport_if<TYPES> {
82  std::string get_parent(char const* hier_name) {
83  std::string ret(hier_name);
84  auto pos = ret.rfind('.');
85  return pos == std::string::npos ? ret : ret.substr(0, pos);
86  }
87 
88 public:
92 
94  sc_core::sc_attribute<bool> enableBlTracing;
95 
97  sc_core::sc_attribute<bool> enableNbTracing;
98 
100  sc_core::sc_attribute<bool> enableTimedTracing{"enableTimedTracing", true};
101 
103  sc_core::sc_attribute<bool> enableDmiTracing{"enableDmiTracing", false};
104 
106  sc_core::sc_port_b<tlm::tlm_fw_transport_if<TYPES>>& fw_port;
107 
109  sc_core::sc_port_b<tlm::tlm_bw_transport_if<TYPES>>& bw_port;
110 
124  tlm_recorder(sc_core::sc_port_b<tlm::tlm_fw_transport_if<TYPES>>& fw_port, sc_core::sc_port_b<tlm::tlm_bw_transport_if<TYPES>>& bw_port,
125  bool recording_enabled = true, SCVNS scv_tr_db* tr_db = SCVNS scv_tr_db::get_default_db())
126  : tlm_recorder(sc_core::sc_gen_unique_name("tlm_recorder"), fw_port, bw_port, recording_enabled, tr_db) {}
141  tlm_recorder(const char* name, sc_core::sc_port_b<tlm::tlm_fw_transport_if<TYPES>>& fw_port,
142  sc_core::sc_port_b<tlm::tlm_bw_transport_if<TYPES>>& bw_port, bool recording_enabled = true,
143  SCVNS scv_tr_db* tr_db = SCVNS scv_tr_db::get_default_db())
144  : enableBlTracing("enableBlTracing", recording_enabled)
145  , enableNbTracing("enableNbTracing", recording_enabled)
146  , fw_port(fw_port)
147  , bw_port(bw_port)
148  , b_timed_peq(this, &tlm_recorder::btx_cb)
149  , nb_timed_peq(this, &tlm_recorder::nbtx_cb)
150  , m_db(tr_db)
151  , fixed_basename(name) {}
152 
153  virtual ~tlm_recorder() override {
154  btx_handle_map.clear();
155  nbtx_req_handle_map.clear();
156  nbtx_last_req_handle_map.clear();
157  delete b_streamHandle;
158  for(auto* p : b_trHandle)
159  delete p; // NOLINT
160  delete b_streamHandleTimed;
161  for(auto* p : b_trTimedHandle)
162  delete p; // NOLINT
163  delete nb_streamHandle;
164  for(auto* p : nb_trHandle)
165  delete p; // NOLINT
166  delete nb_streamHandleTimed;
167  for(auto* p : nb_trTimedHandle)
168  delete p; // NOLINT
169  delete dmi_streamHandle;
170  delete dmi_trGetHandle;
171  delete dmi_trInvalidateHandle;
172  }
173 
174  // TLM-2.0 interface methods for initiator and target sockets, surrounded with
175  // Tx Recording
185  tlm::tlm_sync_enum nb_transport_fw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
186  sc_core::sc_time& delay) override;
187 
197  tlm::tlm_sync_enum nb_transport_bw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
198  sc_core::sc_time& delay) override;
199 
208  void b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) override;
216  bool get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) override;
223  void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override;
230  unsigned int transport_dbg(typename TYPES::tlm_payload_type& trans) override;
236  inline bool isRecordingBlockingTxEnabled() const { return m_db && enableBlTracing.value; }
242  inline bool isRecordingNonBlockingTxEnabled() const { return m_db && enableNbTracing.value; }
243 
244 private:
246  tlm_utils::peq_with_cb_and_phase<tlm_recorder, recording_types> b_timed_peq;
248  tlm_utils::peq_with_cb_and_phase<tlm_recorder, recording_types> nb_timed_peq;
253  void btx_cb(tlm_recording_payload& rec_parts, const typename TYPES::tlm_phase_type& phase);
258  void nbtx_cb(tlm_recording_payload& rec_parts, const typename TYPES::tlm_phase_type& phase);
260  SCVNS scv_tr_db* m_db{nullptr};
262  SCVNS scv_tr_stream* b_streamHandle{nullptr};
264  std::array<SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>*, 3> b_trHandle{{nullptr, nullptr, nullptr}};
266  SCVNS scv_tr_stream* b_streamHandleTimed{nullptr};
269  std::array<SCVNS scv_tr_generator<>*, 3> b_trTimedHandle{{nullptr, nullptr, nullptr}};
270  std::unordered_map<uint64_t, SCVNS scv_tr_handle> btx_handle_map;
271 
272  enum DIR { FW, BW, REQ = FW, RESP = BW };
274  SCVNS scv_tr_stream* nb_streamHandle{nullptr};
276  SCVNS scv_tr_stream* nb_streamHandleTimed{nullptr};
278  std::array<SCVNS scv_tr_generator<std::string, std::string>*, 2> nb_trHandle{{nullptr, nullptr}};
280  std::array<SCVNS scv_tr_generator<>*, 2> nb_trTimedHandle{{nullptr, nullptr}};
281  std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_req_handle_map;
282  std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_last_req_handle_map;
283 
285  SCVNS scv_tr_stream* dmi_streamHandle{nullptr};
287  SCVNS scv_tr_generator<>* dmi_trGetHandle{nullptr};
288  SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>* dmi_trInvalidateHandle{nullptr};
289 
290 public:
291  void initialize_streams() {
292  if(isRecordingBlockingTxEnabled() && !b_streamHandle) {
293  b_streamHandle = new SCVNS scv_tr_stream((fixed_basename + "_bl").c_str(), "[TLM][base-protocol][b]", m_db);
294  b_trHandle[tlm::TLM_READ_COMMAND] =
295  new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("read", *b_streamHandle, "start_delay", "end_delay");
296  b_trHandle[tlm::TLM_WRITE_COMMAND] =
297  new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("write", *b_streamHandle, "start_delay", "end_delay");
298  b_trHandle[tlm::TLM_IGNORE_COMMAND] =
299  new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("ignore", *b_streamHandle, "start_delay", "end_delay");
300  if(enableTimedTracing.value) {
301  b_streamHandleTimed =
302  new SCVNS scv_tr_stream((fixed_basename + "_bl_timed").c_str(), "[TLM][base-protocol][b][timed]", m_db);
303  b_trTimedHandle[tlm::TLM_READ_COMMAND] = new SCVNS scv_tr_generator<>("read", *b_streamHandleTimed);
304  b_trTimedHandle[tlm::TLM_WRITE_COMMAND] = new SCVNS scv_tr_generator<>("write", *b_streamHandleTimed);
305  b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] = new SCVNS scv_tr_generator<>("ignore", *b_streamHandleTimed);
306  }
307  }
308  if(isRecordingNonBlockingTxEnabled() && !nb_streamHandle) {
309  nb_streamHandle = new SCVNS scv_tr_stream((fixed_basename + "_nb").c_str(), "[TLM][base-protocol][nb]", m_db);
310  nb_trHandle[FW] =
311  new SCVNS scv_tr_generator<std::string, std::string>("fw", *nb_streamHandle, "tlm_phase", "tlm_phase[return_path]");
312  nb_trHandle[BW] =
313  new SCVNS scv_tr_generator<std::string, std::string>("bw", *nb_streamHandle, "tlm_phase", "tlm_phase[return_path]");
314  if(enableTimedTracing.value) {
315  nb_streamHandleTimed =
316  new SCVNS scv_tr_stream((fixed_basename + "_nb_timed").c_str(), "[TLM][base-protocol][nb][timed]", m_db);
317  nb_trTimedHandle[FW] = new SCVNS scv_tr_generator<>("request", *nb_streamHandleTimed);
318  nb_trTimedHandle[BW] = new SCVNS scv_tr_generator<>("response", *nb_streamHandleTimed);
319  }
320  }
321  if(m_db && enableDmiTracing.value && !dmi_streamHandle) {
322  dmi_streamHandle = new SCVNS scv_tr_stream((fixed_basename + "_dmi").c_str(), "[TLM][base-protocol][dmi]", m_db);
323  dmi_trGetHandle = new SCVNS scv_tr_generator<>("get", *dmi_streamHandle);
324  dmi_trInvalidateHandle =
325  new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("invalidate", *dmi_streamHandle, "start_addr", "end_addr");
326  }
327  }
328 
329 private:
330  const std::string fixed_basename;
331  inline std::string phase2string(const tlm::tlm_phase& p) {
332  std::stringstream ss;
333  ss << p;
334  return ss.str();
335  }
336 };
337 
339 // implementations of functions
341 
342 template <typename TYPES> void tlm_recorder<TYPES>::b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) {
343  tlm_recording_payload* req{nullptr};
344  if(!isRecordingBlockingTxEnabled()) {
345  fw_port->b_transport(trans, delay);
346  return;
347  } else if(!b_streamHandle)
348  initialize_streams();
349  // Get a handle for the new transaction
350  SCVNS scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_core::sc_time_stamp());
351  /*************************************************************************
352  * do the timed notification
353  *************************************************************************/
354  if(b_streamHandleTimed) {
355  req = mm::get().allocate();
356  req->acquire();
357  (*req) = trans;
358  req->parent = h;
359  req->id = h.get_id();
360  b_timed_peq.notify(*req, tlm::BEGIN_REQ, delay);
361  }
362 
363  for(auto& extensionRecording : tlm_extension_recording_registry<TYPES>::inst().get())
364  if(extensionRecording)
365  extensionRecording->recordBeginTx(h, trans);
366  tlm_recording_extension* preExt = nullptr;
367 
368  trans.get_extension(preExt);
369  if(preExt == nullptr) { // we are the first recording this transaction
370  preExt = new tlm_recording_extension(h, this);
371  if(trans.has_mm())
372  trans.set_auto_extension(preExt);
373  else
374  trans.set_extension(preExt);
375  } else {
376  h.add_relation(rel_str(PREDECESSOR_SUCCESSOR), preExt->txHandle);
377  }
378  SCVNS scv_tr_handle preTx{preExt->txHandle};
379  preExt->txHandle = h;
380  fw_port->b_transport(trans, delay);
381  if(preExt && preExt->get_creator() == this) {
382  // clean-up the extension if this is the original creator
383  trans.set_extension(static_cast<tlm_recording_extension*>(nullptr));
384  if(!trans.has_mm()) {
385  delete preExt;
386  }
387  } else {
388  preExt->txHandle = preTx;
389  }
390  record(h, trans);
391  for(auto& extensionRecording : tlm_extension_recording_registry<TYPES>::inst().get())
392  if(extensionRecording)
393  extensionRecording->recordEndTx(h, trans);
394  // End the transaction
395  b_trHandle[trans.get_command()]->end_transaction(h, delay.value(), sc_core::sc_time_stamp());
396  // and now the stuff for the timed tx
397  if(b_streamHandleTimed) {
398  b_timed_peq.notify(*req, tlm::END_RESP, delay);
399  }
400 }
401 
402 template <typename TYPES> void tlm_recorder<TYPES>::btx_cb(tlm_recording_payload& rec_parts, const typename TYPES::tlm_phase_type& phase) {
403  SCVNS scv_tr_handle h;
404  // Now process outstanding recordings
405  switch(phase) {
406  case tlm::BEGIN_REQ: {
407  h = b_trTimedHandle[rec_parts.get_command()]->begin_transaction();
408  h.add_relation(rel_str(PARENT_CHILD), rec_parts.parent);
409  btx_handle_map[rec_parts.id] = h;
410  } break;
411  case tlm::END_RESP: {
412  auto it = btx_handle_map.find(rec_parts.id);
413  sc_assert(it != btx_handle_map.end());
414  h = it->second;
415  btx_handle_map.erase(it);
416  record(h, rec_parts);
417  h.end_transaction();
418  rec_parts.release();
419  } break;
420  default:
421  sc_assert(!"phase not supported!");
422  }
423  return;
424 }
425 
426 template <typename TYPES>
427 tlm::tlm_sync_enum tlm_recorder<TYPES>::nb_transport_fw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
428  sc_core::sc_time& delay) {
429  if(!isRecordingNonBlockingTxEnabled())
430  return fw_port->nb_transport_fw(trans, phase, delay);
431  else if(!nb_streamHandle)
432  initialize_streams();
433  /*************************************************************************
434  * prepare recording
435  *************************************************************************/
436  // Get a handle for the new transaction
437  SCVNS scv_tr_handle h = nb_trHandle[FW]->begin_transaction(phase2string(phase));
438  tlm_recording_extension* preExt = nullptr;
439  trans.get_extension(preExt);
440  if(preExt == nullptr) { // we are the first recording this transaction
441  preExt = new tlm_recording_extension(h, this);
442  if(trans.has_mm())
443  trans.set_auto_extension(preExt);
444  else
445  trans.set_extension(preExt);
446  } else {
447  // link handle if we have a predecessor
448  h.add_relation(rel_str(PREDECESSOR_SUCCESSOR), preExt->txHandle);
449  }
450  // update the extension
451  if(preExt)
452  preExt->txHandle = h;
453  h.record_attribute("delay", delay.to_string());
454  for(auto& extensionRecording : tlm_extension_recording_registry<TYPES>::inst().get())
455  if(extensionRecording)
456  extensionRecording->recordBeginTx(h, trans);
457  /*************************************************************************
458  * do the timed notification
459  *************************************************************************/
460  if(nb_streamHandleTimed) {
461  auto* req = mm::get().allocate();
462  req->acquire();
463  (*req) = trans;
464  req->parent = h;
465  nb_timed_peq.notify(*req, phase, delay);
466  }
467  /*************************************************************************
468  * do the access
469  *************************************************************************/
470  tlm::tlm_sync_enum status = fw_port->nb_transport_fw(trans, phase, delay);
471  /*************************************************************************
472  * handle recording
473  *************************************************************************/
474  record(h, status);
475  h.record_attribute("delay[return_path]", delay.to_string());
476  record(h, trans);
477  for(auto& extensionRecording : tlm_extension_recording_registry<TYPES>::inst().get())
478  if(extensionRecording)
479  extensionRecording->recordEndTx(h, trans);
480  // get the extension and free the memory if it was mine
481  if(status == tlm::TLM_COMPLETED || (status == tlm::TLM_ACCEPTED && phase == tlm::END_RESP)) {
482  trans.get_extension(preExt);
483  if(preExt && preExt->get_creator() == this) {
484  trans.set_extension(static_cast<tlm_recording_extension*>(nullptr));
485  if(!trans.has_mm()) {
486  delete preExt;
487  }
488  }
489  /*************************************************************************
490  * do the timed notification if req. finished here
491  *************************************************************************/
492  if(nb_streamHandleTimed) {
493  tlm_recording_payload* req = mm::get().allocate();
494  req->acquire();
495  (*req) = trans;
496  req->parent = h;
497  nb_timed_peq.notify(*req, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase, delay);
498  }
499  } else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
500  tlm_recording_payload* req = mm::get().allocate();
501  req->acquire();
502  (*req) = trans;
503  req->parent = h;
504  nb_timed_peq.notify(*req, phase, delay);
505  }
506  // End the transaction
507  nb_trHandle[FW]->end_transaction(h, phase2string(phase));
508  return status;
509 }
510 
511 template <typename TYPES>
512 tlm::tlm_sync_enum tlm_recorder<TYPES>::nb_transport_bw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
513  sc_core::sc_time& delay) {
514  if(!isRecordingNonBlockingTxEnabled())
515  return bw_port->nb_transport_bw(trans, phase, delay);
516  else if(!nb_streamHandle)
517  initialize_streams();
518  /*************************************************************************
519  * prepare recording
520  *************************************************************************/
521  tlm_recording_extension* preExt = nullptr;
522  trans.get_extension(preExt);
523  // sc_assert(preExt != nullptr && "ERROR on backward path");
524  // Get a handle for the new transaction
525  SCVNS scv_tr_handle h = nb_trHandle[BW]->begin_transaction(phase2string(phase));
526  // link handle if we have a predecessor and that's not ourself
527  if(preExt) {
528  h.add_relation(rel_str(PREDECESSOR_SUCCESSOR), preExt->txHandle);
529  // and set the extension handle to this transaction
530  preExt->txHandle = h;
531  }
532  h.record_attribute("delay", delay.to_string());
533  for(auto& extensionRecording : tlm_extension_recording_registry<TYPES>::inst().get())
534  if(extensionRecording)
535  extensionRecording->recordBeginTx(h, trans);
536  /*************************************************************************
537  * do the timed notification
538  *************************************************************************/
539  if(nb_streamHandleTimed) {
540  tlm_recording_payload* req = mm::get().allocate();
541  req->acquire();
542  (*req) = trans;
543  req->parent = h;
544  nb_timed_peq.notify(*req, phase, delay);
545  }
546  /*************************************************************************
547  * do the access
548  *************************************************************************/
549  tlm::tlm_sync_enum status = bw_port->nb_transport_bw(trans, phase, delay);
550  /*************************************************************************
551  * handle recording
552  *************************************************************************/
553  record(h, status);
554  h.record_attribute("delay[return_path]", delay.to_string());
555  record(h, trans);
556  for(auto& extensionRecording : tlm_extension_recording_registry<TYPES>::inst().get())
557  if(extensionRecording)
558  extensionRecording->recordEndTx(h, trans);
559  // End the transaction
560  nb_trHandle[BW]->end_transaction(h, phase2string(phase));
561  if(status == tlm::TLM_COMPLETED || (status == tlm::TLM_UPDATED && phase == tlm::END_RESP)) {
562  // the transaction is finished
563  if(preExt && preExt->get_creator() == this) {
564  // clean-up the extension if this is the original creator
565  trans.set_extension(static_cast<tlm_recording_extension*>(nullptr));
566  if(!trans.has_mm()) {
567  delete preExt;
568  }
569  }
570  /*************************************************************************
571  * do the timed notification if req. finished here
572  *************************************************************************/
573  if(nb_streamHandleTimed) {
574  tlm_recording_payload* req = mm::get().allocate();
575  req->acquire();
576  (*req) = trans;
577  req->parent = h;
578  nb_timed_peq.notify(*req, phase, delay);
579  }
580  }
581  return status;
582 }
583 
584 template <typename TYPES> void tlm_recorder<TYPES>::nbtx_cb(tlm_recording_payload& rec_parts, const typename TYPES::tlm_phase_type& phase) {
585  SCVNS scv_tr_handle h;
586  std::unordered_map<uint64_t, SCVNS scv_tr_handle>::iterator it;
587  switch(phase) { // Now process outstanding recordings
588  case tlm::BEGIN_REQ:
589  h = nb_trTimedHandle[REQ]->begin_transaction(rel_str(PARENT_CHILD), rec_parts.parent);
590  record(h, rec_parts);
591  nbtx_req_handle_map[rec_parts.id] = h;
592  break;
593  case tlm::END_REQ:
594  it = nbtx_req_handle_map.find(rec_parts.id);
595  sc_assert(it != nbtx_req_handle_map.end());
596  h = it->second;
597  nbtx_req_handle_map.erase(it);
598  h.end_transaction();
599  nbtx_last_req_handle_map[rec_parts.id] = h;
600  break;
601  case tlm::BEGIN_RESP:
602  it = nbtx_req_handle_map.find(rec_parts.id);
603  if(it != nbtx_req_handle_map.end()) {
604  h = it->second;
605  nbtx_req_handle_map.erase(it);
606  h.end_transaction();
607  nbtx_last_req_handle_map[rec_parts.id] = h;
608  }
609  h = nb_trTimedHandle[RESP]->begin_transaction(rel_str(PARENT_CHILD), rec_parts.parent);
610  record(h, rec_parts);
611  nbtx_req_handle_map[rec_parts.id] = h;
612  it = nbtx_last_req_handle_map.find(rec_parts.id);
613  if(it != nbtx_last_req_handle_map.end()) {
614  SCVNS scv_tr_handle pred = it->second;
615  nbtx_last_req_handle_map.erase(it);
616  h.add_relation(rel_str(PREDECESSOR_SUCCESSOR), pred);
617  }
618  break;
619  case tlm::END_RESP:
620  it = nbtx_req_handle_map.find(rec_parts.id);
621  if(it != nbtx_req_handle_map.end()) {
622  h = it->second;
623  nbtx_req_handle_map.erase(it);
624  h.end_transaction();
625  }
626  break;
627  default:
628  // sc_assert(!"phase not supported!");
629  break;
630  }
631  rec_parts.release();
632  return;
633 }
634 
635 template <typename TYPES> bool tlm_recorder<TYPES>::get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) {
636  if(!(m_db && enableDmiTracing.value))
637  return fw_port->get_direct_mem_ptr(trans, dmi_data);
638  else if(!dmi_streamHandle)
639  initialize_streams();
640  SCVNS scv_tr_handle h = dmi_trGetHandle->begin_transaction();
641  bool status = fw_port->get_direct_mem_ptr(trans, dmi_data);
642  record(h, trans);
643  record(h, dmi_data);
644  h.end_transaction();
645  return status;
646 }
653 template <typename TYPES> void tlm_recorder<TYPES>::invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) {
654  if(!(m_db && enableDmiTracing.value)) {
655  bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
656  return;
657  } else if(!dmi_streamHandle)
658  initialize_streams();
659  SCVNS scv_tr_handle h = dmi_trInvalidateHandle->begin_transaction(start_addr);
660  bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
661  dmi_trInvalidateHandle->end_transaction(h, end_addr);
662  return;
663 }
670 template <typename TYPES> unsigned int tlm_recorder<TYPES>::transport_dbg(typename TYPES::tlm_payload_type& trans) {
671  unsigned int count = fw_port->transport_dbg(trans);
672  return count;
673 }
674 
675 } // namespace scv
676 } // namespace scc
677 } // namespace tlm
678 
679 #endif /* TLM2_RECORDER_H_ */
The TLM transaction extensions recorder registry.
The TLM2 transaction recorder.
Definition: tlm_recorder.h:81
void b_transport(typename TYPES::tlm_payload_type &trans, sc_core::sc_time &delay) override
The blocking transport function.
Definition: tlm_recorder.h:342
bool isRecordingBlockingTxEnabled() const
get the current state of transaction recording
Definition: tlm_recorder.h:236
sc_core::sc_attribute< bool > enableBlTracing
the attribute to selectively enable/disable recording of blocking protocol tx
Definition: tlm_recorder.h:94
unsigned int transport_dbg(typename TYPES::tlm_payload_type &trans) override
The debug transportfunction.
Definition: tlm_recorder.h:670
sc_core::sc_attribute< bool > enableTimedTracing
the attribute to selectively enable/disable timed recording
Definition: tlm_recorder.h:100
bool isRecordingNonBlockingTxEnabled() const
get the current state of transaction recording
Definition: tlm_recorder.h:242
bool get_direct_mem_ptr(typename TYPES::tlm_payload_type &trans, tlm::tlm_dmi &dmi_data) override
The direct memory interface forward function.
Definition: tlm_recorder.h:635
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: tlm_recorder.h:427
sc_core::sc_attribute< bool > enableDmiTracing
the attribute to selectively enable/disable DMI recording
Definition: tlm_recorder.h:103
sc_core::sc_attribute< bool > enableNbTracing
the attribute to selectively enable/disable recording of non-blocking protocol tx
Definition: tlm_recorder.h:97
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: tlm_recorder.h:512
sc_core::sc_port_b< tlm::tlm_fw_transport_if< TYPES > > & fw_port
the port where fw accesses are forwarded to
Definition: tlm_recorder.h:106
sc_core::sc_port_b< tlm::tlm_bw_transport_if< TYPES > > & bw_port
the port where bw accesses are forwarded to
Definition: tlm_recorder.h:109
void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override
The direct memory interface backward function.
Definition: tlm_recorder.h:653
generic payload extension class holding the handle of the last recorded SCV transaction
SCVNS scv_tr_handle txHandle
accessor to the SCV transaction handle.
void * get_creator()
accessor to the owner, the property is read only.
a tlm memory manager
Definition: tlm_mm.h:161
SCC SystemC utilities.
const char * rel_str(tx_rel rel)
cast the tx_rel enum to a string
SystemC TLM.