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