scc 2026.07
SystemC components library
ace_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 <axi/axi_tlm.h>
25#include <axi/checker/checker_if.h>
26#include <cci_configuration>
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
34namespace axi {
35namespace scv {
36
37bool register_extensions();
38
47template <typename TYPES = axi::axi_protocol_types>
48class ace_recorder : public virtual axi::ace_fw_transport_if<TYPES>, public virtual axi::ace_bw_transport_if<TYPES> {
49public:
50 template <unsigned int BUSWIDTH = 32, int N = 1, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
51 using initiator_socket_type = axi::ace_initiator_socket<BUSWIDTH, TYPES, N, POL>;
52
53 template <unsigned int BUSWIDTH = 32, int N = 1, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
54 using target_socket_type = axi::ace_target_socket<BUSWIDTH, TYPES, N, POL>;
55
57 cci::cci_param<bool> enableBlTracing;
58
60 cci::cci_param<bool> enableNbTracing;
61
63 cci::cci_param<bool> enableTimedTracing{"enableTimedTracing", true};
64
66 cci::cci_param<bool> enableDmiTracing{"enableDmiTracing", false};
67
69 cci::cci_param<bool> enableTrDbgTracing{"enableTrDbgTracing", false};
70
72 cci::cci_param<bool> enableProtocolChecker{"enableProtocolChecker", false};
73
74 cci::cci_param<unsigned> rd_response_timeout{"rd_response_timeout", 0};
75
76 cci::cci_param<unsigned> wr_response_timeout{"wr_response_timeout", 0};
77
80
83
92 ace_recorder(const char* name, unsigned bus_width, bool recording_enabled = true,
93 SCVNS scv_tr_db* tr_db = SCVNS scv_tr_db::get_default_db())
94 : enableBlTracing("enableBlTracing", recording_enabled)
95 , enableNbTracing("enableNbTracing", recording_enabled)
96 , m_db(tr_db)
97 , fixed_basename(name) {
98 register_extensions();
99 }
100
101 virtual ~ace_recorder() override {
102 nbtx_req_handle_map.clear();
103 nbtx_last_req_handle_map.clear();
104 nbtx_resp_handle_map.clear();
105 nbtx_last_resp_handle_map.clear();
106 delete b_streamHandle;
107 for(auto* p : b_trHandle)
108 delete p; // NOLINT
109 delete b_streamHandleTimed;
110 for(auto* p : b_trTimedHandle)
111 delete p; // NOLINT
112 delete nb_streamHandle;
113 for(auto* p : nb_trHandle)
114 delete p; // NOLINT
115 delete nb_streamHandleTimed;
116 for(auto* p : nb_trTimedHandle)
117 delete p; // NOLINT
118 delete dmi_streamHandle;
119 delete dmi_trGetHandle;
120 delete dmi_trInvalidateHandle;
121 }
122
123 // TLM-2.0 interface methods for initiator and target sockets, surrounded with
124 // Tx Recording
134 tlm::tlm_sync_enum nb_transport_fw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
135 sc_core::sc_time& delay) override;
145 tlm::tlm_sync_enum nb_transport_bw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
146 sc_core::sc_time& delay) override;
155 void b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) override;
164 void b_snoop(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) override;
172 bool get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) override;
179 void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override;
186 unsigned int transport_dbg(typename TYPES::tlm_payload_type& trans) override;
192 inline bool isRecordingBlockingTxEnabled() const { return m_db && enableBlTracing.get_value(); }
198 inline bool isRecordingNonBlockingTxEnabled() const { return m_db && enableNbTracing.get_value(); }
199
200private:
205 void record_nb_tx(typename TYPES::tlm_payload_type&, const typename TYPES::tlm_phase_type&, sc_core::sc_time, SCVNS scv_tr_handle,
206 bool);
208 SCVNS scv_tr_db* m_db{nullptr};
210 SCVNS scv_tr_stream* b_streamHandle{nullptr};
212 std::array<SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>*, 3> b_trHandle{{nullptr, nullptr, nullptr}};
214 SCVNS scv_tr_stream* b_streamHandleTimed{nullptr};
217 std::array<SCVNS scv_tr_generator<>*, 3> b_trTimedHandle{{nullptr, nullptr, nullptr}};
218 std::unordered_map<uint64_t, SCVNS scv_tr_handle> btx_handle_map;
219
220 enum DIR { FW, BW, REQ = FW, RESP = BW, ACK };
222 SCVNS scv_tr_stream* nb_streamHandle{nullptr};
224 SCVNS scv_tr_stream* nb_streamHandleTimed{nullptr};
226 std::array<SCVNS scv_tr_generator<std::string, std::string>*, 2> nb_trHandle{{nullptr, nullptr}};
228 std::array<SCVNS scv_tr_generator<>*, 3> nb_trTimedHandle{{nullptr, nullptr, nullptr}};
229 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_req_handle_map;
230 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_last_req_handle_map;
231 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_resp_handle_map;
232 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_last_resp_handle_map;
234 SCVNS scv_tr_stream* dmi_streamHandle{nullptr};
236 SCVNS scv_tr_generator<>* dmi_trGetHandle{nullptr};
237 SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>* dmi_trInvalidateHandle{nullptr};
238
239protected:
240 void initialize_streams() {
242 b_streamHandle = new SCVNS scv_tr_stream((fixed_basename + "_bl").c_str(), "[TLM][ace][b]", m_db);
243 b_trHandle[tlm::TLM_READ_COMMAND] =
244 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("read", *b_streamHandle, "start_delay", "end_delay");
245 b_trHandle[tlm::TLM_WRITE_COMMAND] =
246 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("write", *b_streamHandle, "start_delay", "end_delay");
247 b_trHandle[tlm::TLM_IGNORE_COMMAND] =
248 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("ignore", *b_streamHandle, "start_delay", "end_delay");
249 if(enableTimedTracing.get_value()) {
250 b_streamHandleTimed = new SCVNS scv_tr_stream((fixed_basename + "_bl_timed").c_str(), "[TLM][ace][b][timed]", m_db);
251 b_trTimedHandle[tlm::TLM_READ_COMMAND] = new SCVNS scv_tr_generator<>("read", *b_streamHandleTimed);
252 b_trTimedHandle[tlm::TLM_WRITE_COMMAND] = new SCVNS scv_tr_generator<>("write", *b_streamHandleTimed);
253 b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] = new SCVNS scv_tr_generator<>("ignore", *b_streamHandleTimed);
254 }
255 }
256 if(isRecordingNonBlockingTxEnabled() && !nb_streamHandle) {
257 nb_streamHandle = new SCVNS scv_tr_stream((fixed_basename + "_nb").c_str(), "[TLM][ace][nb]", m_db);
258 nb_trHandle[FW] =
259 new SCVNS scv_tr_generator<std::string, std::string>("fw", *nb_streamHandle, "tlm_phase", "tlm_phase[return_path]");
260 nb_trHandle[BW] =
261 new SCVNS scv_tr_generator<std::string, std::string>("bw", *nb_streamHandle, "tlm_phase", "tlm_phase[return_path]");
262 if(enableTimedTracing.get_value()) {
263 nb_streamHandleTimed = new SCVNS scv_tr_stream((fixed_basename + "_nb_timed").c_str(), "[TLM][ace][nb][timed]", m_db);
264 nb_trTimedHandle[FW] = new SCVNS scv_tr_generator<>("request", *nb_streamHandleTimed);
265 nb_trTimedHandle[BW] = new SCVNS scv_tr_generator<>("response", *nb_streamHandleTimed);
266 nb_trTimedHandle[ACK] = new SCVNS scv_tr_generator<>("ack", *nb_streamHandleTimed);
267 }
268 }
269 if(m_db && enableDmiTracing.get_value() && !dmi_streamHandle) {
270 dmi_streamHandle = new SCVNS scv_tr_stream((fixed_basename + "_dmi").c_str(), "[TLM][ace][dmi]", m_db);
271 dmi_trGetHandle = new SCVNS scv_tr_generator<>("get", *dmi_streamHandle);
272 dmi_trInvalidateHandle =
273 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("invalidate", *dmi_streamHandle, "start_addr", "end_addr");
274 }
275 // if(enableProtocolChecker.get_value()) {
276 // checker=new axi::checker::ace_protocol(fixed_basename, bus_width/8, rd_response_timeout.get_value(),
277 // wr_response_timeout.get_value());
278 // }
279 }
280
281private:
282 const std::string fixed_basename;
283 axi::checker::checker_if<TYPES>* checker{nullptr};
284};
285
287// implementations of functions
289
290template <typename TYPES> void ace_recorder<TYPES>::b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) {
292 get_fw_if()->b_transport(trans, delay);
293 return;
294 }
295 // Get a handle for the new transaction
296 SCVNS scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_core::sc_time_stamp());
297 /*************************************************************************
298 * do the timed notification
299 *************************************************************************/
300 SCVNS scv_tr_handle bh;
301 if(b_streamHandleTimed) {
302 bh = b_trTimedHandle[trans.get_command()]->begin_transaction(sc_core::sc_time_stamp() + delay);
304 }
305
306 auto addr = trans.get_address();
307 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get().get())
308 if(ext)
309 ext->recordBeginTx(h, trans);
311
312 trans.get_extension(preExt);
313 if(preExt == nullptr) { // we are the first recording this transaction
314 preExt = new tlm::scc::scv::tlm_recording_extension(h, this);
315 if(trans.has_mm())
316 trans.set_auto_extension(preExt);
317 else
318 trans.set_extension(preExt);
319 } else {
321 }
322 SCVNS scv_tr_handle preTx(preExt->txHandle);
323 preExt->txHandle = h;
324 get_fw_if()->b_transport(trans, delay);
325 trans.get_extension(preExt);
326 if(preExt->get_creator() == this) {
327 // clean-up the extension if this is the original creator
328 if(trans.has_mm())
329 trans.set_auto_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
330 else
331 delete trans.set_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
332 } else {
333 preExt->txHandle = preTx;
334 }
335
336 trans.set_address(addr);
337 tlm::scc::scv::record(h, trans);
338 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get().get())
339 if(ext)
340 ext->recordEndTx(h, trans);
341 // End the transaction
342 b_trHandle[trans.get_command()]->end_transaction(h, delay.value(), sc_core::sc_time_stamp());
343 // and now the stuff for the timed tx
344 if(bh.is_valid()) {
345 tlm::scc::scv::record(bh, trans);
346 bh.end_transaction(sc_core::sc_time_stamp() + delay);
347 }
348}
349
350template <typename TYPES> void ace_recorder<TYPES>::b_snoop(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) {
351 if(!b_streamHandleTimed) {
352 get_fw_if()->b_transport(trans, delay);
353 return;
354 }
355 // Get a handle for the new transaction
356 SCVNS scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_core::sc_time_stamp());
357 /*************************************************************************
358 * do the timed notification
359 *************************************************************************/
360 SCVNS scv_tr_handle bh;
361 if(b_streamHandleTimed) {
362 bh = b_trTimedHandle[trans.get_command()]->begin_transaction(sc_core::sc_time_stamp() + delay);
364 }
365
366 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get().get())
367 if(ext)
368 ext->recordBeginTx(h, trans);
370
371 trans.get_extension(preExt);
372 if(preExt == NULL) { // we are the first recording this transaction
373 preExt = new tlm::scc::scv::tlm_recording_extension(h, this);
374 if(trans.has_mm())
375 trans.set_auto_extension(preExt);
376 else
377 trans.set_extension(preExt);
378 } else {
380 }
381 SCVNS scv_tr_handle preTx(preExt->txHandle);
382 preExt->txHandle = h;
383 get_bw_if()->b_snoop(trans, delay);
384 trans.get_extension(preExt);
385 if(preExt->get_creator() == this) {
386 // clean-up the extension if this is the original creator
387 if(trans.has_mm())
388 trans.set_auto_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
389 else
390 delete trans.set_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
391 } else {
392 preExt->txHandle = preTx;
393 }
394
395 tlm::scc::scv::record(h, trans);
396 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get().get())
397 if(ext)
398 ext->recordEndTx(h, trans);
399 // End the transaction
400 b_trHandle[trans.get_command()]->end_transaction(h, delay.value(), sc_core::sc_time_stamp());
401 // and now the stuff for the timed tx
402 if(bh.is_valid()) {
403 tlm::scc::scv::record(bh, trans);
404 bh.end_transaction(sc_core::sc_time_stamp() + delay);
405 }
406}
407
408template <typename TYPES>
409tlm::tlm_sync_enum ace_recorder<TYPES>::nb_transport_fw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
410 sc_core::sc_time& delay) {
412 if(checker) {
413 checker->fw_pre(trans, phase);
414 tlm::tlm_sync_enum status = get_fw_if()->nb_transport_fw(trans, phase, delay);
415 checker->fw_post(trans, phase, status);
416 return status;
417 } else
418 return get_fw_if()->nb_transport_fw(trans, phase, delay);
419 }
420 /*************************************************************************
421 * prepare recording
422 *************************************************************************/
423 // Get a handle for the new transaction
424 SCVNS scv_tr_handle h = nb_trHandle[FW]->begin_transaction(phase.get_name());
426 trans.get_extension(preExt);
427 if((phase == axi::BEGIN_PARTIAL_REQ || phase == tlm::BEGIN_REQ) && preExt == nullptr) { // we are the first recording this transaction
428 preExt = new tlm::scc::scv::tlm_recording_extension(h, this);
429 if(trans.has_mm())
430 trans.set_auto_extension(preExt);
431 else
432 trans.set_extension(preExt);
433 } else if(preExt != nullptr) {
434 // link handle if we have a predecessor
436 } else {
437 sc_assert(preExt != nullptr && "ERROR on forward path in phase other than tlm::BEGIN_REQ");
438 }
439 // update the extension
440 preExt->txHandle = h;
441 h.record_attribute("delay", delay.to_string());
442 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get().get())
443 if(ext)
444 ext->recordBeginTx(h, trans);
445 /*************************************************************************
446 * do the timed notification
447 *************************************************************************/
448 if(nb_streamHandleTimed) {
449 record_nb_tx(trans, phase, sc_core::sc_time_stamp() + delay, h, phase == tlm::BEGIN_RESP || phase == axi::BEGIN_PARTIAL_RESP);
450 }
451 /*************************************************************************
452 * do the access
453 *************************************************************************/
454 if(checker)
455 checker->fw_pre(trans, phase);
456 tlm::tlm_sync_enum status = get_fw_if()->nb_transport_fw(trans, phase, delay);
457 if(checker)
458 checker->fw_post(trans, phase, status);
459 /*************************************************************************
460 * handle recording
461 *************************************************************************/
462 tlm::scc::scv::record(h, status);
463 h.record_attribute("delay[return_path]", delay.to_string());
464 tlm::scc::scv::record(h, trans);
465 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get().get())
466 if(ext)
467 ext->recordEndTx(h, trans);
468 // get the extension and free the memory if it was mine
469 if(status == tlm::TLM_COMPLETED || (phase == axi::ACK)) {
470 // the transaction is finished
471 trans.get_extension(preExt);
472 if(preExt && preExt->get_creator() == this) {
473 // clean-up the extension if this is the original creator
474 if(trans.has_mm())
475 trans.set_auto_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
476 else
477 delete trans.set_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
478 }
479 /*************************************************************************
480 * do the timed notification if req. finished here
481 *************************************************************************/
482 if(nb_streamHandleTimed) {
483 record_nb_tx(trans, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase,
484 sc_core::sc_time_stamp() + delay, h, false);
485 }
486 } else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
487 record_nb_tx(trans, phase, sc_core::sc_time_stamp() + delay, h, false);
488 }
489 // End the transaction
490 nb_trHandle[FW]->end_transaction(h, phase.get_name());
491 return status;
492}
493
494template <typename TYPES>
495tlm::tlm_sync_enum ace_recorder<TYPES>::nb_transport_bw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
496 sc_core::sc_time& delay) {
498 if(checker) {
499 checker->bw_pre(trans, phase);
500 tlm::tlm_sync_enum status = get_bw_if()->nb_transport_bw(trans, phase, delay);
501 checker->bw_post(trans, phase, status);
502 return status;
503 } else
504 return get_bw_if()->nb_transport_bw(trans, phase, delay);
505 }
506 /*************************************************************************
507 * prepare recording
508 *************************************************************************/
509 // Get a handle for the new transaction
510 SCVNS scv_tr_handle h = nb_trHandle[BW]->begin_transaction(phase.get_name());
512 trans.get_extension(preExt);
513 if(phase == tlm::BEGIN_REQ && preExt == nullptr) { // we are the first recording this transaction
514 preExt = new tlm::scc::scv::tlm_recording_extension(h, this);
515 if(trans.has_mm())
516 trans.set_auto_extension(preExt);
517 else
518 trans.set_extension(preExt);
519 } else if(preExt != nullptr) {
520 // link handle if we have a predecessor
522 } else {
523 sc_assert(preExt != nullptr && "ERROR on backward path in phase other than tlm::BEGIN_REQ");
524 }
525 // and set the extension handle to this transaction
526 preExt->txHandle = h;
527 h.record_attribute("delay", delay.to_string());
528 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get().get())
529 if(ext)
530 ext->recordBeginTx(h, trans);
531 /*************************************************************************
532 * do the timed notification
533 *************************************************************************/
534 if(nb_streamHandleTimed) {
535 record_nb_tx(trans, phase, sc_core::sc_time_stamp() + delay, h, phase == tlm::BEGIN_REQ);
536 }
537 /*************************************************************************
538 * do the access
539 *************************************************************************/
540 if(checker)
541 checker->bw_pre(trans, phase);
542 tlm::tlm_sync_enum status = get_bw_if()->nb_transport_bw(trans, phase, delay);
543 if(checker)
544 checker->bw_post(trans, phase, status);
545 /*************************************************************************
546 * handle recording
547 *************************************************************************/
548 tlm::scc::scv::record(h, status);
549 h.record_attribute("delay[return_path]", delay.to_string());
550 tlm::scc::scv::record(h, trans);
551 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::get().get())
552 if(ext)
553 ext->recordEndTx(h, trans);
554 // get the extension and free the memory if it was mine
555 if(status == tlm::TLM_COMPLETED || (status == tlm::TLM_UPDATED && phase == axi::ACK)) {
556 // the transaction is finished
557 trans.get_extension(preExt);
558 if(preExt->get_creator() == this) {
559 // clean-up the extension if this is the original creator
560 if(trans.has_mm())
561 trans.set_auto_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
562 else
563 delete trans.set_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
564 }
565 /*************************************************************************
566 * do the timed notification if req. finished here
567 *************************************************************************/
568 if(nb_streamHandleTimed) {
569 record_nb_tx(trans, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase,
570 sc_core::sc_time_stamp() + delay, h, false);
571 }
572 } else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
573 record_nb_tx(trans, phase, sc_core::sc_time_stamp() + delay, h, false);
574 }
575 // End the transaction
576 nb_trHandle[BW]->end_transaction(h, phase.get_name());
577 return status;
578}
579
580template <typename TYPES>
581void ace_recorder<TYPES>::record_nb_tx(typename TYPES::tlm_payload_type& trans, const typename TYPES::tlm_phase_type& phase,
582 sc_core::sc_time delay, SCVNS scv_tr_handle parent, bool is_snoop) {
583 SCVNS scv_tr_handle h;
584 // Now process outstanding recordings
585 auto t = sc_core::sc_time_stamp() + delay;
586 auto id = reinterpret_cast<uintptr_t>(&trans);
587 if(phase == tlm::BEGIN_REQ || phase == axi::BEGIN_PARTIAL_REQ) {
588 h = nb_trTimedHandle[REQ]->begin_transaction(t);
589 tlm::scc::scv::record(h, trans);
591 nbtx_req_handle_map[id] = h;
592 } else if(phase == tlm::END_REQ || phase == axi::END_PARTIAL_REQ) {
593 auto it = nbtx_req_handle_map.find(id);
594 sc_assert(it != nbtx_req_handle_map.end());
595 h = it->second;
596 nbtx_req_handle_map.erase(it);
597 h.end_transaction(t);
598 nbtx_last_req_handle_map[id] = h;
599 } else if(phase == tlm::BEGIN_RESP || phase == axi::BEGIN_PARTIAL_RESP) {
600 auto it = nbtx_req_handle_map.find(id);
601 if(it != nbtx_req_handle_map.end()) {
602 h = it->second;
603 nbtx_req_handle_map.erase(it);
604 h.end_transaction(t);
605 nbtx_last_req_handle_map[id] = h;
606 }
607 h = nb_trTimedHandle[RESP]->begin_transaction(t);
608 tlm::scc::scv::record(h, trans);
610 nbtx_resp_handle_map[id] = h;
611 it = nbtx_last_req_handle_map.find(id);
612 if(it != nbtx_last_req_handle_map.end()) {
613 SCVNS scv_tr_handle& pred = it->second;
615 nbtx_last_req_handle_map.erase(it);
616 } else {
617 it = nbtx_last_resp_handle_map.find(id);
618 if(it != nbtx_last_resp_handle_map.end()) {
619 SCVNS scv_tr_handle& pred = it->second;
621 nbtx_last_resp_handle_map.erase(it);
622 }
623 }
624 } else if(phase == tlm::END_RESP || phase == axi::END_PARTIAL_RESP) {
625 auto it = nbtx_resp_handle_map.find(id);
626 if(it != nbtx_resp_handle_map.end()) {
627 h = it->second;
628 nbtx_resp_handle_map.erase(it);
629 h.end_transaction(t);
630 if(phase == axi::END_PARTIAL_RESP) {
631 nbtx_last_resp_handle_map[id] = h;
632 }
633 }
634 } else if(phase == axi::ACK) {
635 h = nb_trTimedHandle[ACK]->begin_transaction(t);
636 tlm::scc::scv::record(h, trans);
638 h.end_transaction(t);
639 } else
640 sc_assert(!"phase not supported!");
641 return;
642}
643
644template <typename TYPES> bool ace_recorder<TYPES>::get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) {
645 if(!(m_db && enableDmiTracing.get_value()))
646 return get_fw_if()->get_direct_mem_ptr(trans, dmi_data);
647 else if(!dmi_streamHandle)
648 initialize_streams();
649 SCVNS scv_tr_handle h = dmi_trGetHandle->begin_transaction();
650 bool status = get_fw_if()->get_direct_mem_ptr(trans, dmi_data);
651 tlm::scc::scv::record(h, trans);
652 tlm::scc::scv::record(h, dmi_data);
653 h.end_transaction();
654 return status;
655}
656
662template <typename TYPES> void ace_recorder<TYPES>::invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) {
663 if(!(m_db && enableDmiTracing.get_value())) {
664 get_bw_if()->invalidate_direct_mem_ptr(start_addr, end_addr);
665 return;
666 } else if(!dmi_streamHandle)
667 initialize_streams();
668 SCVNS scv_tr_handle h = dmi_trInvalidateHandle->begin_transaction(start_addr);
669 get_bw_if()->invalidate_direct_mem_ptr(start_addr, end_addr);
670 dmi_trInvalidateHandle->end_transaction(h, end_addr);
671 return;
672}
673
679template <typename TYPES> unsigned int ace_recorder<TYPES>::transport_dbg(typename TYPES::tlm_payload_type& trans) {
680 unsigned int count = get_fw_if()->transport_dbg(trans);
681 return count;
682}
683} // namespace scv
684} // namespace axi
The TLM2 transaction recorder.
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.
cci::cci_param< bool > enableProtocolChecker
the attribute to enable/disable protocol checking
ace_recorder(const char *name, unsigned bus_width, bool recording_enabled=true, SCVNS scv_tr_db *tr_db=SCVNS scv_tr_db::get_default_db())
The constructor of the component.
void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override
The direct memory interface backward 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.
cci::cci_param< bool > enableTimedTracing
the attribute to selectively enable/disable timed recording
cci::cci_param< bool > enableTrDbgTracing
the attribute to selectively enable/disable transport dbg recording
void b_snoop(typename TYPES::tlm_payload_type &trans, sc_core::sc_time &delay) override
The blocking snoop function.
virtual axi::ace_bw_transport_if< TYPES > * get_bw_if()=0
the port where bw accesses are forwarded to
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
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
virtual axi::ace_fw_transport_if< TYPES > * get_fw_if()=0
the port where fw accesses are forwarded to
cci::cci_param< bool > enableDmiTracing
the attribute to selectively enable/disable DMI recording
unsigned int transport_dbg(typename TYPES::tlm_payload_type &trans) override
The debug transportfunction.
bool isRecordingNonBlockingTxEnabled() const
get the current state of transaction recording
cci::cci_param< bool > enableBlTracing
the attribute to selectively enable/disable recording of blocking protocol tx
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 AHB.
tlm::tlm_fw_transport_if< TYPES > ace_fw_transport_if
alias declaration for the ACE forward interface
Definition axi_tlm.h:955
const char * rel_str(tx_rel rel)
cast the tx_rel enum to a string