Deleted Added
sdiff udiff text old ( 13205:e965ce37608e ) new ( 13245:c666c5d4996b )
full compact
1/*
2 * Copyright 2018 Google, Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met: redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer;
8 * redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution;
11 * neither the name of the copyright holders nor the names of its
12 * contributors may be used to endorse or promote products derived from
13 * this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 * Authors: Gabe Black
28 */
29
30#ifndef __SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__
31#define __SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__
32
33#include <iostream>
34#include <string>
35#include <vector>
36
37#include "../core/sc_event.hh"
38#include "../core/sc_module.hh" // for sc_gen_unique_name
39#include "../core/sc_prim.hh"
40#include "../dt/bit/sc_logic.hh"
41#include "sc_signal_inout_if.hh"
42#include "warn_unimpl.hh" // for warn_unimpl
43
44namespace sc_core
45{
46
47class sc_port_base;
48class sc_trace_file;
49
50// Nonstandard
51// Despite having a warning "FOR INTERNAL USE ONLY!" in all caps above this
52// class definition in the Accellera implementation, it appears in their
53// examples and test programs, and so we need to have it here as well.
54struct sc_trace_params
55{
56 sc_trace_file *tf;
57 std::string name;
58
59 sc_trace_params(sc_trace_file *tf, const std::string &name) :
60 tf(tf), name(name)
61 {}
62};
63typedef std::vector<sc_trace_params *> sc_trace_params_vec;
64
65template <class T, sc_writer_policy WRITER_POLICY=SC_ONE_WRITER>
66class sc_signal : public sc_signal_inout_if<T>,
67 public sc_prim_channel
68{
69 public:
70 sc_signal() : sc_signal_inout_if<T>(),
71 sc_prim_channel(sc_gen_unique_name("signal")),
72 m_cur_val(T()), m_new_val(T()), _changeStamp(~0ULL)
73 {}
74 explicit sc_signal(const char *name) :
75 sc_signal_inout_if<T>(), sc_prim_channel(name),
76 m_cur_val(T()), m_new_val(T()), _changeStamp(~0ULL)
77 {}
78 explicit sc_signal(const char *name, const T &initial_value) :
79 sc_signal_inout_if<T>(), sc_prim_channel(name),
80 m_cur_val(initial_value), m_new_val(initial_value), _changeStamp(~0ULL)
81 {}
82 virtual ~sc_signal() {}
83
84 virtual void
85 register_port(sc_port_base &, const char *)
86 {
87 sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
88 }
89
90 virtual const T &read() const { return m_cur_val; }
91 operator const T&() const { return read(); }
92
93 virtual sc_writer_policy
94 get_writer_policy() const
95 {
96 return WRITER_POLICY;
97 }
98 virtual void
99 write(const T &t)
100 {
101 m_new_val = t;
102 bool changed = !(m_cur_val == m_new_val);
103 //TODO check whether this write follows the write policy.
104 if (changed)
105 request_update();
106 }
107 sc_signal<T, WRITER_POLICY> &
108 operator = (const T &t)
109 {
110 write(t);
111 return *this;
112 }
113 sc_signal<T, WRITER_POLICY> &
114 operator = (const sc_signal<T, WRITER_POLICY> &s)
115 {
116 write(s.read());
117 return *this;
118 }
119
120 virtual const sc_event &
121 default_event() const
122 {
123 return value_changed_event();
124 }
125 virtual const sc_event &
126 value_changed_event() const
127 {
128 return _valueChangedEvent;
129 }
130 virtual bool
131 event() const
132 {
133 return _changeStamp == ::sc_gem5::getChangeStamp();
134 }
135
136 virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; }
137 virtual void
138 dump(std::ostream &os=std::cout) const
139 {
140 os << " name = " << name() << ::std::endl;
141 os << " value = " << m_cur_val << ::std::endl;
142 os << "new value = " << m_new_val << ::std::endl;
143 }
144 virtual const char *kind() const { return "sc_signal"; }
145
146 protected:
147 virtual void
148 update()
149 {
150 if (m_new_val == m_cur_val)
151 return;
152
153 m_cur_val = m_new_val;
154 _signalChange();
155 _changeStamp = ::sc_gem5::getChangeStamp();
156 _valueChangedEvent.notify(SC_ZERO_TIME);
157 }
158
159 void
160 _signalChange()
161 {
162 _changeStamp = ::sc_gem5::getChangeStamp();
163 _valueChangedEvent.notify(SC_ZERO_TIME);
164 }
165
166 // These members which store the current and future value of the signal
167 // are not specified in the standard but are referred to directly by one
168 // of the tests.
169 T m_cur_val;
170 T m_new_val;
171
172 private:
173 sc_event _valueChangedEvent;
174 uint64_t _changeStamp;
175
176 // Disabled
177 sc_signal(const sc_signal<T, WRITER_POLICY> &) :
178 sc_signal_inout_if<T>(), sc_prim_channel("")
179 {}
180};
181
182template <class T, sc_writer_policy WRITER_POLICY>
183inline std::ostream &
184operator << (std::ostream &os, const sc_signal<T, WRITER_POLICY> &s)
185{
186 os << s.read();
187 return os;
188}
189
190template <sc_writer_policy WRITER_POLICY>
191class sc_signal<bool, WRITER_POLICY> :
192 public sc_signal_inout_if<bool>, public sc_prim_channel
193{
194 public:
195 sc_signal() : sc_signal_inout_if<bool>(),
196 sc_prim_channel(sc_gen_unique_name("signal")),
197 m_cur_val(bool()), m_new_val(bool()),
198 _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
199 {}
200 explicit sc_signal(const char *name) :
201 sc_signal_inout_if<bool>(), sc_prim_channel(name),
202 m_cur_val(bool()), m_new_val(bool()),
203 _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
204 {}
205 explicit sc_signal(const char *name, const bool &initial_value) :
206 sc_signal_inout_if<bool>(), sc_prim_channel(name),
207 m_cur_val(initial_value), m_new_val(initial_value),
208 _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
209 {}
210 virtual ~sc_signal() {}
211
212 virtual void
213 register_port(sc_port_base &, const char *)
214 {
215 sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
216 }
217
218 virtual const bool &read() const { return m_cur_val; }
219 operator const bool &() const { return read(); }
220
221 virtual sc_writer_policy
222 get_writer_policy() const
223 {
224 return WRITER_POLICY;
225 }
226 virtual void
227 write(const bool &b)
228 {
229 m_new_val = b;
230 bool changed = !(m_cur_val == m_new_val);
231 //TODO check whether this write follows the write policy.
232 if (changed)
233 request_update();
234 }
235 sc_signal<bool, WRITER_POLICY> &
236 operator = (const bool &b)
237 {
238 write(b);
239 return *this;
240 }
241 sc_signal<bool, WRITER_POLICY> &
242 operator = (const sc_signal<bool, WRITER_POLICY> &s)
243 {
244 write(s.read());
245 return *this;
246 }
247
248 virtual const sc_event &
249 default_event() const
250 {
251 return value_changed_event();
252 }
253
254 virtual const sc_event &
255 value_changed_event() const
256 {
257 return _valueChangedEvent;
258 }
259 virtual const sc_event &
260 posedge_event() const
261 {
262 return _posedgeEvent;
263 }
264 virtual const sc_event &
265 negedge_event() const
266 {
267 return _negedgeEvent;
268 }
269
270 virtual bool
271 event() const
272 {
273 return _changeStamp == ::sc_gem5::getChangeStamp();
274 }
275 virtual bool
276 posedge() const
277 {
278 return _posStamp == ::sc_gem5::getChangeStamp();
279 }
280 virtual bool
281 negedge() const
282 {
283 return _negStamp == ::sc_gem5::getChangeStamp();
284 }
285
286 virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; }
287 virtual void
288 dump(std::ostream &os=std::cout) const
289 {
290 os << " name = " << name() << ::std::endl;
291 os << " value = " << m_cur_val << ::std::endl;
292 os << "new value = " << m_new_val << ::std::endl;
293 }
294 virtual const char *kind() const { return "sc_signal"; }
295
296 protected:
297 virtual void
298 update()
299 {
300 if (m_new_val == m_cur_val)
301 return;
302
303 m_cur_val = m_new_val;
304 _signalChange();
305 if (m_cur_val) {
306 _posStamp = ::sc_gem5::getChangeStamp();
307 _posedgeEvent.notify(SC_ZERO_TIME);
308 } else {
309 _negStamp = ::sc_gem5::getChangeStamp();
310 _negedgeEvent.notify(SC_ZERO_TIME);
311 }
312 }
313
314 void
315 _signalChange()
316 {
317 _changeStamp = ::sc_gem5::getChangeStamp();
318 _valueChangedEvent.notify(SC_ZERO_TIME);
319 }
320
321 bool m_cur_val;
322 bool m_new_val;
323
324 private:
325 sc_event _valueChangedEvent;
326 sc_event _posedgeEvent;
327 sc_event _negedgeEvent;
328
329 uint64_t _changeStamp;
330 uint64_t _posStamp;
331 uint64_t _negStamp;
332
333 // Disabled
334 sc_signal(const sc_signal<bool, WRITER_POLICY> &) :
335 sc_signal_inout_if<bool>(), sc_prim_channel("")
336 {}
337};
338
339template <sc_writer_policy WRITER_POLICY>
340class sc_signal<sc_dt::sc_logic, WRITER_POLICY> :
341 public sc_signal_inout_if<sc_dt::sc_logic>, public sc_prim_channel
342{
343 public:
344 sc_signal() : sc_signal_inout_if<sc_dt::sc_logic>(),
345 sc_prim_channel(sc_gen_unique_name("signal")),
346 m_cur_val(sc_dt::sc_logic()), m_new_val(sc_dt::sc_logic()),
347 _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
348 {}
349 explicit sc_signal(const char *name) :
350 sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel(name),
351 m_cur_val(sc_dt::sc_logic()), m_new_val(sc_dt::sc_logic()),
352 _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
353 {}
354 explicit sc_signal(const char *name,
355 const sc_dt::sc_logic &initial_value) :
356 sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel(name),
357 m_cur_val(initial_value), m_new_val(initial_value),
358 _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
359 {}
360 virtual ~sc_signal() {}
361
362 virtual void
363 register_port(sc_port_base &, const char *)
364 {
365 sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
366 }
367
368 virtual const sc_dt::sc_logic &read() const { return m_cur_val; }
369 operator const sc_dt::sc_logic &() const { return read(); }
370
371 virtual sc_writer_policy
372 get_writer_policy() const
373 {
374 return WRITER_POLICY;
375 }
376 virtual void
377 write(const sc_dt::sc_logic &l)
378 {
379 m_new_val = l;
380 bool changed = !(m_cur_val == m_new_val);
381 //TODO check whether this write follows the write policy.
382 if (changed)
383 request_update();
384 }
385 sc_signal<sc_dt::sc_logic, WRITER_POLICY> &
386 operator = (const sc_dt::sc_logic &l)
387 {
388 write(l);
389 return *this;
390 }
391 sc_signal<sc_dt::sc_logic, WRITER_POLICY> &
392 operator = (const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &s)
393 {
394 write(s.read());
395 return *this;
396 }
397
398 virtual const sc_event &
399 default_event() const
400 {
401 return value_changed_event();
402 }
403
404 virtual const sc_event &
405 value_changed_event() const
406 {
407 return _valueChangedEvent;
408 }
409 virtual const sc_event &
410 posedge_event() const
411 {
412 return _posedgeEvent;
413 }
414 virtual const sc_event &
415 negedge_event() const
416 {
417 return _negedgeEvent;
418 }
419
420 virtual bool
421 event() const
422 {
423 return _changeStamp == ::sc_gem5::getChangeStamp();
424 }
425 virtual bool
426 posedge() const
427 {
428 return _posStamp == ::sc_gem5::getChangeStamp();
429 }
430 virtual bool
431 negedge() const
432 {
433 return _negStamp == ::sc_gem5::getChangeStamp();
434 }
435
436 virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; }
437 virtual void
438 dump(std::ostream &os=std::cout) const
439 {
440 os << " name = " << name() << ::std::endl;
441 os << " value = " << m_cur_val << ::std::endl;
442 os << "new value = " << m_new_val << ::std::endl;
443 }
444 virtual const char *kind() const { return "sc_signal"; }
445
446 protected:
447 virtual void
448 update()
449 {
450 if (m_new_val == m_cur_val)
451 return;
452
453 m_cur_val = m_new_val;
454 _signalChange();
455 if (m_cur_val == sc_dt::SC_LOGIC_1) {
456 _posStamp = ::sc_gem5::getChangeStamp();
457 _posedgeEvent.notify(SC_ZERO_TIME);
458 } else if (m_cur_val == sc_dt::SC_LOGIC_0) {
459 _negStamp = ::sc_gem5::getChangeStamp();
460 _negedgeEvent.notify(SC_ZERO_TIME);
461 }
462 }
463
464 void
465 _signalChange()
466 {
467 _changeStamp = ::sc_gem5::getChangeStamp();
468 _valueChangedEvent.notify(SC_ZERO_TIME);
469 }
470
471 sc_dt::sc_logic m_cur_val;
472 sc_dt::sc_logic m_new_val;
473
474 private:
475 sc_event _valueChangedEvent;
476 sc_event _posedgeEvent;
477 sc_event _negedgeEvent;
478
479 uint64_t _changeStamp;
480 uint64_t _posStamp;
481 uint64_t _negStamp;
482
483 // Disabled
484 sc_signal(const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &) :
485 sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel("")
486 {}
487};
488
489} // namespace sc_core
490
491#endif //__SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__