scc 2025.09
SystemC components library
ace_lwtr.h
1/*
2 * Copyright 2023 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 <tlm/scc/lwtr/tlm2_lwtr.h>
24#include <cci_configuration>
25#include <axi/checker/axi_protocol.h>
26#include <tlm/scc/tlm_mm.h>
27#include <array>
28#include <axi/axi_tlm.h>
29#include <regex>
30#include <string>
31#include <scc/peq.h>
32#include <unordered_map>
33#include <vector>
34
36namespace axi {
37namespace lwtr {
38
39using tx_db = ::lwtr::tx_db;
40using tx_fiber = ::lwtr::tx_fiber;
41template <typename BEGIN = ::lwtr::no_data, typename END = ::lwtr::no_data>
42using tx_generator = ::lwtr::tx_generator<BEGIN, END>;
43using tx_handle = ::lwtr::tx_handle;
44using mm = tlm::scc::tlm_mm<>;
45using namespace tlm::scc::lwtr;
46
47struct nb_ace_rec_entry: public nb_rec_entry {
48 bool snoop;
49 nb_ace_rec_entry(tlm::scc::tlm_gp_shared_ptr tr,tlm::tlm_phase const ph, uintptr_t const id, tx_handle parent, bool snoop)
50 : nb_rec_entry{tr, ph, id, parent}
51 , snoop(snoop) {}
52};
53extern bool registered;
54
63template <typename TYPES = axi::axi_protocol_types>
64class ace_lwtr : public virtual axi::ace_fw_transport_if<TYPES>, public virtual axi::ace_bw_transport_if<TYPES> {
65public:
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
86 ace_lwtr(char const* full_name, unsigned bus_width, bool recording_enabled = true, tx_db* tr_db = tx_db::get_default_db())
87 : enableBlTracing("enableBlTracing", recording_enabled)
88 , enableNbTracing("enableNbTracing", recording_enabled)
89 , full_name(full_name)
90 , nb_timed_peq()
91 , bus_width(bus_width)
92 , m_db(tr_db)
93 {
94 sc_core::sc_spawn_options opts;
95 opts.spawn_method();
96 opts.dont_initialize();
97 opts.set_sensitivity(&nb_timed_peq.event());
98 sc_core::sc_spawn([this](){
99 nbtx_cb();
100 }, nullptr, &opts);
101 initialize_streams();
102 }
103
104 virtual ~ace_lwtr() override {
105 nbtx_req_handle_map.clear();
106 nbtx_last_req_handle_map.clear();
107 nbtx_resp_handle_map.clear();
108 nbtx_last_resp_handle_map.clear();
109 delete b_streamHandle;
110 for(auto* p : b_trHandle)
111 delete p; // NOLINT
112 delete b_streamHandleTimed;
113 for(auto* p : b_trTimedHandle)
114 delete p; // NOLINT
115 delete nb_streamHandle;
116 for(auto* p : nb_trHandle)
117 delete p; // NOLINT
118 delete nb_streamHandleTimed;
119 for(auto* p : nb_trTimedHandle)
120 delete p; // NOLINT
121 delete dmi_streamHandle;
122 delete dmi_trGetHandle;
123 delete dmi_trInvalidateHandle;
124 delete checker;
125 }
126
127 // TLM-2.0 interface methods for initiator and target sockets, surrounded with
128 // Tx Recording
138 tlm::tlm_sync_enum nb_transport_fw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
139 sc_core::sc_time& delay) override;
149 tlm::tlm_sync_enum nb_transport_bw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
150 sc_core::sc_time& delay) override;
159 void b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) override;
168 void b_snoop(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) override;
176 bool get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) override;
183 void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override;
190 unsigned int transport_dbg(typename TYPES::tlm_payload_type& trans) override;
196 inline bool isRecordingBlockingTxEnabled() const { return m_db && enableBlTracing.get_value(); }
202 inline bool isRecordingNonBlockingTxEnabled() const { return m_db && enableNbTracing.get_value(); }
203
204protected:
206 sc_core::sc_port<axi::ace_fw_transport_if<TYPES>> fw_port{"fw_port"};
207
209 sc_core::sc_port<axi::ace_bw_transport_if<TYPES>> bw_port{"bw_port"};
210
211private:
212 std::string const full_name;
214 ::scc::peq<nb_ace_rec_entry> nb_timed_peq;
219 void nbtx_cb();
220 const unsigned bus_width{0};
222 tx_db* m_db{nullptr};
224 ::lwtr::tx_relation_handle pred_succ_hndl{0}, par_chld_hndl{0};
226 tx_fiber* b_streamHandle{nullptr};
228 std::array<tx_generator<sc_core::sc_time, sc_core::sc_time>*, 3> b_trHandle{{nullptr, nullptr, nullptr}};
230 tx_fiber* b_streamHandleTimed{nullptr};
233 std::array<tx_generator<>*, 3> b_trTimedHandle{{nullptr, nullptr, nullptr}};
234
235 enum DIR { FW, BW, REQ = FW, RESP = BW, ACK };
237 tx_fiber* nb_streamHandle{nullptr};
239 tx_fiber* nb_streamHandleTimed{nullptr};
241 std::array<tx_generator<std::string, std::string>*, 3> nb_trHandle{{nullptr, nullptr, nullptr}};
243 std::array<tx_generator<>*, 3> nb_trTimedHandle{{nullptr, nullptr, nullptr}};
244 std::unordered_map<uint64_t, tx_handle> nbtx_req_handle_map;
245 std::unordered_map<uint64_t, tx_handle> nbtx_last_req_handle_map;
246 std::unordered_map<uint64_t, tx_handle> nbtx_resp_handle_map;
247 std::unordered_map<uint64_t, tx_handle> nbtx_last_resp_handle_map;
249 tx_fiber* dmi_streamHandle{nullptr};
251 tx_generator<>* dmi_trGetHandle{nullptr};
252 tx_generator<sc_dt::uint64, sc_dt::uint64>* dmi_trInvalidateHandle{nullptr};
253
254protected:
255 void initialize_streams() {
256 if(m_db) {
257 pred_succ_hndl = m_db->create_relation("PREDECESSOR_SUCCESSOR");
258 par_chld_hndl = m_db->create_relation("PARENT_CHILD");
259 }
260 if(isRecordingBlockingTxEnabled() && !b_streamHandle) {
261 b_streamHandle = new tx_fiber((full_name + "_bl").c_str(), "[TLM][ace][b]", m_db);
262 b_trHandle[tlm::TLM_READ_COMMAND] = new tx_generator<sc_core::sc_time, sc_core::sc_time>(
263 "read", *b_streamHandle, "start_delay", "end_delay");
264 b_trHandle[tlm::TLM_WRITE_COMMAND] = new tx_generator<sc_core::sc_time, sc_core::sc_time>(
265 "write", *b_streamHandle, "start_delay", "end_delay");
266 b_trHandle[tlm::TLM_IGNORE_COMMAND] = new tx_generator<sc_core::sc_time, sc_core::sc_time>(
267 "ignore", *b_streamHandle, "start_delay", "end_delay");
268 if(enableTimedTracing.get_value()) {
269 b_streamHandleTimed =
270 new tx_fiber((full_name + "_bl_timed").c_str(), "[TLM][ace][b][timed]", m_db);
271 b_trTimedHandle[tlm::TLM_READ_COMMAND] = new tx_generator<>("read", *b_streamHandleTimed);
272 b_trTimedHandle[tlm::TLM_WRITE_COMMAND] = new tx_generator<>("write", *b_streamHandleTimed);
273 b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] = new tx_generator<>("ignore", *b_streamHandleTimed);
274 }
275 }
276 if(isRecordingNonBlockingTxEnabled() && !nb_streamHandle) {
277 nb_streamHandle = new tx_fiber((full_name + "_nb").c_str(), "[TLM][ace][nb]", m_db);
278 nb_trHandle[FW] = new tx_generator<std::string, std::string>("fw", *nb_streamHandle, "tlm_phase",
279 "tlm_phase[return_path]");
280 nb_trHandle[BW] = new tx_generator<std::string, std::string>("bw", *nb_streamHandle, "tlm_phase",
281 "tlm_phase[return_path]");
282 if(enableTimedTracing.get_value()) {
283 nb_streamHandleTimed =
284 new tx_fiber((full_name + "_nb_timed").c_str(), "[TLM][ace][nb][timed]", m_db);
285 nb_trTimedHandle[FW] = new tx_generator<>("request", *nb_streamHandleTimed);
286 nb_trTimedHandle[BW] = new tx_generator<>("response", *nb_streamHandleTimed);
287 nb_trTimedHandle[ACK] = new tx_generator<>("ack", *nb_streamHandleTimed);
288 }
289 }
290 if(m_db && enableDmiTracing.get_value() && !dmi_streamHandle) {
291 dmi_streamHandle = new tx_fiber((full_name + "_dmi").c_str(), "[TLM][ace][dmi]", m_db);
292 dmi_trGetHandle = new tx_generator<>("get", *dmi_streamHandle);
293 dmi_trInvalidateHandle = new tx_generator<sc_dt::uint64, sc_dt::uint64>(
294 "invalidate", *dmi_streamHandle, "start_addr", "end_addr");
295 }
296 }
297
298private:
299 axi::checker::checker_if<TYPES>* checker{nullptr};
300};
301
302template <unsigned BUSWIDTH=32, typename TYPES = axi::axi_protocol_types, int N = 1,
303 sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
304class ace_lwtr_recorder : public sc_core::sc_module, public ace_lwtr<TYPES> {
305public:
308
309 ace_lwtr_recorder(sc_core::sc_module_name nm, bool recording_enabled = true, tx_db* tr_db = tx_db::get_default_db())
310 : sc_core::sc_module(nm)
311 , ace_lwtr<TYPES>(name(), BUSWIDTH, recording_enabled, tr_db)
312 {
313 is(*this);
314 ts(*this);
315 this->bw_port(ts.get_base_port());
316 this->fw_port(is.get_base_port());
317 }
318};
319
320// implementations of functions
322
323template <typename TYPES>
324void ace_lwtr<TYPES>::b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) {
326 fw_port->b_transport(trans, delay);
327 return;
328 }
329 // Get a handle for the new transaction
330 tx_handle h = b_trHandle[trans.get_command()]->begin_tx(delay);
331 tx_handle htim;
332 /*************************************************************************
333 * do the timed notification
334 *************************************************************************/
335 if(b_streamHandleTimed)
336 htim = b_trTimedHandle[trans.get_command()]->begin_tx_delayed(sc_core::sc_time_stamp()+delay, par_chld_hndl, h);
337
338 if(registered)
339 for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
340 if(extensionRecording) {
341 extensionRecording->recordBeginTx(h, trans);
342 if(htim.is_valid())
343 extensionRecording->recordBeginTx(htim, trans);
344 }
345 link_pred_ext* preExt = nullptr;
346
347 trans.get_extension(preExt);
348 if(preExt == nullptr) { // we are the first recording this transaction
349 preExt = new link_pred_ext(h, this);
350 if(trans.has_mm())
351 trans.set_auto_extension(preExt);
352 else
353 trans.set_extension(preExt);
354 } else {
355 h.add_relation(pred_succ_hndl, preExt->txHandle);
356 }
357 tx_handle preTx(preExt->txHandle);
358 preExt->txHandle = h;
359 fw_port->b_transport(trans, delay);
360 trans.get_extension(preExt);
361 if(preExt->creator == this) {
362 // clean-up the extension if this is the original creator
363 trans.set_extension(static_cast<link_pred_ext*>(nullptr));
364 if(!trans.has_mm()) {
365 delete preExt;
366 }
367 } else {
368 preExt->txHandle = preTx;
369 }
370
371 h.record_attribute("trans", trans);
372 if(registered)
373 for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
374 if(extensionRecording) {
375 extensionRecording->recordEndTx(h, trans);
376 if(htim.is_active())
377 extensionRecording->recordEndTx(htim, trans);
378 }
379 // End the transaction
380 h.end_tx(delay);
381 // and now the stuff for the timed tx
382 if(htim.is_valid()) {
383 htim.record_attribute("trans", trans);
384 htim.end_tx_delayed(sc_core::sc_time_stamp()+delay);
385 }
386}
387
388template <typename TYPES>
389void ace_lwtr<TYPES>::b_snoop(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) {
390 if(!b_streamHandleTimed) {
391 bw_port->b_snoop(trans, delay);
392 return;
393 }
394 // Get a handle for the new transaction
395 tx_handle h = b_trHandle[trans.get_command()]->begin_tx(delay);
396 tx_handle htim;
397 /*************************************************************************
398 * do the timed notification
399 *************************************************************************/
400 if(b_streamHandleTimed)
401 htim = b_trTimedHandle[trans.get_command()]->begin_tx_delayed(sc_core::sc_time_stamp()+delay, par_chld_hndl, h);
402
403 if(registered)
404 for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
405 if(extensionRecording) {
406 extensionRecording->recordBeginTx(h, trans);
407 if(htim.is_valid())
408 extensionRecording->recordBeginTx(htim, trans);
409 }
410 link_pred_ext* preExt = nullptr;
411
412 trans.get_extension(preExt);
413 if(preExt == nullptr) { // we are the first recording this transaction
414 preExt = new link_pred_ext(h, this);
415 trans.set_extension(preExt);
416 } else {
417 h.add_relation(pred_succ_hndl, preExt->txHandle);
418 }
419 tx_handle preTx(preExt->txHandle);
420 preExt->txHandle = h;
421 bw_port->b_snoop(trans, delay);
422 trans.get_extension(preExt);
423 if(preExt->creator == this) {
424 // clean-up the extension if this is the original creator
425 trans.set_extension(static_cast<link_pred_ext*>(nullptr));
426 if(!trans.has_mm())
427 delete preExt;
428 } else {
429 preExt->txHandle = preTx;
430 }
431
432 h.record_attribute("trans", trans);
433 if(registered)
434 for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
435 if(extensionRecording) {
436 extensionRecording->recordEndTx(h, trans);
437 if(htim.is_active())
438 extensionRecording->recordEndTx(htim, trans);
439 }
440 // End the transaction
441 h.end_tx(delay);
442 // and now the stuff for the timed tx
443 if(htim.is_valid()) {
444 htim.record_attribute("trans", trans);
445 htim.end_tx_delayed(sc_core::sc_time_stamp()+delay);
446 }
447}
448
449template <typename TYPES>
450tlm::tlm_sync_enum ace_lwtr<TYPES>::nb_transport_fw(typename TYPES::tlm_payload_type& trans,
451 typename TYPES::tlm_phase_type& phase,
452 sc_core::sc_time& delay) {
454 return fw_port->nb_transport_fw(trans, phase, delay);
455 }
456 /*************************************************************************
457 * prepare recording
458 *************************************************************************/
459 // Get a handle for the new transaction
460 tx_handle h = nb_trHandle[FW]->begin_tx(phase.get_name());
461 link_pred_ext* preExt = nullptr;
462 trans.get_extension(preExt);
463 if((phase == axi::BEGIN_PARTIAL_REQ || phase == tlm::BEGIN_REQ) && preExt == nullptr) { // we are the first recording this transaction
464 preExt = new link_pred_ext(h, this);
465 if(trans.has_mm())
466 trans.set_auto_extension(preExt);
467 else
468 trans.set_extension(preExt);
469 } else if(preExt != nullptr) {
470 // link handle if we have a predecessor
471 h.add_relation(pred_succ_hndl, preExt->txHandle);
472 } else {
473 sc_assert(preExt != nullptr && "ERROR on forward path in phase other than tlm::BEGIN_REQ");
474 }
475 // update the extension
476 preExt->txHandle = h;
477 h.record_attribute("delay", delay);
478 if(registered)
479 for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
480 if(extensionRecording)
481 extensionRecording->recordBeginTx(h, trans);
482 /*************************************************************************
483 * do the timed notification
484 *************************************************************************/
485 if(nb_streamHandleTimed) {
486 nb_ace_rec_entry rec(mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h, (phase == tlm::BEGIN_RESP || phase == axi::BEGIN_PARTIAL_RESP));
487 rec.tr->deep_copy_from(trans);
488 nb_timed_peq.notify(rec, delay);
489 }
490 /*************************************************************************
491 * do the access
492 *************************************************************************/
493 if(checker) checker->fw_pre(trans, phase);
494 tlm::tlm_sync_enum status = fw_port->nb_transport_fw(trans, phase, delay);
495 if(checker) checker->fw_post(trans, phase, status);
496 /*************************************************************************
497 * handle recording
498 *************************************************************************/
499 h.record_attribute("tlm_sync", status);
500 h.record_attribute("delay[return_path]", delay);
501 h.record_attribute("trans", trans);
502 if(registered)
503 for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
504 if(extensionRecording)
505 extensionRecording->recordEndTx(h, trans);
506 // get the extension and free the memory if it was mine
507 if(status == tlm::TLM_COMPLETED || (phase == axi::ACK)) {
508 trans.get_extension(preExt);
509 if(preExt && preExt->creator == this) {
510 trans.set_extension(static_cast<link_pred_ext*>(nullptr));
511 if(!trans.has_mm()) {
512 delete preExt;
513 }
514 }
515 /*************************************************************************
516 * do the timed notification if req. finished here
517 *************************************************************************/
518 if(nb_streamHandleTimed) {
519 nb_ace_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h, (phase == tlm::BEGIN_RESP || phase == axi::BEGIN_PARTIAL_RESP)};
520 rec.tr->deep_copy_from(trans);
521 nb_timed_peq.notify(rec, delay);
522 }
523 } else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
524 nb_ace_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h, (phase == tlm::BEGIN_RESP || phase == axi::BEGIN_PARTIAL_RESP)};
525 rec.tr->deep_copy_from(trans);
526 nb_timed_peq.notify(rec, delay);
527 }
528 // End the transaction
529 nb_trHandle[FW]->end_tx(h, phase.get_name());
530 return status;
531}
532
533template <typename TYPES>
534tlm::tlm_sync_enum ace_lwtr<TYPES>::nb_transport_bw(typename TYPES::tlm_payload_type& trans,
535 typename TYPES::tlm_phase_type& phase,
536 sc_core::sc_time& delay) {
538 if(checker) {
539 checker->bw_pre(trans, phase);
540 tlm::tlm_sync_enum status = bw_port->nb_transport_bw(trans, phase, delay);
541 checker->bw_post(trans, phase, status);
542 return status;
543 } else
544 return bw_port->nb_transport_bw(trans, phase, delay);
545 }
546 /*************************************************************************
547 * prepare recording
548 *************************************************************************/
549 link_pred_ext* preExt = nullptr;
550 trans.get_extension(preExt);
551 // Get a handle for the new transaction
552 tx_handle h = nb_trHandle[BW]->begin_tx(phase.get_name());
553 // link handle if we have a predecessor and that's not ourself
554 if(phase == tlm::BEGIN_REQ && preExt == nullptr) { // we are the first recording this transaction
555 preExt = new link_pred_ext(h, this);
556 trans.set_extension(preExt);
557 preExt->txHandle = h;
558 } else if(preExt) {
559 // link handle if we have a predecessor
560 h.add_relation(pred_succ_hndl, preExt->txHandle);
561 // and set the extension handle to this transaction
562 preExt->txHandle = h;
563 } else {
564 sc_assert(preExt != nullptr && "ERROR on backward path in phase other than tlm::BEGIN_REQ");
565 }
566 // and set the extension handle to this transaction
567 h.record_attribute("delay", delay);
568 for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
569 if(extensionRecording)
570 extensionRecording->recordBeginTx(h, trans);
571 /*************************************************************************
572 * do the timed notification
573 *************************************************************************/
574 if(nb_streamHandleTimed) {
575 nb_ace_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h, phase == tlm::BEGIN_REQ};
576 rec.tr->deep_copy_from(trans);
577 nb_timed_peq.notify(rec, delay);
578 }
579 /*************************************************************************
580 * do the access
581 *************************************************************************/
582 if(checker) checker->bw_pre(trans, phase);
583 tlm::tlm_sync_enum status = bw_port->nb_transport_bw(trans, phase, delay);
584 if(checker) checker->bw_post(trans, phase, status);
585 /*************************************************************************
586 * handle recording
587 *************************************************************************/
588 h.record_attribute("tlm_sync", status);
589 h.record_attribute("delay[return_path]", delay);
590 h.record_attribute("trans", trans);
591 if(registered)
592 for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
593 if(extensionRecording)
594 extensionRecording->recordEndTx(h, trans);
595 // End the transaction
596 nb_trHandle[BW]->end_tx(h, phase.get_name());
597 // get the extension and free the memory if it was mine
598 if(status == tlm::TLM_COMPLETED || (status == tlm::TLM_UPDATED && phase == axi::ACK)) {
599 // the transaction is finished
600 if(preExt && preExt->creator == this) {
601 // clean-up the extension if this is the original creator
602 trans.set_extension(static_cast<link_pred_ext*>(nullptr));
603 if(!trans.has_mm()) {
604 delete preExt;
605 }
606 }
607 /*************************************************************************
608 * do the timed notification if req. finished here
609 *************************************************************************/
610 if(nb_streamHandleTimed) {
611 nb_ace_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h, phase == tlm::BEGIN_REQ};
612 rec.tr->deep_copy_from(trans);
613 nb_timed_peq.notify(rec, delay);
614 }
615 } else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
616 nb_ace_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h, phase == tlm::BEGIN_REQ};
617 rec.tr->deep_copy_from(trans);
618 nb_timed_peq.notify(rec, delay);
619 }
620 return status;
621}
622
623template <typename TYPES>
624void ace_lwtr<TYPES>::nbtx_cb() {
625 auto opt = nb_timed_peq.get_next();
626 if(opt) {
627 auto& e = opt.get();
628 tx_handle h;
629 // Now process outstanding recordings
630 if(e.ph == tlm::BEGIN_REQ || e.ph == axi::BEGIN_PARTIAL_REQ) {
631 h = nb_trTimedHandle[REQ]->begin_tx(par_chld_hndl, e.parent);
632 nbtx_req_handle_map[e.id] = h;
633 } else if(e.ph == tlm::END_REQ || e.ph == axi::END_PARTIAL_REQ) {
634 auto it = nbtx_req_handle_map.find(e.id);
635 if(it != nbtx_req_handle_map.end()) {
636 h = it->second;
637 nbtx_req_handle_map.erase(it);
638 h.record_attribute("trans", *e.tr);
639 h.end_tx();
640 nbtx_last_req_handle_map[e.id] = h;
641 }
642 } else if(e.ph == tlm::BEGIN_RESP || e.ph == axi::BEGIN_PARTIAL_RESP) {
643 auto it = nbtx_req_handle_map.find(e.id);
644 if(it != nbtx_req_handle_map.end()) {
645 h = it->second;
646 nbtx_req_handle_map.erase(it);
647 h.record_attribute("trans", *e.tr);
648 h.end_tx();
649 nbtx_last_req_handle_map[e.id] = h;
650 }
651 h = nb_trTimedHandle[RESP]->begin_tx(par_chld_hndl, e.parent);
652 nbtx_resp_handle_map[e.id] = h;
653 it = nbtx_last_req_handle_map.find(e.id);
654 if(it != nbtx_last_req_handle_map.end()) {
655 tx_handle& pred = it->second;
656 h.add_relation(pred_succ_hndl, pred);
657 nbtx_last_req_handle_map.erase(it);
658 } else {
659 it = nbtx_last_resp_handle_map.find(e.id);
660 if(it != nbtx_last_resp_handle_map.end()) {
661 tx_handle& pred = it->second;
662 h.add_relation(pred_succ_hndl, pred);
663 nbtx_last_resp_handle_map.erase(it);
664 }
665 }
666 } else if(e.ph == tlm::END_RESP || e.ph == axi::END_PARTIAL_RESP) {
667 auto it = nbtx_resp_handle_map.find(e.id);
668 if(it != nbtx_resp_handle_map.end()) {
669 h = it->second;
670 nbtx_resp_handle_map.erase(it);
671 h.record_attribute("trans", *e.tr);
672 h.end_tx();
673 if(e.ph == axi::END_PARTIAL_RESP) {
674 nbtx_last_resp_handle_map[e.id] = h;
675 }
676 }
677 } else if(e.ph == axi::ACK) {
678 h = nb_trTimedHandle[ACK]->begin_tx(par_chld_hndl, e.parent);
679 h.record_attribute("trans", *e.tr);
680 h.end_tx();
681 } else
682 sc_assert(!"phase not supported!");
683 }
684 return;
685}
686
687template <typename TYPES>
688bool ace_lwtr<TYPES>::get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) {
689 if(!(m_db && enableDmiTracing.get_value()))
690 return fw_port->get_direct_mem_ptr(trans, dmi_data);
691 tx_handle h = dmi_trGetHandle->begin_tx();
692 bool status = fw_port->get_direct_mem_ptr(trans, dmi_data);
693 h.record_attribute("trans", trans);
694 h.record_attribute("dmi_data", dmi_data);
695 h.end_tx();
696 return status;
697}
698
704template <typename TYPES>
705void ace_lwtr<TYPES>::invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) {
706 if(!(m_db && enableDmiTracing.get_value())) {
707 bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
708 return;
709 }
710 tx_handle h = dmi_trInvalidateHandle->begin_tx(start_addr);
711 bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
712 dmi_trInvalidateHandle->end_tx(h, end_addr);
713 return;
714}
715
721template <typename TYPES> unsigned int ace_lwtr<TYPES>::transport_dbg(typename TYPES::tlm_payload_type& trans) {
722 return fw_port->transport_dbg(trans);
723}
724} // namespace lwtr
725} // namespace axi
The TLM2 transaction recorder.
Definition ace_lwtr.h:64
sc_core::sc_port< axi::ace_bw_transport_if< TYPES > > bw_port
the port where bw accesses are forwarded to
Definition ace_lwtr.h:209
bool isRecordingBlockingTxEnabled() const
get the current state of transaction recording
Definition ace_lwtr.h:196
ace_lwtr(char const *full_name, unsigned bus_width, bool recording_enabled=true, tx_db *tr_db=tx_db::get_default_db())
The constructor of the component.
Definition ace_lwtr.h:86
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.
Definition ace_lwtr.h:450
cci::cci_param< bool > enableTimedTracing
the attribute to selectively enable/disable timed recording
Definition ace_lwtr.h:73
bool get_direct_mem_ptr(typename TYPES::tlm_payload_type &trans, tlm::tlm_dmi &dmi_data) override
The direct memory interface forward function.
Definition ace_lwtr.h:688
sc_core::sc_port< axi::ace_fw_transport_if< TYPES > > fw_port
the port where fw accesses are forwarded to
Definition ace_lwtr.h:206
cci::cci_param< bool > enableBlTracing
the attribute to selectively enable/disable recording of blocking protocol tx
Definition ace_lwtr.h:67
bool isRecordingNonBlockingTxEnabled() const
get the current state of transaction recording
Definition ace_lwtr.h:202
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.
Definition ace_lwtr.h:534
cci::cci_param< bool > enableDmiTracing
the attribute to selectively enable/disable DMI recording
Definition ace_lwtr.h:76
void b_snoop(typename TYPES::tlm_payload_type &trans, sc_core::sc_time &delay) override
The blocking snoop function.
Definition ace_lwtr.h:389
unsigned int transport_dbg(typename TYPES::tlm_payload_type &trans) override
The debug transportfunction.
Definition ace_lwtr.h:721
cci::cci_param< bool > enableNbTracing
the attribute to selectively enable/disable recording of non-blocking protocol tx
Definition ace_lwtr.h:70
void b_transport(typename TYPES::tlm_payload_type &trans, sc_core::sc_time &delay) override
The blocking transport function.
Definition ace_lwtr.h:324
void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override
The direct memory interface backward function.
Definition ace_lwtr.h:705
payload_type * allocate()
get a plain tlm_payload_type without extensions
Definition tlm_mm.h:218
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
Definition ace_lwtr.h:47
priority event queue
Definition peq.h:41
boost::optional< TYPE > get_next()
non-blocking get
Definition peq.h:124
Definition tlm2_lwtr.h:102
static tlm_mm & get()
accessor function of the singleton
Definition tlm_mm.h:338