sc_signal.hh revision 13303:045f002c325c
112771Sqtt2@cornell.edu/*
212771Sqtt2@cornell.edu * Copyright 2018 Google, Inc.
312771Sqtt2@cornell.edu *
412771Sqtt2@cornell.edu * Redistribution and use in source and binary forms, with or without
512771Sqtt2@cornell.edu * modification, are permitted provided that the following conditions are
612771Sqtt2@cornell.edu * met: redistributions of source code must retain the above copyright
712771Sqtt2@cornell.edu * notice, this list of conditions and the following disclaimer;
812771Sqtt2@cornell.edu * redistributions in binary form must reproduce the above copyright
912771Sqtt2@cornell.edu * notice, this list of conditions and the following disclaimer in the
1012771Sqtt2@cornell.edu * documentation and/or other materials provided with the distribution;
1112771Sqtt2@cornell.edu * neither the name of the copyright holders nor the names of its
1212771Sqtt2@cornell.edu * contributors may be used to endorse or promote products derived from
1312771Sqtt2@cornell.edu * this software without specific prior written permission.
1412771Sqtt2@cornell.edu *
1512771Sqtt2@cornell.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1612771Sqtt2@cornell.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1712771Sqtt2@cornell.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1812771Sqtt2@cornell.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1912771Sqtt2@cornell.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2012771Sqtt2@cornell.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2112771Sqtt2@cornell.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2212771Sqtt2@cornell.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2312771Sqtt2@cornell.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2412771Sqtt2@cornell.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2512771Sqtt2@cornell.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2612771Sqtt2@cornell.edu *
2712771Sqtt2@cornell.edu * Authors: Gabe Black
2812771Sqtt2@cornell.edu */
2912771Sqtt2@cornell.edu
3012771Sqtt2@cornell.edu#ifndef __SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__
3112771Sqtt2@cornell.edu#define __SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__
3212771Sqtt2@cornell.edu
3312771Sqtt2@cornell.edu#include <iostream>
3412771Sqtt2@cornell.edu#include <string>
3512771Sqtt2@cornell.edu#include <vector>
3612771Sqtt2@cornell.edu
3712771Sqtt2@cornell.edu#include "../core/sc_event.hh"
3812771Sqtt2@cornell.edu#include "../core/sc_module.hh" // for sc_gen_unique_name
3912771Sqtt2@cornell.edu#include "../core/sc_prim.hh"
4012771Sqtt2@cornell.edu#include "../dt/bit/sc_logic.hh"
4112771Sqtt2@cornell.edu#include "sc_signal_inout_if.hh"
4212771Sqtt2@cornell.edu
4312771Sqtt2@cornell.edunamespace sc_core
4412771Sqtt2@cornell.edu{
4512771Sqtt2@cornell.edu
4612771Sqtt2@cornell.educlass sc_port_base;
4712771Sqtt2@cornell.edu
4812771Sqtt2@cornell.edu} // namespace sc_core
4912771Sqtt2@cornell.edu
5012771Sqtt2@cornell.edunamespace sc_gem5
5112771Sqtt2@cornell.edu{
5212771Sqtt2@cornell.edu
5312771Sqtt2@cornell.educlass Process;
5412771Sqtt2@cornell.educlass Reset;
5512771Sqtt2@cornell.edu
5612771Sqtt2@cornell.educlass ScSignalBase : public sc_core::sc_prim_channel
5712771Sqtt2@cornell.edu{
5812771Sqtt2@cornell.edu  public:
5912771Sqtt2@cornell.edu    virtual const char *kind() const { return "sc_signal"; }
6012771Sqtt2@cornell.edu
6112771Sqtt2@cornell.edu  protected:
6212771Sqtt2@cornell.edu    ScSignalBase(const char *_name);
6312771Sqtt2@cornell.edu    virtual ~ScSignalBase();
6412771Sqtt2@cornell.edu
6512771Sqtt2@cornell.edu    const sc_core::sc_event &defaultEvent() const;
6612771Sqtt2@cornell.edu    const sc_core::sc_event &valueChangedEvent() const;
6712771Sqtt2@cornell.edu
6812771Sqtt2@cornell.edu    bool event() const;
6912771Sqtt2@cornell.edu
7012771Sqtt2@cornell.edu    void _signalChange();
7112771Sqtt2@cornell.edu
7212771Sqtt2@cornell.edu    virtual sc_core::sc_writer_policy get_writer_policy() const = 0;
7312771Sqtt2@cornell.edu
7412771Sqtt2@cornell.edu    InternalScEvent _valueChangedEvent;
7512771Sqtt2@cornell.edu    uint64_t _changeStamp;
7612771Sqtt2@cornell.edu    sc_core::sc_port_base *_gem5WriterPort;
7712771Sqtt2@cornell.edu};
7812771Sqtt2@cornell.edu
7912771Sqtt2@cornell.educlass ScSignalBaseBinary : public ScSignalBase
8012771Sqtt2@cornell.edu{
8112771Sqtt2@cornell.edu  protected:
8212771Sqtt2@cornell.edu    ScSignalBaseBinary(const char *_name);
8312771Sqtt2@cornell.edu
8412771Sqtt2@cornell.edu    mutable std::vector<sc_gem5::Reset *> _resets;
8512771Sqtt2@cornell.edu    void _signalReset(sc_gem5::Reset *reset);
8612771Sqtt2@cornell.edu    void _signalReset();
8712771Sqtt2@cornell.edu
8812771Sqtt2@cornell.edu    const sc_core::sc_event &posedgeEvent() const;
8912771Sqtt2@cornell.edu    const sc_core::sc_event &negedgeEvent() const;
9012771Sqtt2@cornell.edu
9112771Sqtt2@cornell.edu    bool posedge() const;
9212771Sqtt2@cornell.edu    bool negedge() const;
9312771Sqtt2@cornell.edu
9412771Sqtt2@cornell.edu    InternalScEvent _posedgeEvent;
9512771Sqtt2@cornell.edu    InternalScEvent _negedgeEvent;
9612771Sqtt2@cornell.edu
9712771Sqtt2@cornell.edu    uint64_t _posStamp;
9812771Sqtt2@cornell.edu    uint64_t _negStamp;
9912771Sqtt2@cornell.edu};
10012771Sqtt2@cornell.edu
10112771Sqtt2@cornell.edutemplate <class T>
10212771Sqtt2@cornell.educlass ScSignalBasePicker : public ScSignalBase
10312771Sqtt2@cornell.edu{
10412771Sqtt2@cornell.edu  protected:
10512771Sqtt2@cornell.edu    ScSignalBasePicker(const char *_name) : ScSignalBase(_name) {}
10612771Sqtt2@cornell.edu};
10712771Sqtt2@cornell.edu
10812771Sqtt2@cornell.edutemplate <>
10912771Sqtt2@cornell.educlass ScSignalBasePicker<bool> : public ScSignalBaseBinary
11012771Sqtt2@cornell.edu{
11112771Sqtt2@cornell.edu  protected:
11212771Sqtt2@cornell.edu    ScSignalBasePicker(const char *_name) : ScSignalBaseBinary(_name) {}
11312771Sqtt2@cornell.edu};
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