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