scc 2026.07
SystemC components library
axi_ace_scv.cpp
1/*
2 * Copyright 2020 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#include <axi/axi_tlm.h>
18#include <fmt/format.h>
19#include <tlm/scc/scv/tlm_extension_recording_registry.h>
20#include <tlm/scc/scv/tlm_recorder.h>
21#include <tlm/scc/tlm_id.h>
22
23namespace axi {
24namespace scv {
25
26using namespace tlm::scc::scv;
27
28struct tlm_id_ext_recording : public tlm_extensions_recording_if<axi::axi_protocol_types> {
29
30 tlm_id_ext_recording() { recordBegin = &recordBeginTx; }
31
32 static void recordBeginTx(SCVNS scv_tr_handle& handle, axi_protocol_types::tlm_payload_type& trans) {
33 tlm_extension_record_registry::get().recordBeginTx(tlm::scc::tlm_id_extension::ID, handle,
34 trans.get_extension<tlm::scc::tlm_id_extension>(), "trans.");
35 }
36};
37
38struct axi3_ext_record : public tlm_extension_record_if {
39
40 axi3_ext_record() {
41 recordBegin = &recordBeginTx;
42 recordEnd = recordEndTx;
43 }
44
45 static void recordBeginTx(SCVNS scv_tr_handle& handle, tlm::tlm_extension_base* e, std::string const& prefix) {
46 if(auto ext = dynamic_cast<axi3_extension*>(e)) {
47 handle.record_attribute(fmt::format("{}id", prefix).c_str(), ext->get_id());
48 handle.record_attribute(fmt::format("{}user[CTRL]", prefix).c_str(), ext->get_user(common::id_type::CTRL));
49 handle.record_attribute(fmt::format("{}user[DATA]", prefix).c_str(), ext->get_user(common::id_type::DATA));
50 handle.record_attribute(fmt::format("{}user[RESP]", prefix).c_str(), ext->get_user(common::id_type::RESP));
51 handle.record_attribute(fmt::format("{}length", prefix).c_str(), ext->get_length());
52 handle.record_attribute(fmt::format("{}size", prefix).c_str(), ext->get_size());
53 handle.record_attribute(fmt::format("{}burst", prefix).c_str(), std::string(to_char(ext->get_burst())));
54 handle.record_attribute(fmt::format("{}prot", prefix).c_str(), ext->get_prot());
55 handle.record_attribute(fmt::format("{}exclusive", prefix).c_str(), std::string(ext->is_exclusive() ? "true" : "false"));
56 handle.record_attribute(fmt::format("{}cache", prefix).c_str(), ext->get_cache());
57 handle.record_attribute(fmt::format("{}cache_bufferable", prefix).c_str(), ext->is_bufferable());
58 handle.record_attribute(fmt::format("{}cache_cacheable", prefix).c_str(), ext->is_cacheable());
59 handle.record_attribute(fmt::format("{}cache_read_alloc", prefix).c_str(), ext->is_read_allocate());
60 handle.record_attribute(fmt::format("{}cache_write_alloc", prefix).c_str(), ext->is_write_allocate());
61 handle.record_attribute(fmt::format("{}qos", prefix).c_str(), ext->get_qos());
62 handle.record_attribute(fmt::format("{}region", prefix).c_str(), ext->get_region());
63 }
64 }
65 static void recordEndTx(SCVNS scv_tr_handle& handle, tlm::tlm_extension_base* e, std::string const& prefix) {
66 if(auto ext = dynamic_cast<axi3_extension*>(e)) {
67 handle.record_attribute(fmt::format("{}resp", prefix).c_str(), std::string(to_char(ext->get_resp())));
68 }
69 }
70};
71
72struct axi3_ext_recording : public tlm_extensions_recording_if<axi_protocol_types> {
73
74 axi3_ext_recording() {
75 recordBegin = &recordBeginTx;
76 recordEnd = &recordEndTx;
77 }
78
79 static void recordBeginTx(SCVNS scv_tr_handle& handle, axi_protocol_types::tlm_payload_type& trans) {
80 tlm_extension_record_registry::get().recordBeginTx(axi3_extension::ID, handle, trans.get_extension<axi3_extension>(),
81 "trans.axi3.");
82 }
83
84 static void recordEndTx(SCVNS scv_tr_handle& handle, axi_protocol_types::tlm_payload_type& trans) {
85 tlm_extension_record_registry::get().recordEndTx(axi3_extension::ID, handle, trans.get_extension<axi3_extension>(), "trans.axi3.");
86 }
87};
88
89struct axi4_ext_record : public tlm_extension_record_if {
90
91 axi4_ext_record() {
92 recordBegin = &recordBeginTx;
93 recordEnd = &recordEndTx;
94 }
95
96 static void recordBeginTx(SCVNS scv_tr_handle& handle, tlm::tlm_extension_base* e, std::string const& prefix) {
97 if(auto ext = dynamic_cast<axi4_extension*>(e)) {
98 handle.record_attribute(fmt::format("{}id", prefix).c_str(), ext->get_id());
99 handle.record_attribute(fmt::format("{}user[CTRL]", prefix).c_str(), ext->get_user(common::id_type::CTRL));
100 handle.record_attribute(fmt::format("{}user[DATA]", prefix).c_str(), ext->get_user(common::id_type::DATA));
101 handle.record_attribute(fmt::format("{}user[RESP]", prefix).c_str(), ext->get_user(common::id_type::RESP));
102 handle.record_attribute(fmt::format("{}length", prefix).c_str(), ext->get_length());
103 handle.record_attribute(fmt::format("{}size", prefix).c_str(), ext->get_size());
104 handle.record_attribute(fmt::format("{}burst", prefix).c_str(), std::string(to_char(ext->get_burst())));
105 handle.record_attribute(fmt::format("{}prot", prefix).c_str(), ext->get_prot());
106 handle.record_attribute(fmt::format("{}exclusive", prefix).c_str(), std::string(ext->is_exclusive() ? "true" : "false"));
107 handle.record_attribute(fmt::format("{}cache", prefix).c_str(), ext->get_cache());
108 handle.record_attribute(fmt::format("{}cache_bufferable", prefix).c_str(), ext->is_bufferable());
109 handle.record_attribute(fmt::format("{}cache_modifiable", prefix).c_str(), ext->is_modifiable());
110 handle.record_attribute(fmt::format("{}cache_allocate", prefix).c_str(), ext->is_allocate());
111 handle.record_attribute(fmt::format("{}cache_other_alloc", prefix).c_str(), ext->is_other_allocate());
112 handle.record_attribute(fmt::format("{}qos", prefix).c_str(), ext->get_qos());
113 handle.record_attribute(fmt::format("{}region", prefix).c_str(), ext->get_region());
114 }
115 }
116
117 static void recordEndTx(SCVNS scv_tr_handle& handle, tlm::tlm_extension_base* e, std::string const& prefix) {
118 if(auto ext = dynamic_cast<axi4_extension*>(e)) {
119 handle.record_attribute(fmt::format("{}resp", prefix).c_str(), std::string(to_char(ext->get_resp())));
120 }
121 }
122};
123
124struct axi4_ext_recording : public tlm_extensions_recording_if<axi_protocol_types> {
125
126 axi4_ext_recording() {
127 recordBegin = &recordBeginTx;
128 recordEnd = &recordEndTx;
129 }
130
131 static void recordBeginTx(SCVNS scv_tr_handle& handle, axi_protocol_types::tlm_payload_type& trans) {
132 tlm_extension_record_registry::get().recordBeginTx(axi4_extension::ID, handle, trans.get_extension<axi4_extension>(),
133 "trans.axi4.");
134 }
135
136 static void recordEndTx(SCVNS scv_tr_handle& handle, axi_protocol_types::tlm_payload_type& trans) {
137 tlm_extension_record_registry::get().recordEndTx(axi4_extension::ID, handle, trans.get_extension<axi4_extension>(), "trans.axi4.");
138 }
139};
140
141struct ace_ext_record : public tlm_extension_record_if {
142
143 ace_ext_record() {
144 recordBegin = &recordBeginTx;
145 recordEnd = &recordEndTx;
146 }
147
148 static void recordBeginTx(SCVNS scv_tr_handle& handle, tlm::tlm_extension_base* e, std::string const& prefix) {
149 if(auto ext = dynamic_cast<ace_extension*>(e)) {
150 handle.record_attribute(fmt::format("{}id", prefix).c_str(), ext->get_id());
151 handle.record_attribute(fmt::format("{}user[CTRL]", prefix).c_str(), ext->get_user(common::id_type::CTRL));
152 handle.record_attribute(fmt::format("{}user[DATA]", prefix).c_str(), ext->get_user(common::id_type::DATA));
153 handle.record_attribute(fmt::format("{}length", prefix).c_str(), ext->get_length());
154 handle.record_attribute(fmt::format("{}size", prefix).c_str(), ext->get_size());
155 handle.record_attribute(fmt::format("{}burst", prefix).c_str(), std::string(to_char(ext->get_burst())));
156 handle.record_attribute(fmt::format("{}prot", prefix).c_str(), ext->get_prot());
157 handle.record_attribute(fmt::format("{}exclusive", prefix).c_str(), std::string(ext->is_exclusive() ? "true" : "false"));
158 handle.record_attribute(fmt::format("{}cache", prefix).c_str(), ext->get_cache());
159 handle.record_attribute(fmt::format("{}cache_bufferable", prefix).c_str(), ext->is_bufferable());
160 handle.record_attribute(fmt::format("{}cache_modifiable", prefix).c_str(), ext->is_modifiable());
161 handle.record_attribute(fmt::format("{}cache_allocate", prefix).c_str(), ext->is_allocate());
162 handle.record_attribute(fmt::format("{}cache_other_alloc", prefix).c_str(), ext->is_other_allocate());
163 handle.record_attribute(fmt::format("{}qos", prefix).c_str(), ext->get_qos());
164 handle.record_attribute(fmt::format("{}region", prefix).c_str(), ext->get_region());
165 handle.record_attribute(fmt::format("{}domain", prefix).c_str(), std::string(to_char(ext->get_domain())));
166 handle.record_attribute(fmt::format("{}snoop", prefix).c_str(), std::string(to_char(ext->get_snoop())));
167 handle.record_attribute(fmt::format("{}barrier", prefix).c_str(), std::string(to_char(ext->get_barrier())));
168 handle.record_attribute(fmt::format("{}unique", prefix).c_str(), ext->get_unique());
169 }
170 }
171
172 static void recordEndTx(SCVNS scv_tr_handle& handle, tlm::tlm_extension_base* e, std::string const& prefix) {
173 if(auto ext = dynamic_cast<ace_extension*>(e)) {
174 handle.record_attribute(fmt::format("{}resp", prefix).c_str(), std::string(to_char(ext->get_resp())));
175 handle.record_attribute(fmt::format("{}cresp", prefix).c_str(), static_cast<unsigned>(ext->get_cresp()));
176 handle.record_attribute(fmt::format("{}cresp_PassDirty", prefix).c_str(), ext->is_pass_dirty());
177 handle.record_attribute(fmt::format("{}cresp_IsShared", prefix).c_str(), ext->is_shared());
178 handle.record_attribute(fmt::format("{}cresp_SnoopDataTransfer", prefix).c_str(), ext->is_snoop_data_transfer());
179 handle.record_attribute(fmt::format("{}cresp_SnoopError", prefix).c_str(), ext->is_snoop_error());
180 handle.record_attribute(fmt::format("{}cresp_SnoopWasUnique", prefix).c_str(), ext->is_snoop_was_unique());
181 }
182 }
183};
184
185struct ace_ext_recording : public tlm_extensions_recording_if<axi_protocol_types> {
186
187 ace_ext_recording() {
188 recordBegin = &recordBeginTx;
189 recordEnd = &recordEndTx;
190 }
191
192 static void recordBeginTx(SCVNS scv_tr_handle& handle, axi_protocol_types::tlm_payload_type& trans) {
193 tlm_extension_record_registry::get().recordBeginTx(ace_extension::ID, handle, trans.get_extension<ace_extension>(), "trans.ace.");
194 }
195
196 static void recordEndTx(SCVNS scv_tr_handle& handle, axi_protocol_types::tlm_payload_type& trans) {
197 tlm_extension_record_registry::get().recordEndTx(ace_extension::ID, handle, trans.get_extension<ace_extension>(), "trans.ace.");
198 }
199};
200
201#if defined(__GNUG__)
202__attribute__((constructor))
203#endif
204bool register_extensions() {
205 tlm::scc::tlm_id_extension ext(nullptr); // NOLINT
206 if(!tlm_extension_recording_registry<axi_protocol_types>::get().is_ext_registered(ext.ID)) // NOLINT
207 tlm_extension_recording_registry<axi_protocol_types>::get().register_ext_rec(ext.ID,
208 util::make_unique<tlm_id_ext_recording>()); // NOLINT
209 /********************************************************************************************************************/ axi::
210 axi3_extension ext3; // NOLINT
211 if(!tlm_extension_recording_registry<axi_protocol_types>::get().is_ext_registered(ext3.ID)) // NOLINT
212 tlm_extension_recording_registry<axi::axi_protocol_types>::get().register_ext_rec(
213 ext3.ID,
214 util::make_unique<axi::scv::axi3_ext_recording>()); // NOLINT
215 if(!tlm_extension_record_registry::get().is_ext_registered(ext3.ID))
216 tlm_extension_record_registry::get().register_ext_rec(ext3.ID,
217 util::make_unique<axi3_ext_record>()); // NOLINT
218 /********************************************************************************************************************/ axi::
219 axi4_extension ext4; // NOLINT
220 if(!tlm_extension_recording_registry<axi_protocol_types>::get().is_ext_registered(ext4.ID)) // NOLINT
221 tlm_extension_recording_registry<axi::axi_protocol_types>::get().register_ext_rec(
222 ext4.ID,
223 util::make_unique<axi::scv::axi4_ext_recording>()); // NOLINT
224 if(!tlm_extension_record_registry::get().is_ext_registered(ext4.ID))
225 tlm_extension_record_registry::get().register_ext_rec(ext4.ID,
226 util::make_unique<axi4_ext_record>()); // NOLINT
227 /********************************************************************************************************************/ axi::
228 ace_extension extace; // NOLINT
229 if(!tlm_extension_recording_registry<axi_protocol_types>::get().is_ext_registered(extace.ID)) // NOLINT
230 tlm_extension_recording_registry<axi::axi_protocol_types>::get().register_ext_rec(
231 extace.ID,
232 util::make_unique<axi::scv::ace_ext_recording>()); // NOLINT
233 if(!tlm_extension_record_registry::get().is_ext_registered(extace.ID))
234 tlm_extension_record_registry::get().register_ext_rec(extace.ID,
235 util::make_unique<ace_ext_record>()); // NOLINT
236 return true; // NOLINT
237}
238bool registered = register_extensions();
239} // namespace scv
240} // namespace axi
TLM2.0 components modeling AHB.
const char * to_char(E t)
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
util::delegate< void(SCVNS scv_tr_handle &, tlm::tlm_extension_base *, std::string const &)> recordEnd
recording attributes in extensions at the end, 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