scc  2022.4.0
SystemC components library
observer.h
1 /*******************************************************************************
2  * Copyright 2018-2021 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_OBSERVER_H_
18 #define _SCC_OBSERVER_H_
19 
20 #include <string>
21 // needed for typedefs like sc_dt::int64
22 #include <sysc/communication/sc_signal_ifs.h>
23 #include <sysc/datatypes/int/sc_nbdefs.h>
24 #include <sysc/kernel/sc_dynamic_processes.h>
25 #include <sysc/kernel/sc_process.h>
26 #include <sysc/kernel/sc_process_handle.h>
27 #include <sysc/kernel/sc_ver.h>
28 // Some forward declarations
29 namespace sc_dt {
30 class sc_bit;
31 class sc_logic;
32 class sc_bv_base;
33 class sc_lv_base;
34 class sc_signed;
35 class sc_unsigned;
36 class sc_int_base;
37 class sc_uint_base;
38 class sc_fxval;
39 class sc_fxval_fast;
40 class sc_fxnum;
41 class sc_fxnum_fast;
42 } // namespace sc_dt
43 
49 namespace scc {
53 struct observer {
58  virtual bool notify() = 0;
59  virtual ~notification_handle() {}
60  };
61  virtual notification_handle* observe(bool const& o, std::string const& nm) = 0;
62  virtual notification_handle* observe(sc_dt::sc_bit const& o, std::string const& nm) = 0;
63  virtual notification_handle* observe(sc_dt::sc_logic const& o, std::string const& nm) = 0;
64 
65  virtual notification_handle* observe(unsigned char const& o, std::string const& nm) = 0;
66  virtual notification_handle* observe(unsigned short const& o, std::string const& nm) = 0;
67  virtual notification_handle* observe(unsigned int const& o, std::string const& nm) = 0;
68  virtual notification_handle* observe(unsigned long const& o, std::string const& nm) = 0;
69  virtual notification_handle* observe(char const& o, std::string const& nm) = 0;
70  virtual notification_handle* observe(short const& o, std::string const& nm) = 0;
71  virtual notification_handle* observe(int const& o, std::string const& nm) = 0;
72  virtual notification_handle* observe(long const& o, std::string const& nm) = 0;
73  virtual notification_handle* observe(sc_dt::int64 const& o, std::string const& nm) = 0;
74  virtual notification_handle* observe(sc_dt::uint64 const& o, std::string const& nm) = 0;
75 
76  virtual notification_handle* observe(float const& o, std::string const& nm) = 0;
77  virtual notification_handle* observe(double const& o, std::string const& nm) = 0;
78  virtual notification_handle* observe(sc_dt::sc_int_base const& o, std::string const& nm) = 0;
79  virtual notification_handle* observe(sc_dt::sc_uint_base const& o, std::string const& nm) = 0;
80  virtual notification_handle* observe(sc_dt::sc_signed const& o, std::string const& nm) = 0;
81  virtual notification_handle* observe(sc_dt::sc_unsigned const& o, std::string const& nm) = 0;
82 
83  virtual notification_handle* observe(sc_dt::sc_fxval const& o, std::string const& nm) = 0;
84  virtual notification_handle* observe(sc_dt::sc_fxval_fast const& o, std::string const& nm) = 0;
85  virtual notification_handle* observe(sc_dt::sc_fxnum const& o, std::string const& nm) = 0;
86  virtual notification_handle* observe(sc_dt::sc_fxnum_fast const& o, std::string const& nm) = 0;
87 
88  virtual notification_handle* observe(sc_dt::sc_bv_base const& o, std::string const& nm) = 0;
89  virtual notification_handle* observe(sc_dt::sc_lv_base const& o, std::string const& nm) = 0;
90 #if(SYSTEMC_VERSION >= 20171012)
91  virtual notification_handle* observe(sc_core::sc_time const& o, std::string const& nm) = 0;
92  virtual notification_handle* observe(sc_core::sc_event const& o, std::string const& nm) = 0;
93 #endif
94  virtual ~observer() {}
95 };
96 
97 #define DECL_REGISTER_METHOD_A(tp) \
98  inline observer::notification_handle* observe(observer* obs, tp const& o, std::string const& nm) { return obs->observe(o, nm); }
99 #if(SYSTEMC_VERSION >= 20171012)
100 DECL_REGISTER_METHOD_A(sc_core::sc_event)
101 DECL_REGISTER_METHOD_A(sc_core::sc_time)
102 #endif
103 DECL_REGISTER_METHOD_A(bool)
104 DECL_REGISTER_METHOD_A(sc_dt::sc_bit)
105 DECL_REGISTER_METHOD_A(sc_dt::sc_logic)
106 
107 DECL_REGISTER_METHOD_A(unsigned char)
108 DECL_REGISTER_METHOD_A(unsigned short)
109 DECL_REGISTER_METHOD_A(unsigned int)
110 DECL_REGISTER_METHOD_A(unsigned long)
111 DECL_REGISTER_METHOD_A(char)
112 DECL_REGISTER_METHOD_A(short)
113 DECL_REGISTER_METHOD_A(int)
114 DECL_REGISTER_METHOD_A(long)
115 DECL_REGISTER_METHOD_A(sc_dt::int64)
116 DECL_REGISTER_METHOD_A(sc_dt::uint64)
117 
118 DECL_REGISTER_METHOD_A(float)
119 DECL_REGISTER_METHOD_A(double)
120 DECL_REGISTER_METHOD_A(sc_dt::sc_int_base)
121 DECL_REGISTER_METHOD_A(sc_dt::sc_uint_base)
122 DECL_REGISTER_METHOD_A(sc_dt::sc_signed)
123 DECL_REGISTER_METHOD_A(sc_dt::sc_unsigned)
124 
125 DECL_REGISTER_METHOD_A(sc_dt::sc_fxval)
126 DECL_REGISTER_METHOD_A(sc_dt::sc_fxval_fast)
127 DECL_REGISTER_METHOD_A(sc_dt::sc_fxnum)
128 DECL_REGISTER_METHOD_A(sc_dt::sc_fxnum_fast)
129 
130 DECL_REGISTER_METHOD_A(sc_dt::sc_bv_base)
131 DECL_REGISTER_METHOD_A(sc_dt::sc_lv_base)
132 
133 #undef DECL_REGISTER_METHOD_A
134 
135 template <class T> inline void sc_trace(sc_core::sc_trace_file* tf, const sc_core::sc_signal_in_if<T>& object, const char* name) {
136  if(auto* obs = dynamic_cast<observer*>(tf)) {
137  if(auto* handle = obs->observe(object.read(), std::string(name))) {
138  sc_core::sc_spawn_options scopts;
139  scopts.spawn_method();
140  scopts.set_sensitivity(&object.default_event());
141  sc_core::sc_spawn(
142  [handle]() {
143  if(!handle->notify()) // suspend if trace is an alias
144  sc_core::sc_get_current_process_handle().disable();
145  },
146  nullptr, &scopts);
147  }
148  } else
149  sc_core::sc_trace(tf, object.read(), name);
150 }
151 
152 template <class T> inline void sc_trace(sc_core::sc_trace_file* tf, const sc_core::sc_signal_in_if<T>& object, const std::string& name) {
153  sc_trace(tf, object, name.c_str());
154 }
155 
156 template <class T> inline void sc_trace(sc_core::sc_trace_file* tf, const sc_core::sc_in<T>& port, char const* name) {
157  const sc_core::sc_signal_in_if<T>* iface = 0;
158  if(sc_core::sc_get_curr_simcontext()->elaboration_done())
159  iface = dynamic_cast<const sc_core::sc_signal_in_if<T>*>(port.get_interface());
160  if(iface)
161  if(auto* obs = dynamic_cast<observer*>(tf)) {
162  if(auto* handle = obs->observe(port.read(), name)) {
163  sc_core::sc_spawn_options scopts;
164  scopts.spawn_method();
165  scopts.set_sensitivity(&port.default_event());
166  sc_core::sc_spawn(
167  [handle]() {
168  if(!handle->notify()) // suspend if trace is an alias
169  sc_core::sc_get_current_process_handle().disable();
170  },
171  nullptr, &scopts);
172  }
173  } else
174  sc_trace(tf, iface->read(), name);
175  else
176  port.add_trace_internal(tf, name);
177 }
178 
179 template <class T> inline void sc_trace(sc_core::sc_trace_file* tf, const sc_core::sc_in<T>& port, const std::string& name) {
180  sc_trace(tf, port, name.c_str());
181 }
182 
183 template <class T> inline void sc_trace(sc_core::sc_trace_file* tf, const sc_core::sc_inout<T>& port, char const* name) {
184  const sc_core::sc_signal_in_if<T>* iface = 0;
185  if(sc_core::sc_get_curr_simcontext()->elaboration_done())
186  iface = dynamic_cast<const sc_core::sc_signal_in_if<T>*>(port.get_interface());
187  if(iface)
188  if(auto* obs = dynamic_cast<observer*>(tf)) {
189  if(auto* handle = obs->observe(port.read(), name)) {
190  sc_core::sc_spawn_options scopts;
191  scopts.spawn_method();
192  scopts.set_sensitivity(&port.default_event());
193  sc_core::sc_spawn(
194  [handle]() {
195  if(!handle->notify()) // suspend if trace is an alias
196  sc_core::sc_get_current_process_handle().disable();
197  },
198  nullptr, &scopts);
199  }
200  } else
201  sc_trace(tf, iface->read(), name);
202  else
203  port.add_trace_internal(tf, name);
204 }
205 
206 template <class T> inline void sc_trace(sc_core::sc_trace_file* tf, const sc_core::sc_inout<T>& port, const std::string& name) {
207  sc_trace(tf, port, name.c_str());
208 }
209 
210 #define DEFN_TRACE_FUNC_REF_A(tp) \
211  inline void sc_trace(sc_core::sc_trace_file* tf, const tp& object, const std::string& name) { sc_core::sc_trace(tf, object, name); }
212 
213 #define DEFN_TRACE_FUNC_PTR_A(tp) \
214  inline void sc_trace(sc_core::sc_trace_file* tf, const tp* object, const std::string& name) { sc_core::sc_trace(tf, object, name); }
215 
216 #define DEFN_TRACE_FUNC_A(tp) \
217  DEFN_TRACE_FUNC_REF_A(tp) \
218  DEFN_TRACE_FUNC_PTR_A(tp)
219 
220 #define DEFN_TRACE_FUNC_REF_B(tp) \
221  inline void sc_trace(sc_core::sc_trace_file* tf, const tp& object, const std::string& name, int width) { \
222  sc_core::sc_trace(tf, object, name, width); \
223  } \
224  inline void sc_trace(sc_core::sc_trace_file* tf, const tp& object, const std::string& name) { \
225  sc_core::sc_trace(tf, object, name, sizeof(tp) * 8); \
226  }
227 
228 #define DEFN_TRACE_FUNC_PTR_B(tp) \
229  inline void sc_trace(sc_core::sc_trace_file* tf, const tp* object, const std::string& name, int width) { \
230  sc_core::sc_trace(tf, object, name, width); \
231  } \
232  inline void sc_trace(sc_core::sc_trace_file* tf, const tp* object, const std::string& name) { \
233  sc_core::sc_trace(tf, object, name, sizeof(tp) * 8); \
234  }
235 
236 #define DEFN_TRACE_FUNC_B(tp) \
237  DEFN_TRACE_FUNC_REF_B(tp) \
238  DEFN_TRACE_FUNC_PTR_B(tp)
239 
240 #ifndef NCSC
241 DEFN_TRACE_FUNC_A(sc_core::sc_event)
242 DEFN_TRACE_FUNC_A(sc_core::sc_time)
243 #endif
244 
245 DEFN_TRACE_FUNC_A(bool)
246 DEFN_TRACE_FUNC_A(float)
247 DEFN_TRACE_FUNC_A(double)
248 
249 DEFN_TRACE_FUNC_B(unsigned char)
250 DEFN_TRACE_FUNC_B(unsigned short)
251 DEFN_TRACE_FUNC_B(unsigned int)
252 DEFN_TRACE_FUNC_B(unsigned long)
253 #ifdef SYSTEMC_64BIT_PATCHES
254 DEFN_TRACE_FUNC_B(unsigned long long)
255 #endif
256 DEFN_TRACE_FUNC_B(char)
257 DEFN_TRACE_FUNC_B(short)
258 DEFN_TRACE_FUNC_B(int)
259 DEFN_TRACE_FUNC_B(long)
260 #ifdef SYSTEMC_64BIT_PATCHES
261 DEFN_TRACE_FUNC_B(long long)
262 #endif
263 DEFN_TRACE_FUNC_B(sc_dt::int64)
264 DEFN_TRACE_FUNC_B(sc_dt::uint64)
265 
266 DEFN_TRACE_FUNC_A(sc_dt::sc_bit)
267 DEFN_TRACE_FUNC_A(sc_dt::sc_logic)
268 
269 DEFN_TRACE_FUNC_A(sc_dt::sc_int_base)
270 DEFN_TRACE_FUNC_A(sc_dt::sc_uint_base)
271 DEFN_TRACE_FUNC_A(sc_dt::sc_signed)
272 DEFN_TRACE_FUNC_A(sc_dt::sc_unsigned)
273 
274 DEFN_TRACE_FUNC_A(sc_dt::sc_bv_base)
275 DEFN_TRACE_FUNC_A(sc_dt::sc_lv_base)
276 
277 #ifdef SC_INCLUDE_FX
278 
279 DEFN_TRACE_FUNC_A(sc_dt::sc_fxval)
280 DEFN_TRACE_FUNC_A(sc_dt::sc_fxval_fast)
281 DEFN_TRACE_FUNC_A(sc_dt::sc_fxnum)
282 DEFN_TRACE_FUNC_A(sc_dt::sc_fxnum_fast)
283 
284 #endif // SC_INCLUDE_FX
285 
286 #undef DEFN_TRACE_FUNC_REF_A
287 #undef DEFN_TRACE_FUNC_PTR_A
288 #undef DEFN_TRACE_FUNC_A
289 
290 #undef DEFN_TRACE_FUNC_REF_B
291 #undef DEFN_TRACE_FUNC_PTR_B
292 #undef DEFN_TRACE_FUNC_B
293 
294 } /* namespace scc */ // end of scc-sysc
296 #endif /* _SCC_OBSERVER_H_ */
SCC SystemC utilities.
A handle to be used be the observed object to notify the observer about a change.
Definition: observer.h:57
The interface defining an observer.
Definition: observer.h:53