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