scc 2026.07
SystemC components library
tlm_recorder.cpp
1/*******************************************************************************
2 * Copyright 2016-2022 MINRES Technologies GmbH
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#ifndef SC_INCLUDE_DYNAMIC_PROCESSES
18#define SC_INCLUDE_DYNAMIC_PROCESSES
19#include <tlm>
20#endif
21#include "tlm_extension_recording_registry.h"
22#include "tlm_recorder.h"
23#include <fmt/format.h>
24#include <tlm/scc/tlm_id.h>
25
26namespace tlm {
27namespace scc {
28namespace scv {
29namespace {
30const std::array<std::string, 3> cmd2char{{"READ", "WRITE", "IGNORE"}};
31const std::array<std::string, 7> resp2char{
32 {"OK", "INCOMPLETE", "GENERIC_ERROR", "ADDRESS_ERROR", "COMMAND_ERROR", "BURST_ERROR", "BYTE_ENABLE_ERROR"}};
33const std::array<std::string, 3> gp_option2char{{"MIN_PAYLOAD", "FULL_PAYLOAD", "FULL_PAYLOAD_ACCEPTED"}};
34const std::array<std::string, 5> phase2char{{"UNINITIALIZED_PHASE", "BEGIN_REQ", "END_REQ", "BEGIN_RESP", "END_RESP"}};
35const std::array<std::string, 4> dmi2char{{"DMI_ACCESS_NONE", "DMI_ACCESS_READ", "DMI_ACCESS_WRITE", "DMI_ACCESS_READ_WRITE"}};
36const std::array<std::string, 3> sync2char{{"ACCEPTED", "UPDATED", "COMPLETED"}};
37
38} // namespace
39void record(SCVNS scv_tr_handle& handle, tlm::tlm_generic_payload const& o) {
40 handle.record_attribute("trans.ptr", reinterpret_cast<uintptr_t>(&o));
41 handle.record_attribute("trans.address", o.get_address());
42 handle.record_attribute("trans.cmd", cmd2char.at(o.get_command()));
43 handle.record_attribute("trans.data_ptr", o.get_data_ptr());
44 handle.record_attribute("trans.data_length", o.get_data_length());
45 handle.record_attribute("trans.response", resp2char.at(1 - o.get_response_status()));
46 handle.record_attribute("trans.dmi_allowed", o.is_dmi_allowed());
47 handle.record_attribute("trans.byte_enable", o.get_byte_enable_ptr());
48 handle.record_attribute("trans.byte_enable_length", o.get_byte_enable_length());
49 handle.record_attribute("trans.streaming_width", o.get_streaming_width());
50 handle.record_attribute("trans.gp_option", gp_option2char.at(o.get_gp_option()));
51 if(o.get_data_length() && o.get_data_length() < 9 && o.get_data_ptr()) {
52 uint64_t buf = 0;
53 memcpy(&buf, o.get_data_ptr(), o.get_data_length());
54 handle.record_attribute("trans.data_value", buf);
55 }
56}
57void record(SCVNS scv_tr_handle& handle, tlm::tlm_phase const& o) {
58 unsigned id = o;
59 if(id < phase2char.size())
60 handle.record_attribute("phase", phase2char[id]);
61 else
62 handle.record_attribute("phase_id", id);
63}
64void record(SCVNS scv_tr_handle& handle, tlm::tlm_sync_enum o) { handle.record_attribute("tlm_sync", sync2char.at(o)); }
65void record(SCVNS scv_tr_handle& handle, tlm::tlm_dmi const& o) {
66 handle.record_attribute("trans.dmi_ptr", o.get_dmi_ptr());
67 handle.record_attribute("trans.start_address", o.get_start_address());
68 handle.record_attribute("trans.end_address", o.get_end_address());
69 handle.record_attribute("trans.granted_access", dmi2char.at(o.get_granted_access()));
70 handle.record_attribute("trans.read_latency", o.get_read_latency().to_string());
71 handle.record_attribute("trans.write_latency", o.get_write_latency().to_string());
72}
73
74struct tlm_id_ext_record : public tlm_extension_record_if {
75
76 tlm_id_ext_record() { recordBegin = &tlm_id_ext_record::recordBeginTx; }
77
78 static void recordBeginTx(SCVNS scv_tr_handle& handle, tlm::tlm_extension_base* e, std::string const& prefix) {
79 if(auto ext = dynamic_cast<tlm_id_extension*>(e)) {
80 handle.record_attribute(fmt::format("{}uid", prefix).c_str(), ext->id);
81 }
82 }
83};
84
85struct tlm_id_ext_recording : public tlm_extensions_recording_if<tlm::tlm_base_protocol_types> {
86
87 tlm_id_ext_recording() { recordBegin = &recordBeginTx; }
88
89 static void recordBeginTx(SCVNS scv_tr_handle& handle, tlm::tlm_base_protocol_types::tlm_payload_type& trans) {
90 tlm_extension_record_registry::get().recordBeginTx(tlm_id_extension::ID, handle, trans.get_extension<tlm_id_extension>(), "trans.");
91 }
92};
93
94using namespace tlm::scc::scv;
95#if defined(__GNUG__)
96__attribute__((constructor))
97#endif
98bool register_extensions() {
99 tlm::scc::tlm_id_extension ext(nullptr);
100 if(!tlm_extension_recording_registry<tlm::tlm_base_protocol_types>::get().is_ext_registered(ext.ID)) // NOLINT
101 tlm_extension_recording_registry<tlm::tlm_base_protocol_types>::get().register_ext_rec(
102 ext.ID,
103 util::make_unique<tlm_id_ext_recording>()); // NOLINT
104 if(!tlm_extension_record_registry::get().is_ext_registered(ext.ID))
105 tlm_extension_record_registry::get().register_ext_rec(ext.ID, util::make_unique<tlm_id_ext_record>()); // NOLINT
106 return true; // NOLINT
107}
108bool registered = register_extensions();
109
110} // namespace scv
111} // namespace scc
112} // namespace tlm
SCC SCV4TLM classes and functions.
SCC TLM utilities.
Definition axis_tlm.h:56
SystemC TLM.
Definition dmi_mgr.h:19
util::delegate< void(SCVNS scv_tr_handle &, tlm::tlm_extension_base *, std::string const &)> recordBegin
recording attributes in extensions at the beginning, it is intended to be overload as it does nothing
The TLM transaction extensions recorder interface.
void recordBeginTx(SCVNS scv_tr_handle &h, typename TYPES::tlm_payload_type &trans)
recording attributes in extensions at the beginning, it is intended to be overload as it does nothing