scc 2026.07
SystemC components library
sc_variable.h
1/*******************************************************************************
2 * Copyright 2019 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 _SCC_SC_VARIABLE_H_
18#define _SCC_SC_VARIABLE_H_
19
20#include "observer.h"
21#include "report.h"
22#include "utilities.h"
23#include <array>
24#include <functional>
25#include <sstream>
26#include <sysc/kernel/sc_event.h>
27#include <sysc/kernel/sc_simcontext.h>
28#include <sysc/tracing/sc_trace.h>
29
30#ifndef SC_API
31#define SC_API
32#endif
33
39namespace scc {
40class trace_handle;
49struct sc_variable_b : sc_core::sc_object {
56 sc_variable_b(const char* name)
57 : sc_core::sc_object(name) {}
58 // Rule of 5 - non-copyable, non-assignable
59 sc_variable_b() = delete;
60 sc_variable_b(sc_variable_b const&) = delete;
61 sc_variable_b(sc_variable_b&&) = delete;
62 sc_variable_b& operator=(const sc_variable_b& other) = delete;
63 sc_variable_b& operator=(sc_variable_b&& other) = delete;
64
71 const char* kind() const { return "sc_variable"; }
78 virtual std::string to_string() const { return ""; };
79
80 virtual void trace(observer* obs) const = 0;
81};
82
88template <typename T> struct sc_variable : public sc_variable_b {
89 using this_type = sc_variable<T>;
96 const T& operator*() { return value; }
103 const T* operator->() { return &value; }
111 sc_variable(const std::string& name, const T& value)
112 : sc_variable_b(name.c_str())
113 , value(value)
114 , hndl{} {}
115 // Rule of 5 - non-copyable, non-assignable
116 sc_variable() = delete;
117 sc_variable(sc_variable<T> const&) = delete;
118 sc_variable(sc_variable<T>&&) = delete;
119 sc_variable& operator=(sc_variable<T>&& other) = delete;
120
121 virtual ~sc_variable() = default;
128 std::string to_string() const override {
129 std::stringstream ss;
130 ss << value;
131 return ss.str();
132 }
133
137 T get() const { return value; }
142 operator bool() const { return value; }
143
148 operator T() const { return value; }
149 // assignment operator overload
150 sc_variable& operator=(T other) {
151 value = other;
152 for(auto h : hndl)
153 h->notify();
154 return *this;
155 }
156
157 sc_variable& operator=(const sc_variable<T>& other) {
158 value = other.value;
159 for(auto h : hndl)
160 h->notify();
161 return *this;
162 }
168 bool operator==(T other) const { return value == other; }
174 bool operator!=(T other) const { return value != other; }
180 bool operator>(T other) const { return value > other; }
186 bool operator<(T other) const { return value < other; }
192 bool operator>=(T other) const { return value >= other; }
198 bool operator<=(T other) const { return value <= other; }
201 ++value; // increment this object
202 for(auto h : hndl)
203 h->notify();
204 return *this;
205 }
206
208 T operator++(int) {
209 auto orig = value;
210 ++value;
211 for(auto h : hndl)
212 h->notify();
213 return orig;
214 }
215
217 --value; // increment this object
218 for(auto h : hndl)
219 h->notify();
220 return *this;
221 }
222
224 T operator--(int) {
225 auto orig = value;
226 --value;
227 for(auto h : hndl)
228 h->notify();
229 return orig;
230 }
231
232 //" arithmetic operator overloads
233 T operator+=(const T other) {
234 value += other;
235 for(auto h : hndl)
236 h->notify();
237 return value;
238 }
239 T operator-=(const T other) {
240 value -= other;
241 for(auto h : hndl)
242 h->notify();
243 return value;
244 }
245 T operator*=(const T other) {
246 value *= other;
247 for(auto h : hndl)
248 h->notify();
249 return value;
250 }
251 T operator/=(const T other) {
252 value /= other;
253 for(auto h : hndl)
254 h->notify();
255 return value;
256 }
257 T operator+(const T other) const { return value + other; }
258 T operator-(const T other) const { return value - other; }
259 T operator*(const T other) const { return value * other; }
260 T operator/(const T other) const { return value / other; }
261 T operator+(const this_type& other) const { return value + other.value; }
262 T operator-(const this_type& other) const { return value - other.value; }
263 T operator*(const this_type& other) const { return value * other.value; }
264 T operator/(const this_type& other) const { return value / other.value; }
271 void trace(sc_core::sc_trace_file* tf) const override {
272 if(auto* obs = dynamic_cast<observer*>(tf))
273 hndl.push_back(observe(obs, value, name()));
274 else
275 sc_core::sc_trace(tf, value, name());
276 }
277
278 void trace(observer* obs) const override { hndl.push_back(observe(obs, value, name())); }
279
280 struct creator {
281 creator(T const& default_val)
282 : default_val{default_val} {}
283 sc_variable<T>* operator()(const char* n, size_t i) { return new sc_variable<T>(n, default_val); }
284
285 private:
286 T default_val{};
287 };
288
289private:
291 T value;
293 mutable std::vector<observer::notification_handle*> hndl;
294};
295
296template <typename T> T operator+(sc_variable<T> const& a, sc_variable<T> const& b) { return a.get() + b.get(); }
297template <typename T> T operator-(sc_variable<T> const& a, sc_variable<T> const& b) { return a.get() - b.get(); }
298template <typename T> T operator*(sc_variable<T> const& a, sc_variable<T> const& b) { return a.get() * b.get(); }
299template <typename T> T operator/(sc_variable<T> const& a, sc_variable<T> const& b) { return a.get() / b.get(); }
300template <typename T> T operator+(T const& a, sc_variable<T> const& b) { return a + b.get(); }
301template <typename T> T operator-(T const& a, sc_variable<T> const& b) { return a - b.get(); }
302template <typename T> T operator*(T const& a, sc_variable<T> const& b) { return a * b.get(); }
303template <typename T> T operator/(T const& a, sc_variable<T> const& b) { return a / b.get(); }
304
308template <> struct sc_variable<bool> : public sc_variable_b {
309 const bool& operator*() { return value; }
310 sc_variable(const std::string& name, const bool& value)
311 : sc_variable_b(name.c_str())
312 , value(value)
313 , hndl{} {}
314 sc_variable() = delete;
315 sc_variable(sc_variable<bool> const&) = delete;
316 sc_variable(sc_variable<bool>&&) = delete;
317 sc_variable& operator=(sc_variable<bool>&& other) = delete;
318 virtual ~sc_variable() = default;
319 std::string to_string() const override {
320 std::stringstream ss;
321 ss << value;
322 return ss.str();
323 }
324 bool get() const { return value; }
325 operator bool() const { return value; }
326 sc_variable& operator=(const bool other) {
327 value = other;
328 for(auto h : hndl)
329 h->notify();
330 return *this;
331 }
332 sc_variable& operator=(const sc_variable<bool>& other) {
333 value = other.value;
334 for(auto h : hndl)
335 h->notify();
336 return *this;
337 }
338 bool operator==(bool other) const { return value == other; }
339 bool operator!=(bool other) const { return value != other; }
340 void trace(sc_core::sc_trace_file* tf) const override {
341 if(auto* obs = dynamic_cast<observer*>(tf))
342 hndl.push_back(observe(obs, value, name()));
343 else
344 sc_core::sc_trace(tf, value, name());
345 }
346 void trace(observer* obs) const override { hndl.push_back(observe(obs, value, name())); }
347
348 struct creator {
349 creator(bool const& default_val)
350 : default_val{default_val} {}
351 sc_variable<bool>* operator()(const char* n, size_t i) { return new sc_variable<bool>(n, default_val); }
352
353 private:
354 bool default_val{};
355 };
356
357private:
358 bool value;
359 mutable std::vector<observer::notification_handle*> hndl;
360};
361
370template <typename T> struct sc_variable_vector {
371
372 sc_variable_vector(std::string const& name, size_t size)
373 : name(name)
374 , values(size)
375 , creator{} {}
376
377 sc_variable_vector(std::string const& name, size_t size, T const& def_val)
378 : name(name) {
379 resize(size, def_val);
380 }
381
382 sc_variable_vector(std::string const& name, size_t size, std::function<sc_variable<T>*(char const*, size_t)> creator)
383 : name(name)
384 , values(size)
385 , creator(std::move(creator)) {}
386
387 size_t size() const { return values.size(); }
388
389 void resize(size_t sz) {
390 assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
391 values.resize(sz);
392 }
393
394 void resize(size_t sz, T const& def_val) {
395 assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
396 auto old_size = values.size();
397 values.resize(sz);
398 auto idx = 0U;
399 for(size_t i = old_size; i < sz; ++i) {
400 std::stringstream ss;
401 ss << name << "(" << i << ")";
402 values[i] = scc::make_unique<sc_variable<T>>(ss.str().c_str(), def_val);
403 }
404 }
405
406 bool is_valid(size_t idx) const { return values.size() > idx && values.at(idx) != nullptr; }
407
408 sc_variable<T>& operator[](size_t idx) {
409 auto& ret = values.at(idx);
410 if(!ret) {
411 if(sc_core::sc_get_curr_simcontext()->elaboration_done())
412 SCCFATAL(sc_core::sc_get_current_object()->name()) << "Trying to create a sc_variable vector entry in " << name
413 << " with index " << idx << " while elaboration finished is not allowed";
414 assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
415 assert(creator);
416 std::stringstream ss;
417 ss << name << "(" << idx << ")";
418 ret.reset(creator(ss.str().c_str(), idx));
419 }
420 return *ret;
421 }
422
423 sc_variable<T> const& operator[](size_t idx) const {
424 assert(values.at(idx) && "No initialized value in sc_variable_vector position");
425 return *values.at(idx);
426 }
427
428private:
429 std::string name{};
430 std::vector<std::unique_ptr<sc_variable<T>>> values;
431 std::function<sc_variable<T>*(char const*, size_t)> creator;
432};
433
441template <typename T> struct sc_ref_variable : public sc_variable_b {
443 const T& value;
450 const T& operator*() { return value; }
458 sc_ref_variable(const std::string& name, const T& value, bool active_notification = false)
459 : sc_variable_b(name.c_str())
460 , value(value)
461 , active_notification(active_notification) {}
462
463 virtual ~sc_ref_variable() = default;
470 std::string to_string() const override {
471 std::stringstream ss;
472 ss << value;
473 return ss.str();
474 }
475
481 void trace(sc_core::sc_trace_file* tf) const override {
482 if(active_notification)
483 if(auto* obs = dynamic_cast<observer*>(tf)) {
484 hndl.push_back(observe(obs, value, name()));
485 return;
486 }
487 sc_core::sc_trace(tf, value, name());
488 }
489
490 void trace(observer* obs) const override { hndl.push_back(observe(obs, value, name())); }
491
492 void notify() const {
493 for(auto h : hndl)
494 h->notify();
495 }
496
497private:
498 const bool active_notification;
500 mutable std::vector<observer::notification_handle*> hndl;
501};
502template <> struct sc_ref_variable<sc_core::sc_event> : public sc_variable_b {
503 const sc_core::sc_event& value;
504 const sc_core::sc_event& operator*() { return value; }
505 sc_ref_variable(const std::string& name, const sc_core::sc_event& value)
506 : sc_variable_b(name.c_str())
507 , value(value) {}
508 std::string to_string() const override {
509 std::stringstream ss;
510 ss << value.name();
511 return ss.str();
512 }
513
514 void trace(observer* obs) const override {}
515
516 void trace(sc_core::sc_trace_file* tf) const override { sc_core::sc_trace(tf, value, name()); }
517};
518
524template <typename T> struct sc_ref_variable_masked : public sc_variable_b {
525 const T& value;
526
527 const T mask;
528
529 sc_ref_variable_masked(const std::string& name, const T& value, int width)
530 : sc_variable_b(name.c_str())
531 , value(value)
532 , mask((1 << width) - 1) {}
533
534 virtual ~sc_ref_variable_masked() = default;
535
536 std::string to_string() const override {
537 std::stringstream ss;
538 ss << (value & mask);
539 return ss.str();
540 }
541
542 void trace(observer* obs) const override {}
543
544 void trace(sc_core::sc_trace_file* tf) const override { sc_core::sc_trace(tf, value, name()); }
545};
546
547} // namespace scc
548
549namespace sc_core {
550template <class T> inline void sc_trace(sc_trace_file* tf, const ::scc::sc_variable<T>& object, const char* name) { object.trace(tf); }
551template <class T> inline void sc_trace(sc_trace_file* tf, const ::scc::sc_variable<T>* object, const char* name) { object->trace(tf); }
552
553template <class T> inline void sc_trace(sc_trace_file* tf, const ::scc::sc_ref_variable<T>& object, const char* name) { object.trace(tf); }
554template <class T> inline void sc_trace(sc_trace_file* tf, const ::scc::sc_ref_variable<T>* object, const char* name) { object->trace(tf); }
555
556} // namespace sc_core // end of scc-sysc
558#endif /* _SCC_SC_VARIABLE_H_ */
SCC SystemC tracing utilities.
Definition fst_trace.cpp:33
SCC TLM utilities.
The interface defining an observer.
Definition observer.h:53
std::string to_string() const override
retrieve the textual representation of the value
std::string to_string() const override
retrieve the textual representation of the value
the sc_ref_variable for a particular plain data type. This marks an existing C++ variable as discover...
const T & value
the wrapped value
std::string to_string() const override
create a textual representation of the wrapped value
void trace(sc_core::sc_trace_file *tf) const override
register the value with the SystemC trace implementation
const T & operator*()
get a reference to the wrapped value
std::string to_string() const override
retrieve the textual representation of the value
virtual std::string to_string() const
retrieve the textual representation of the value
Definition sc_variable.h:78
const char * kind() const
get the kind of this sc_object
Definition sc_variable.h:71
SystemC variable.
Definition sc_variable.h:88
void trace(sc_core::sc_trace_file *tf) const override
register the value with the SystemC trace implementation
bool operator==(T other) const
bool operator<=(T other) const
T operator++(int)
overloaded postfix ++ operator
bool operator!=(T other) const
bool operator<(T other) const
std::string to_string() const override
create a textual representation of the wrapped value
const T & operator*()
get a reference to the wrapped value
Definition sc_variable.h:96
bool operator>=(T other) const
sc_variable(const std::string &name, const T &value)
constructor taking a name and a reference of the variable to be wrapped
bool operator>(T other) const
sc_variable & operator++()
overloaded prefix ++ operator
sc_variable & operator--()
overloaded prefix – operator
T get() const
value getter
T operator--(int)
overloaded postfix – operator