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