scc 2025.09
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
29namespace sc_dt {
30class sc_bit;
31class sc_logic;
32class sc_bv_base;
33class sc_lv_base;
34class sc_signed;
35class sc_unsigned;
36class sc_int_base;
37class sc_uint_base;
38class sc_fxval;
39class sc_fxval_fast;
40class sc_fxnum;
41class sc_fxnum_fast;
42} // namespace sc_dt
43
49namespace scc {
53struct 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)
100DECL_REGISTER_METHOD_A(sc_core::sc_event)
101DECL_REGISTER_METHOD_A(sc_core::sc_time)
102#endif
103DECL_REGISTER_METHOD_A(bool)
104DECL_REGISTER_METHOD_A(sc_dt::sc_bit)
105DECL_REGISTER_METHOD_A(sc_dt::sc_logic)
106
107DECL_REGISTER_METHOD_A(unsigned char)
108DECL_REGISTER_METHOD_A(unsigned short)
109DECL_REGISTER_METHOD_A(unsigned int)
110DECL_REGISTER_METHOD_A(unsigned long)
111DECL_REGISTER_METHOD_A(char)
112DECL_REGISTER_METHOD_A(short)
113DECL_REGISTER_METHOD_A(int)
114DECL_REGISTER_METHOD_A(long)
115DECL_REGISTER_METHOD_A(sc_dt::int64)
116DECL_REGISTER_METHOD_A(sc_dt::uint64)
117
118DECL_REGISTER_METHOD_A(float)
119DECL_REGISTER_METHOD_A(double)
120DECL_REGISTER_METHOD_A(sc_dt::sc_int_base)
121DECL_REGISTER_METHOD_A(sc_dt::sc_uint_base)
122DECL_REGISTER_METHOD_A(sc_dt::sc_signed)
123DECL_REGISTER_METHOD_A(sc_dt::sc_unsigned)
124
125DECL_REGISTER_METHOD_A(sc_dt::sc_fxval)
126DECL_REGISTER_METHOD_A(sc_dt::sc_fxval_fast)
127DECL_REGISTER_METHOD_A(sc_dt::sc_fxnum)
128DECL_REGISTER_METHOD_A(sc_dt::sc_fxnum_fast)
129
130DECL_REGISTER_METHOD_A(sc_dt::sc_bv_base)
131DECL_REGISTER_METHOD_A(sc_dt::sc_lv_base)
132
133#undef DECL_REGISTER_METHOD_A
134
135template <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
152template <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
156template <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
179template <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
183template <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
206template <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
241DEFN_TRACE_FUNC_A(sc_core::sc_event)
242DEFN_TRACE_FUNC_A(sc_core::sc_time)
243#endif
244
245DEFN_TRACE_FUNC_A(bool)
246DEFN_TRACE_FUNC_A(float)
247DEFN_TRACE_FUNC_A(double)
248
249DEFN_TRACE_FUNC_B(unsigned char)
250DEFN_TRACE_FUNC_B(unsigned short)
251DEFN_TRACE_FUNC_B(unsigned int)
252DEFN_TRACE_FUNC_B(unsigned long)
253#ifdef SYSTEMC_64BIT_PATCHES
254DEFN_TRACE_FUNC_B(unsigned long long)
255#endif
256DEFN_TRACE_FUNC_B(char)
257DEFN_TRACE_FUNC_B(short)
258DEFN_TRACE_FUNC_B(int)
259DEFN_TRACE_FUNC_B(long)
260#ifdef SYSTEMC_64BIT_PATCHES
261DEFN_TRACE_FUNC_B(long long)
262#endif
263DEFN_TRACE_FUNC_B(sc_dt::int64)
264DEFN_TRACE_FUNC_B(sc_dt::uint64)
265
266DEFN_TRACE_FUNC_A(sc_dt::sc_bit)
267DEFN_TRACE_FUNC_A(sc_dt::sc_logic)
268
269DEFN_TRACE_FUNC_A(sc_dt::sc_int_base)
270DEFN_TRACE_FUNC_A(sc_dt::sc_uint_base)
271DEFN_TRACE_FUNC_A(sc_dt::sc_signed)
272DEFN_TRACE_FUNC_A(sc_dt::sc_unsigned)
273
274DEFN_TRACE_FUNC_A(sc_dt::sc_bv_base)
275DEFN_TRACE_FUNC_A(sc_dt::sc_lv_base)
276
277#ifdef SC_INCLUDE_FX
278
279DEFN_TRACE_FUNC_A(sc_dt::sc_fxval)
280DEFN_TRACE_FUNC_A(sc_dt::sc_fxval_fast)
281DEFN_TRACE_FUNC_A(sc_dt::sc_fxnum)
282DEFN_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 TLM 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