scc  2022.4.0
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_cfg/cci_param_typed.h>
36 #include <locale>
37 
43 namespace scc {
44 template <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 
61 namespace 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 
72 void sc_trace(sc_trace_file*, const sc_time&, const std::string&);
73 
78 inline void sc_trace(sc_core::sc_trace_file*&, const sc_core::sc_event&, const char*) {}
79 
80 #endif
88 template <> void sc_trace(sc_trace_file* tf, const sc_in<sc_time>& value, const std::string& name);
96 template <> 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
106 inline sc_core::sc_time operator"" _sec(long double val) { return sc_core::sc_time(val, sc_core::SC_SEC); }
113 inline sc_core::sc_time operator"" _sec(unsigned long long val) { return sc_core::sc_time(double(val), sc_core::SC_SEC); }
120 inline sc_core::sc_time operator"" _ms(long double val) { return sc_core::sc_time(val, sc_core::SC_MS); }
127 inline sc_core::sc_time operator"" _ms(unsigned long long val) { return sc_core::sc_time(double(val), sc_core::SC_MS); }
134 inline sc_core::sc_time operator"" _us(long double val) { return sc_core::sc_time(val, sc_core::SC_US); }
141 inline sc_core::sc_time operator"" _us(unsigned long long val) { return sc_core::sc_time(double(val), sc_core::SC_US); }
148 inline sc_core::sc_time operator"" _ns(long double val) { return sc_core::sc_time(val, sc_core::SC_NS); }
155 inline sc_core::sc_time operator"" _ns(unsigned long long val) { return sc_core::sc_time(double(val), sc_core::SC_NS); }
162 inline sc_core::sc_time operator"" _ps(long double val) { return sc_core::sc_time(val, sc_core::SC_PS); }
169 inline sc_core::sc_time operator"" _ps(unsigned long long val) { return sc_core::sc_time(double(val), sc_core::SC_PS); }
176 inline sc_core::sc_time operator"" _fs(long double val) { return sc_core::sc_time(val, sc_core::SC_FS); }
183 inline sc_core::sc_time operator"" _fs(unsigned long long val) { return sc_core::sc_time(double(val), sc_core::SC_FS); }
185 inline constexpr uint64_t operator"" _kB(unsigned long long val) { return val * 1 << 10; }
187 inline constexpr uint64_t operator"" _MB(unsigned long long val) { return val * 1 << 20; }
189 inline constexpr uint64_t operator"" _GB(unsigned long long val) { return val * 1 << 30; }
190 
191 namespace scc {
192 
193 enum { LT = 0 };
194 
195 inline char* legalize_name(char* const name) {
196  char* ptr = name;
197  while(*ptr) {
198  if(*ptr == '.' || std::isspace(*ptr)) {
199  *ptr = '_';
200  }
201  ptr++;
202  }
203  return name;
204 }
205 
206 inline std::string legalize_name(std::string const& name) {
207  std::string ret;
208  for(auto c : name) {
209  ret += (c == '.' || std::isspace(c)) ? '_' : c;
210  }
211  return ret;
212 }
220 inline bool icompare(std::string const& a, std::string const& b) {
221  if(a.length() == b.length()) {
222  return std::equal(b.begin(), b.end(), a.begin(),
223  [](unsigned char a, unsigned char b) -> bool { return std::tolower(a) == std::tolower(b); });
224  } else {
225  return false;
226  }
227 }
235 inline sc_core::sc_time parse_from_string(std::string value, std::string unit) noexcept {
236  std::string::size_type offs{0};
237  double t_val = std::stod(value, &offs);
238  if(offs > 0) {
239  if(icompare(unit, "fs"))
240  return t_val * 1_fs;
241  if(icompare(unit, "ps"))
242  return t_val * 1_ps;
243  if(icompare(unit, "ns"))
244  return t_val * 1_ns;
245  if(icompare(unit, "us"))
246  return t_val * 1_us;
247  if(icompare(unit, "ms"))
248  return t_val * 1_ms;
249  if(icompare(unit, "s"))
250  return t_val * 1_sec;
251  }
252  return sc_core::SC_ZERO_TIME;
253 }
260 inline sc_core::sc_time parse_from_string(std::string value) noexcept {
261  std::string::size_type offs{0};
262  double t_val = std::stod(value, &offs);
263  if(offs > 0) {
264  std::string unit = value.substr(offs);
265  if(icompare(unit, "fs"))
266  return t_val * 1_fs;
267  if(icompare(unit, "ps"))
268  return t_val * 1_ps;
269  if(icompare(unit, "ns"))
270  return t_val * 1_ns;
271  if(icompare(unit, "us"))
272  return t_val * 1_us;
273  if(icompare(unit, "ms"))
274  return t_val * 1_ms;
275  if(icompare(unit, "s"))
276  return t_val * 1_sec;
277  }
278  return sc_core::SC_ZERO_TIME;
279 }
280 
281 inline sc_core::sc_time time_to_next_posedge(sc_core::sc_clock const* clk) {
282  if(clk) {
283  auto period = clk->period();
284  auto clk_run_time = sc_core::sc_time_stamp() - clk->start_time();
285  auto clk_period_point = clk_run_time % period;
286  if(clk->posedge_first())
287  return period - clk_period_point;
288  auto time_to_negedge = period * clk->duty_cycle();
289  auto time_to_posedge = period - time_to_negedge;
290  if(clk_period_point < time_to_posedge) {
291  return time_to_posedge - clk_period_point;
292  } else {
293  return period + time_to_posedge - clk_period_point;
294  }
295  }
296  return sc_core::SC_ZERO_TIME;
297 }
298 
299 #if __cplusplus < 201402L
300 inline unsigned ilog2(uint32_t val) {
301 #else
302 inline constexpr unsigned ilog2(uint32_t val) {
303 #endif
304  assert(val > 0);
305 #ifdef __GNUG__
306  return sizeof(uint32_t) * 8 - 1 - __builtin_clz(static_cast<unsigned>(val));
307 #else
308  if(val == 1)
309  return 0;
310  auto ret = 0U;
311  while(val > 1) {
312  val >>= 1;
313  ++ret;
314  }
315  return ret;
316 #endif
317 }
318 
319 template <typename T> inline T get_value(sc_core::sc_attribute<T>& a) { return a.value; }
320 
321 template <typename T> inline void set_value(sc_core::sc_attribute<T>& a, T&& value) { a.value = value; }
322 
323 template <typename T> inline T get_value(cci::cci_param_typed<T>& a) { return a.get_value(); }
324 
325 template <typename T> inline void set_value(cci::cci_param_typed<T>& a, T&& value) { a.set_value(value); }
326 } // namespace scc // end of scc-sysc
328 
329 #define declare_method_process_cl(handle, name, host_tag, func) \
330  { \
331  ::sc_core::sc_spawn_options opt; \
332  opt.dont_initialize(); \
333  opt.spawn_method(); \
334  ::sc_core::sc_process_handle handle = ::sc_core::sc_spawn(func, name, &opt); \
335  this->sensitive << handle; \
336  this->sensitive_pos << handle; \
337  this->sensitive_neg << handle; \
338  }
339 
340 #define declare_thread_process_cl(handle, name, host_tag, func) \
341  { \
342  ::sc_core::sc_spawn_options opt; \
343  ::sc_core::sc_process_handle handle = ::sc_core::sc_spawn(func, name, &opt); \
344  this->sensitive << handle; \
345  this->sensitive_pos << handle; \
346  }
347 
348 #define SC_METHOD_CL(name, func) declare_method_process_cl(name##_handle, #name, SC_CURRENT_USER_MODULE, func)
349 
350 #define SC_THREAD_CL(name, func) declare_thread_process_cl(name##_handle, #name, SC_CURRENT_USER_MODULE, func)
351 
352 #endif /* _SYSC_UTILITIES_H_ */
SCC SystemC utilities.
bool icompare(std::string const &a, std::string const &b)
Definition: utilities.h:220
sc_core::sc_time parse_from_string(std::string value, std::string unit) noexcept
Definition: utilities.h:235
CONSTEXPR unsigned ilog2(uint32_t val)
Definition: ities.h:163