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