scc 2025.09
SystemC components library
axi_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#include <tlm/scc/lwtr/tlm2_lwtr.h>
20#include <cci_configuration>
21#include <axi/checker/axi_protocol.h>
22#include <tlm/scc/tlm_mm.h>
23#include <array>
24#include <axi/axi_tlm.h>
25#include <regex>
26#include <string>
27#include <scc/peq.h>
28#include <unordered_map>
29#include <vector>
30
32namespace axi {
33namespace lwtr {
34
35using tx_db = ::lwtr::tx_db;
36using tx_fiber = ::lwtr::tx_fiber;
37template <typename BEGIN = ::lwtr::no_data, typename END = ::lwtr::no_data>
38using tx_generator = ::lwtr::tx_generator<BEGIN, END>;
39using tx_handle = ::lwtr::tx_handle;
40using mm = tlm::scc::tlm_mm<>;
41using namespace tlm::scc::lwtr;
42
43extern bool registered;
44
53template <typename TYPES = axi::axi_protocol_types>
54class axi_lwtr : public virtual axi::axi_fw_transport_if<TYPES>, public virtual axi::axi_bw_transport_if<TYPES> {
55public:
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> enableProtocolChecker{"enableProtocolChecker", false};
70
71 cci::cci_param<unsigned> rd_response_timeout{"rd_response_timeout", 0};
72
73 cci::cci_param<unsigned> wr_response_timeout{"wr_response_timeout", 0};
74
83 axi_lwtr(char const* full_name, unsigned bus_width, bool recording_enabled = true, tx_db* tr_db = tx_db::get_default_db())
84 : enableBlTracing("enableBlTracing", recording_enabled)
85 , enableNbTracing("enableNbTracing", recording_enabled)
86 , full_name(full_name)
87 , nb_timed_peq()
88 , bus_width(bus_width)
89 , m_db(tr_db)
90 {
91 sc_core::sc_spawn_options opts;
92 opts.spawn_method();
93 opts.dont_initialize();
94 opts.set_sensitivity(&nb_timed_peq.event());
95 sc_core::sc_spawn([this](){nbtx_cb();}, nullptr, &opts);
96 initialize_streams();
97 }
98
99 virtual ~axi_lwtr() override {
100 nbtx_req_handle_map.clear();
101 nbtx_last_req_handle_map.clear();
102 nbtx_resp_handle_map.clear();
103 nbtx_last_resp_handle_map.clear();
104 delete checker;
105 delete dmi_trInvalidateHandle;
106 delete dmi_trGetHandle;
107 delete dmi_streamHandle;
108 for(auto* p : nb_trTimedHandle) delete p; // NOLINT
109 delete nb_streamHandleTimed;
110 for(auto* p : nb_trHandle) delete p; // NOLINT
111 delete nb_streamHandle;
112 for(auto* p : b_trTimedHandle) delete p; // NOLINT
113 delete b_streamHandleTimed;
114 for(auto* p : b_trHandle) delete p; // NOLINT
115 delete b_streamHandle;
116 }
117
118 // TLM-2.0 interface methods for initiator and target sockets, surrounded with
119 // Tx Recording
129 tlm::tlm_sync_enum nb_transport_fw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
130 sc_core::sc_time& delay) override;
140 tlm::tlm_sync_enum nb_transport_bw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase,
141 sc_core::sc_time& delay) override;
150 void b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) override;
158 bool get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) override;
165 void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override;
172 unsigned int transport_dbg(typename TYPES::tlm_payload_type& trans) override;
178 inline bool isRecordingBlockingTxEnabled() const { return m_db && enableBlTracing.get_value(); }
184 inline bool isRecordingNonBlockingTxEnabled() const { return m_db && enableNbTracing.get_value(); }
185
186protected:
188 sc_core::sc_port<axi::axi_fw_transport_if<TYPES>> fw_port{"fw_port"};
189
191 sc_core::sc_port<axi::axi_bw_transport_if<TYPES>> bw_port{"bw_port"};
192
193private:
194 std::string const full_name;
196 ::scc::peq<nb_rec_entry> nb_timed_peq;
201 void nbtx_cb();
202 const unsigned bus_width{0};
204 tx_db* m_db{nullptr};
206 ::lwtr::tx_relation_handle pred_succ_hndl{0}, par_chld_hndl{0};
208 tx_fiber* b_streamHandle{nullptr};
210 std::array<tx_generator<sc_core::sc_time, sc_core::sc_time>*, 3> b_trHandle{{nullptr, nullptr, nullptr}};
212 tx_fiber* b_streamHandleTimed{nullptr};
215 std::array<tx_generator<>*, 3> b_trTimedHandle{{nullptr, nullptr, nullptr}};
216
217 enum DIR { FW, BW, REQ = FW, RESP = BW };
219 tx_fiber* nb_streamHandle{nullptr};
221 tx_fiber* nb_streamHandleTimed{nullptr};
223 std::array<tx_generator<std::string, std::string>*, 2> nb_trHandle{{nullptr, nullptr}};
225 std::array<tx_generator<>*, 2> nb_trTimedHandle{{nullptr, nullptr}};
226 std::unordered_map<uint64_t, tx_handle> nbtx_req_handle_map;
227 std::unordered_map<uint64_t, tx_handle> nbtx_last_req_handle_map;
228 std::unordered_map<uint64_t, tx_handle> nbtx_resp_handle_map;
229 std::unordered_map<uint64_t, tx_handle> nbtx_last_resp_handle_map;
231 tx_fiber* dmi_streamHandle{nullptr};
233 tx_generator<>* dmi_trGetHandle{nullptr};
234 tx_generator<sc_dt::uint64, sc_dt::uint64>* dmi_trInvalidateHandle{nullptr};
235
236protected:
237 void initialize_streams() {
238 if(m_db) {
239 pred_succ_hndl = m_db->create_relation("PREDECESSOR_SUCCESSOR");
240 par_chld_hndl = m_db->create_relation("PARENT_CHILD");
241 }
242 if(isRecordingBlockingTxEnabled() && !b_streamHandle) {
243 b_streamHandle = new tx_fiber((full_name + "_bl").c_str(), "[TLM][axi][b]", m_db);
244 b_trHandle[tlm::TLM_READ_COMMAND] = new tx_generator<sc_core::sc_time, sc_core::sc_time>(
245 "read", *b_streamHandle, "start_delay", "end_delay");
246 b_trHandle[tlm::TLM_WRITE_COMMAND] = new tx_generator<sc_core::sc_time, sc_core::sc_time>(
247 "write", *b_streamHandle, "start_delay", "end_delay");
248 b_trHandle[tlm::TLM_IGNORE_COMMAND] = new tx_generator<sc_core::sc_time, sc_core::sc_time>(
249 "ignore", *b_streamHandle, "start_delay", "end_delay");
250 if(enableTimedTracing.get_value()) {
251 b_streamHandleTimed =
252 new tx_fiber((full_name + "_bl_timed").c_str(), "[TLM][axi][b][timed]", m_db);
253 b_trTimedHandle[tlm::TLM_READ_COMMAND] = new tx_generator<>("read", *b_streamHandleTimed);
254 b_trTimedHandle[tlm::TLM_WRITE_COMMAND] = new tx_generator<>("write", *b_streamHandleTimed);
255 b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] = new tx_generator<>("ignore", *b_streamHandleTimed);
256 }
257 }
258 if(isRecordingNonBlockingTxEnabled() && !nb_streamHandle) {
259 nb_streamHandle = new tx_fiber((full_name + "_nb").c_str(), "[TLM][axi][nb]", m_db);
260 nb_trHandle[FW] = new tx_generator<std::string, std::string>("fw", *nb_streamHandle, "tlm_phase",
261 "tlm_phase[return_path]");
262 nb_trHandle[BW] = new tx_generator<std::string, std::string>("bw", *nb_streamHandle, "tlm_phase",
263 "tlm_phase[return_path]");
264 if(enableTimedTracing.get_value()) {
265 nb_streamHandleTimed =
266 new tx_fiber((full_name + "_nb_timed").c_str(), "[TLM][axi][nb][timed]", m_db);
267 nb_trTimedHandle[FW] = new tx_generator<>("request", *nb_streamHandleTimed);
268 nb_trTimedHandle[BW] = new tx_generator<>("response", *nb_streamHandleTimed);
269 }
270 }
271 if(m_db && enableDmiTracing.get_value() && !dmi_streamHandle) {
272 dmi_streamHandle = new tx_fiber((full_name + "_dmi").c_str(), "[TLM][axi][dmi]", m_db);
273 dmi_trGetHandle = new tx_generator<>("get", *dmi_streamHandle);
274 dmi_trInvalidateHandle = new tx_generator<sc_dt::uint64, sc_dt::uint64>(
275 "invalidate", *dmi_streamHandle, "start_addr", "end_addr");
276 }
277 if(enableProtocolChecker.get_value()) {
278 checker=new axi::checker::axi_protocol(full_name, bus_width/8, rd_response_timeout.get_value(), wr_response_timeout.get_value());
279 }
280 }
281
282private:
283 axi::checker::checker_if<TYPES>* checker{nullptr};
284};
285
286template <unsigned BUSWIDTH=32, typename TYPES = axi::axi_protocol_types, int N = 1,
287 sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
288class axi_lwtr_recorder : public sc_core::sc_module, public axi_lwtr<TYPES> {
289public:
292
293 axi_lwtr_recorder(sc_core::sc_module_name nm, bool recording_enabled = true, tx_db* tr_db = tx_db::get_default_db())
294 : sc_core::sc_module(nm)
295 , axi_lwtr<TYPES>(name(), BUSWIDTH, recording_enabled, tr_db)
296 {
297 is(*this);
298 ts(*this);
299 this->bw_port(ts.get_base_port());
300 this->fw_port(is.get_base_port());
301 }
302};
303
304// implementations of functions
306
307template <typename TYPES>
308void axi_lwtr<TYPES>::b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) {
310 fw_port->b_transport(trans, delay);
311 return;
312 }
313 // Get a handle for the new transaction
314 tx_handle h = b_trHandle[trans.get_command()]->begin_tx(delay);
315 tx_handle htim;
316 /*************************************************************************
317 * do the timed notification
318 *************************************************************************/
319 if(b_streamHandleTimed)
320 htim = b_trTimedHandle[trans.get_command()]->begin_tx_delayed(sc_core::sc_time_stamp()+delay, par_chld_hndl, h);
321
322 if(registered)
323 for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
324 if(extensionRecording) {
325 extensionRecording->recordBeginTx(h, trans);
326 if(htim.is_valid())
327 extensionRecording->recordBeginTx(htim, trans);
328 }
329 link_pred_ext* preExt = nullptr;
330
331 trans.get_extension(preExt);
332 if(preExt == nullptr) { // we are the first recording this transaction
333 preExt = new link_pred_ext(h, this);
334 if(trans.has_mm())
335 trans.set_auto_extension(preExt);
336 else
337 trans.set_extension(preExt);
338 } else {
339 h.add_relation(pred_succ_hndl, preExt->txHandle);
340 }
341 tx_handle preTx{preExt->txHandle};
342 preExt->txHandle = h;
343 fw_port->b_transport(trans, delay);
344 trans.get_extension(preExt);
345 if(preExt->creator == this) {
346 // clean-up the extension if this is the original creator
347 trans.set_extension(static_cast<link_pred_ext*>(nullptr));
348 if(!trans.has_mm()) {
349 delete preExt;
350 }
351 } else {
352 preExt->txHandle = preTx;
353 }
354
355 h.record_attribute("trans", trans);
356 if(registered)
357 for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
358 if(extensionRecording) {
359 extensionRecording->recordEndTx(h, trans);
360 if(htim.is_active())
361 extensionRecording->recordEndTx(htim, trans);
362 }
363 // End the transaction
364 h.end_tx(delay);
365 // and now the stuff for the timed tx
366 if(htim.is_valid()) {
367 htim.record_attribute("trans", trans);
368 htim.end_tx_delayed(sc_core::sc_time_stamp()+delay);
369 }
370}
371
372template <typename TYPES>
373tlm::tlm_sync_enum axi_lwtr<TYPES>::nb_transport_fw(typename TYPES::tlm_payload_type& trans,
374 typename TYPES::tlm_phase_type& phase,
375 sc_core::sc_time& delay) {
377 if(checker){
378 checker->fw_pre(trans, phase);
379 tlm::tlm_sync_enum status = fw_port->nb_transport_fw(trans, phase, delay);
380 checker->fw_post(trans, phase, status);
381 return status;
382 } else
383 return fw_port->nb_transport_fw(trans, phase, delay);
384 }
385 /*************************************************************************
386 * prepare recording
387 *************************************************************************/
388 // Get a handle for the new transaction
389 tx_handle h = nb_trHandle[FW]->begin_tx(phase.get_name());
390 link_pred_ext* preExt = nullptr;
391 trans.get_extension(preExt);
392 if((phase == axi::BEGIN_PARTIAL_REQ || phase == tlm::BEGIN_REQ) && preExt == nullptr) { // we are the first recording this transaction
393 preExt = new link_pred_ext(h, this);
394 if(trans.has_mm())
395 trans.set_auto_extension(preExt);
396 else
397 trans.set_extension(preExt);
398 } else if(preExt != nullptr) {
399 // link handle if we have a predecessor
400 h.add_relation(pred_succ_hndl, preExt->txHandle);
401 } else {
402 sc_assert(preExt != nullptr && "ERROR on forward path in phase other than tlm::BEGIN_REQ");
403 }
404 // update the extension
405 preExt->txHandle = h;
406 h.record_attribute("delay", delay);
407 if(registered)
408 for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
409 if(extensionRecording)
410 extensionRecording->recordBeginTx(h, trans);
411 /*************************************************************************
412 * do the timed notification
413 *************************************************************************/
414 if(nb_streamHandleTimed) {
415 nb_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h};
416 rec.tr->deep_copy_from(trans);
417 nb_timed_peq.notify(rec, delay);
418 }
419 /*************************************************************************
420 * do the access
421 *************************************************************************/
422 if(checker) checker->fw_pre(trans, phase);
423 tlm::tlm_sync_enum status = fw_port->nb_transport_fw(trans, phase, delay);
424 if(checker) checker->fw_post(trans, phase, status);
425 /*************************************************************************
426 * handle recording
427 *************************************************************************/
428 h.record_attribute("tlm_sync", status);
429 h.record_attribute("delay[return_path]", delay);
430 h.record_attribute("trans", trans);
431 if(registered)
432 for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
433 if(extensionRecording)
434 extensionRecording->recordEndTx(h, trans);
435 // get the extension and free the memory if it was mine
436 if(status == tlm::TLM_COMPLETED || (status == tlm::TLM_ACCEPTED && phase == tlm::END_RESP)) {
437 trans.get_extension(preExt);
438 if(preExt && preExt->creator == this) {
439 trans.set_extension(static_cast<link_pred_ext*>(nullptr));
440 if(!trans.has_mm()) {
441 delete preExt;
442 }
443 }
444 /*************************************************************************
445 * do the timed notification if req. finished here
446 *************************************************************************/
447 if(nb_streamHandleTimed) {
448 nb_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h};
449 rec.tr->deep_copy_from(trans);
450 nb_timed_peq.notify(rec, delay);
451 }
452 } else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
453 nb_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h};
454 rec.tr->deep_copy_from(trans);
455 nb_timed_peq.notify(rec, delay);
456 }
457 // End the transaction
458 nb_trHandle[FW]->end_tx(h, phase.get_name());
459 return status;
460}
461
462template <typename TYPES>
463tlm::tlm_sync_enum axi_lwtr<TYPES>::nb_transport_bw(typename TYPES::tlm_payload_type& trans,
464 typename TYPES::tlm_phase_type& phase,
465 sc_core::sc_time& delay) {
467 if(checker) {
468 checker->bw_pre(trans, phase);
469 tlm::tlm_sync_enum status = bw_port->nb_transport_bw(trans, phase, delay);
470 checker->bw_post(trans, phase, status);
471 return status;
472 } else
473 return bw_port->nb_transport_bw(trans, phase, delay);
474 }
475 /*************************************************************************
476 * prepare recording
477 *************************************************************************/
478 link_pred_ext* preExt = nullptr;
479 trans.get_extension(preExt);
480 // Get a handle for the new transaction
481 tx_handle h = nb_trHandle[BW]->begin_tx(phase.get_name());
482 // link handle if we have a predecessor and that's not ourself
483 if(phase == tlm::BEGIN_REQ && preExt == nullptr) { // we are the first recording this transaction
484 preExt = new link_pred_ext(h, this);
485 trans.set_extension(preExt);
486 preExt->txHandle = h;
487 } else if(preExt) {
488 // link handle if we have a predecessor
489 h.add_relation(pred_succ_hndl, preExt->txHandle);
490 // and set the extension handle to this transaction
491 preExt->txHandle = h;
492 } else {
493 sc_assert(preExt != nullptr && "ERROR on backward path in phase other than tlm::BEGIN_REQ");
494 }
495 // and set the extension handle to this transaction
496 h.record_attribute("delay", delay);
497 for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
498 if(extensionRecording)
499 extensionRecording->recordBeginTx(h, trans);
500 /*************************************************************************
501 * do the timed notification
502 *************************************************************************/
503 if(nb_streamHandleTimed) {
504 nb_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h};
505 rec.tr->deep_copy_from(trans);
506 nb_timed_peq.notify(rec, delay);
507 }
508 /*************************************************************************
509 * do the access
510 *************************************************************************/
511 if(checker) checker->bw_pre(trans, phase);
512 tlm::tlm_sync_enum status = bw_port->nb_transport_bw(trans, phase, delay);
513 if(checker) checker->bw_post(trans, phase, status);
514 /*************************************************************************
515 * handle recording
516 *************************************************************************/
517 h.record_attribute("tlm_sync", status);
518 h.record_attribute("delay[return_path]", delay);
519 h.record_attribute("trans", trans);
520 if(registered)
521 for(auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
522 if(extensionRecording)
523 extensionRecording->recordEndTx(h, trans);
524 // End the transaction
525 nb_trHandle[BW]->end_tx(h, phase.get_name());
526 // get the extension and free the memory if it was mine
527 if(status == tlm::TLM_COMPLETED || (status == tlm::TLM_UPDATED && phase == tlm::END_RESP)) {
528 // the transaction is finished
529 if(preExt && preExt->creator == this) {
530 // clean-up the extension if this is the original creator
531 trans.set_extension(static_cast<link_pred_ext*>(nullptr));
532 if(!trans.has_mm()) {
533 delete preExt;
534 }
535 }
536 /*************************************************************************
537 * do the timed notification if req. finished here
538 *************************************************************************/
539 if(nb_streamHandleTimed) {
540 nb_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h};
541 rec.tr->deep_copy_from(trans);
542 nb_timed_peq.notify(rec, delay);
543 }
544 } else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
545 nb_rec_entry rec {mm::get().allocate(), phase, reinterpret_cast<uint64_t>(&trans), h};
546 rec.tr->deep_copy_from(trans);
547 nb_timed_peq.notify(rec, delay);
548 }
549 return status;
550}
551
552template <typename TYPES>
553void axi_lwtr<TYPES>::nbtx_cb() {
554 auto opt = nb_timed_peq.get_next();
555 if(opt) {
556 auto& e = opt.get();
557 tx_handle h;
558 // Now process outstanding recordings
559 if(e.ph == tlm::BEGIN_REQ || e.ph == axi::BEGIN_PARTIAL_REQ) {
560 h = nb_trTimedHandle[REQ]->begin_tx(par_chld_hndl, e.parent);
561 nbtx_req_handle_map[e.id] = h;
562 } else if(e.ph == tlm::END_REQ || e.ph == axi::END_PARTIAL_REQ) {
563 auto it = nbtx_req_handle_map.find(e.id);
564 if(it != nbtx_req_handle_map.end()) {
565 h = it->second;
566 nbtx_req_handle_map.erase(it);
567 h.record_attribute("trans", *e.tr);
568 h.end_tx();
569 nbtx_last_req_handle_map[e.id] = h;
570 }
571 } else if(e.ph == tlm::BEGIN_RESP || e.ph == axi::BEGIN_PARTIAL_RESP) {
572 auto it = nbtx_req_handle_map.find(e.id);
573 if(it != nbtx_req_handle_map.end()) {
574 h = it->second;
575 nbtx_req_handle_map.erase(it);
576 h.record_attribute("trans", *e.tr);
577 h.end_tx();
578 nbtx_last_req_handle_map[e.id] = h;
579 }
580 h = nb_trTimedHandle[RESP]->begin_tx(par_chld_hndl, e.parent);
581 nbtx_resp_handle_map[e.id] = h;
582 it = nbtx_last_req_handle_map.find(e.id);
583 if(it != nbtx_last_req_handle_map.end()) {
584 tx_handle& pred = it->second;
585 h.add_relation(pred_succ_hndl, pred);
586 nbtx_last_req_handle_map.erase(it);
587 } else {
588 it = nbtx_last_resp_handle_map.find(e.id);
589 if(it != nbtx_last_resp_handle_map.end()) {
590 tx_handle& pred = it->second;
591 h.add_relation(pred_succ_hndl, pred);
592 nbtx_last_resp_handle_map.erase(it);
593 }
594 }
595 } else if(e.ph == tlm::END_RESP || e.ph == axi::END_PARTIAL_RESP) {
596 auto it = nbtx_resp_handle_map.find(e.id);
597 if(it != nbtx_resp_handle_map.end()) {
598 h = it->second;
599 h.record_attribute("trans", *e.tr);
600 nbtx_resp_handle_map.erase(it);
601 h.end_tx();
602 if(e.ph == axi::END_PARTIAL_RESP) {
603 nbtx_last_resp_handle_map[e.id] = h;
604 }
605 }
606 } else
607 sc_assert(!"phase not supported!");
608 }
609 return;
610}
611
612template <typename TYPES>
613bool axi_lwtr<TYPES>::get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) {
614 if(!(m_db && enableDmiTracing.get_value()))
615 return fw_port->get_direct_mem_ptr(trans, dmi_data);
616 tx_handle h = dmi_trGetHandle->begin_tx();
617 bool status = fw_port->get_direct_mem_ptr(trans, dmi_data);
618 h.record_attribute("trans", trans);
619 h.record_attribute("dmi_data", dmi_data);
620 h.end_tx();
621 return status;
622}
623
629template <typename TYPES>
630void axi_lwtr<TYPES>::invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) {
631 if(!(m_db && enableDmiTracing.get_value())) {
632 bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
633 return;
634 }
635 tx_handle h = dmi_trInvalidateHandle->begin_tx(start_addr);
636 bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
637 dmi_trInvalidateHandle->end_tx(h, end_addr);
638 return;
639}
640
646template <typename TYPES> unsigned int axi_lwtr<TYPES>::transport_dbg(typename TYPES::tlm_payload_type& trans) {
647 return fw_port->transport_dbg(trans);
648}
649} // namespace lwtr
650} // namespace axi
The TLM2 transaction recorder.
Definition axi_lwtr.h:54
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 axi_lwtr.h:373
cci::cci_param< bool > enableDmiTracing
the attribute to selectively enable/disable DMI recording
Definition axi_lwtr.h:66
bool isRecordingNonBlockingTxEnabled() const
get the current state of transaction recording
Definition axi_lwtr.h:184
void b_transport(typename TYPES::tlm_payload_type &trans, sc_core::sc_time &delay) override
The blocking transport function.
Definition axi_lwtr.h:308
axi_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 axi_lwtr.h:83
bool get_direct_mem_ptr(typename TYPES::tlm_payload_type &trans, tlm::tlm_dmi &dmi_data) override
The direct memory interface forward function.
Definition axi_lwtr.h:613
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 axi_lwtr.h:463
void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) override
The direct memory interface backward function.
Definition axi_lwtr.h:630
cci::cci_param< bool > enableNbTracing
the attribute to selectively enable/disable recording of non-blocking protocol tx
Definition axi_lwtr.h:60
bool isRecordingBlockingTxEnabled() const
get the current state of transaction recording
Definition axi_lwtr.h:178
cci::cci_param< bool > enableTimedTracing
the attribute to selectively enable/disable timed recording
Definition axi_lwtr.h:63
cci::cci_param< bool > enableProtocolChecker
the attribute to enable/disable protocol checking
Definition axi_lwtr.h:69
sc_core::sc_port< axi::axi_fw_transport_if< TYPES > > fw_port
the port where fw accesses are forwarded to
Definition axi_lwtr.h:188
cci::cci_param< bool > enableBlTracing
the attribute to selectively enable/disable recording of blocking protocol tx
Definition axi_lwtr.h:57
unsigned int transport_dbg(typename TYPES::tlm_payload_type &trans) override
The debug transportfunction.
Definition axi_lwtr.h:646
sc_core::sc_port< axi::axi_bw_transport_if< TYPES > > bw_port
the port where bw accesses are forwarded to
Definition axi_lwtr.h:191
payload_type * allocate()
get a plain tlm_payload_type without extensions
Definition tlm_mm.h:218
TLM2.0 components modeling AHB.
tlm::tlm_bw_transport_if< TYPES > axi_bw_transport_if
alias declaration for the backward interface:
Definition axi_tlm.h:956
tlm::tlm_fw_transport_if< TYPES > axi_fw_transport_if
alias declaration for the forward interface
Definition axi_tlm.h:954
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