sc_signal.hh revision 13277:b479038de4d9
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
43namespace sc_core
44{
45
46class sc_port_base;
47
48} // namespace sc_core
49
50namespace sc_gem5
51{
52
53class Process;
54
55class ScSignalBase : public sc_core::sc_prim_channel
56{
57  public:
58    virtual const char *kind() const { return "sc_signal"; }
59
60  protected:
61    ScSignalBase(const char *_name);
62    virtual ~ScSignalBase();
63
64    const sc_core::sc_event &defaultEvent() const;
65    const sc_core::sc_event &valueChangedEvent() const;
66
67    bool event() const;
68
69    void _signalChange();
70
71    virtual sc_core::sc_writer_policy get_writer_policy() const = 0;
72
73    sc_core::sc_event _valueChangedEvent;
74    uint64_t _changeStamp;
75    sc_core::sc_port_base *_gem5WriterPort;
76};
77
78class ScSignalBaseBinary : public ScSignalBase
79{
80  protected:
81    ScSignalBaseBinary(const char *_name);
82
83    const sc_core::sc_event &posedgeEvent() const;
84    const sc_core::sc_event &negedgeEvent() const;
85
86    bool posedge() const;
87    bool negedge() const;
88
89    sc_core::sc_event _posedgeEvent;
90    sc_core::sc_event _negedgeEvent;
91
92    uint64_t _posStamp;
93    uint64_t _negStamp;
94};
95
96template <class T>
97class ScSignalBasePicker : public ScSignalBase
98{
99  protected:
100    ScSignalBasePicker(const char *_name) : ScSignalBase(_name) {}
101};
102
103template <>
104class ScSignalBasePicker<bool> : public ScSignalBaseBinary
105{
106  protected:
107    ScSignalBasePicker(const char *_name) : ScSignalBaseBinary(_name) {}
108};
109
110template <>
111class ScSignalBasePicker<sc_dt::sc_logic> : public ScSignalBaseBinary
112{
113  protected:
114    ScSignalBasePicker(const char *_name) : ScSignalBaseBinary(_name) {}
115};
116
117template <sc_core::sc_writer_policy WRITER_POLICY>
118class WriteChecker;
119
120template <>
121class WriteChecker<sc_core::SC_ONE_WRITER>
122{
123  public:
124    WriteChecker(ScSignalBase *_sig);
125
126    void checkPort(sc_core::sc_port_base &port,
127            std::string iface_type_name, std::string out_name);
128    void checkWriter();
129
130  private:
131    ScSignalBase *sig;
132    sc_core::sc_port_base *firstPort;
133    Process *proc;
134    uint64_t writeStamp;
135};
136
137template <>
138class WriteChecker<sc_core::SC_MANY_WRITERS>
139{
140  public:
141    WriteChecker(ScSignalBase *_sig);
142
143    void checkPort(sc_core::sc_port_base &port,
144            std::string iface_type_name, std::string out_name);
145    void checkWriter();
146
147  private:
148    ScSignalBase *sig;
149    Process *proc;
150    uint64_t writeStamp;
151};
152
153template <class T, sc_core::sc_writer_policy WRITER_POLICY>
154class ScSignalBaseT :
155    public ScSignalBasePicker<T>, public sc_core::sc_signal_inout_if<T>
156{
157  public:
158    ScSignalBaseT(const char *_name) :
159        ScSignalBasePicker<T>(_name), m_cur_val(T()), m_new_val(T()),
160        _checker(this)
161    {}
162    ScSignalBaseT(const char *_name, const T &initial_value) :
163        ScSignalBasePicker<T>(_name), m_cur_val(initial_value),
164        m_new_val(initial_value), _checker(this)
165    {}
166    virtual ~ScSignalBaseT() {}
167
168    virtual void
169    register_port(sc_core::sc_port_base &port, const char *iface_type_name)
170    {
171#       if !defined(SC_NO_WRITE_CHECK)
172        {
173            _checker.checkPort(port, iface_type_name,
174                typeid(sc_core::sc_signal_inout_if<T>).name());
175        }
176#       endif
177    }
178
179    virtual const T &read() const { return m_cur_val; }
180    operator const T&() const { return read(); }
181
182    virtual void
183    write(const T &t)
184    {
185#       if !defined(SC_NO_WRITE_CHECK)
186        {
187            _checker.checkWriter();
188        }
189#       endif
190        m_new_val = t;
191        bool changed = !(m_cur_val == m_new_val);
192        if (changed)
193            this->request_update();
194    }
195
196    virtual const sc_core::sc_event &
197    default_event() const
198    {
199        return ScSignalBase::defaultEvent();
200    }
201
202    virtual const sc_core::sc_event &
203    value_changed_event() const
204    {
205        return ScSignalBase::valueChangedEvent();
206    }
207
208    virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; }
209    virtual void
210    dump(std::ostream &os=std::cout) const
211    {
212        os << "     name = " << this->name() << ::std::endl;
213        os << "    value = " << m_cur_val << ::std::endl;
214        os << "new value = " << m_new_val << ::std::endl;
215    }
216
217    virtual bool event() const { return ScSignalBase::event(); }
218
219    virtual sc_core::sc_writer_policy
220    get_writer_policy() const
221    {
222        return WRITER_POLICY;
223    }
224
225  protected:
226    // These members which store the current and future value of the signal
227    // are not specified in the standard but are referred to directly by one
228    // of the tests.
229    T m_cur_val;
230    T m_new_val;
231
232    WriteChecker<WRITER_POLICY> _checker;
233};
234
235template <typename T, sc_core::sc_writer_policy WRITER_POLICY>
236class ScSignalBinary : public ScSignalBaseT<T, WRITER_POLICY>
237{
238  public:
239    ScSignalBinary(const char *_name) : ScSignalBaseT<T, WRITER_POLICY>(_name)
240    {}
241    ScSignalBinary(const char *_name, const T& initial_value) :
242        ScSignalBaseT<T, WRITER_POLICY>(_name, initial_value)
243    {}
244
245    const sc_core::sc_event &
246    posedge_event() const
247    {
248        return ScSignalBaseBinary::posedgeEvent();
249    }
250    const sc_core::sc_event &
251    negedge_event() const
252    {
253        return ScSignalBaseBinary::negedgeEvent();
254    }
255
256    bool posedge() const { return ScSignalBaseBinary::posedge(); }
257    bool negedge() const { return ScSignalBaseBinary::negedge(); }
258};
259
260} // namespace sc_gem5
261
262namespace sc_core
263{
264
265template <class T, sc_writer_policy WRITER_POLICY=SC_ONE_WRITER>
266class sc_signal : public sc_gem5::ScSignalBaseT<T, WRITER_POLICY>
267{
268  public:
269    sc_signal() : sc_gem5::ScSignalBaseT<T, WRITER_POLICY>(
270            sc_gen_unique_name("signal"))
271    {}
272    explicit sc_signal(const char *name) :
273        sc_gem5::ScSignalBaseT<T, WRITER_POLICY>(name)
274    {}
275    explicit sc_signal(const char *name, const T &initial_value) :
276        sc_gem5::ScSignalBaseT<T, WRITER_POLICY>(name, initial_value)
277    {}
278    virtual ~sc_signal() {}
279
280    sc_signal<T, WRITER_POLICY> &
281    operator = (const T &t)
282    {
283        this->write(t);
284        return *this;
285    }
286    sc_signal<T, WRITER_POLICY> &
287    operator = (const sc_signal<T, WRITER_POLICY> &s)
288    {
289        this->write(s.read());
290        return *this;
291    }
292
293  protected:
294    virtual void
295    update()
296    {
297        if (this->m_new_val == this->m_cur_val)
298            return;
299
300        this->m_cur_val = this->m_new_val;
301        this->_signalChange();
302    }
303
304  private:
305    // Disabled
306    sc_signal(const sc_signal<T, WRITER_POLICY> &);
307};
308
309template <class T, sc_writer_policy WRITER_POLICY>
310inline std::ostream &
311operator << (std::ostream &os, const sc_signal<T, WRITER_POLICY> &s)
312{
313    os << s.read();
314    return os;
315}
316
317template <sc_writer_policy WRITER_POLICY>
318class sc_signal<bool, WRITER_POLICY> :
319    public sc_gem5::ScSignalBinary<bool, WRITER_POLICY>
320{
321  public:
322    sc_signal() :
323        sc_gem5::ScSignalBinary<bool, WRITER_POLICY>(
324                sc_gen_unique_name("signal"))
325    {}
326    explicit sc_signal(const char *name) :
327        sc_gem5::ScSignalBinary<bool, WRITER_POLICY>(name)
328    {}
329    explicit sc_signal(const char *name, const bool &initial_value) :
330        sc_gem5::ScSignalBinary<bool, WRITER_POLICY>(name, initial_value)
331    {}
332    virtual ~sc_signal() {}
333
334    sc_signal<bool, WRITER_POLICY> &
335    operator = (const bool &b)
336    {
337        this->write(b);
338        return *this;
339    }
340    sc_signal<bool, WRITER_POLICY> &
341    operator = (const sc_signal<bool, WRITER_POLICY> &s)
342    {
343        this->write(s.read());
344        return *this;
345    }
346
347  protected:
348    virtual void
349    update()
350    {
351        if (this->m_new_val == this->m_cur_val)
352            return;
353
354        this->m_cur_val = this->m_new_val;
355        this->_signalChange();
356        if (this->m_cur_val) {
357            this->_posStamp = ::sc_gem5::getChangeStamp();
358            this->_posedgeEvent.notify(SC_ZERO_TIME);
359        } else {
360            this->_negStamp = ::sc_gem5::getChangeStamp();
361            this->_negedgeEvent.notify(SC_ZERO_TIME);
362        }
363    }
364
365  private:
366    // Disabled
367    sc_signal(const sc_signal<bool, WRITER_POLICY> &);
368};
369
370template <sc_writer_policy WRITER_POLICY>
371class sc_signal<sc_dt::sc_logic, WRITER_POLICY> :
372    public sc_gem5::ScSignalBinary<sc_dt::sc_logic, WRITER_POLICY>
373{
374  public:
375    sc_signal() :
376        sc_gem5::ScSignalBinary<sc_dt::sc_logic, WRITER_POLICY>(
377                sc_gen_unique_name("signal"))
378    {}
379    explicit sc_signal(const char *name) :
380        sc_gem5::ScSignalBinary<sc_dt::sc_logic, WRITER_POLICY>(name)
381    {}
382    explicit sc_signal(const char *name,
383            const sc_dt::sc_logic &initial_value) :
384        sc_gem5::ScSignalBinary<sc_dt::sc_logic, WRITER_POLICY>(
385                name, initial_value)
386    {}
387    virtual ~sc_signal() {}
388
389    sc_signal<sc_dt::sc_logic, WRITER_POLICY> &
390    operator = (const sc_dt::sc_logic &l)
391    {
392        this->write(l);
393        return *this;
394    }
395    sc_signal<sc_dt::sc_logic, WRITER_POLICY> &
396    operator = (const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &s)
397    {
398        this->write(s.read());
399        return *this;
400    }
401
402  protected:
403    virtual void
404    update()
405    {
406        if (this->m_new_val == this->m_cur_val)
407            return;
408
409        this->m_cur_val = this->m_new_val;
410        this->_signalChange();
411        if (this->m_cur_val == sc_dt::SC_LOGIC_1) {
412            this->_posStamp = ::sc_gem5::getChangeStamp();
413            this->_posedgeEvent.notify(SC_ZERO_TIME);
414        } else if (this->m_cur_val == sc_dt::SC_LOGIC_0) {
415            this->_negStamp = ::sc_gem5::getChangeStamp();
416            this->_negedgeEvent.notify(SC_ZERO_TIME);
417        }
418    }
419
420  private:
421    // Disabled
422    sc_signal(const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &);
423};
424
425} // namespace sc_core
426
427#endif  //__SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__
428