scc 2025.09
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 <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 <cci_configuration>
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, bool);
207 SCVNS scv_tr_db* m_db{nullptr};
209 SCVNS scv_tr_stream* b_streamHandle{nullptr};
211 std::array<SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>*, 3> b_trHandle{{nullptr, nullptr, nullptr}};
213 SCVNS scv_tr_stream* b_streamHandleTimed{nullptr};
216 std::array<SCVNS scv_tr_generator<>*, 3> b_trTimedHandle{{nullptr, nullptr, nullptr}};
217 std::unordered_map<uint64_t, SCVNS scv_tr_handle> btx_handle_map;
218
219 enum DIR { FW, BW, REQ = FW, RESP = BW, ACK };
221 SCVNS scv_tr_stream* nb_streamHandle{nullptr};
223 SCVNS scv_tr_stream* nb_streamHandleTimed{nullptr};
225 std::array<SCVNS scv_tr_generator<std::string, std::string>*, 2> nb_trHandle{{nullptr, nullptr}};
227 std::array<SCVNS scv_tr_generator<>*, 3> nb_trTimedHandle{{nullptr, nullptr, nullptr}};
228 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_req_handle_map;
229 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_last_req_handle_map;
230 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_resp_handle_map;
231 std::unordered_map<uint64_t, SCVNS scv_tr_handle> nbtx_last_resp_handle_map;
233 SCVNS scv_tr_stream* dmi_streamHandle{nullptr};
235 SCVNS scv_tr_generator<>* dmi_trGetHandle{nullptr};
236 SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>* dmi_trInvalidateHandle{nullptr};
237
238protected:
239 void initialize_streams() {
241 b_streamHandle = new SCVNS scv_tr_stream((fixed_basename + "_bl").c_str(), "[TLM][ace][b]", m_db);
242 b_trHandle[tlm::TLM_READ_COMMAND] =
243 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("read", *b_streamHandle, "start_delay", "end_delay");
244 b_trHandle[tlm::TLM_WRITE_COMMAND] =
245 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("write", *b_streamHandle, "start_delay", "end_delay");
246 b_trHandle[tlm::TLM_IGNORE_COMMAND] =
247 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("ignore", *b_streamHandle, "start_delay", "end_delay");
248 if(enableTimedTracing.get_value()) {
249 b_streamHandleTimed = new SCVNS scv_tr_stream((fixed_basename + "_bl_timed").c_str(), "[TLM][ace][b][timed]", m_db);
250 b_trTimedHandle[tlm::TLM_READ_COMMAND] = new SCVNS scv_tr_generator<>("read", *b_streamHandleTimed);
251 b_trTimedHandle[tlm::TLM_WRITE_COMMAND] = new SCVNS scv_tr_generator<>("write", *b_streamHandleTimed);
252 b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] = new SCVNS scv_tr_generator<>("ignore", *b_streamHandleTimed);
253 }
254 }
255 if(isRecordingNonBlockingTxEnabled() && !nb_streamHandle) {
256 nb_streamHandle = new SCVNS scv_tr_stream((fixed_basename + "_nb").c_str(), "[TLM][ace][nb]", m_db);
257 nb_trHandle[FW] =
258 new SCVNS scv_tr_generator<std::string, std::string>("fw", *nb_streamHandle, "tlm_phase", "tlm_phase[return_path]");
259 nb_trHandle[BW] =
260 new SCVNS scv_tr_generator<std::string, std::string>("bw", *nb_streamHandle, "tlm_phase", "tlm_phase[return_path]");
261 if(enableTimedTracing.get_value()) {
262 nb_streamHandleTimed = new SCVNS scv_tr_stream((fixed_basename + "_nb_timed").c_str(), "[TLM][ace][nb][timed]", m_db);
263 nb_trTimedHandle[FW] = new SCVNS scv_tr_generator<>("request", *nb_streamHandleTimed);
264 nb_trTimedHandle[BW] = new SCVNS scv_tr_generator<>("response", *nb_streamHandleTimed);
265 nb_trTimedHandle[ACK] = new SCVNS scv_tr_generator<>("ack", *nb_streamHandleTimed);
266 }
267 }
268 if(m_db && enableDmiTracing.get_value() && !dmi_streamHandle) {
269 dmi_streamHandle = new SCVNS scv_tr_stream((fixed_basename + "_dmi").c_str(), "[TLM][ace][dmi]", m_db);
270 dmi_trGetHandle = new SCVNS scv_tr_generator<>("get", *dmi_streamHandle);
271 dmi_trInvalidateHandle =
272 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("invalidate", *dmi_streamHandle, "start_addr", "end_addr");
273 }
274 // if(enableProtocolChecker.get_value()) {
275 // checker=new axi::checker::ace_protocol(fixed_basename, bus_width/8, rd_response_timeout.get_value(),
276 // wr_response_timeout.get_value());
277 // }
278 }
279
280private:
281 const std::string fixed_basename;
282 axi::checker::checker_if<TYPES>* checker{nullptr};
283};
284
286// implementations of functions
288
289template <typename TYPES> void ace_recorder<TYPES>::b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) {
291 get_fw_if()->b_transport(trans, delay);
292 return;
293 }
294 // Get a handle for the new transaction
295 SCVNS scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_core::sc_time_stamp());
296 /*************************************************************************
297 * do the timed notification
298 *************************************************************************/
299 SCVNS scv_tr_handle bh;
300 if(b_streamHandleTimed) {
301 bh = b_trTimedHandle[trans.get_command()]->begin_transaction(sc_core::sc_time_stamp()+delay);
303 }
304
305 auto addr = trans.get_address();
306 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
307 if(ext)
308 ext->recordBeginTx(h, trans);
310
311 trans.get_extension(preExt);
312 if(preExt == nullptr) { // we are the first recording this transaction
313 preExt = new tlm::scc::scv::tlm_recording_extension(h, this);
314 if(trans.has_mm())
315 trans.set_auto_extension(preExt);
316 else
317 trans.set_extension(preExt);
318 } else {
320 }
321 SCVNS scv_tr_handle preTx(preExt->txHandle);
322 preExt->txHandle = h;
323 get_fw_if()->b_transport(trans, delay);
324 trans.get_extension(preExt);
325 if(preExt->get_creator() == this) {
326 // clean-up the extension if this is the original creator
327 if(trans.has_mm())
328 trans.set_auto_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
329 else
330 delete trans.set_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
331 } else {
332 preExt->txHandle = preTx;
333 }
334
335 trans.set_address(addr);
336 tlm::scc::scv::record(h, trans);
337 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
338 if(ext)
339 ext->recordEndTx(h, trans);
340 // End the transaction
341 b_trHandle[trans.get_command()]->end_transaction(h, delay.value(), sc_core::sc_time_stamp());
342 // and now the stuff for the timed tx
343 if(bh.is_valid()) {
344 tlm::scc::scv::record(bh, trans);
345 bh.end_transaction(sc_core::sc_time_stamp()+delay);
346 }
347}
348
349template <typename TYPES> void ace_recorder<TYPES>::b_snoop(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) {
350 if(!b_streamHandleTimed) {
351 get_fw_if()->b_transport(trans, delay);
352 return;
353 }
354 // Get a handle for the new transaction
355 SCVNS scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_core::sc_time_stamp());
356 /*************************************************************************
357 * do the timed notification
358 *************************************************************************/
359 SCVNS scv_tr_handle bh;
360 if(b_streamHandleTimed) {
361 bh = b_trTimedHandle[trans.get_command()]->begin_transaction(sc_core::sc_time_stamp()+delay);
363 }
364
365 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
366 if(ext)
367 ext->recordBeginTx(h, trans);
369
370 trans.get_extension(preExt);
371 if(preExt == NULL) { // we are the first recording this transaction
372 preExt = new tlm::scc::scv::tlm_recording_extension(h, this);
373 if(trans.has_mm())
374 trans.set_auto_extension(preExt);
375 else
376 trans.set_extension(preExt);
377 } else {
379 }
380 SCVNS scv_tr_handle preTx(preExt->txHandle);
381 preExt->txHandle = h;
382 get_bw_if()->b_snoop(trans, delay);
383 trans.get_extension(preExt);
384 if(preExt->get_creator() == this) {
385 // clean-up the extension if this is the original creator
386 if(trans.has_mm())
387 trans.set_auto_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
388 else
389 delete trans.set_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
390 } else {
391 preExt->txHandle = preTx;
392 }
393
394 tlm::scc::scv::record(h, trans);
395 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
396 if(ext)
397 ext->recordEndTx(h, trans);
398 // End the transaction
399 b_trHandle[trans.get_command()]->end_transaction(h, delay.value(), sc_core::sc_time_stamp());
400 // and now the stuff for the timed tx
401 if(bh.is_valid()) {
402 tlm::scc::scv::record(bh, trans);
403 bh.end_transaction(sc_core::sc_time_stamp()+delay);
404 }
405}
406
407template <typename TYPES>
408tlm::tlm_sync_enum ace_recorder<TYPES>::nb_transport_fw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
409 sc_core::sc_time& delay) {
411 if(checker) {
412 checker->fw_pre(trans, phase);
413 tlm::tlm_sync_enum status = get_fw_if()->nb_transport_fw(trans, phase, delay);
414 checker->fw_post(trans, phase, status);
415 return status;
416 } else
417 return get_fw_if()->nb_transport_fw(trans, phase, delay);
418 }
419 /*************************************************************************
420 * prepare recording
421 *************************************************************************/
422 // Get a handle for the new transaction
423 SCVNS scv_tr_handle h = nb_trHandle[FW]->begin_transaction(phase.get_name());
425 trans.get_extension(preExt);
426 if((phase == axi::BEGIN_PARTIAL_REQ || phase == tlm::BEGIN_REQ) && preExt == nullptr) { // we are the first recording this transaction
427 preExt = new tlm::scc::scv::tlm_recording_extension(h, this);
428 if(trans.has_mm())
429 trans.set_auto_extension(preExt);
430 else
431 trans.set_extension(preExt);
432 } else if(preExt != nullptr) {
433 // link handle if we have a predecessor
435 } else {
436 sc_assert(preExt != nullptr && "ERROR on forward path in phase other than tlm::BEGIN_REQ");
437 }
438 // update the extension
439 preExt->txHandle = h;
440 h.record_attribute("delay", delay.to_string());
441 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
442 if(ext)
443 ext->recordBeginTx(h, trans);
444 /*************************************************************************
445 * do the timed notification
446 *************************************************************************/
447 if(nb_streamHandleTimed) {
448 record_nb_tx(trans, phase, sc_core::sc_time_stamp()+delay, h, phase == tlm::BEGIN_RESP || phase == axi::BEGIN_PARTIAL_RESP);
449 }
450 /*************************************************************************
451 * do the access
452 *************************************************************************/
453 if(checker)
454 checker->fw_pre(trans, phase);
455 tlm::tlm_sync_enum status = get_fw_if()->nb_transport_fw(trans, phase, delay);
456 if(checker)
457 checker->fw_post(trans, phase, status);
458 /*************************************************************************
459 * handle recording
460 *************************************************************************/
461 tlm::scc::scv::record(h, status);
462 h.record_attribute("delay[return_path]", delay.to_string());
463 tlm::scc::scv::record(h, trans);
464 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
465 if(ext)
466 ext->recordEndTx(h, trans);
467 // get the extension and free the memory if it was mine
468 if(status == tlm::TLM_COMPLETED || (phase == axi::ACK)) {
469 // the transaction is finished
470 trans.get_extension(preExt);
471 if(preExt && preExt->get_creator() == this) {
472 // clean-up the extension if this is the original creator
473 if(trans.has_mm())
474 trans.set_auto_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
475 else
476 delete trans.set_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
477 }
478 /*************************************************************************
479 * do the timed notification if req. finished here
480 *************************************************************************/
481 if(nb_streamHandleTimed) {
482 record_nb_tx(trans, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase, sc_core::sc_time_stamp()+delay, h, false);
483 }
484 } else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
485 record_nb_tx(trans, phase, sc_core::sc_time_stamp()+delay, h, false);
486 }
487 // End the transaction
488 nb_trHandle[FW]->end_transaction(h, phase.get_name());
489 return status;
490}
491
492template <typename TYPES>
493tlm::tlm_sync_enum ace_recorder<TYPES>::nb_transport_bw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
494 sc_core::sc_time& delay) {
496 if(checker) {
497 checker->bw_pre(trans, phase);
498 tlm::tlm_sync_enum status = get_bw_if()->nb_transport_bw(trans, phase, delay);
499 checker->bw_post(trans, phase, status);
500 return status;
501 } else
502 return get_bw_if()->nb_transport_bw(trans, phase, delay);
503 }
504 /*************************************************************************
505 * prepare recording
506 *************************************************************************/
507 // Get a handle for the new transaction
508 SCVNS scv_tr_handle h = nb_trHandle[BW]->begin_transaction(phase.get_name());
510 trans.get_extension(preExt);
511 if(phase == tlm::BEGIN_REQ && preExt == nullptr) { // we are the first recording this transaction
512 preExt = new tlm::scc::scv::tlm_recording_extension(h, this);
513 if(trans.has_mm())
514 trans.set_auto_extension(preExt);
515 else
516 trans.set_extension(preExt);
517 } else if(preExt != nullptr) {
518 // link handle if we have a predecessor
520 } else {
521 sc_assert(preExt != nullptr && "ERROR on backward path in phase other than tlm::BEGIN_REQ");
522 }
523 // and set the extension handle to this transaction
524 preExt->txHandle = h;
525 h.record_attribute("delay", delay.to_string());
526 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
527 if(ext)
528 ext->recordBeginTx(h, trans);
529 /*************************************************************************
530 * do the timed notification
531 *************************************************************************/
532 if(nb_streamHandleTimed) {
533 record_nb_tx(trans, phase, sc_core::sc_time_stamp()+delay, h, phase == tlm::BEGIN_REQ);
534 }
535 /*************************************************************************
536 * do the access
537 *************************************************************************/
538 if(checker)
539 checker->bw_pre(trans, phase);
540 tlm::tlm_sync_enum status = get_bw_if()->nb_transport_bw(trans, phase, delay);
541 if(checker)
542 checker->bw_post(trans, phase, status);
543 /*************************************************************************
544 * handle recording
545 *************************************************************************/
546 tlm::scc::scv::record(h, status);
547 h.record_attribute("delay[return_path]", delay.to_string());
548 tlm::scc::scv::record(h, trans);
549 for(auto& ext : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
550 if(ext)
551 ext->recordEndTx(h, trans);
552 // get the extension and free the memory if it was mine
553 if(status == tlm::TLM_COMPLETED || (status == tlm::TLM_UPDATED && phase == axi::ACK)) {
554 // the transaction is finished
555 trans.get_extension(preExt);
556 if(preExt->get_creator() == this) {
557 // clean-up the extension if this is the original creator
558 if(trans.has_mm())
559 trans.set_auto_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
560 else
561 delete trans.set_extension(static_cast<tlm::scc::scv::tlm_recording_extension*>(nullptr));
562 }
563 /*************************************************************************
564 * do the timed notification if req. finished here
565 *************************************************************************/
566 if(nb_streamHandleTimed) {
567 record_nb_tx(trans, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase, sc_core::sc_time_stamp()+delay, h, false);
568 }
569 } else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
570 record_nb_tx(trans, phase, sc_core::sc_time_stamp()+delay, h, false);
571 }
572 // End the transaction
573 nb_trHandle[BW]->end_transaction(h, phase.get_name());
574 return status;
575}
576
577template <typename TYPES> void ace_recorder<TYPES>::record_nb_tx(typename TYPES::tlm_payload_type & trans, const typename TYPES::tlm_phase_type& phase, sc_core::sc_time delay, SCVNS scv_tr_handle parent, bool is_snoop) {
578 SCVNS scv_tr_handle h;
579 // Now process outstanding recordings
580 auto t = sc_core::sc_time_stamp()+delay;
581 auto id = reinterpret_cast<uintptr_t>(&trans);
582 if(phase == tlm::BEGIN_REQ || phase == axi::BEGIN_PARTIAL_REQ) {
583 h = nb_trTimedHandle[REQ]->begin_transaction(t);
584 tlm::scc::scv::record(h, trans);
586 nbtx_req_handle_map[id] = h;
587 } else if(phase == tlm::END_REQ || phase == axi::END_PARTIAL_REQ) {
588 auto it = nbtx_req_handle_map.find(id);
589 sc_assert(it != nbtx_req_handle_map.end());
590 h = it->second;
591 nbtx_req_handle_map.erase(it);
592 h.end_transaction(t);
593 nbtx_last_req_handle_map[id] = h;
594 } else if(phase == tlm::BEGIN_RESP || phase == axi::BEGIN_PARTIAL_RESP) {
595 auto it = nbtx_req_handle_map.find(id);
596 if(it != nbtx_req_handle_map.end()) {
597 h = it->second;
598 nbtx_req_handle_map.erase(it);
599 h.end_transaction(t);
600 nbtx_last_req_handle_map[id] = h;
601 }
602 h = nb_trTimedHandle[RESP]->begin_transaction(t);
603 tlm::scc::scv::record(h, trans);
605 nbtx_resp_handle_map[id] = h;
606 it = nbtx_last_req_handle_map.find(id);
607 if(it != nbtx_last_req_handle_map.end()) {
608 SCVNS scv_tr_handle& pred = it->second;
610 nbtx_last_req_handle_map.erase(it);
611 } else {
612 it = nbtx_last_resp_handle_map.find(id);
613 if(it != nbtx_last_resp_handle_map.end()) {
614 SCVNS scv_tr_handle& pred = it->second;
616 nbtx_last_resp_handle_map.erase(it);
617 }
618 }
619 } else if(phase == tlm::END_RESP || phase == axi::END_PARTIAL_RESP) {
620 auto it = nbtx_resp_handle_map.find(id);
621 if(it != nbtx_resp_handle_map.end()) {
622 h = it->second;
623 nbtx_resp_handle_map.erase(it);
624 h.end_transaction(t);
625 if(phase == axi::END_PARTIAL_RESP) {
626 nbtx_last_resp_handle_map[id] = h;
627 }
628 }
629 } else if(phase == axi::ACK) {
630 h = nb_trTimedHandle[ACK]->begin_transaction(t);
631 tlm::scc::scv::record(h, trans);
633 h.end_transaction(t);
634 } else
635 sc_assert(!"phase not supported!");
636 return;
637}
638
639template <typename TYPES> bool ace_recorder<TYPES>::get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) {
640 if(!(m_db && enableDmiTracing.get_value()))
641 return get_fw_if()->get_direct_mem_ptr(trans, dmi_data);
642 else if(!dmi_streamHandle)
643 initialize_streams();
644 SCVNS scv_tr_handle h = dmi_trGetHandle->begin_transaction();
645 bool status = get_fw_if()->get_direct_mem_ptr(trans, dmi_data);
646 tlm::scc::scv::record(h, trans);
647 tlm::scc::scv::record(h, dmi_data);
648 h.end_transaction();
649 return status;
650}
651
657template <typename TYPES> void ace_recorder<TYPES>::invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) {
658 if(!(m_db && enableDmiTracing.get_value())) {
659 get_bw_if()->invalidate_direct_mem_ptr(start_addr, end_addr);
660 return;
661 } else if(!dmi_streamHandle)
662 initialize_streams();
663 SCVNS scv_tr_handle h = dmi_trInvalidateHandle->begin_transaction(start_addr);
664 get_bw_if()->invalidate_direct_mem_ptr(start_addr, end_addr);
665 dmi_trInvalidateHandle->end_transaction(h, end_addr);
666 return;
667}
668
674template <typename TYPES> unsigned int ace_recorder<TYPES>::transport_dbg(typename TYPES::tlm_payload_type& trans) {
675 unsigned int count = get_fw_if()->transport_dbg(trans);
676 return count;
677}
678} // namespace scv
679} // 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:958
const char * rel_str(tx_rel rel)
cast the tx_rel enum to a string