sc_signal.hh revision 13142
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        _changeStamp = ::sc_gem5::getChangeStamp();
155        _valueChangedEvent.notify(SC_ZERO_TIME);
156    }
157
158    // These members which store the current and future value of the signal
159    // are not specified in the standard but are referred to directly by one
160    // of the tests.
161    T m_cur_val;
162    T m_new_val;
163
164  private:
165    sc_event _valueChangedEvent;
166    uint64_t _changeStamp;
167
168    // Disabled
169    sc_signal(const sc_signal<T, WRITER_POLICY> &) :
170            sc_signal_inout_if<T>(), sc_prim_channel("")
171    {}
172};
173
174template <class T, sc_writer_policy WRITER_POLICY>
175inline std::ostream &
176operator << (std::ostream &os, const sc_signal<T, WRITER_POLICY> &s)
177{
178    os << s.read();
179    return os;
180}
181
182template <sc_writer_policy WRITER_POLICY>
183class sc_signal<bool, WRITER_POLICY> :
184    public sc_signal_inout_if<bool>, public sc_prim_channel
185{
186  public:
187    sc_signal() : sc_signal_inout_if<bool>(),
188                  sc_prim_channel(sc_gen_unique_name("signal")),
189                  m_cur_val(bool()), m_new_val(bool()),
190                  _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
191    {}
192    explicit sc_signal(const char *name) :
193        sc_signal_inout_if<bool>(), sc_prim_channel(name),
194        m_cur_val(bool()), m_new_val(bool()),
195        _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
196    {}
197    explicit sc_signal(const char *name, const bool &initial_value) :
198        sc_signal_inout_if<bool>(), sc_prim_channel(name),
199        m_cur_val(initial_value), m_new_val(initial_value),
200        _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
201    {}
202    virtual ~sc_signal() {}
203
204    virtual void
205    register_port(sc_port_base &, const char *)
206    {
207        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
208    }
209
210    virtual const bool &read() const { return m_cur_val; }
211    operator const bool &() const { return read(); }
212
213    virtual sc_writer_policy
214    get_writer_policy() const
215    {
216        return WRITER_POLICY;
217    }
218    virtual void
219    write(const bool &b)
220    {
221        m_new_val = b;
222        bool changed = !(m_cur_val == m_new_val);
223        //TODO check whether this write follows the write policy.
224        if (changed)
225            request_update();
226    }
227    sc_signal<bool, WRITER_POLICY> &
228    operator = (const bool &b)
229    {
230        write(b);
231        return *this;
232    }
233    sc_signal<bool, WRITER_POLICY> &
234    operator = (const sc_signal<bool, WRITER_POLICY> &s)
235    {
236        write(s.read());
237        return *this;
238    }
239
240    virtual const sc_event &
241    default_event() const
242    {
243        return value_changed_event();
244    }
245
246    virtual const sc_event &
247    value_changed_event() const
248    {
249        return _valueChangedEvent;
250    }
251    virtual const sc_event &
252    posedge_event() const
253    {
254        return _posedgeEvent;
255    }
256    virtual const sc_event &
257    negedge_event() const
258    {
259        return _negedgeEvent;
260    }
261
262    virtual bool
263    event() const
264    {
265        return _changeStamp == ::sc_gem5::getChangeStamp();
266    }
267    virtual bool
268    posedge() const
269    {
270        return _posStamp == ::sc_gem5::getChangeStamp();
271    }
272    virtual bool
273    negedge() const
274    {
275        return _negStamp == ::sc_gem5::getChangeStamp();
276    }
277
278    virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; }
279    virtual void
280    dump(std::ostream &os=std::cout) const
281    {
282        os << "     name = " << name() << ::std::endl;
283        os << "    value = " << m_cur_val << ::std::endl;
284        os << "new value = " << m_new_val << ::std::endl;
285    }
286    virtual const char *kind() const { return "sc_signal"; }
287
288  protected:
289    virtual void
290    update()
291    {
292        if (m_new_val == m_cur_val)
293            return;
294
295        m_cur_val = m_new_val;
296        uint64_t change_stamp = ::sc_gem5::getChangeStamp();
297        _changeStamp = change_stamp;
298        _valueChangedEvent.notify(SC_ZERO_TIME);
299        if (m_cur_val) {
300            _posStamp = change_stamp;
301            _posedgeEvent.notify(SC_ZERO_TIME);
302        } else {
303            _negStamp = change_stamp;
304            _negedgeEvent.notify(SC_ZERO_TIME);
305        }
306    }
307
308    bool m_cur_val;
309    bool m_new_val;
310
311  private:
312    sc_event _valueChangedEvent;
313    sc_event _posedgeEvent;
314    sc_event _negedgeEvent;
315
316    uint64_t _changeStamp;
317    uint64_t _posStamp;
318    uint64_t _negStamp;
319
320    // Disabled
321    sc_signal(const sc_signal<bool, WRITER_POLICY> &) :
322            sc_signal_inout_if<bool>(), sc_prim_channel("")
323    {}
324};
325
326template <sc_writer_policy WRITER_POLICY>
327class sc_signal<sc_dt::sc_logic, WRITER_POLICY> :
328    public sc_signal_inout_if<sc_dt::sc_logic>, public sc_prim_channel
329{
330  public:
331    sc_signal() : sc_signal_inout_if<sc_dt::sc_logic>(),
332                  sc_prim_channel(sc_gen_unique_name("signal")),
333                  m_cur_val(sc_dt::sc_logic()), m_new_val(sc_dt::sc_logic()),
334                  _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
335    {}
336    explicit sc_signal(const char *name) :
337        sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel(name),
338        m_cur_val(sc_dt::sc_logic()), m_new_val(sc_dt::sc_logic()),
339        _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
340    {}
341    explicit sc_signal(const char *name,
342            const sc_dt::sc_logic &initial_value) :
343        sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel(name),
344        m_cur_val(initial_value), m_new_val(initial_value),
345        _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
346    {}
347    virtual ~sc_signal() {}
348
349    virtual void
350    register_port(sc_port_base &, const char *)
351    {
352        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
353    }
354
355    virtual const sc_dt::sc_logic &read() const { return m_cur_val; }
356    operator const sc_dt::sc_logic &() const { return read(); }
357
358    virtual sc_writer_policy
359    get_writer_policy() const
360    {
361        return WRITER_POLICY;
362    }
363    virtual void
364    write(const sc_dt::sc_logic &l)
365    {
366        m_new_val = l;
367        bool changed = !(m_cur_val == m_new_val);
368        //TODO check whether this write follows the write policy.
369        if (changed)
370            request_update();
371    }
372    sc_signal<sc_dt::sc_logic, WRITER_POLICY> &
373    operator = (const sc_dt::sc_logic &l)
374    {
375        write(l);
376        return *this;
377    }
378    sc_signal<sc_dt::sc_logic, WRITER_POLICY> &
379    operator = (const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &s)
380    {
381        write(s.read());
382        return *this;
383    }
384
385    virtual const sc_event &
386    default_event() const
387    {
388        return value_changed_event();
389    }
390
391    virtual const sc_event &
392    value_changed_event() const
393    {
394        return _valueChangedEvent;
395    }
396    virtual const sc_event &
397    posedge_event() const
398    {
399        return _posedgeEvent;
400    }
401    virtual const sc_event &
402    negedge_event() const
403    {
404        return _negedgeEvent;
405    }
406
407    virtual bool
408    event() const
409    {
410        return _changeStamp == ::sc_gem5::getChangeStamp();
411    }
412    virtual bool
413    posedge() const
414    {
415        return _posStamp == ::sc_gem5::getChangeStamp();
416    }
417    virtual bool
418    negedge() const
419    {
420        return _negStamp == ::sc_gem5::getChangeStamp();
421    }
422
423    virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; }
424    virtual void
425    dump(std::ostream &os=std::cout) const
426    {
427        os << "     name = " << name() << ::std::endl;
428        os << "    value = " << m_cur_val << ::std::endl;
429        os << "new value = " << m_new_val << ::std::endl;
430    }
431    virtual const char *kind() const { return "sc_signal"; }
432
433  protected:
434    virtual void
435    update()
436    {
437        if (m_new_val == m_cur_val)
438            return;
439
440        m_cur_val = m_new_val;
441        _valueChangedEvent.notify(SC_ZERO_TIME);
442        if (m_cur_val == sc_dt::SC_LOGIC_1)
443            _posedgeEvent.notify(SC_ZERO_TIME);
444        else if (m_cur_val == sc_dt::SC_LOGIC_0)
445            _negedgeEvent.notify(SC_ZERO_TIME);
446    }
447
448    sc_dt::sc_logic m_cur_val;
449    sc_dt::sc_logic m_new_val;
450
451  private:
452    sc_event _valueChangedEvent;
453    sc_event _posedgeEvent;
454    sc_event _negedgeEvent;
455
456    uint64_t _changeStamp;
457    uint64_t _posStamp;
458    uint64_t _negStamp;
459
460    // Disabled
461    sc_signal(const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &) :
462            sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel("")
463    {}
464};
465
466} // namespace sc_core
467
468#endif  //__SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__
469