scc 2025.09
SystemC components library
utilities.h
1/*******************************************************************************
2 * Copyright 2016, 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#ifndef _SYSC_UTILITIES_H_
18#define _SYSC_UTILITIES_H_
19
20#include <array>
21#include <cctype>
22#include <limits>
23#include <memory>
24
25#if defined(__GNUG__)
26// pragmas to disable the deprecated warnings for SystemC headers
27#pragma GCC diagnostic push
28#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
29#endif
30#include <systemc>
31#if defined(__GNUG__)
32#pragma GCC diagnostic pop
33#endif
34
35#include <cci_configuration>
36#include <locale>
37
43namespace scc {
44template <typename T, typename... Args> std::unique_ptr<T> make_unique(Args&&... args) {
45#if __cplusplus < 201402L
46 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
47#else
48 return std::make_unique<T>(std::forward<Args>(args)...);
49#endif
50}
51} // namespace scc
53#define NAMED(X, ...) X(#X, ##__VA_ARGS__)
54#define NAMEDD(X, T, ...) X(scc::make_unique<T>(#X, ##__VA_ARGS__))
55#define NAMEDC(X, T, I, ...) X(T::create<I>(#X, ##__VA_ARGS__))
57#define TRACE_VAR(F, X) sc_core::sc_trace(F, X, std::string(this->name()) + "." #X)
58#define TRACE_ARR(F, X, I) sc_core::sc_trace(F, X[I], (std::string(this->name()) + "." #X "(" + std::to_string(I) + ")").c_str());
59#define TRACE_SIG(F, X) sc_core::sc_trace(F, X, X.name())
60
61namespace sc_core {
62// needed to be able to use sc_time as signal value
63#if SC_VERSION_MAJOR <= 2 && SC_VERSION_MINOR <= 3 && SC_VERSION_PATCH < 2
64#define HAS_NO_TIME_TRACE
65#endif
66#ifdef NCSC
67#define HAS_NO_TIME_TRACE
68#endif
69
70#ifdef HAS_NO_TIME_TRACE
71
72void sc_trace(sc_trace_file*, const sc_time&, const std::string&);
73
78inline void sc_trace(sc_core::sc_trace_file*&, const sc_core::sc_event&, const char*) {}
79
80#endif
88template <> void sc_trace(sc_trace_file* tf, const sc_in<sc_time>& value, const std::string& name);
96template <> void sc_trace(sc_trace_file* tf, const sc_inout<sc_time>& value, const std::string& name);
97
98} // namespace sc_core
99// user-defined literals for easy time creation
106inline sc_core::sc_time operator"" _sec(long double val) { return sc_core::sc_time(val, sc_core::SC_SEC); }
113inline sc_core::sc_time operator"" _sec(unsigned long long val) { return sc_core::sc_time(double(val), sc_core::SC_SEC); }
120inline sc_core::sc_time operator"" _ms(long double val) { return sc_core::sc_time(val, sc_core::SC_MS); }
127inline sc_core::sc_time operator"" _ms(unsigned long long val) { return sc_core::sc_time(double(val), sc_core::SC_MS); }
134inline sc_core::sc_time operator"" _us(long double val) { return sc_core::sc_time(val, sc_core::SC_US); }
141inline sc_core::sc_time operator"" _us(unsigned long long val) { return sc_core::sc_time(double(val), sc_core::SC_US); }
148inline sc_core::sc_time operator"" _ns(long double val) { return sc_core::sc_time(val, sc_core::SC_NS); }
155inline sc_core::sc_time operator"" _ns(unsigned long long val) { return sc_core::sc_time(double(val), sc_core::SC_NS); }
162inline sc_core::sc_time operator"" _ps(long double val) { return sc_core::sc_time(val, sc_core::SC_PS); }
169inline sc_core::sc_time operator"" _ps(unsigned long long val) { return sc_core::sc_time(double(val), sc_core::SC_PS); }
176inline sc_core::sc_time operator"" _fs(long double val) { return sc_core::sc_time(val, sc_core::SC_FS); }
183inline sc_core::sc_time operator"" _fs(unsigned long long val) { return sc_core::sc_time(double(val), sc_core::SC_FS); }
184
185namespace scc {
186
187enum { LT = 0 };
188
189inline char* legalize_name(char* const name) {
190 char* ptr = name;
191 while(*ptr) {
192 if(*ptr == '.' || std::isspace(*ptr)) {
193 *ptr = '_';
194 }
195 ptr++;
196 }
197 return name;
198}
199
200inline std::string legalize_name(std::string const& name) {
201 std::string ret;
202 for(auto c : name) {
203 ret += (c == '.' || std::isspace(c)) ? '_' : c;
204 }
205 return ret;
206}
214inline bool icompare(std::string const& a, std::string const& b) {
215 if(a.length() == b.length()) {
216 return std::equal(b.begin(), b.end(), a.begin(),
217 [](unsigned char a, unsigned char b) -> bool { return std::tolower(a) == std::tolower(b); });
218 } else {
219 return false;
220 }
221}
222
229inline sc_core::sc_time parse_from_string(std::string value, std::string unit) noexcept {
230 std::string::size_type offs{0};
231 double t_val = std::stod(value, &offs);
232 if(offs > 0) {
233 if(icompare(unit, "fs"))
234 return t_val * 1_fs;
235 if(icompare(unit, "ps"))
236 return t_val * 1_ps;
237 if(icompare(unit, "ns"))
238 return t_val * 1_ns;
239 if(icompare(unit, "us"))
240 return t_val * 1_us;
241 if(icompare(unit, "ms"))
242 return t_val * 1_ms;
243 if(icompare(unit, "s"))
244 return t_val * 1_sec;
245 }
246 return sc_core::SC_ZERO_TIME;
247}
248
254inline sc_core::sc_time parse_from_string(std::string value) noexcept {
255 std::string::size_type offs{0};
256 double t_val = std::stod(value, &offs);
257 if(offs > 0) {
258 std::string unit = value.substr(offs);
259 if(icompare(unit, "fs"))
260 return t_val * 1_fs;
261 if(icompare(unit, "ps"))
262 return t_val * 1_ps;
263 if(icompare(unit, "ns"))
264 return t_val * 1_ns;
265 if(icompare(unit, "us"))
266 return t_val * 1_us;
267 if(icompare(unit, "ms"))
268 return t_val * 1_ms;
269 if(icompare(unit, "s"))
270 return t_val * 1_sec;
271 }
272 return sc_core::SC_ZERO_TIME;
273}
274
275inline sc_core::sc_time time_to_next_posedge(sc_core::sc_clock const* clk) {
276 if(clk) {
277 auto period = clk->period();
278 auto clk_run_time = sc_core::sc_time_stamp() - clk->start_time();
279 auto clk_period_point = clk_run_time % period;
280 if(clk->posedge_first())
281 return period - clk_period_point;
282 auto time_to_negedge = period * clk->duty_cycle();
283 auto time_to_posedge = period - time_to_negedge;
284 if(clk_period_point < time_to_posedge) {
285 return time_to_posedge - clk_period_point;
286 } else {
287 return period + time_to_posedge - clk_period_point;
288 }
289 }
290 return sc_core::SC_ZERO_TIME;
291}
292
293#if __cplusplus < 201402L
294inline unsigned ilog2(uint32_t val) {
295#else
296inline constexpr unsigned ilog2(uint32_t val) {
297#endif
298 assert(val > 0);
299#ifdef __GNUG__
300 return sizeof(uint32_t) * 8 - 1 - __builtin_clz(static_cast<unsigned>(val));
301#else
302 if(val == 1)
303 return 0;
304 auto ret = 0U;
305 while(val > 1) {
306 val >>= 1;
307 ++ret;
308 }
309 return ret;
310#endif
311}
312
313template <typename T> inline T get_value(sc_core::sc_attribute<T>& a) { return a.value; }
314
315template <typename T> inline void set_value(sc_core::sc_attribute<T>& a, T&& value) { a.value = value; }
316
317template <typename T> inline T get_value(cci::cci_param_typed<T>& a) { return a.get_value(); }
318
319template <typename T> inline void set_value(cci::cci_param_typed<T>& a, T&& value) { a.set_value(value); }
320} // namespace scc // end of scc-sysc
322
323#define declare_method_process_cl(handle, name, host_tag, func) \
324 { \
325 ::sc_core::sc_spawn_options opt; \
326 opt.dont_initialize(); \
327 opt.spawn_method(); \
328 ::sc_core::sc_process_handle handle = ::sc_core::sc_spawn(func, name, &opt); \
329 this->sensitive << handle; \
330 this->sensitive_pos << handle; \
331 this->sensitive_neg << handle; \
332 }
333
334#define declare_thread_process_cl(handle, name, host_tag, func) \
335 { \
336 ::sc_core::sc_spawn_options opt; \
337 ::sc_core::sc_process_handle handle = ::sc_core::sc_spawn(func, name, &opt); \
338 this->sensitive << handle; \
339 this->sensitive_pos << handle; \
340 }
341
342#define SC_METHOD_CL(name, func) declare_method_process_cl(name##_handle, #name, SC_CURRENT_USER_MODULE, func)
343
344#define SC_THREAD_CL(name, func) declare_thread_process_cl(name##_handle, #name, SC_CURRENT_USER_MODULE, func)
345
346#endif /* _SYSC_UTILITIES_H_ */
SCC TLM utilities.
bool icompare(std::string const &a, std::string const &b)
Definition utilities.h:214
sc_core::sc_time parse_from_string(std::string value, std::string unit) noexcept
Definition utilities.h:229