scc 2026.07
SystemC components library
chi_recorder.h
1/*
2 * Copyright 2020, 2021 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 <array>
24#include <cci_configuration>
25#include <chi/chi_tlm.h>
26#include <regex>
27#include <string>
28#include <tlm/scc/scv/tlm_recorder.h>
29#include <tlm/scc/scv/tlm_recording_extension.h>
30#include <tlm_utils/peq_with_cb_and_phase.h>
31#include <unordered_map>
32#include <vector>
33#ifdef HAS_SCV
34#include <scv.h>
35#else
36#include <scv-tr.h>
37#ifndef SCVNS
38#define SCVNS ::scv_tr::
39#endif
40#endif
41
43namespace chi {
44namespace scv {
45namespace {
46inline bool has_credit(chi::chi_protocol_types::tlm_payload_type& trans) {
47 return trans.get_extension<chi::chi_credit_extension<chi::credit_type_e::REQ>>() ||
48 trans.get_extension<chi::chi_credit_extension<chi::credit_type_e::RESP>>() ||
49 trans.get_extension<chi::chi_credit_extension<chi::credit_type_e::DATA>>();
50}
51} // namespace
52
53bool register_extensions();
54
63template <typename TYPES = chi::chi_protocol_types>
64class chi_trx_recorder : public virtual chi::chi_fw_transport_if<TYPES>, public virtual chi::chi_bw_transport_if<TYPES> {
65public:
66 template <unsigned int BUSWIDTH = 32, int N = 1, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
67 using initiator_socket_type = chi::chi_initiator_socket<BUSWIDTH, TYPES, N, POL>;
68
69 template <unsigned int BUSWIDTH = 32, int N = 1, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
70 using target_socket_type = chi::chi_target_socket<BUSWIDTH, TYPES, N, POL>;
71
73 cci::cci_param<bool> enableBlTracing;
74
76 cci::cci_param<bool> enableNbTracing;
77
79 cci::cci_param<bool> enableTimedTracing{"enableTimedTracing", true};
80
82 cci::cci_param<bool> enableDmiTracing{"enableDmiTracing", false};
83
85 cci::cci_param<bool> enableTrDbgTracing{"enableTrDbgTracing", false};
86
88 virtual tlm::tlm_fw_transport_if<TYPES>* get_fw_if() = 0;
89
91 virtual tlm::tlm_bw_transport_if<TYPES>* get_bw_if() = 0;
92
101 chi_trx_recorder(const char* name, bool recording_enabled = true, SCVNS scv_tr_db* tr_db = SCVNS scv_tr_db::get_default_db())
102 : enableBlTracing("enableBlTracing", recording_enabled)
103 , enableNbTracing("enableNbTracing", recording_enabled)
104 , m_db(tr_db)
105 , fixed_basename(name) {
106 register_extensions();
107 }
108
109 virtual ~chi_trx_recorder() override {
110 btx_handle_map.clear();
111 nbtx_req_handle_map.clear();
112 nbtx_last_req_handle_map.clear();
113 nbtx_resp_handle_map.clear();
114 nbtx_last_resp_handle_map.clear();
115 nbtx_data_handle_map.clear();
116 nbtx_last_data_handle_map.clear();
117 nbtx_ack_handle_map.clear();
118
119 delete b_streamHandle;
120 for(auto* p : b_trHandle)
121 delete p; // NOLINT
122 delete b_streamHandleTimed;
123 for(auto* p : b_trTimedHandle)
124 delete p; // NOLINT
125 delete nb_streamHandle;
126 for(auto* p : nb_trHandle)
127 delete p; // NOLINT
128 delete nb_streamHandleTimed;
129 for(auto* p : nb_trTimedHandle)
130 delete p; // NOLINT
131 delete dmi_streamHandle;
132 delete dmi_trGetHandle;
133 delete dmi_trInvalidateHandle;
134 }
135
136 // TLM-2.0 interface methods for initiator and target sockets, surrounded with
137 // Tx Recording
147 tlm::tlm_sync_enum nb_transport_fw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
148 sc_core::sc_time& delay) override;
158 tlm::tlm_sync_enum nb_transport_bw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
159 sc_core::sc_time& delay) override;
168 void b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) override;
177 void b_snoop(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) override;
185 bool get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) override;
192 void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override;
199 unsigned int transport_dbg(typename TYPES::tlm_payload_type& trans) override;
205 inline bool isRecordingBlockingTxEnabled() const { return m_db && enableBlTracing.get_value(); }
211 inline bool isRecordingNonBlockingTxEnabled() const { return m_db && enableNbTracing.get_value(); }
212
213private:
214 void record_nb_timed(typename TYPES::tlm_payload_type& rec_parts, const typename TYPES::tlm_phase_type& phase,
215 sc_core::sc_time const& ts, SCVNS scv_tr_handle parent, bool is_credit);
217 SCVNS scv_tr_db* m_db{nullptr};
219 SCVNS scv_tr_stream* b_streamHandle{nullptr};
221 std::array<SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>*, 3> b_trHandle{{nullptr, nullptr, nullptr}};
223 SCVNS scv_tr_stream* b_streamHandleTimed{nullptr};
226 std::array<SCVNS scv_tr_generator<>*, 3> b_trTimedHandle{{nullptr, nullptr, nullptr}};
227 std::unordered_map<uint64_t, SCVNS scv_tr_handle> btx_handle_map;
228
229 enum DIR { FW, BW, DATA, ACK, CREDIT, REQ = FW, RESP = BW };
230 enum TYPE { READ = tlm::TLM_READ_COMMAND, WRITE = tlm::TLM_WRITE_COMMAND, OTHER = tlm::TLM_IGNORE_COMMAND, SNOOP, NO_OF_TYPES };
232 SCVNS scv_tr_stream* nb_streamHandle{nullptr};
234 SCVNS scv_tr_stream* nb_streamHandleTimed{nullptr};
236 std::array<SCVNS scv_tr_generator<std::string, std::string>*, 2> nb_trHandle{{nullptr, nullptr}};
238 std::array<SCVNS scv_tr_generator<>*, 5> nb_trTimedHandle{{nullptr, nullptr, nullptr, nullptr, nullptr}};
239 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_req_handle_map;
240 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_last_req_handle_map;
241 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_resp_handle_map;
242 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_last_resp_handle_map;
243 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_data_handle_map;
244 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_last_data_handle_map;
245 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_ack_handle_map;
247 SCVNS scv_tr_stream* dmi_streamHandle{nullptr};
249 SCVNS scv_tr_generator<>* dmi_trGetHandle{nullptr};
250 SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>* dmi_trInvalidateHandle{nullptr};
251
252protected:
253 void initialize_streams() {
255 b_streamHandle = new SCVNS scv_tr_stream((fixed_basename + "_bl").c_str(), "[TLM][chi][b]", m_db);
256 b_trHandle[tlm::TLM_READ_COMMAND] =
257 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("read", *b_streamHandle, "start_delay", "end_delay");
258 b_trHandle[tlm::TLM_WRITE_COMMAND] =
259 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("write", *b_streamHandle, "start_delay", "end_delay");
260 b_trHandle[tlm::TLM_IGNORE_COMMAND] =
261 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("ignore", *b_streamHandle, "start_delay", "end_delay");
262 if(enableTimedTracing.get_value()) {
263 b_streamHandleTimed = new SCVNS scv_tr_stream((fixed_basename + "_bl_timed").c_str(), "[TLM][chi][b][timed]", m_db);
264 b_trTimedHandle[tlm::TLM_READ_COMMAND] = new SCVNS scv_tr_generator<>("read", *b_streamHandleTimed);
265 b_trTimedHandle[tlm::TLM_WRITE_COMMAND] = new SCVNS scv_tr_generator<>("write", *b_streamHandleTimed);
266 b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] = new SCVNS scv_tr_generator<>("ignore", *b_streamHandleTimed);
267 }
268 }
269 if(isRecordingNonBlockingTxEnabled() && !nb_streamHandle) {
270 nb_streamHandle = new SCVNS scv_tr_stream((fixed_basename + "_nb").c_str(), "[TLM][chi][nb]", m_db);
271 nb_trHandle[FW] =
272 new SCVNS scv_tr_generator<std::string, std::string>("fw", *nb_streamHandle, "tlm_phase", "tlm_phase[return_path]");
273 nb_trHandle[BW] =
274 new SCVNS scv_tr_generator<std::string, std::string>("bw", *nb_streamHandle, "tlm_phase", "tlm_phase[return_path]");
275 if(enableTimedTracing.get_value()) {
276 nb_streamHandleTimed = new SCVNS scv_tr_stream((fixed_basename + "_nb_timed").c_str(), "[TLM][chi][nb][timed]", m_db);
277 nb_trTimedHandle[REQ] = new SCVNS scv_tr_generator<>("request", *nb_streamHandleTimed);
278 nb_trTimedHandle[RESP] = new SCVNS scv_tr_generator<>("response", *nb_streamHandleTimed);
279 nb_trTimedHandle[DATA] = new SCVNS scv_tr_generator<>("data", *nb_streamHandleTimed);
280 nb_trTimedHandle[ACK] = new SCVNS scv_tr_generator<>("ack", *nb_streamHandleTimed);
281 nb_trTimedHandle[CREDIT] = new SCVNS scv_tr_generator<>("link", *nb_streamHandleTimed);
282 }
283 }
284 if(m_db && enableDmiTracing.get_value() && !dmi_streamHandle) {
285 dmi_streamHandle = new SCVNS scv_tr_stream((fixed_basename + "_dmi").c_str(), "[TLM][ace][dmi]", m_db);
286 dmi_trGetHandle = new SCVNS scv_tr_generator<>("get", *dmi_streamHandle, "trans", "dmi_data");
287 dmi_trInvalidateHandle =
288 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("invalidate", *dmi_streamHandle, "start_addr", "end_addr");
289 }
290 }
291
292private:
293 const std::string fixed_basename;
294
295 inline std::string phase2string(const tlm::tlm_phase& p) {
296 std::stringstream ss;
297 ss << p;
298 return ss.str();
299 }
300};
301
303// implementations of functions
305
306template <typename TYPES> void chi_trx_recorder<TYPES>::b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) {
308 get_fw_if()->b_transport(trans, delay);
309 return;
310 }
311 // Get a handle for the new transaction
312 SCVNS scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_core::sc_time_stamp());
313
314 /*************************************************************************
315 * do the timed notification
316 *************************************************************************/
317 SCVNS scv_tr_handle bh;
318 if(b_streamHandleTimed) {
319 bh = b_trTimedHandle[static_cast<unsigned>(trans.get_command())]->begin_transaction(sc_core::sc_time_stamp() + delay);
320 bh.add_relation(rel_str(tlm::scc::scv::PARENT_CHILD), h);
321 }
322
323 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
324 if(ext)
325 ext->recordBeginTx(h, trans);
327
328 trans.get_extension(preExt);
329 if(preExt == nullptr) { // we are the first recording this transaction
330 preExt = new tlm::scc::scv::tlm_recording_extension(h, this);
331 trans.set_extension(preExt);
332 } else {
334 }
335 SCVNS scv_tr_handle preTx(preExt->txHandle);
336 preExt->txHandle = h;
337 get_fw_if()->b_transport(trans, delay);
338 trans.get_extension(preExt);
339 if(preExt->get_creator() == this) {
340 // clean-up the extension if this is the original creator
341 delete trans.set_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
342 } else {
343 preExt->txHandle = preTx;
344 }
345 tlm::scc::scv::record(h, trans);
346 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
347 if(ext)
348 ext->recordEndTx(h, trans);
349 // End the transaction
350 b_trHandle[trans.get_command()]->end_transaction(h, delay.value(), sc_core::sc_time_stamp());
351 // and now the stuff for the timed tx
352 if(b_streamHandleTimed) {
353 tlm::scc::scv::record(bh, trans);
354 b_trTimedHandle[static_cast<unsigned>(trans.get_command())]->end_transaction(bh, sc_core::sc_time_stamp() + delay);
355 }
356}
357
358template <typename TYPES> void chi_trx_recorder<TYPES>::b_snoop(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) {
359 if(!b_streamHandleTimed) {
360 get_fw_if()->b_transport(trans, delay);
361 return;
362 }
363 // Get a handle for the new transaction
364 SCVNS scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_core::sc_time_stamp());
365 /*************************************************************************
366 * do the timed notification
367 *************************************************************************/
368 SCVNS scv_tr_handle bh;
369 if(b_streamHandleTimed) {
370 bh = b_trTimedHandle[static_cast<unsigned>(trans.get_command())]->begin_transaction(sc_core::sc_time_stamp() + delay);
371 bh.add_relation(rel_str(tlm::scc::scv::PARENT_CHILD), h);
372 }
373
374 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
375 if(ext)
376 ext->recordBeginTx(h, trans);
378
379 trans.get_extension(preExt);
380 if(preExt == NULL) { // we are the first recording this transaction
381 preExt = new tlm::scc::scv::tlm_recording_extension(h, this);
382 trans.set_extension(preExt);
383 } else {
385 }
386 SCVNS scv_tr_handle preTx(preExt->txHandle);
387 preExt->txHandle = h;
388 get_fw_if()->b_transport(trans, delay);
389 trans.get_extension(preExt);
390 if(preExt->get_creator() == this) {
391 // clean-up the extension if this is the original creator
392 delete trans.set_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
393 } else {
394 preExt->txHandle = preTx;
395 }
396
397 tlm::scc::scv::record(h, trans);
398 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
399 if(ext)
400 ext->recordEndTx(h, trans);
401 // End the transaction
402 b_trHandle[trans.get_command()]->end_transaction(h, delay.value());
403 // and now the stuff for the timed tx
404 if(b_streamHandleTimed) {
405 tlm::scc::scv::record(bh, trans);
406 b_trTimedHandle[static_cast<unsigned>(trans.get_command())]->end_transaction(bh, sc_core::sc_time_stamp() + delay);
407 }
408}
409
410template <typename TYPES>
411tlm::tlm_sync_enum chi_trx_recorder<TYPES>::nb_transport_fw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
412 sc_core::sc_time& delay) {
413 if(!nb_trHandle[FW])
414 return get_fw_if()->nb_transport_fw(trans, phase, delay);
415 /*************************************************************************
416 * prepare recording
417 *************************************************************************/
418 // Get a handle for the new transaction
419 bool is_snoop = (trans.template get_extension<chi::chi_snp_extension>() != nullptr);
420 SCVNS scv_tr_handle h = nb_trHandle[FW]->begin_transaction(phase2string(phase));
422 trans.get_extension(preExt);
423 if(phase == tlm::BEGIN_REQ && preExt == nullptr) { // we are the first recording this transaction
424 preExt = new tlm::scc::scv::tlm_recording_extension(h, this);
425 trans.set_extension(preExt);
426 } else if(preExt != nullptr) {
427 // link handle if we have a predecessor
429 } else {
430 sc_assert(preExt != nullptr && "ERROR on forward path in phase other than tlm::BEGIN_REQ");
431 }
432 // update the extension
433 preExt->txHandle = h;
434 h.record_attribute("delay", delay.to_string());
435 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
436 if(ext)
437 ext->recordBeginTx(h, trans);
438 /*************************************************************************
439 * do the timed notification
440 *************************************************************************/
441 if(nb_streamHandleTimed) {
442 record_nb_timed(trans, phase, delay, h, (phase == tlm::BEGIN_REQ && has_credit(trans)));
443 }
444 /*************************************************************************
445 * do the access
446 *************************************************************************/
447 tlm::tlm_sync_enum status = get_fw_if()->nb_transport_fw(trans, phase, delay);
448 /*************************************************************************
449 * handle recording
450 *************************************************************************/
451 tlm::scc::scv::record(h, status);
452 h.record_attribute("delay[return_path]", delay.to_string());
453 tlm::scc::scv::record(h, trans);
454 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
455 if(ext)
456 ext->recordEndTx(h, trans);
457 // get the extension and free the memory if it was mine
458 if(status == tlm::TLM_COMPLETED) {
459 // the transaction is finished
460 trans.get_extension(preExt);
461 if(preExt && preExt->get_creator() == this) {
462 // clean-up the extension if this is the original creator
463 delete trans.set_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
464 }
465 /*************************************************************************
466 * do the timed notification if req. finished here
467 *************************************************************************/
468 if(nb_streamHandleTimed) {
469 record_nb_timed(trans, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase, delay, h,
470 (phase == tlm::BEGIN_REQ && has_credit(trans)));
471 }
472 } else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
473 record_nb_timed(trans, phase, delay, h, (phase == tlm::BEGIN_REQ && has_credit(trans)));
474 }
475 // End the transaction
476 nb_trHandle[FW]->end_transaction(h, phase2string(phase));
477 return status;
478}
479
480template <typename TYPES>
481tlm::tlm_sync_enum chi_trx_recorder<TYPES>::nb_transport_bw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
482 sc_core::sc_time& delay) {
483 if(!nb_trHandle[BW])
484 return get_bw_if()->nb_transport_bw(trans, phase, delay);
485 /*************************************************************************
486 * prepare recording
487 *************************************************************************/
488 // Get a handle for the new transaction
489 bool is_snoop = (trans.template get_extension<chi::chi_snp_extension>() != nullptr);
490 SCVNS scv_tr_handle h = nb_trHandle[BW]->begin_transaction(phase2string(phase));
492 trans.get_extension(preExt);
493 if(phase == tlm::BEGIN_REQ && preExt == nullptr) { // we are the first recording this transaction
494 preExt = new tlm::scc::scv::tlm_recording_extension(h, this);
495 trans.set_extension(preExt);
496 } else if(preExt != nullptr) {
497 // link handle if we have a predecessor
499 } else {
500 sc_assert(preExt != nullptr && "ERROR on backward path in phase other than tlm::BEGIN_REQ");
501 }
502 // and set the extension handle to this transaction
503 preExt->txHandle = h;
504 h.record_attribute("delay", delay.to_string());
505 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
506 if(ext)
507 ext->recordBeginTx(h, trans);
508 /*************************************************************************
509 * do the timed notification
510 *************************************************************************/
511 if(nb_streamHandleTimed) {
512 record_nb_timed(trans, phase, delay, h, (phase == tlm::BEGIN_REQ && has_credit(trans)));
513 }
514 /*************************************************************************
515 * do the access
516 *************************************************************************/
517 tlm::tlm_sync_enum status = get_bw_if()->nb_transport_bw(trans, phase, delay);
518 /*************************************************************************
519 * handle recording
520 *************************************************************************/
521 tlm::scc::scv::record(h, status);
522 h.record_attribute("delay[return_path]", delay.to_string());
523 tlm::scc::scv::record(h, trans);
524 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get())
525 if(ext)
526 ext->recordEndTx(h, trans);
527 // get the extension and free the memory if it was mine
528 if(status == tlm::TLM_COMPLETED) {
529 // the transaction is finished
530 trans.get_extension(preExt);
531 if(preExt->get_creator() == this) {
532 // clean-up the extension if this is the original creator
533 delete trans.set_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
534 }
535 /*************************************************************************
536 * do the timed notification if req. finished here
537 *************************************************************************/
538 if(nb_streamHandleTimed) {
539 record_nb_timed(trans, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase, delay, h,
540 (phase == tlm::BEGIN_REQ && has_credit(trans)));
541 }
542 } else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
543 record_nb_timed(trans, phase, delay, h, (phase == tlm::BEGIN_REQ && has_credit(trans)));
544 }
545 // End the transaction
546 nb_trHandle[BW]->end_transaction(h, phase2string(phase));
547 return status;
548}
549
550template <typename TYPES>
551void chi_trx_recorder<TYPES>::record_nb_timed(typename TYPES::tlm_payload_type& trans, const typename TYPES::tlm_phase_type& phase,
552 sc_core::sc_time const& delay, SCVNS scv_tr_handle parent, bool is_credit) {
553 SCVNS scv_tr_handle h;
554 std::unordered_map<uint64_t, SCVNS scv_tr_handle>::iterator it;
555 auto t = delay + sc_core::sc_time_stamp();
556 auto id = reinterpret_cast<uintptr_t>(&trans);
557 // Now process outstanding recordings
558 if(is_credit) {
559 if(phase == tlm::BEGIN_REQ) {
560 h = nb_trTimedHandle[CREDIT]->begin_transaction(t);
562 nbtx_req_handle_map[id] = h;
563 } else {
564 it = nbtx_req_handle_map.find(id);
565 if(it != nbtx_req_handle_map.end()) {
566 it->second.end_transaction(t);
567 nbtx_req_handle_map.erase(it);
568 }
569 }
570 } else if(phase == tlm::BEGIN_REQ) {
571 h = nb_trTimedHandle[REQ]->begin_transaction(t);
572 tlm::scc::scv::record(h, trans);
574 nbtx_req_handle_map[id] = h;
575 nbtx_last_req_handle_map[id] = h;
576 } else if(phase == tlm::END_REQ) {
577 it = nbtx_req_handle_map.find(id);
578 if(it != nbtx_req_handle_map.end()) {
579 it->second.end_transaction(t);
580 nbtx_req_handle_map.erase(it);
581 }
582 } else if(phase == tlm::BEGIN_RESP) {
583 it = nbtx_req_handle_map.find(id);
584 if(it != nbtx_req_handle_map.end()) {
585 it->second.end_transaction(t);
586 nbtx_req_handle_map.erase(it);
587 }
588 h = nb_trTimedHandle[RESP]->begin_transaction();
589 tlm::scc::scv::record(h, trans);
591 nbtx_resp_handle_map[id] = h;
592 it = nbtx_last_req_handle_map.find(id);
593 if(it != nbtx_last_req_handle_map.end()) {
594 SCVNS scv_tr_handle pred = it->second;
595 nbtx_last_req_handle_map.erase(it);
597 } else {
598 it = nbtx_last_resp_handle_map.find(id);
599 if(it != nbtx_last_resp_handle_map.end()) {
600 SCVNS scv_tr_handle pred = it->second;
601 nbtx_last_resp_handle_map.erase(it);
603 }
604 }
605 } else if(phase == tlm::END_RESP) {
606 it = nbtx_resp_handle_map.find(id);
607 if(it != nbtx_resp_handle_map.end()) {
608 h = it->second;
609 nbtx_resp_handle_map.erase(it);
610 h.end_transaction(t);
611 } else {
612 it = nbtx_req_handle_map.find(id);
613 if(it != nbtx_req_handle_map.end()) {
614 h = it->second;
615 nbtx_req_handle_map.erase(it);
616 h.end_transaction(t);
617 }
618 }
619 } else if(phase == chi::BEGIN_DATA || phase == chi::BEGIN_PARTIAL_DATA) {
620 it = nbtx_req_handle_map.find(id);
621 if(it != nbtx_req_handle_map.end()) {
622 h = it->second;
623 h.end_transaction(t);
624 nbtx_last_req_handle_map[id] = h;
625 }
626 h = nb_trTimedHandle[DATA]->begin_transaction();
627 tlm::scc::scv::record(h, trans);
629 nbtx_data_handle_map[id] = h;
630 it = nbtx_last_data_handle_map.find(id);
631 if(it != nbtx_last_data_handle_map.end()) {
632 SCVNS scv_tr_handle pred = it->second;
633 nbtx_last_data_handle_map.erase(it);
635 }
636 } else if(phase == chi::END_DATA || phase == chi::END_PARTIAL_DATA) {
637 it = nbtx_data_handle_map.find(id);
638 if(it != nbtx_data_handle_map.end()) {
639 h = it->second;
640 nbtx_data_handle_map.erase(it);
641 h.end_transaction(t);
642 }
643 } else if(phase == chi::ACK) {
644 it = nbtx_ack_handle_map.find(id);
645 if(it == nbtx_ack_handle_map.end()) {
646 auto h = nb_trTimedHandle[ACK]->begin_transaction(t);
647 nbtx_ack_handle_map[id] = h;
649 } else {
650 it->second.end_transaction(t);
651 nbtx_ack_handle_map.erase(it);
652 }
653 } else
654 sc_assert(!"phase not supported!");
655}
656
657template <typename TYPES>
658bool chi_trx_recorder<TYPES>::get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) {
659 if(!(m_db && enableDmiTracing.get_value()))
660 return get_fw_if()->get_direct_mem_ptr(trans, dmi_data);
661 else if(!dmi_streamHandle)
662 initialize_streams();
663 SCVNS scv_tr_handle h = dmi_trGetHandle->begin_transaction();
664 bool status = get_fw_if()->get_direct_mem_ptr(trans, dmi_data);
665 tlm::scc::scv::record(h, trans);
666 tlm::scc::scv::record(h, dmi_data);
667 h.end_transaction();
668 return status;
669}
670
676template <typename TYPES> void chi_trx_recorder<TYPES>::invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) {
677 if(!(m_db && enableDmiTracing.get_value())) {
678 get_bw_if()->invalidate_direct_mem_ptr(start_addr, end_addr);
679 return;
680 } else if(!dmi_streamHandle)
681 initialize_streams();
682 SCVNS scv_tr_handle h = dmi_trInvalidateHandle->begin_transaction(start_addr);
683 get_bw_if()->invalidate_direct_mem_ptr(start_addr, end_addr);
684 dmi_trInvalidateHandle->end_transaction(h, end_addr);
685 return;
686}
687
693template <typename TYPES> unsigned int chi_trx_recorder<TYPES>::transport_dbg(typename TYPES::tlm_payload_type& trans) {
694 unsigned int count = get_fw_if()->transport_dbg(trans);
695 return count;
696}
697} // namespace scv
698} // namespace chi
The TLM2 transaction recorder.
cci::cci_param< bool > enableDmiTracing
the attribute to selectively enable/disable DMI recording
virtual tlm::tlm_bw_transport_if< TYPES > * get_bw_if()=0
the port where bw accesses are forwarded to
void b_snoop(typename TYPES::tlm_payload_type &trans, sc_core::sc_time &delay) override
The blocking snoop function.
virtual tlm::tlm_fw_transport_if< TYPES > * get_fw_if()=0
the port where fw accesses are forwarded to
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.
bool get_direct_mem_ptr(typename TYPES::tlm_payload_type &trans, tlm::tlm_dmi &dmi_data) override
The direct memory interface forward function.
cci::cci_param< bool > enableNbTracing
the attribute to selectively enable/disable recording of non-blocking protocol tx
void b_transport(typename TYPES::tlm_payload_type &trans, sc_core::sc_time &delay) override
The blocking transport function.
void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override
The direct memory interface backward function.
cci::cci_param< bool > enableTrDbgTracing
the attribute to selectively enable/disable transport dbg recording
cci::cci_param< bool > enableTimedTracing
the attribute to selectively enable/disable timed recording
unsigned int transport_dbg(typename TYPES::tlm_payload_type &trans) override
The debug transportfunction.
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.
cci::cci_param< bool > enableBlTracing
the attribute to selectively enable/disable recording of blocking protocol tx
bool isRecordingBlockingTxEnabled() const
get the current state of transaction recording
bool isRecordingNonBlockingTxEnabled() const
get the current state of transaction recording
chi_trx_recorder(const char *name, bool recording_enabled=true, SCVNS scv_tr_db *tr_db=SCVNS scv_tr_db::get_default_db())
The constructor of the component.
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.
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:894
const char * rel_str(tx_rel rel)
cast the tx_rel enum to a string