scc  2022.4.0
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; }
96  sc_variable(const std::string& name, const T& value)
97  : sc_variable_b(name.c_str())
98  , value(value)
99  , hndl{} {}
100 
101  virtual ~sc_variable() = default;
108  std::string to_string() const override {
109  std::stringstream ss;
110  ss << value;
111  return ss.str();
112  }
117  T get() const { return value; }
122  operator bool() const { return value; }
123 
128  operator T() const { return value; }
129  // assignment operator overload
130  sc_variable& operator=(const T other) {
131  value = other;
132  for(auto h : hndl)
133  h->notify();
134  return *this;
135  }
141  bool operator==(T other) const { return value == other; }
147  bool operator!=(T other) const { return value != other; }
153  bool operator>(T other) const { return value > other; }
159  bool operator<(T other) const { return value < other; }
165  bool operator>=(T other) const { return value >= other; }
171  bool operator<=(T other) const { return value <= other; }
174  ++value; // increment this object
175  for(auto h : hndl)
176  h->notify();
177  return *this;
178  }
179 
181  T operator++(int) {
182  auto orig = value;
183  ++value;
184  for(auto h : hndl)
185  h->notify();
186  return orig;
187  }
190  --value; // increment this object
191  for(auto h : hndl)
192  h->notify();
193  return *this;
194  }
195 
197  T operator--(int) {
198  auto orig = value;
199  --value;
200  for(auto h : hndl)
201  h->notify();
202  return orig;
203  }
204 
205  //" arithmetic operator overloads
206  T operator+=(const T other) {
207  value += other;
208  for(auto h : hndl)
209  h->notify();
210  return value;
211  }
212  T operator-=(const T other) {
213  value += other;
214  for(auto h : hndl)
215  h->notify();
216  return value;
217  }
218  T operator*=(const T other) {
219  value *= other;
220  for(auto h : hndl)
221  h->notify();
222  return value;
223  }
224  T operator/=(const T other) {
225  value /= other;
226  for(auto h : hndl)
227  h->notify();
228  return value;
229  }
230  T operator+(const T other) const { return value - other; }
231  T operator-(const T other) const { return value - other; }
232  T operator*(const T other) const { return value * other; }
233  T operator/(const T other) const { return value / other; }
234  T operator+(const this_type& other) const { return value + other.value; }
235  T operator-(const this_type& other) const { return value - other.value; }
236  T operator*(const this_type& other) const { return value * other.value; }
237  T operator/(const this_type& other) const { return value / other.value; }
244  void trace(sc_core::sc_trace_file* tf) const override {
245  if(auto* obs = dynamic_cast<observer*>(tf))
246  hndl.push_back(observe(obs, value, name()));
247  else
248  sc_core::sc_trace(tf, value, name());
249  }
250 
251  void trace(observer* obs) const override { hndl.push_back(observe(obs, value, name())); }
252 
253  static sc_variable<T> create(const char* n, size_t i, T default_val) {
254  std::ostringstream os;
255  os << n << "[" << i << "];";
256  return scc::sc_variable<T>(os.str(), default_val);
257  }
258 
259  struct creator {
260  creator(T const& default_val)
261  : default_val{default_val} {}
262  sc_variable<T>* operator()(const char* n, size_t i) { return new sc_variable<T>(n, default_val); }
263 
264  private:
265  T default_val{};
266  };
267 
268 private:
270  T value;
272  mutable std::vector<observer::notification_handle*> hndl;
273 };
274 
275 template <typename T> T operator+(sc_variable<T> const& a, sc_variable<T> const& b) { return a.get() + b.get(); }
276 template <typename T> T operator-(sc_variable<T> const& a, sc_variable<T> const& b) { return a.get() - b.get(); }
277 template <typename T> T operator*(sc_variable<T> const& a, sc_variable<T> const& b) { return a.get() * b.get(); }
278 template <typename T> T operator/(sc_variable<T> const& a, sc_variable<T> const& b) { return a.get() / b.get(); }
279 template <typename T> T operator+(T const& a, sc_variable<T> const& b) { return a + b.get(); }
280 template <typename T> T operator-(T const& a, sc_variable<T> const& b) { return a - b.get(); }
281 template <typename T> T operator*(T const& a, sc_variable<T> const& b) { return a * b.get(); }
282 template <typename T> T operator/(T const& a, sc_variable<T> const& b) { return a / b.get(); }
283 
287 template <> struct sc_variable<bool> : public sc_variable_b {
288  const bool& operator*() { return value; }
289  sc_variable(const std::string& name, const bool& value)
290  : sc_variable_b(name.c_str())
291  , value(value)
292  , hndl{} {}
293  virtual ~sc_variable() = default;
294  std::string to_string() const override {
295  std::stringstream ss;
296  ss << value;
297  return ss.str();
298  }
299  bool get() const { return value; }
300  operator bool() const { return value; }
301  sc_variable& operator=(const bool other) {
302  value = other;
303  for(auto h : hndl)
304  h->notify();
305  return *this;
306  }
307  bool operator==(bool other) const { return value == other; }
308  bool operator!=(bool other) const { return value != other; }
309  void trace(sc_core::sc_trace_file* tf) const override {
310  if(auto* obs = dynamic_cast<observer*>(tf))
311  hndl.push_back(observe(obs, value, name()));
312  else
313  sc_core::sc_trace(tf, value, name());
314  }
315  void trace(observer* obs) const override { hndl.push_back(observe(obs, value, name())); }
316  static scc::sc_variable<bool> create(const char* n, size_t i, bool default_val) {
317  std::ostringstream os;
318  os << n << "[" << i << "];";
319  return sc_variable<bool>(os.str(), default_val);
320  }
321 
322  struct creator {
323  creator(bool const& default_val)
324  : default_val{default_val} {}
325  sc_variable<bool>* operator()(const char* n, size_t i) { return new sc_variable<bool>(n, default_val); }
326 
327  private:
328  bool default_val{};
329  };
330 
331 private:
332  bool value;
333  mutable std::vector<observer::notification_handle*> hndl;
334 };
344 template <typename T> struct sc_variable_vector {
345 
346  sc_variable_vector(std::string const& name, size_t size)
347  : name(name)
348  , values(size, nullptr)
349  , creator{} {}
350 
351  sc_variable_vector(std::string const& name, size_t size, T const& def_val)
352  : name(name)
353  , values(size, nullptr) {
354  resize(size, def_val);
355  }
356 
357  sc_variable_vector(std::string const& name, size_t size, std::function<sc_variable<T>*(char const*, size_t)> creator)
358  : name(name)
359  , values(size, nullptr)
360  , creator(creator) {}
361 
362  size_t size() { return values.size(); }
363 
364  void resize(size_t sz) {
365  assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
366  values.resize(sz);
367  }
368 
369  void resize(size_t sz, T def_val) {
370  assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
371  values.resize(sz);
372  auto idx = 0U;
373  for(auto& e : values) {
374  std::stringstream ss;
375  ss << name << "(" << idx++ << ")";
376  e = new sc_variable<T>(ss.str().c_str(), def_val);
377  }
378  }
379 
380  bool is_valid(size_t idx) const { return values.size() > idx && values.at(idx) != nullptr; }
381 
382  sc_variable<T>& operator[](size_t idx) {
383  auto ret = values.at(idx);
384  if(!ret) {
385  if(sc_core::sc_get_curr_simcontext()->elaboration_done())
386  SCCFATAL(sc_core::sc_get_current_object()->name()) << "Trying to create a sc_variable vector entry in " << name
387  << " with index " << idx << " while elaboration finished is not allowed";
388  assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
389  assert(creator);
390  std::stringstream ss;
391  ss << name << "(" << idx << ")";
392  ret = values.at(idx) = creator(ss.str().c_str(), idx);
393  }
394  return *ret;
395  }
396 
397  sc_variable<T> const& operator[](size_t idx) const {
398  assert(values.at(idx) && "No initialized value in sc_variable_vector position");
399  return *values.at(idx);
400  }
401  ~sc_variable_vector() {
402  for(auto p : values)
403  delete p;
404  }
405 
406 private:
407  std::string name{};
408  std::vector<sc_variable<T>*> values;
409  std::function<sc_variable<T>*(char const*, size_t)> creator;
410 };
419 template <typename T> struct sc_ref_variable : public sc_variable_b {
421  const T& value;
428  const T& operator*() { return value; }
436  sc_ref_variable(const std::string& name, const T& value)
437  : sc_variable_b(name.c_str())
438  , value(value) {}
439  virtual ~sc_ref_variable() = default;
446  std::string to_string() const override {
447  std::stringstream ss;
448  ss << value;
449  return ss.str();
450  }
457  void trace(sc_core::sc_trace_file* tf) const override { sc_core::sc_trace(tf, value, name()); }
458 
459  void trace(observer* obs) const override {}
460 };
461 template <> struct sc_ref_variable<sc_core::sc_event> : public sc_variable_b {
462  const sc_core::sc_event& value;
463  const sc_core::sc_event& operator*() { return value; }
464  sc_ref_variable(const std::string& name, const sc_core::sc_event& value)
465  : sc_variable_b(name.c_str())
466  , value(value) {}
467  std::string to_string() const override {
468  std::stringstream ss;
469  ss << value.name();
470  return ss.str();
471  }
472 
473  void trace(observer* obs) const override {}
474 
475  void trace(sc_core::sc_trace_file* tf) const override { sc_core::sc_trace(tf, value, name()); }
476 };
483 template <typename T> struct sc_ref_variable_masked : public sc_variable_b {
484  const T& value;
485 
486  const T mask;
487 
488  sc_ref_variable_masked(const std::string& name, const T& value, int width)
489  : sc_variable_b(name.c_str())
490  , value(value)
491  , mask((1 << width) - 1) {}
492 
493  virtual ~sc_ref_variable_masked() = default;
494 
495  std::string to_string() const override {
496  std::stringstream ss;
497  ss << (value & mask);
498  return ss.str();
499  }
500 
501  void trace(observer* obs) const override {}
502 
503  void trace(sc_core::sc_trace_file* tf) const override { sc_core::sc_trace(tf, value, name()); }
504 };
505 
506 } // namespace scc
507 
508 namespace sc_core {
509 template <class T> inline void sc_trace(sc_trace_file* tf, const ::scc::sc_variable<T>& object, const char* name) { object.trace(tf); }
510 template <class T> inline void sc_trace(sc_trace_file* tf, const ::scc::sc_variable<T>* object, const char* name) { object->trace(tf); }
511 
512 template <class T> inline void sc_trace(sc_trace_file* tf, const ::scc::sc_ref_variable<T>& object, const char* name) { object.trace(tf); }
513 template <class T> inline void sc_trace(sc_trace_file* tf, const ::scc::sc_ref_variable<T>* object, const char* name) { object->trace(tf); }
514 
515 } // namespace sc_core // end of scc-sysc
517 #endif /* _SCC_SC_VARIABLE_H_ */
SCC SystemC 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:467
the sc_variable for a particular plain data type with limited bit width
Definition: sc_variable.h:483
std::string to_string() const override
retrieve the textual representation of the value
Definition: sc_variable.h:495
the sc_ref_variable for a particular plain data type. This marks an existing C++ variable as discover...
Definition: sc_variable.h:419
const T & value
the wrapped value
Definition: sc_variable.h:421
std::string to_string() const override
create a textual representation of the wrapped value
Definition: sc_variable.h:446
void trace(sc_core::sc_trace_file *tf) const override
register the value with the SystemC trace implementation
Definition: sc_variable.h:457
const T & operator*()
get a reference to the wrapped value
Definition: sc_variable.h:428
std::string to_string() const override
retrieve the textual representation of the value
Definition: sc_variable.h:294
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:244
bool operator==(T other) const
Definition: sc_variable.h:141
bool operator<=(T other) const
Definition: sc_variable.h:171
T operator++(int)
overloaded postfix ++ operator
Definition: sc_variable.h:181
bool operator!=(T other) const
Definition: sc_variable.h:147
bool operator<(T other) const
Definition: sc_variable.h:159
std::string to_string() const override
create a textual representation of the wrapped value
Definition: sc_variable.h:108
const T & operator*()
get a reference to the wrapped value
Definition: sc_variable.h:88
bool operator>=(T other) const
Definition: sc_variable.h:165
sc_variable & operator++()
overloaded prefix ++ operator
Definition: sc_variable.h:173
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:96
sc_variable & operator--()
overloaded prefix – operator
Definition: sc_variable.h:189
bool operator>(T other) const
Definition: sc_variable.h:153
T get() const
value getter
Definition: sc_variable.h:117
T operator--(int)
overloaded postfix – operator
Definition: sc_variable.h:197