scc 2025.09
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 <array>
23#include <functional>
24#include <sstream>
25#include <sysc/kernel/sc_event.h>
26#include <sysc/kernel/sc_simcontext.h>
27#include <sysc/tracing/sc_trace.h>
28
29#ifndef SC_API
30#define SC_API
31#endif
32
38namespace scc {
39class trace_handle;
48struct sc_variable_b : sc_core::sc_object {
55 sc_variable_b(const char* name)
56 : sc_core::sc_object(name) {}
57 // Rule of 5 - non-copyable, non-assignable
58 sc_variable_b() = delete;
59 sc_variable_b(sc_variable_b const&) = delete;
60 sc_variable_b(sc_variable_b&&) = delete;
61 sc_variable_b& operator=(const sc_variable_b& other) = delete;
62 sc_variable_b& operator=(sc_variable_b&& other) = delete;
63
70 const char* kind() const { return "sc_variable"; }
77 virtual std::string to_string() const { return ""; };
78
79 virtual void trace(observer* obs) const = 0;
80};
81
87template <typename T> struct sc_variable : public sc_variable_b {
88 using this_type = sc_variable<T>;
95 const T& operator*() { return value; }
102 const T* operator->() { return &value; }
110 sc_variable(const std::string& name, const T& value)
111 : sc_variable_b(name.c_str())
112 , value(value)
113 , hndl{} {}
114 // Rule of 5 - non-copyable, non-assignable
115 sc_variable() = delete;
116 sc_variable(sc_variable<T> const&) = delete;
117 sc_variable(sc_variable<T>&&) = delete;
118 sc_variable& operator=(sc_variable<T>&& other) = delete;
119
120 virtual ~sc_variable() = default;
127 std::string to_string() const override {
128 std::stringstream ss;
129 ss << value;
130 return ss.str();
131 }
132
136 T get() const { return value; }
141 operator bool() const { return value; }
142
147 operator T() const { return value; }
148 // assignment operator overload
149 sc_variable& operator=(T other) {
150 value = other;
151 for(auto h : hndl)
152 h->notify();
153 return *this;
154 }
155
156 sc_variable& operator=(const sc_variable<T>& other) {
157 value = other.value;
158 for(auto h : hndl)
159 h->notify();
160 return *this;
161 }
167 bool operator==(T other) const { return value == other; }
173 bool operator!=(T other) const { return value != other; }
179 bool operator>(T other) const { return value > other; }
185 bool operator<(T other) const { return value < other; }
191 bool operator>=(T other) const { return value >= other; }
197 bool operator<=(T other) const { return value <= other; }
200 ++value; // increment this object
201 for(auto h : hndl)
202 h->notify();
203 return *this;
204 }
205
207 T operator++(int) {
208 auto orig = value;
209 ++value;
210 for(auto h : hndl)
211 h->notify();
212 return orig;
213 }
214
216 --value; // increment this object
217 for(auto h : hndl)
218 h->notify();
219 return *this;
220 }
221
223 T operator--(int) {
224 auto orig = value;
225 --value;
226 for(auto h : hndl)
227 h->notify();
228 return orig;
229 }
230
231 //" arithmetic operator overloads
232 T operator+=(const T other) {
233 value += other;
234 for(auto h : hndl)
235 h->notify();
236 return value;
237 }
238 T operator-=(const T other) {
239 value -= other;
240 for(auto h : hndl)
241 h->notify();
242 return value;
243 }
244 T operator*=(const T other) {
245 value *= other;
246 for(auto h : hndl)
247 h->notify();
248 return value;
249 }
250 T operator/=(const T other) {
251 value /= other;
252 for(auto h : hndl)
253 h->notify();
254 return value;
255 }
256 T operator+(const T other) const { return value - other; }
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 this_type& other) const { return value + other.value; }
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; }
270 void trace(sc_core::sc_trace_file* tf) const override {
271 if(auto* obs = dynamic_cast<observer*>(tf))
272 hndl.push_back(observe(obs, value, name()));
273 else
274 sc_core::sc_trace(tf, value, name());
275 }
276
277 void trace(observer* obs) const override { hndl.push_back(observe(obs, value, name())); }
278
279 struct creator {
280 creator(T const& default_val)
281 : default_val{default_val} {}
282 sc_variable<T>* operator()(const char* n, size_t i) { return new sc_variable<T>(n, default_val); }
283
284 private:
285 T default_val{};
286 };
287
288private:
290 T value;
292 mutable std::vector<observer::notification_handle*> hndl;
293};
294
295template <typename T> T operator+(sc_variable<T> const& a, sc_variable<T> const& b) { return a.get() + b.get(); }
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+(T const& a, sc_variable<T> const& b) { return a + 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(); }
303
307template <> struct sc_variable<bool> : public sc_variable_b {
308 const bool& operator*() { return value; }
309 sc_variable(const std::string& name, const bool& value)
310 : sc_variable_b(name.c_str())
311 , value(value)
312 , hndl{} {}
313 sc_variable() = delete;
314 sc_variable(sc_variable<bool> const&) = delete;
315 sc_variable(sc_variable<bool>&&) = delete;
316 sc_variable& operator=(sc_variable<bool>&& other) = delete;
317 virtual ~sc_variable() = default;
318 std::string to_string() const override {
319 std::stringstream ss;
320 ss << value;
321 return ss.str();
322 }
323 bool get() const { return value; }
324 operator bool() const { return value; }
325 sc_variable& operator=(const bool other) {
326 value = other;
327 for(auto h : hndl)
328 h->notify();
329 return *this;
330 }
331 sc_variable& operator=(const sc_variable<bool>& other) {
332 value = other.value;
333 for(auto h : hndl)
334 h->notify();
335 return *this;
336 }
337 bool operator==(bool other) const { return value == other; }
338 bool operator!=(bool other) const { return value != other; }
339 void trace(sc_core::sc_trace_file* tf) const override {
340 if(auto* obs = dynamic_cast<observer*>(tf))
341 hndl.push_back(observe(obs, value, name()));
342 else
343 sc_core::sc_trace(tf, value, name());
344 }
345 void trace(observer* obs) const override { hndl.push_back(observe(obs, value, name())); }
346
347 struct creator {
348 creator(bool const& default_val)
349 : default_val{default_val} {}
350 sc_variable<bool>* operator()(const char* n, size_t i) { return new sc_variable<bool>(n, default_val); }
351
352 private:
353 bool default_val{};
354 };
355
356private:
357 bool value;
358 mutable std::vector<observer::notification_handle*> hndl;
359};
360
369template <typename T> struct sc_variable_vector {
370
371 sc_variable_vector(std::string const& name, size_t size)
372 : name(name)
373 , values(size, nullptr)
374 , creator{} {}
375
376 sc_variable_vector(std::string const& name, size_t size, T const& def_val)
377 : name(name)
378 , values(size, nullptr) {
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, nullptr)
385 , creator(creator) {}
386
387 size_t size() { 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 def_val) {
395 assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
396 values.resize(sz);
397 auto idx = 0U;
398 for(auto& e : values) {
399 std::stringstream ss;
400 ss << name << "(" << idx++ << ")";
401 e = new sc_variable<T>(ss.str().c_str(), def_val);
402 }
403 }
404
405 bool is_valid(size_t idx) const { return values.size() > idx && values.at(idx) != nullptr; }
406
407 sc_variable<T>& operator[](size_t idx) {
408 auto ret = values.at(idx);
409 if(!ret) {
410 if(sc_core::sc_get_curr_simcontext()->elaboration_done())
411 SCCFATAL(sc_core::sc_get_current_object()->name()) << "Trying to create a sc_variable vector entry in " << name
412 << " with index " << idx << " while elaboration finished is not allowed";
413 assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
414 assert(creator);
415 std::stringstream ss;
416 ss << name << "(" << idx << ")";
417 ret = values.at(idx) = creator(ss.str().c_str(), idx);
418 }
419 return *ret;
420 }
421
422 sc_variable<T> const& operator[](size_t idx) const {
423 assert(values.at(idx) && "No initialized value in sc_variable_vector position");
424 return *values.at(idx);
425 }
426 ~sc_variable_vector() {
427 for(auto p : values)
428 delete p;
429 }
430
431private:
432 std::string name{};
433 std::vector<sc_variable<T>*> values;
434 std::function<sc_variable<T>*(char const*, size_t)> creator;
435};
436
444template <typename T> struct sc_ref_variable : public sc_variable_b {
446 const T& value;
453 const T& operator*() { return value; }
461 sc_ref_variable(const std::string& name, const T& value, bool active_notification = false)
462 : sc_variable_b(name.c_str())
463 , value(value)
464 , active_notification(active_notification) {}
465
466 virtual ~sc_ref_variable() = default;
473 std::string to_string() const override {
474 std::stringstream ss;
475 ss << value;
476 return ss.str();
477 }
478
484 void trace(sc_core::sc_trace_file* tf) const override {
485 if(active_notification)
486 if(auto* obs = dynamic_cast<observer*>(tf)) {
487 hndl.push_back(observe(obs, value, name()));
488 return;
489 }
490 sc_core::sc_trace(tf, value, name());
491 }
492
493 void trace(observer* obs) const override { hndl.push_back(observe(obs, value, name())); }
494
495 void notify() const {
496 for(auto h : hndl)
497 h->notify();
498 }
499
500private:
501 const bool active_notification;
503 mutable std::vector<observer::notification_handle*> hndl;
504};
505template <> struct sc_ref_variable<sc_core::sc_event> : public sc_variable_b {
506 const sc_core::sc_event& value;
507 const sc_core::sc_event& operator*() { return value; }
508 sc_ref_variable(const std::string& name, const sc_core::sc_event& value)
509 : sc_variable_b(name.c_str())
510 , value(value) {}
511 std::string to_string() const override {
512 std::stringstream ss;
513 ss << value.name();
514 return ss.str();
515 }
516
517 void trace(observer* obs) const override {}
518
519 void trace(sc_core::sc_trace_file* tf) const override { sc_core::sc_trace(tf, value, name()); }
520};
521
527template <typename T> struct sc_ref_variable_masked : public sc_variable_b {
528 const T& value;
529
530 const T mask;
531
532 sc_ref_variable_masked(const std::string& name, const T& value, int width)
533 : sc_variable_b(name.c_str())
534 , value(value)
535 , mask((1 << width) - 1) {}
536
537 virtual ~sc_ref_variable_masked() = default;
538
539 std::string to_string() const override {
540 std::stringstream ss;
541 ss << (value & mask);
542 return ss.str();
543 }
544
545 void trace(observer* obs) const override {}
546
547 void trace(sc_core::sc_trace_file* tf) const override { sc_core::sc_trace(tf, value, name()); }
548};
549
550} // namespace scc
551
552namespace sc_core {
553template <class T> inline void sc_trace(sc_trace_file* tf, const ::scc::sc_variable<T>& object, const char* name) { object.trace(tf); }
554template <class T> inline void sc_trace(sc_trace_file* tf, const ::scc::sc_variable<T>* object, const char* name) { object->trace(tf); }
555
556template <class T> inline void sc_trace(sc_trace_file* tf, const ::scc::sc_ref_variable<T>& object, const char* name) { object.trace(tf); }
557template <class T> inline void sc_trace(sc_trace_file* tf, const ::scc::sc_ref_variable<T>* object, const char* name) { object->trace(tf); }
558
559} // namespace sc_core // end of scc-sysc
561#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:77
const char * kind() const
get the kind of this sc_object
Definition sc_variable.h:70
SystemC variable.
Definition sc_variable.h:87
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:95
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