scc 2025.09
SystemC components library
tracer_base.cpp
1/*******************************************************************************
2 * Copyright 2017, 2018 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#include "tracer_base.h"
18#include "observer.h"
19#include "traceable.h"
20#include <cstring>
21#include <sysc/communication/sc_signal_ifs.h>
22#include <systemc>
23
24#define SC_TRACE_NS ::scc::
25
26using namespace sc_core;
27using namespace sc_dt;
28
29namespace scc {
30using sc_trace_file = sc_core::sc_trace_file;
31using sc_object = sc_core::sc_object;
32
33template <typename T> inline auto try_trace_obj(sc_trace_file* trace_file, const sc_object* object, trace_types types_to_trace) -> bool {
34 if((types_to_trace & trace_types::PORTS) == trace_types::PORTS) {
35 if(auto const* ptr = dynamic_cast<sc_core::sc_port_b<sc_core::sc_signal_in_if<T>> const*>(object)) {
36 if(auto* if_ptr = ptr->get_interface(0)) {
37 SC_TRACE_NS sc_trace(trace_file, *if_ptr, object->name());
38 return true;
39 }
40 }
41 if(auto const* ptr = dynamic_cast<sc_core::sc_port_b<sc_core::sc_signal_inout_if<T>> const*>(object)) {
42 if(auto* if_ptr = ptr->get_interface(0)) {
43 SC_TRACE_NS sc_trace(trace_file, *if_ptr, object->name());
44 return true;
45 }
46 }
47 }
48 if((types_to_trace & trace_types::SIGNALS) == trace_types::SIGNALS) {
49 if(auto const* ptr = dynamic_cast<sc_core::sc_signal_inout_if<T> const*>(object)) {
50 SC_TRACE_NS sc_trace(trace_file, *ptr, object->name());
51 return true;
52 }
53 }
54 return false;
55}
56
57template <size_t SIZE> struct ForLoop {
58 template <template <size_t> class Func>
59 static bool iterate(sc_trace_file* trace_file, const sc_object* object, trace_types types_to_trace) {
60 if(ForLoop<SIZE - (SIZE > 128 ? 8 : 1)>::template iterate<Func>(trace_file, object, types_to_trace))
61 return true;
62 else
63 return Func<SIZE>()(trace_file, object, types_to_trace);
64 }
65};
66
67template <> struct ForLoop<1> {
68 template <template <size_t> class Func>
69 static bool iterate(sc_trace_file* trace_file, const sc_object* object, trace_types types_to_trace) {
70 return Func<1>()(trace_file, object, types_to_trace);
71 }
72};
73
74template <size_t size> struct sc_uint_tester {
75 bool operator()(sc_trace_file* trace_file, const sc_object* object, trace_types types_to_trace) {
76 return try_trace_obj<sc_uint<size>>(trace_file, object, types_to_trace);
77 }
78};
79
80template <size_t size> struct sc_int_tester {
81 bool operator()(sc_trace_file* trace_file, const sc_object* object, trace_types types_to_trace) {
82 return try_trace_obj<sc_int<size>>(trace_file, object, types_to_trace);
83 }
84};
85
86template <size_t size> struct sc_biguint_tester {
87 bool operator()(sc_trace_file* trace_file, const sc_object* object, trace_types types_to_trace) {
88 return try_trace_obj<sc_biguint<size>>(trace_file, object, types_to_trace);
89 }
90};
91
92template <size_t size> struct sc_bigint_tester {
93 bool operator()(sc_trace_file* trace_file, const sc_object* object, trace_types types_to_trace) {
94 return try_trace_obj<sc_bigint<size>>(trace_file, object, types_to_trace);
95 }
96};
97
98template <size_t size> struct sc_bv_tester {
99 bool operator()(sc_trace_file* trace_file, const sc_object* object, trace_types types_to_trace) {
100 return try_trace_obj<sc_bv<size>>(trace_file, object, types_to_trace);
101 }
102};
103
104template <size_t size> struct sc_lv_tester {
105 bool operator()(sc_trace_file* trace_file, const sc_object* object, trace_types types_to_trace) {
106 return try_trace_obj<sc_lv<size>>(trace_file, object, types_to_trace);
107 }
108};
109
110void tracer_base::try_trace(sc_trace_file* trace_file, const sc_object* object, trace_types types_to_trace) {
111 if(try_trace_obj<bool>(trace_file, object, types_to_trace))
112 return;
113
114 if(try_trace_obj<char>(trace_file, object, types_to_trace))
115 return;
116 if(try_trace_obj<unsigned char>(trace_file, object, types_to_trace))
117 return;
118
119 if(try_trace_obj<short>(trace_file, object, types_to_trace))
120 return;
121 if(try_trace_obj<unsigned short>(trace_file, object, types_to_trace))
122 return;
123
124 if(try_trace_obj<int>(trace_file, object, types_to_trace))
125 return;
126 if(try_trace_obj<unsigned int>(trace_file, object, types_to_trace))
127 return;
128
129 if(try_trace_obj<long>(trace_file, object, types_to_trace))
130 return;
131 if(try_trace_obj<unsigned long>(trace_file, object, types_to_trace))
132 return;
133
134 if(try_trace_obj<long long>(trace_file, object, types_to_trace))
135 return;
136 if(try_trace_obj<unsigned long long>(trace_file, object, types_to_trace))
137 return;
138
139 if(try_trace_obj<float>(trace_file, object, types_to_trace))
140 return;
141 if(try_trace_obj<double>(trace_file, object, types_to_trace))
142 return;
143#if(SYSTEMC_VERSION >= 20171012)
144 if(try_trace_obj<sc_core::sc_time>(trace_file, object, types_to_trace))
145 return;
146#endif
147 if(try_trace_obj<sc_bit>(trace_file, object, types_to_trace))
148 return;
149 if(try_trace_obj<sc_logic>(trace_file, object, types_to_trace))
150 return;
151#if defined(FULL_TRACE_TYPE_LIST)
152 if(ForLoop<64>::iterate<sc_uint_tester>(trace_file, object, types_to_trace))
153 return;
154 if(ForLoop<64>::iterate<sc_int_tester>(trace_file, object, types_to_trace))
155 return;
156 if(ForLoop<1024>::iterate<sc_biguint_tester>(trace_file, object, types_to_trace))
157 return;
158 if(ForLoop<1024>::iterate<sc_bigint_tester>(trace_file, object, types_to_trace))
159 return;
160 if(ForLoop<1024>::iterate<sc_bv_tester>(trace_file, object, types_to_trace))
161 return;
162 if(ForLoop<1024>::iterate<sc_lv_tester>(trace_file, object, types_to_trace))
163 return;
164#else
165 if(ForLoop<31>::iterate<sc_uint_tester>(trace_file, object, types_to_trace))
166 return;
167 if(try_trace_obj<sc_uint<32>>(trace_file, object, types_to_trace))
168 return;
169 if(try_trace_obj<sc_uint<40>>(trace_file, object, types_to_trace))
170 return;
171 if(try_trace_obj<sc_uint<48>>(trace_file, object, types_to_trace))
172 return;
173 if(try_trace_obj<sc_uint<56>>(trace_file, object, types_to_trace))
174 return;
175 if(try_trace_obj<sc_uint<64>>(trace_file, object, types_to_trace))
176 return;
177
178 if(ForLoop<31>::iterate<sc_int_tester>(trace_file, object, types_to_trace))
179 return;
180 if(try_trace_obj<sc_int<32>>(trace_file, object, types_to_trace))
181 return;
182 if(try_trace_obj<sc_int<40>>(trace_file, object, types_to_trace))
183 return;
184 if(try_trace_obj<sc_int<48>>(trace_file, object, types_to_trace))
185 return;
186 if(try_trace_obj<sc_int<56>>(trace_file, object, types_to_trace))
187 return;
188 if(try_trace_obj<sc_int<64>>(trace_file, object, types_to_trace))
189 return;
190
191 if(try_trace_obj<sc_biguint<32>>(trace_file, object, types_to_trace))
192 return;
193 if(try_trace_obj<sc_biguint<64>>(trace_file, object, types_to_trace))
194 return;
195 if(try_trace_obj<sc_biguint<128>>(trace_file, object, types_to_trace))
196 return;
197 if(try_trace_obj<sc_biguint<256>>(trace_file, object, types_to_trace))
198 return;
199 if(try_trace_obj<sc_biguint<384>>(trace_file, object, types_to_trace))
200 return;
201 if(try_trace_obj<sc_biguint<512>>(trace_file, object, types_to_trace))
202 return;
203 if(try_trace_obj<sc_biguint<1024>>(trace_file, object, types_to_trace))
204 return;
205
206 if(try_trace_obj<sc_bigint<32>>(trace_file, object, types_to_trace))
207 return;
208 if(try_trace_obj<sc_bigint<64>>(trace_file, object, types_to_trace))
209 return;
210 if(try_trace_obj<sc_bigint<128>>(trace_file, object, types_to_trace))
211 return;
212 if(try_trace_obj<sc_bigint<256>>(trace_file, object, types_to_trace))
213 return;
214 if(try_trace_obj<sc_bigint<384>>(trace_file, object, types_to_trace))
215 return;
216 if(try_trace_obj<sc_bigint<512>>(trace_file, object, types_to_trace))
217 return;
218 if(try_trace_obj<sc_bigint<1024>>(trace_file, object, types_to_trace))
219 return;
220
221 if(ForLoop<31>::iterate<sc_bv_tester>(trace_file, object, types_to_trace))
222 return;
223 if(try_trace_obj<sc_bv<32>>(trace_file, object, types_to_trace))
224 return;
225 if(try_trace_obj<sc_bv<40>>(trace_file, object, types_to_trace))
226 return;
227 if(try_trace_obj<sc_bv<48>>(trace_file, object, types_to_trace))
228 return;
229 if(try_trace_obj<sc_bv<56>>(trace_file, object, types_to_trace))
230 return;
231 if(try_trace_obj<sc_bv<64>>(trace_file, object, types_to_trace))
232 return;
233 if(try_trace_obj<sc_bv<128>>(trace_file, object, types_to_trace))
234 return;
235 if(try_trace_obj<sc_bv<256>>(trace_file, object, types_to_trace))
236 return;
237 if(try_trace_obj<sc_bv<384>>(trace_file, object, types_to_trace))
238 return;
239 if(try_trace_obj<sc_bv<512>>(trace_file, object, types_to_trace))
240 return;
241 if(try_trace_obj<sc_bv<1024>>(trace_file, object, types_to_trace))
242 return;
243
244 if(ForLoop<31>::iterate<sc_lv_tester>(trace_file, object, types_to_trace))
245 return;
246 if(try_trace_obj<sc_lv<32>>(trace_file, object, types_to_trace))
247 return;
248 if(try_trace_obj<sc_lv<40>>(trace_file, object, types_to_trace))
249 return;
250 if(try_trace_obj<sc_lv<48>>(trace_file, object, types_to_trace))
251 return;
252 if(try_trace_obj<sc_lv<56>>(trace_file, object, types_to_trace))
253 return;
254 if(try_trace_obj<sc_lv<64>>(trace_file, object, types_to_trace))
255 return;
256 if(try_trace_obj<sc_lv<128>>(trace_file, object, types_to_trace))
257 return;
258 if(try_trace_obj<sc_lv<256>>(trace_file, object, types_to_trace))
259 return;
260 if(try_trace_obj<sc_lv<384>>(trace_file, object, types_to_trace))
261 return;
262 if(try_trace_obj<sc_lv<512>>(trace_file, object, types_to_trace))
263 return;
264 if(try_trace_obj<sc_lv<1024>>(trace_file, object, types_to_trace))
265 return;
266#endif
267}
268
269std::string tracer_base::get_name() { return sc_core::sc_gen_unique_name("$$$scc_tracer$$$", true); }
270
271void tracer_base::descend(const sc_object* obj, bool trace_all) {
272 if(obj == this)
273 return;
274 const char* kind = obj->kind();
275 if(strcmp(kind, "tlm_signal") == 0) {
276 obj->trace(trf);
277 } else if(strcmp(kind, "sc_vector") == 0) {
278 for(auto o : obj->get_child_objects())
279 descend(o, trace_all);
280 } else if((strcmp(kind, "sc_module") == 0 && trace_all) || dynamic_cast<const traceable*>(obj)) {
281 obj->trace(trf);
282 for(auto o : obj->get_child_objects())
283 descend(o, trace_all);
284 } else if(strcmp(kind, "sc_variable") == 0) {
285 if((types_to_trace & trace_types::VARIABLES) == trace_types::VARIABLES)
286 obj->trace(trf);
287 } else if(const auto* tr = dynamic_cast<const scc::traceable*>(obj)) {
288 if(tr->is_trace_enabled())
289 obj->trace(trf);
290 for(auto o : obj->get_child_objects())
291 descend(o, tr->is_trace_enabled());
292 } else {
293 try_trace(trf, obj, types_to_trace);
294 }
295}
296
297namespace {
298tracer_base* find_tracer_base(sc_core::sc_object* obj) {
299 if(auto p = dynamic_cast<tracer_base*>(obj))
300 return p;
301 for(auto* o : obj->get_child_objects()) {
302 if(auto p = find_tracer_base(o))
303 return p;
304 }
305 return nullptr;
306}
307} // namespace
308
309static char const* const default_trace_enable_name = "scc_tracer.default_trace_enable";
310tracer_base::tracer_base(const sc_core::sc_module_name& nm, sc_core::sc_trace_file* tf, bool owned)
311: sc_core::sc_module(nm)
312, cci_broker(cci::cci_get_broker())
313, trf(tf) {
314 default_trace_enable_handle = cci_broker.get_param_handle(default_trace_enable_name);
315 if(!default_trace_enable_handle.is_valid()) {
316 default_trace_enable = scc::make_unique<cci::cci_param<bool>>(
317 default_trace_enable_name, false, "the default for tracing if no attribute is configured", cci::CCI_ABSOLUTE_NAME);
318 default_trace_enable_handle = cci_broker.get_param_handle(default_trace_enable_name);
319 }
320}
321
322bool tracer_base::get_default_trace_enable() {
323 auto cci_broker = cci::cci_get_broker();
324 auto default_trace_enable_handle = cci_broker.get_param_handle(default_trace_enable_name);
325 if(default_trace_enable_handle.is_valid())
326 return default_trace_enable_handle.get_cci_value().get<bool>();
327 else
328 return false; // if the parameter does not exist, no tracer has been instantiated
329}
330
331void tracer_base::set_default_trace_enable(bool v) {
332 auto cci_broker = cci::cci_get_broker();
333 auto default_trace_enable_handle = cci_broker.get_param_handle(default_trace_enable_name);
334 if(default_trace_enable_handle.is_valid())
335 default_trace_enable_handle.get_cci_value().set<bool>(v);
336}
337
338} // namespace scc
SCC TLM utilities.
trace_types
identifies the various type to be traced
Definition tracer_base.h:36
base class for automatic tracer
Definition tracer_base.h:80
cci::cci_param_handle default_trace_enable_handle
Definition tracer_base.h:84
tracer_base(const sc_core::sc_module_name &nm)
named constructor
Definition tracer_base.h:91
cci::cci_broker_handle cci_broker