scc  2024.06
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 
38 namespace scc {
39 class trace_handle;
48 struct sc_variable_b : sc_core::sc_object {
55  sc_variable_b(const char* name)
56  : sc_core::sc_object(name) {}
63  const char* kind() const { return "sc_variable"; }
70  virtual std::string to_string() const { return ""; };
71 
72  virtual void trace(observer* obs) const = 0;
73 };
80 template <typename T> struct sc_variable : public sc_variable_b {
81  using this_type = sc_variable<T>;
88  const T& operator*() { return value; }
95  const T* operator->() { return &value; }
103  sc_variable(const std::string& name, const T& value)
104  : sc_variable_b(name.c_str())
105  , value(value)
106  , hndl{} {}
107 
108  virtual ~sc_variable() = default;
115  std::string to_string() const override {
116  std::stringstream ss;
117  ss << value;
118  return ss.str();
119  }
124  T get() const { return value; }
129  operator bool() const { return value; }
130 
135  operator T() const { return value; }
136  // assignment operator overload
137  sc_variable& operator=(const T other) {
138  value = other;
139  for(auto h : hndl)
140  h->notify();
141  return *this;
142  }
148  bool operator==(T other) const { return value == other; }
154  bool operator!=(T other) const { return value != other; }
160  bool operator>(T other) const { return value > other; }
166  bool operator<(T other) const { return value < other; }
172  bool operator>=(T other) const { return value >= other; }
178  bool operator<=(T other) const { return value <= other; }
181  ++value; // increment this object
182  for(auto h : hndl)
183  h->notify();
184  return *this;
185  }
186 
188  T operator++(int) {
189  auto orig = value;
190  ++value;
191  for(auto h : hndl)
192  h->notify();
193  return orig;
194  }
197  --value; // increment this object
198  for(auto h : hndl)
199  h->notify();
200  return *this;
201  }
202 
204  T operator--(int) {
205  auto orig = value;
206  --value;
207  for(auto h : hndl)
208  h->notify();
209  return orig;
210  }
211 
212  //" arithmetic operator overloads
213  T operator+=(const T other) {
214  value += other;
215  for(auto h : hndl)
216  h->notify();
217  return value;
218  }
219  T operator-=(const T other) {
220  value -= other;
221  for(auto h : hndl)
222  h->notify();
223  return value;
224  }
225  T operator*=(const T other) {
226  value *= other;
227  for(auto h : hndl)
228  h->notify();
229  return value;
230  }
231  T operator/=(const T other) {
232  value /= other;
233  for(auto h : hndl)
234  h->notify();
235  return value;
236  }
237  T operator+(const T other) const { return value - other; }
238  T operator-(const T other) const { return value - other; }
239  T operator*(const T other) const { return value * other; }
240  T operator/(const T other) const { return value / other; }
241  T operator+(const this_type& other) const { return value + other.value; }
242  T operator-(const this_type& other) const { return value - other.value; }
243  T operator*(const this_type& other) const { return value * other.value; }
244  T operator/(const this_type& other) const { return value / other.value; }
251  void trace(sc_core::sc_trace_file* tf) const override {
252  if(auto* obs = dynamic_cast<observer*>(tf))
253  hndl.push_back(observe(obs, value, name()));
254  else
255  sc_core::sc_trace(tf, value, name());
256  }
257 
258  void trace(observer* obs) const override { hndl.push_back(observe(obs, value, name())); }
259 
260  static sc_variable<T> create(const char* n, size_t i, T default_val) {
261  std::ostringstream os;
262  os << n << "[" << i << "];";
263  return scc::sc_variable<T>(os.str(), default_val);
264  }
265 
266  struct creator {
267  creator(T const& default_val)
268  : default_val{default_val} {}
269  sc_variable<T>* operator()(const char* n, size_t i) { return new sc_variable<T>(n, default_val); }
270 
271  private:
272  T default_val{};
273  };
274 
275 private:
277  T value;
279  mutable std::vector<observer::notification_handle*> hndl;
280 };
281 
282 template <typename T> T operator+(sc_variable<T> const& a, sc_variable<T> const& b) { return a.get() + b.get(); }
283 template <typename T> T operator-(sc_variable<T> const& a, sc_variable<T> const& b) { return a.get() - b.get(); }
284 template <typename T> T operator*(sc_variable<T> const& a, sc_variable<T> const& b) { return a.get() * b.get(); }
285 template <typename T> T operator/(sc_variable<T> const& a, sc_variable<T> const& b) { return a.get() / b.get(); }
286 template <typename T> T operator+(T const& a, sc_variable<T> const& b) { return a + b.get(); }
287 template <typename T> T operator-(T const& a, sc_variable<T> const& b) { return a - b.get(); }
288 template <typename T> T operator*(T const& a, sc_variable<T> const& b) { return a * b.get(); }
289 template <typename T> T operator/(T const& a, sc_variable<T> const& b) { return a / b.get(); }
290 
294 template <> struct sc_variable<bool> : public sc_variable_b {
295  const bool& operator*() { return value; }
296  sc_variable(const std::string& name, const bool& value)
297  : sc_variable_b(name.c_str())
298  , value(value)
299  , hndl{} {}
300  virtual ~sc_variable() = default;
301  std::string to_string() const override {
302  std::stringstream ss;
303  ss << value;
304  return ss.str();
305  }
306  bool get() const { return value; }
307  operator bool() const { return value; }
308  sc_variable& operator=(const bool other) {
309  value = other;
310  for(auto h : hndl)
311  h->notify();
312  return *this;
313  }
314  bool operator==(bool other) const { return value == other; }
315  bool operator!=(bool other) const { return value != other; }
316  void trace(sc_core::sc_trace_file* tf) const override {
317  if(auto* obs = dynamic_cast<observer*>(tf))
318  hndl.push_back(observe(obs, value, name()));
319  else
320  sc_core::sc_trace(tf, value, name());
321  }
322  void trace(observer* obs) const override { hndl.push_back(observe(obs, value, name())); }
323  static scc::sc_variable<bool> create(const char* n, size_t i, bool default_val) {
324  std::ostringstream os;
325  os << n << "[" << i << "];";
326  return sc_variable<bool>(os.str(), default_val);
327  }
328 
329  struct creator {
330  creator(bool const& default_val)
331  : default_val{default_val} {}
332  sc_variable<bool>* operator()(const char* n, size_t i) { return new sc_variable<bool>(n, default_val); }
333 
334  private:
335  bool default_val{};
336  };
337 
338 private:
339  bool value;
340  mutable std::vector<observer::notification_handle*> hndl;
341 };
351 template <typename T> struct sc_variable_vector {
352 
353  sc_variable_vector(std::string const& name, size_t size)
354  : name(name)
355  , values(size, nullptr)
356  , creator{} {}
357 
358  sc_variable_vector(std::string const& name, size_t size, T const& def_val)
359  : name(name)
360  , values(size, nullptr) {
361  resize(size, def_val);
362  }
363 
364  sc_variable_vector(std::string const& name, size_t size, std::function<sc_variable<T>*(char const*, size_t)> creator)
365  : name(name)
366  , values(size, nullptr)
367  , creator(creator) {}
368 
369  size_t size() { return values.size(); }
370 
371  void resize(size_t sz) {
372  assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
373  values.resize(sz);
374  }
375 
376  void resize(size_t sz, T def_val) {
377  assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
378  values.resize(sz);
379  auto idx = 0U;
380  for(auto& e : values) {
381  std::stringstream ss;
382  ss << name << "(" << idx++ << ")";
383  e = new sc_variable<T>(ss.str().c_str(), def_val);
384  }
385  }
386 
387  bool is_valid(size_t idx) const { return values.size() > idx && values.at(idx) != nullptr; }
388 
389  sc_variable<T>& operator[](size_t idx) {
390  auto ret = values.at(idx);
391  if(!ret) {
392  if(sc_core::sc_get_curr_simcontext()->elaboration_done())
393  SCCFATAL(sc_core::sc_get_current_object()->name()) << "Trying to create a sc_variable vector entry in " << name
394  << " with index " << idx << " while elaboration finished is not allowed";
395  assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
396  assert(creator);
397  std::stringstream ss;
398  ss << name << "(" << idx << ")";
399  ret = values.at(idx) = creator(ss.str().c_str(), idx);
400  }
401  return *ret;
402  }
403 
404  sc_variable<T> const& operator[](size_t idx) const {
405  assert(values.at(idx) && "No initialized value in sc_variable_vector position");
406  return *values.at(idx);
407  }
408  ~sc_variable_vector() {
409  for(auto p : values)
410  delete p;
411  }
412 
413 private:
414  std::string name{};
415  std::vector<sc_variable<T>*> values;
416  std::function<sc_variable<T>*(char const*, size_t)> creator;
417 };
426 template <typename T> struct sc_ref_variable : public sc_variable_b {
428  const T& value;
435  const T& operator*() { return value; }
443  sc_ref_variable(const std::string& name, const T& value, bool active_notification = false)
444  : sc_variable_b(name.c_str())
445  , value(value)
446  , active_notification(active_notification) {}
447 
448  virtual ~sc_ref_variable() = default;
455  std::string to_string() const override {
456  std::stringstream ss;
457  ss << value;
458  return ss.str();
459  }
466  void trace(sc_core::sc_trace_file* tf) const override {
467  if(active_notification)
468  if(auto* obs = dynamic_cast<observer*>(tf)) {
469  hndl.push_back(observe(obs, value, name()));
470  return;
471  }
472  sc_core::sc_trace(tf, value, name());
473  }
474 
475  void trace(observer* obs) const override { hndl.push_back(observe(obs, value, name())); }
476 
477  void notify() const {
478  for(auto h : hndl)
479  h->notify();
480  }
481 
482 private:
483  const bool active_notification;
485  mutable std::vector<observer::notification_handle*> hndl;
486 };
487 template <> struct sc_ref_variable<sc_core::sc_event> : public sc_variable_b {
488  const sc_core::sc_event& value;
489  const sc_core::sc_event& operator*() { return value; }
490  sc_ref_variable(const std::string& name, const sc_core::sc_event& value)
491  : sc_variable_b(name.c_str())
492  , value(value) {}
493  std::string to_string() const override {
494  std::stringstream ss;
495  ss << value.name();
496  return ss.str();
497  }
498 
499  void trace(observer* obs) const override {}
500 
501  void trace(sc_core::sc_trace_file* tf) const override { sc_core::sc_trace(tf, value, name()); }
502 };
509 template <typename T> struct sc_ref_variable_masked : public sc_variable_b {
510  const T& value;
511 
512  const T mask;
513 
514  sc_ref_variable_masked(const std::string& name, const T& value, int width)
515  : sc_variable_b(name.c_str())
516  , value(value)
517  , mask((1 << width) - 1) {}
518 
519  virtual ~sc_ref_variable_masked() = default;
520 
521  std::string to_string() const override {
522  std::stringstream ss;
523  ss << (value & mask);
524  return ss.str();
525  }
526 
527  void trace(observer* obs) const override {}
528 
529  void trace(sc_core::sc_trace_file* tf) const override { sc_core::sc_trace(tf, value, name()); }
530 };
531 
532 } // namespace scc
533 
534 namespace sc_core {
535 template <class T> inline void sc_trace(sc_trace_file* tf, const ::scc::sc_variable<T>& object, const char* name) { object.trace(tf); }
536 template <class T> inline void sc_trace(sc_trace_file* tf, const ::scc::sc_variable<T>* object, const char* name) { object->trace(tf); }
537 
538 template <class T> inline void sc_trace(sc_trace_file* tf, const ::scc::sc_ref_variable<T>& object, const char* name) { object.trace(tf); }
539 template <class T> inline void sc_trace(sc_trace_file* tf, const ::scc::sc_ref_variable<T>* object, const char* name) { object->trace(tf); }
540 
541 } // namespace sc_core // end of scc-sysc
543 #endif /* _SCC_SC_VARIABLE_H_ */
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
Definition: sc_variable.h:493
the sc_variable for a particular plain data type with limited bit width
Definition: sc_variable.h:509
std::string to_string() const override
retrieve the textual representation of the value
Definition: sc_variable.h:521
the sc_ref_variable for a particular plain data type. This marks an existing C++ variable as discover...
Definition: sc_variable.h:426
const T & value
the wrapped value
Definition: sc_variable.h:428
std::string to_string() const override
create a textual representation of the wrapped value
Definition: sc_variable.h:455
void trace(sc_core::sc_trace_file *tf) const override
register the value with the SystemC trace implementation
Definition: sc_variable.h:466
const T & operator*()
get a reference to the wrapped value
Definition: sc_variable.h:435
std::string to_string() const override
retrieve the textual representation of the value
Definition: sc_variable.h:301
const char * kind() const
get the kind of this sc_object
Definition: sc_variable.h:63
virtual std::string to_string() const
retrieve the textual representation of the value
Definition: sc_variable.h:70
SystemC variable.
Definition: sc_variable.h:80
void trace(sc_core::sc_trace_file *tf) const override
register the value with the SystemC trace implementation
Definition: sc_variable.h:251
bool operator==(T other) const
Definition: sc_variable.h:148
bool operator<=(T other) const
Definition: sc_variable.h:178
T operator++(int)
overloaded postfix ++ operator
Definition: sc_variable.h:188
bool operator!=(T other) const
Definition: sc_variable.h:154
bool operator<(T other) const
Definition: sc_variable.h:166
std::string to_string() const override
create a textual representation of the wrapped value
Definition: sc_variable.h:115
const T & operator*()
get a reference to the wrapped value
Definition: sc_variable.h:88
bool operator>=(T other) const
Definition: sc_variable.h:172
sc_variable & operator++()
overloaded prefix ++ operator
Definition: sc_variable.h:180
sc_variable(const std::string &name, const T &value)
constructor taking a name and a reference of the variable to be wrapped
Definition: sc_variable.h:103
sc_variable & operator--()
overloaded prefix – operator
Definition: sc_variable.h:196
bool operator>(T other) const
Definition: sc_variable.h:160
T get() const
value getter
Definition: sc_variable.h:124
T operator--(int)
overloaded postfix – operator
Definition: sc_variable.h:204