scc 2025.09
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 <chi/chi_tlm.h>
25#include <regex>
26#include <string>
27#include <tlm/scc/scv/tlm_recorder.h>
28#include <tlm/scc/scv/tlm_recording_extension.h>
29#include <tlm_utils/peq_with_cb_and_phase.h>
30#include <unordered_map>
31#include <vector>
32#include <cci_configuration>
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 {
45
46bool register_extensions();
47
56template <typename TYPES = chi::chi_protocol_types>
57class chi_trx_recorder : public virtual chi::chi_fw_transport_if<TYPES>,
58 public virtual chi::chi_bw_transport_if<TYPES> {
59public:
60 template <unsigned int BUSWIDTH = 32, int N = 1, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
61 using initiator_socket_type = chi::chi_initiator_socket<BUSWIDTH, TYPES, N, POL>;
62
63 template <unsigned int BUSWIDTH = 32, int N = 1, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
64 using target_socket_type = chi::chi_target_socket<BUSWIDTH, TYPES, N, POL>;
65
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
79 cci::cci_param<bool> enableTrDbgTracing{"enableTrDbgTracing", false};
80
82 virtual tlm::tlm_fw_transport_if<TYPES>* get_fw_if() = 0;
83
85 virtual tlm::tlm_bw_transport_if<TYPES>* get_bw_if() = 0;
86
95 chi_trx_recorder(const char* name, bool recording_enabled = true,
96 SCVNS scv_tr_db* tr_db = SCVNS scv_tr_db::get_default_db())
97 : enableBlTracing("enableBlTracing", recording_enabled)
98 , enableNbTracing("enableNbTracing", recording_enabled)
99 , m_db(tr_db)
100 , fixed_basename(name) {
101 register_extensions();
102 }
103
104 virtual ~chi_trx_recorder() override {
105 btx_handle_map.clear();
106 nbtx_req_handle_map.clear();
107 nbtx_last_req_handle_map.clear();
108 nbtx_resp_handle_map.clear();
109 nbtx_last_resp_handle_map.clear();
110 nbtx_data_handle_map.clear();
111 nbtx_last_data_handle_map.clear();
112 nbtx_ack_handle_map.clear();
113
114 delete b_streamHandle;
115 for(auto* p : b_trHandle)
116 delete p; // NOLINT
117 delete b_streamHandleTimed;
118 for(auto* p : b_trTimedHandle)
119 delete p; // NOLINT
120 delete nb_streamHandle;
121 for(auto* p : nb_trHandle)
122 delete p; // NOLINT
123 delete nb_streamHandleTimed;
124 for(auto* p : nb_trTimedHandle)
125 delete p; // NOLINT
126 delete dmi_streamHandle;
127 delete dmi_trGetHandle;
128 delete dmi_trInvalidateHandle;
129 }
130
131 // TLM-2.0 interface methods for initiator and target sockets, surrounded with
132 // Tx Recording
142 tlm::tlm_sync_enum nb_transport_fw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
143 sc_core::sc_time& delay) override;
153 tlm::tlm_sync_enum nb_transport_bw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
154 sc_core::sc_time& delay) override;
163 void b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) override;
172 void b_snoop(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) override;
180 bool get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) override;
187 void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override;
194 unsigned int transport_dbg(typename TYPES::tlm_payload_type& trans) override;
200 inline bool isRecordingBlockingTxEnabled() const { return m_db && enableBlTracing.get_value(); }
206 inline bool isRecordingNonBlockingTxEnabled() const { return m_db && enableNbTracing.get_value(); }
207
208private:
209 void record_nb_timed(typename TYPES::tlm_payload_type& rec_parts, const typename TYPES::tlm_phase_type& phase, sc_core::sc_time const& ts, SCVNS scv_tr_handle parent, bool is_credit);
211 SCVNS scv_tr_db* m_db{nullptr};
213 SCVNS scv_tr_stream* b_streamHandle{nullptr};
215 std::array<SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>*, 3> b_trHandle{{nullptr, nullptr, nullptr}};
217 SCVNS scv_tr_stream* b_streamHandleTimed{nullptr};
220 std::array<SCVNS scv_tr_generator<>*, 3> b_trTimedHandle{{nullptr, nullptr, nullptr}};
221 std::unordered_map<uint64_t, SCVNS scv_tr_handle> btx_handle_map;
222
223 enum DIR { FW, BW, DATA, ACK, CREDIT, REQ = FW, RESP = BW };
224 enum TYPE {
225 READ = tlm::TLM_READ_COMMAND,
226 WRITE = tlm::TLM_WRITE_COMMAND,
227 OTHER = tlm::TLM_IGNORE_COMMAND,
228 SNOOP,
229 NO_OF_TYPES
230 };
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] = new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
257 "read", *b_streamHandle, "start_delay", "end_delay");
258 b_trHandle[tlm::TLM_WRITE_COMMAND] = new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
259 "write", *b_streamHandle, "start_delay", "end_delay");
260 b_trHandle[tlm::TLM_IGNORE_COMMAND] = new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
261 "ignore", *b_streamHandle, "start_delay", "end_delay");
262 if(enableTimedTracing.get_value()) {
263 b_streamHandleTimed =
264 new SCVNS scv_tr_stream((fixed_basename + "_bl_timed").c_str(), "[TLM][chi][b][timed]", m_db);
265 b_trTimedHandle[tlm::TLM_READ_COMMAND] = new SCVNS scv_tr_generator<>("read", *b_streamHandleTimed);
266 b_trTimedHandle[tlm::TLM_WRITE_COMMAND] = new SCVNS scv_tr_generator<>("write", *b_streamHandleTimed);
267 b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] = new SCVNS scv_tr_generator<>("ignore", *b_streamHandleTimed);
268 }
269 }
270 if(isRecordingNonBlockingTxEnabled() && !nb_streamHandle) {
271 nb_streamHandle = new SCVNS scv_tr_stream((fixed_basename + "_nb").c_str(), "[TLM][chi][nb]", m_db);
272 nb_trHandle[FW] = new SCVNS scv_tr_generator<std::string, std::string>("fw", *nb_streamHandle, "tlm_phase",
273 "tlm_phase[return_path]");
274 nb_trHandle[BW] = new SCVNS scv_tr_generator<std::string, std::string>("bw", *nb_streamHandle, "tlm_phase",
275 "tlm_phase[return_path]");
276 if(enableTimedTracing.get_value()) {
277 nb_streamHandleTimed =
278 new SCVNS scv_tr_stream((fixed_basename + "_nb_timed").c_str(), "[TLM][chi][nb][timed]", m_db);
279 nb_trTimedHandle[REQ] = new SCVNS scv_tr_generator<>("request", *nb_streamHandleTimed);
280 nb_trTimedHandle[RESP] = new SCVNS scv_tr_generator<>("response", *nb_streamHandleTimed);
281 nb_trTimedHandle[DATA] = new SCVNS scv_tr_generator<>("data", *nb_streamHandleTimed);
282 nb_trTimedHandle[ACK] = new SCVNS scv_tr_generator<>("ack", *nb_streamHandleTimed);
283 nb_trTimedHandle[CREDIT] = new SCVNS scv_tr_generator<>("link", *nb_streamHandleTimed);
284 }
285 }
286 if(m_db && enableDmiTracing.get_value() && !dmi_streamHandle) {
287 dmi_streamHandle = new SCVNS scv_tr_stream((fixed_basename + "_dmi").c_str(), "[TLM][ace][dmi]", m_db);
288 dmi_trGetHandle = new SCVNS scv_tr_generator<>("get", *dmi_streamHandle, "trans", "dmi_data");
289 dmi_trInvalidateHandle = new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
290 "invalidate", *dmi_streamHandle, "start_addr", "end_addr");
291 }
292 }
293
294private:
295 const std::string fixed_basename;
296
297 inline std::string phase2string(const tlm::tlm_phase& p) {
298 std::stringstream ss;
299 ss << p;
300 return ss.str();
301 }
302};
303
305// implementations of functions
307
308template <typename TYPES>
309void chi_trx_recorder<TYPES>::b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) {
311 get_fw_if()->b_transport(trans, delay);
312 return;
313 }
314 // Get a handle for the new transaction
315 SCVNS scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_core::sc_time_stamp());
316
317 /*************************************************************************
318 * do the timed notification
319 *************************************************************************/
320 SCVNS scv_tr_handle bh;
321 if(b_streamHandleTimed) {
322 bh = b_trTimedHandle[static_cast<unsigned>(trans.get_command())]->begin_transaction(sc_core::sc_time_stamp() + delay);
323 bh.add_relation(rel_str(tlm::scc::scv::PARENT_CHILD), h);
324 }
325
326 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
327 if(ext)
328 ext->recordBeginTx(h, trans);
330
331 trans.get_extension(preExt);
332 if(preExt == nullptr) { // we are the first recording this transaction
333 preExt = new tlm::scc::scv::tlm_recording_extension(h, this);
334 trans.set_extension(preExt);
335 } else {
337 }
338 SCVNS scv_tr_handle preTx(preExt->txHandle);
339 preExt->txHandle = h;
340 get_fw_if()->b_transport(trans, delay);
341 trans.get_extension(preExt);
342 if(preExt->get_creator() == this) {
343 // clean-up the extension if this is the original creator
344 delete trans.set_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
345 } else {
346 preExt->txHandle = preTx;
347 }
348 tlm::scc::scv::record(h, trans);
349 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
350 if(ext)
351 ext->recordEndTx(h, trans);
352 // End the transaction
353 b_trHandle[trans.get_command()]->end_transaction(h, delay.value(), sc_core::sc_time_stamp());
354 // and now the stuff for the timed tx
355 if(b_streamHandleTimed) {
356 tlm::scc::scv::record(bh, trans);
357 b_trTimedHandle[static_cast<unsigned>(trans.get_command())]->end_transaction(bh, sc_core::sc_time_stamp()+ delay);
358 }
359}
360
361template <typename TYPES>
362void chi_trx_recorder<TYPES>::b_snoop(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) {
363 if(!b_streamHandleTimed) {
364 get_fw_if()->b_transport(trans, delay);
365 return;
366 }
367 // Get a handle for the new transaction
368 SCVNS scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_core::sc_time_stamp());
369 /*************************************************************************
370 * do the timed notification
371 *************************************************************************/
372 SCVNS scv_tr_handle bh;
373 if(b_streamHandleTimed) {
374 bh = b_trTimedHandle[static_cast<unsigned>(trans.get_command())]->begin_transaction(sc_core::sc_time_stamp() + delay);
375 bh.add_relation(rel_str(tlm::scc::scv::PARENT_CHILD), h);
376 }
377
378 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
379 if(ext)
380 ext->recordBeginTx(h, trans);
382
383 trans.get_extension(preExt);
384 if(preExt == NULL) { // we are the first recording this transaction
385 preExt = new tlm::scc::scv::tlm_recording_extension(h, this);
386 trans.set_extension(preExt);
387 } else {
389 }
390 SCVNS scv_tr_handle preTx(preExt->txHandle);
391 preExt->txHandle = h;
392 get_fw_if()->b_transport(trans, delay);
393 trans.get_extension(preExt);
394 if(preExt->get_creator() == this) {
395 // clean-up the extension if this is the original creator
396 delete trans.set_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
397 } else {
398 preExt->txHandle = preTx;
399 }
400
401 tlm::scc::scv::record(h, trans);
402 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
403 if(ext)
404 ext->recordEndTx(h, trans);
405 // End the transaction
406 b_trHandle[trans.get_command()]->end_transaction(h, delay.value());
407 // and now the stuff for the timed tx
408 if(b_streamHandleTimed) {
409 tlm::scc::scv::record(bh, trans);
410 b_trTimedHandle[static_cast<unsigned>(trans.get_command())]->end_transaction(bh, sc_core::sc_time_stamp()+ delay);
411 }
412}
413
414template <typename TYPES>
415tlm::tlm_sync_enum chi_trx_recorder<TYPES>::nb_transport_fw(typename TYPES::tlm_payload_type& trans,
416 typename TYPES::tlm_phase_type& phase,
417 sc_core::sc_time& delay) {
418 if(!nb_trHandle[FW])
419 return get_fw_if()->nb_transport_fw(trans, phase, delay);
420 /*************************************************************************
421 * prepare recording
422 *************************************************************************/
423 // Get a handle for the new transaction
424 bool is_snoop = (trans.template get_extension<chi::chi_snp_extension>() != nullptr);
425 SCVNS scv_tr_handle h = nb_trHandle[FW]->begin_transaction(phase2string(phase));
427 trans.get_extension(preExt);
428 if(phase == tlm::BEGIN_REQ && preExt == nullptr) { // we are the first recording this transaction
429 preExt = new tlm::scc::scv::tlm_recording_extension(h, this);
430 trans.set_extension(preExt);
431 } else if(preExt != nullptr) {
432 // link handle if we have a predecessor
434 } else {
435 sc_assert(preExt != nullptr && "ERROR on forward path in phase other than tlm::BEGIN_REQ");
436 }
437 // update the extension
438 preExt->txHandle = h;
439 h.record_attribute("delay", delay.to_string());
440 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
441 if(ext)
442 ext->recordBeginTx(h, trans);
443 /*************************************************************************
444 * do the timed notification
445 *************************************************************************/
446 chi::chi_credit_extension* chi_ext{nullptr} ;
447 trans.get_extension(chi_ext);
448 if(nb_streamHandleTimed) {
449 record_nb_timed(trans, phase, delay, h, (phase == tlm::BEGIN_REQ && chi_ext != nullptr));
450 }
451 /*************************************************************************
452 * do the access
453 *************************************************************************/
454 tlm::tlm_sync_enum status = get_fw_if()->nb_transport_fw(trans, phase, delay);
455 /*************************************************************************
456 * handle recording
457 *************************************************************************/
458 tlm::scc::scv::record(h, status);
459 h.record_attribute("delay[return_path]", delay.to_string());
460 tlm::scc::scv::record(h, trans);
461 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
462 if(ext)
463 ext->recordEndTx(h, trans);
464 // get the extension and free the memory if it was mine
465 if(status == tlm::TLM_COMPLETED) {
466 // the transaction is finished
467 trans.get_extension(preExt);
468 if(preExt && preExt->get_creator() == this) {
469 // clean-up the extension if this is the original creator
470 delete trans.set_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
471 }
472 /*************************************************************************
473 * do the timed notification if req. finished here
474 *************************************************************************/
475 if(nb_streamHandleTimed) {
476 record_nb_timed(trans, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase,delay, h, (phase == tlm::BEGIN_REQ && chi_ext != nullptr));
477 }
478 } else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
479 record_nb_timed(trans, phase, delay, h, (phase == tlm::BEGIN_REQ && chi_ext != nullptr));
480 }
481 // End the transaction
482 nb_trHandle[FW]->end_transaction(h, phase2string(phase));
483 return status;
484}
485
486template <typename TYPES>
487tlm::tlm_sync_enum chi_trx_recorder<TYPES>::nb_transport_bw(typename TYPES::tlm_payload_type& trans,
488 typename TYPES::tlm_phase_type& phase,
489 sc_core::sc_time& delay) {
490 if(!nb_trHandle[BW])
491 return get_bw_if()->nb_transport_bw(trans, phase, delay);
492 /*************************************************************************
493 * prepare recording
494 *************************************************************************/
495 // Get a handle for the new transaction
496 bool is_snoop = (trans.template get_extension<chi::chi_snp_extension>() != nullptr);
497 SCVNS scv_tr_handle h = nb_trHandle[BW]->begin_transaction(phase2string(phase));
499 trans.get_extension(preExt);
500 if(phase == tlm::BEGIN_REQ && preExt == nullptr) { // we are the first recording this transaction
501 preExt = new tlm::scc::scv::tlm_recording_extension(h, this);
502 trans.set_extension(preExt);
503 } else if(preExt != nullptr) {
504 // link handle if we have a predecessor
506 } else {
507 sc_assert(preExt != nullptr && "ERROR on backward path in phase other than tlm::BEGIN_REQ");
508 }
509 // and set the extension handle to this transaction
510 preExt->txHandle = h;
511 h.record_attribute("delay", delay.to_string());
512 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
513 if(ext)
514 ext->recordBeginTx(h, trans);
515 /*************************************************************************
516 * do the timed notification
517 *************************************************************************/
519 trans.get_extension(chi_ext);
520 if(nb_streamHandleTimed) {
521 record_nb_timed(trans, phase, delay, h, (phase == tlm::BEGIN_REQ && chi_ext != nullptr));
522 }
523 /*************************************************************************
524 * do the access
525 *************************************************************************/
526 tlm::tlm_sync_enum status = get_bw_if()->nb_transport_bw(trans, phase, delay);
527 /*************************************************************************
528 * handle recording
529 *************************************************************************/
530 tlm::scc::scv::record(h, status);
531 h.record_attribute("delay[return_path]", delay.to_string());
532 tlm::scc::scv::record(h, trans);
533 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
534 if(ext)
535 ext->recordEndTx(h, trans);
536 // get the extension and free the memory if it was mine
537 if(status == tlm::TLM_COMPLETED) {
538 // the transaction is finished
539 trans.get_extension(preExt);
540 if(preExt->get_creator() == this) {
541 // clean-up the extension if this is the original creator
542 delete trans.set_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
543 }
544 /*************************************************************************
545 * do the timed notification if req. finished here
546 *************************************************************************/
547 if(nb_streamHandleTimed) {
548 record_nb_timed(trans, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase, delay, h, (phase == tlm::BEGIN_REQ && chi_ext != nullptr));
549 }
550 } else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
551 record_nb_timed(trans, phase, delay, h, (phase == tlm::BEGIN_REQ && chi_ext != nullptr));
552
553 }
554 // End the transaction
555 nb_trHandle[BW]->end_transaction(h, phase2string(phase));
556 return status;
557}
558
559template <typename TYPES>
560void chi_trx_recorder<TYPES>::record_nb_timed(typename TYPES::tlm_payload_type& trans, const typename TYPES::tlm_phase_type& phase, sc_core::sc_time const& delay, SCVNS scv_tr_handle parent, bool is_credit) {
561 SCVNS scv_tr_handle h;
562 std::unordered_map<uint64_t, SCVNS scv_tr_handle>::iterator it;
563 auto t = delay+sc_core::sc_time_stamp();
564 auto id = reinterpret_cast<uintptr_t>(&trans);
565 // Now process outstanding recordings
566 if(is_credit) {
567 if(phase == tlm::BEGIN_REQ) {
568 h = nb_trTimedHandle[CREDIT]->begin_transaction(t);
570 nbtx_req_handle_map[id] = h;
571 } else {
572 it = nbtx_req_handle_map.find(id);
573 if(it != nbtx_req_handle_map.end()) {
574 it->second.end_transaction(t);
575 nbtx_req_handle_map.erase(it);
576 }
577 }
578 } else if(phase == tlm::BEGIN_REQ) {
579 h = nb_trTimedHandle[REQ]->begin_transaction(t);
580 tlm::scc::scv::record(h, trans);
582 nbtx_req_handle_map[id] = h;
583 nbtx_last_req_handle_map[id] = h;
584 } else if(phase == tlm::END_REQ) {
585 it = nbtx_req_handle_map.find(id);
586 if(it != nbtx_req_handle_map.end()) {
587 it->second.end_transaction(t);
588 nbtx_req_handle_map.erase(it);
589 }
590 } else if(phase == tlm::BEGIN_RESP) {
591 it = nbtx_req_handle_map.find(id);
592 if(it != nbtx_req_handle_map.end()) {
593 it->second.end_transaction(t);
594 nbtx_req_handle_map.erase(it);
595 }
596 h = nb_trTimedHandle[RESP]->begin_transaction();
597 tlm::scc::scv::record(h, trans);
599 nbtx_resp_handle_map[id] = h;
600 it = nbtx_last_req_handle_map.find(id);
601 if(it != nbtx_last_req_handle_map.end()) {
602 SCVNS scv_tr_handle pred = it->second;
603 nbtx_last_req_handle_map.erase(it);
605 } else {
606 it = nbtx_last_resp_handle_map.find(id);
607 if(it != nbtx_last_resp_handle_map.end()) {
608 SCVNS scv_tr_handle pred = it->second;
609 nbtx_last_resp_handle_map.erase(it);
611 }
612 }
613 } else if(phase == tlm::END_RESP) {
614 it = nbtx_resp_handle_map.find(id);
615 if(it != nbtx_resp_handle_map.end()) {
616 h = it->second;
617 nbtx_resp_handle_map.erase(it);
618 h.end_transaction(t);
619 } else {
620 it = nbtx_req_handle_map.find(id);
621 if(it != nbtx_req_handle_map.end()) {
622 h = it->second;
623 nbtx_req_handle_map.erase(it);
624 h.end_transaction(t);
625 }
626 }
627 } else if(phase == chi::BEGIN_DATA || phase == chi::BEGIN_PARTIAL_DATA) {
628 it = nbtx_req_handle_map.find(id);
629 if(it != nbtx_req_handle_map.end()) {
630 h = it->second;
631 h.end_transaction(t);
632 nbtx_last_req_handle_map[id] = h;
633 }
634 h = nb_trTimedHandle[DATA]->begin_transaction();
635 tlm::scc::scv::record(h, trans);
637 nbtx_data_handle_map[id] = h;
638 it = nbtx_last_data_handle_map.find(id);
639 if(it != nbtx_last_data_handle_map.end()) {
640 SCVNS scv_tr_handle pred = it->second;
641 nbtx_last_data_handle_map.erase(it);
643 }
644 } else if(phase == chi::END_DATA || phase == chi::END_PARTIAL_DATA) {
645 it = nbtx_data_handle_map.find(id);
646 if(it != nbtx_data_handle_map.end()) {
647 h = it->second;
648 nbtx_data_handle_map.erase(it);
649 h.end_transaction(t);
650 }
651 } else if(phase == chi::ACK) {
652 it = nbtx_ack_handle_map.find(id);
653 if(it == nbtx_ack_handle_map.end()) {
654 auto h = nb_trTimedHandle[ACK]->begin_transaction(t);
655 nbtx_ack_handle_map[id] = h;
657 } else {
658 it->second.end_transaction(t);
659 nbtx_ack_handle_map.erase(it);
660 }
661 } else
662 sc_assert(!"phase not supported!");
663}
664
665template <typename TYPES>
666bool chi_trx_recorder<TYPES>::get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) {
667 if(!(m_db && enableDmiTracing.get_value()))
668 return get_fw_if()->get_direct_mem_ptr(trans, dmi_data);
669 else if(!dmi_streamHandle)
670 initialize_streams();
671 SCVNS scv_tr_handle h = dmi_trGetHandle->begin_transaction();
672 bool status = get_fw_if()->get_direct_mem_ptr(trans, dmi_data);
673 tlm::scc::scv::record(h, trans);
674 tlm::scc::scv::record(h, dmi_data);
675 h.end_transaction();
676 return status;
677}
678
684template <typename TYPES>
685void chi_trx_recorder<TYPES>::invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) {
686 if(!(m_db && enableDmiTracing.get_value())) {
687 get_bw_if()->invalidate_direct_mem_ptr(start_addr, end_addr);
688 return;
689 } else if(!dmi_streamHandle)
690 initialize_streams();
691 SCVNS scv_tr_handle h = dmi_trInvalidateHandle->begin_transaction(start_addr);
692 get_bw_if()->invalidate_direct_mem_ptr(start_addr, end_addr);
693 dmi_trInvalidateHandle->end_transaction(h, end_addr);
694 return;
695}
696
702template <typename TYPES> unsigned int chi_trx_recorder<TYPES>::transport_dbg(typename TYPES::tlm_payload_type& trans) {
703 unsigned int count = get_fw_if()->transport_dbg(trans);
704 return count;
705}
706} // namespace scv
707} // 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:904
const char * rel_str(tx_rel rel)
cast the tx_rel enum to a string