sc_signal.hh revision 13141
12810SN/A/*
22810SN/A * Copyright 2018 Google, Inc.
32810SN/A *
42810SN/A * Redistribution and use in source and binary forms, with or without
52810SN/A * modification, are permitted provided that the following conditions are
62810SN/A * met: redistributions of source code must retain the above copyright
72810SN/A * notice, this list of conditions and the following disclaimer;
82810SN/A * redistributions in binary form must reproduce the above copyright
92810SN/A * notice, this list of conditions and the following disclaimer in the
102810SN/A * documentation and/or other materials provided with the distribution;
112810SN/A * neither the name of the copyright holders nor the names of its
122810SN/A * contributors may be used to endorse or promote products derived from
132810SN/A * this software without specific prior written permission.
142810SN/A *
152810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
162810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
172810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
182810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
192810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
202810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
212810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
222810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
232810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
242810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
252810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
262810SN/A *
272810SN/A * Authors: Gabe Black
282810SN/A */
292810SN/A
302810SN/A#ifndef __SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__
312810SN/A#define __SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__
322810SN/A
332810SN/A#include <iostream>
342810SN/A#include <string>
352810SN/A#include <vector>
363348SN/A
373348SN/A#include "../core/sc_event.hh"
388232Snate@binkert.org#include "../core/sc_module.hh" // for sc_gen_unique_name
395338Sstever@gmail.com#include "../core/sc_prim.hh"
405338Sstever@gmail.com#include "../dt/bit/sc_logic.hh"
412810SN/A#include "sc_signal_inout_if.hh"
422810SN/A#include "warn_unimpl.hh" // for warn_unimpl
432810SN/A
444965SN/Anamespace sc_core
456122SSteve.Reinhardt@amd.com{
465314SN/A
475314SN/Aclass sc_port_base;
486122SSteve.Reinhardt@amd.comclass sc_trace_file;
492810SN/A
504475SN/A// Nonstandard
514475SN/A// Despite having a warning "FOR INTERNAL USE ONLY!" in all caps above this
524475SN/A// class definition in the Accellera implementation, it appears in their
535034SN/A// examples and test programs, and so we need to have it here as well.
545034SN/Astruct sc_trace_params
555314SN/A{
565314SN/A    sc_trace_file *tf;
574628SN/A    std::string name;
585034SN/A
595034SN/A    sc_trace_params(sc_trace_file *tf, const std::string &name) :
605034SN/A        tf(tf), name(name)
616122SSteve.Reinhardt@amd.com    {}
628134SAli.Saidi@ARM.com};
634626SN/Atypedef std::vector<sc_trace_params *> sc_trace_params_vec;
644626SN/A
655034SN/Atemplate <class T, sc_writer_policy WRITER_POLICY=SC_ONE_WRITER>
666122SSteve.Reinhardt@amd.comclass sc_signal : public sc_signal_inout_if<T>,
676978SLisa.Hsu@amd.com                  public sc_prim_channel
686978SLisa.Hsu@amd.com{
694458SN/A  public:
702810SN/A    sc_signal() : sc_signal_inout_if<T>(),
712810SN/A                  sc_prim_channel(sc_gen_unique_name("signal")),
722811SN/A                  m_cur_val(T()), m_new_val(T()), _changeStamp(~0ULL)
732810SN/A    {}
742810SN/A    explicit sc_signal(const char *name) :
754458SN/A        sc_signal_inout_if<T>(), sc_prim_channel(name),
764458SN/A        m_cur_val(T()), m_new_val(T()), _changeStamp(~0ULL)
774458SN/A    {}
782810SN/A    explicit sc_signal(const char *name, const T &initial_value) :
792810SN/A        sc_signal_inout_if<T>(), sc_prim_channel(name),
805314SN/A        m_cur_val(initial_value), m_new_val(initial_value), _changeStamp(~0ULL)
815314SN/A    {}
825314SN/A    virtual ~sc_signal() {}
835314SN/A
845314SN/A    virtual void
855314SN/A    register_port(sc_port_base &, const char *)
865314SN/A    {
875314SN/A        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
885314SN/A    }
895314SN/A
905314SN/A    virtual const T &read() const { return m_cur_val; }
916227Snate@binkert.org    operator const T&() const { return read(); }
926227Snate@binkert.org
932810SN/A    virtual sc_writer_policy
942810SN/A    get_writer_policy() const
952810SN/A    {
962810SN/A        return WRITER_POLICY;
973606SN/A    }
984458SN/A    virtual void
994458SN/A    write(const T &t)
1003013SN/A    {
1013236SN/A        m_new_val = t;
1024458SN/A        bool changed = !(m_cur_val == m_new_val);
1034458SN/A        //TODO check whether this write follows the write policy.
1044458SN/A        if (changed)
1053246SN/A            request_update();
1063309SN/A    }
1073013SN/A    sc_signal<T, WRITER_POLICY> &
1082810SN/A    operator = (const T &t)
1092810SN/A    {
1103013SN/A        write(t);
1113013SN/A        return *this;
1122810SN/A    }
1133013SN/A    sc_signal<T, WRITER_POLICY> &
1143013SN/A    operator = (const sc_signal<T, WRITER_POLICY> &s)
1152810SN/A    {
1162810SN/A        write(s.read());
1172810SN/A        return *this;
1182810SN/A    }
1192810SN/A
1203013SN/A    virtual const sc_event &
1213013SN/A    default_event() const
1223013SN/A    {
1232897SN/A        return value_changed_event();
1242897SN/A    }
1253013SN/A    virtual const sc_event &
1262897SN/A    value_changed_event() const
1274666SN/A    {
1284666SN/A        return _valueChangedEvent;
1298708Sandreas.hansson@arm.com    }
1302897SN/A    virtual bool
1312810SN/A    event() const
1322810SN/A    {
1332844SN/A        return _changeStamp == ::sc_gem5::getChangeStamp();
1342810SN/A    }
1352858SN/A
1362858SN/A    virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; }
1372858SN/A    virtual void
1382858SN/A    dump(std::ostream &os=std::cout) const
1392858SN/A    {
1402858SN/A        os << "     name = " << name() << ::std::endl;
1412858SN/A        os << "    value = " << m_cur_val << ::std::endl;
1424628SN/A        os << "new value = " << m_new_val << ::std::endl;
1432858SN/A    }
1442810SN/A    virtual const char *kind() const { return "sc_signal"; }
1452810SN/A
1462810SN/A  protected:
1472810SN/A    virtual void
1482810SN/A    update()
1494022SN/A    {
1504022SN/A        if (m_new_val == m_cur_val)
1514022SN/A            return;
1522810SN/A
1532810SN/A        m_cur_val = m_new_val;
1546978SLisa.Hsu@amd.com        _changeStamp = ::sc_gem5::getChangeStamp();
1556978SLisa.Hsu@amd.com        _valueChangedEvent.notify(SC_ZERO_TIME);
1566978SLisa.Hsu@amd.com    }
1576978SLisa.Hsu@amd.com
1586978SLisa.Hsu@amd.com    // These members which store the current and future value of the signal
1592810SN/A    // are not specified in the standard but are referred to directly by one
1602810SN/A    // of the tests.
1612810SN/A    T m_cur_val;
1622810SN/A    T m_new_val;
1632810SN/A
1642810SN/A  private:
1654871SN/A    sc_event _valueChangedEvent;
1664871SN/A    uint64_t _changeStamp;
1674871SN/A
1684871SN/A    // Disabled
1694871SN/A    sc_signal(const sc_signal<T, WRITER_POLICY> &) :
1704871SN/A            sc_signal_inout_if<T>(), sc_prim_channel("")
1714871SN/A    {}
1724871SN/A};
1734871SN/A
1744871SN/Atemplate <class T, sc_writer_policy WRITER_POLICY>
1752810SN/Ainline std::ostream &
1762810SN/Aoperator << (std::ostream &os, const sc_signal<T, WRITER_POLICY> &)
1772810SN/A{
1782810SN/A    sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
1792810SN/A    return os;
1804871SN/A}
1812810SN/A
1822810SN/Atemplate <sc_writer_policy WRITER_POLICY>
1832810SN/Aclass sc_signal<bool, WRITER_POLICY> :
1842810SN/A    public sc_signal_inout_if<bool>, public sc_prim_channel
1852810SN/A{
1862810SN/A  public:
1874871SN/A    sc_signal() : sc_signal_inout_if<bool>(),
1882810SN/A                  sc_prim_channel(sc_gen_unique_name("signal")),
1892810SN/A                  m_cur_val(bool()), m_new_val(bool()),
1904022SN/A                  _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
1914022SN/A    {}
1924022SN/A    explicit sc_signal(const char *name) :
1932810SN/A        sc_signal_inout_if<bool>(), sc_prim_channel(name),
1942810SN/A        m_cur_val(bool()), m_new_val(bool()),
1956978SLisa.Hsu@amd.com        _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
1966978SLisa.Hsu@amd.com    {}
1976978SLisa.Hsu@amd.com    explicit sc_signal(const char *name, const bool &initial_value) :
1986978SLisa.Hsu@amd.com        sc_signal_inout_if<bool>(), sc_prim_channel(name),
1996978SLisa.Hsu@amd.com        m_cur_val(initial_value), m_new_val(initial_value),
2002810SN/A        _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
2012810SN/A    {}
2022810SN/A    virtual ~sc_signal() {}
2032810SN/A
2042810SN/A    virtual void
2052810SN/A    register_port(sc_port_base &, const char *)
2062810SN/A    {
2072810SN/A        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
2082810SN/A    }
2092810SN/A
2102810SN/A    virtual const bool &read() const { return m_cur_val; }
2114871SN/A    operator const bool &() const { return read(); }
2122810SN/A
2132810SN/A    virtual sc_writer_policy
2142810SN/A    get_writer_policy() const
2152810SN/A    {
2162810SN/A        return WRITER_POLICY;
2172810SN/A    }
2184871SN/A    virtual void
2192810SN/A    write(const bool &b)
2202810SN/A    {
2214022SN/A        m_new_val = b;
2224022SN/A        bool changed = !(m_cur_val == m_new_val);
2234022SN/A        //TODO check whether this write follows the write policy.
2242810SN/A        if (changed)
2252810SN/A            request_update();
2262810SN/A    }
2272810SN/A    sc_signal<bool, WRITER_POLICY> &
2282810SN/A    operator = (const bool &b)
2292810SN/A    {
2302810SN/A        write(b);
2312810SN/A        return *this;
2322810SN/A    }
2332810SN/A    sc_signal<bool, WRITER_POLICY> &
2342810SN/A    operator = (const sc_signal<bool, WRITER_POLICY> &s)
2352810SN/A    {
2362810SN/A        write(s.read());
2372810SN/A        return *this;
2384871SN/A    }
2392810SN/A
2402810SN/A    virtual const sc_event &
2412810SN/A    default_event() const
2422810SN/A    {
2432810SN/A        return value_changed_event();
2442810SN/A    }
2454871SN/A
2462810SN/A    virtual const sc_event &
2472810SN/A    value_changed_event() const
2484022SN/A    {
2494022SN/A        return _valueChangedEvent;
2504022SN/A    }
2512810SN/A    virtual const sc_event &
2522810SN/A    posedge_event() const
2532810SN/A    {
2542810SN/A        return _posedgeEvent;
2552810SN/A    }
2562810SN/A    virtual const sc_event &
2572810SN/A    negedge_event() const
2582810SN/A    {
2592810SN/A        return _negedgeEvent;
2602810SN/A    }
2612810SN/A
2622810SN/A    virtual bool
2632810SN/A    event() const
2642810SN/A    {
2652810SN/A        return _changeStamp == ::sc_gem5::getChangeStamp();
2662810SN/A    }
2672810SN/A    virtual bool
2682810SN/A    posedge() const
2692810SN/A    {
2702810SN/A        return _posStamp == ::sc_gem5::getChangeStamp();
2712810SN/A    }
2722810SN/A    virtual bool
2732810SN/A    negedge() const
2742810SN/A    {
2752810SN/A        return _negStamp == ::sc_gem5::getChangeStamp();
2764022SN/A    }
2774022SN/A
2784022SN/A    virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; }
2792810SN/A    virtual void
2802810SN/A    dump(std::ostream &os=std::cout) const
2812810SN/A    {
2822810SN/A        os << "     name = " << name() << ::std::endl;
2832810SN/A        os << "    value = " << m_cur_val << ::std::endl;
2842810SN/A        os << "new value = " << m_new_val << ::std::endl;
2852810SN/A    }
2862810SN/A    virtual const char *kind() const { return "sc_signal"; }
2872810SN/A
2882810SN/A  protected:
2892810SN/A    virtual void
2902810SN/A    update()
2912810SN/A    {
2922810SN/A        if (m_new_val == m_cur_val)
2932810SN/A            return;
2942810SN/A
2952810SN/A        m_cur_val = m_new_val;
2962810SN/A        uint64_t change_stamp = ::sc_gem5::getChangeStamp();
2972810SN/A        _changeStamp = change_stamp;
2982810SN/A        _valueChangedEvent.notify(SC_ZERO_TIME);
2992810SN/A        if (m_cur_val) {
3002810SN/A            _posStamp = change_stamp;
3012810SN/A            _posedgeEvent.notify(SC_ZERO_TIME);
3022810SN/A        } else {
3032810SN/A            _negStamp = change_stamp;
3044022SN/A            _negedgeEvent.notify(SC_ZERO_TIME);
3054022SN/A        }
3064022SN/A    }
3072810SN/A
3082810SN/A    bool m_cur_val;
3092810SN/A    bool m_new_val;
3102810SN/A
3112810SN/A  private:
3122810SN/A    sc_event _valueChangedEvent;
3132810SN/A    sc_event _posedgeEvent;
3142810SN/A    sc_event _negedgeEvent;
3152810SN/A
3162810SN/A    uint64_t _changeStamp;
3172810SN/A    uint64_t _posStamp;
3182810SN/A    uint64_t _negStamp;
3192810SN/A
3202810SN/A    // Disabled
3212810SN/A    sc_signal(const sc_signal<bool, WRITER_POLICY> &) :
3222810SN/A            sc_signal_inout_if<bool>(), sc_prim_channel("")
3232810SN/A    {}
3242810SN/A};
3252810SN/A
3262810SN/Atemplate <sc_writer_policy WRITER_POLICY>
3272810SN/Aclass sc_signal<sc_dt::sc_logic, WRITER_POLICY> :
3282810SN/A    public sc_signal_inout_if<sc_dt::sc_logic>, public sc_prim_channel
3292810SN/A{
3302810SN/A  public:
3312810SN/A    sc_signal() : sc_signal_inout_if<sc_dt::sc_logic>(),
3322810SN/A                  sc_prim_channel(sc_gen_unique_name("signal")),
3332810SN/A                  m_cur_val(sc_dt::sc_logic()), m_new_val(sc_dt::sc_logic()),
3342810SN/A                  _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
3352810SN/A    {}
3362810SN/A    explicit sc_signal(const char *name) :
3372810SN/A        sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel(name),
3382810SN/A        m_cur_val(sc_dt::sc_logic()), m_new_val(sc_dt::sc_logic()),
3392810SN/A        _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
3402810SN/A    {}
3412810SN/A    explicit sc_signal(const char *name,
3422810SN/A            const sc_dt::sc_logic &initial_value) :
3432810SN/A        sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel(name),
3442810SN/A        m_cur_val(initial_value), m_new_val(initial_value),
3452810SN/A        _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
3462810SN/A    {}
3472810SN/A    virtual ~sc_signal() {}
3482810SN/A
3492810SN/A    virtual void
3502810SN/A    register_port(sc_port_base &, const char *)
3512810SN/A    {
3522810SN/A        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
3532810SN/A    }
3542810SN/A
3552810SN/A    virtual const sc_dt::sc_logic &read() const { return m_cur_val; }
3562810SN/A    operator const sc_dt::sc_logic &() const { return read(); }
3572810SN/A
3582810SN/A    virtual sc_writer_policy
3592810SN/A    get_writer_policy() const
3602810SN/A    {
3612810SN/A        return WRITER_POLICY;
3622810SN/A    }
3632810SN/A    virtual void
3642810SN/A    write(const sc_dt::sc_logic &l)
3652810SN/A    {
3662810SN/A        m_new_val = l;
3672826SN/A        bool changed = !(m_cur_val == m_new_val);
3684626SN/A        //TODO check whether this write follows the write policy.
3694626SN/A        if (changed)
3704626SN/A            request_update();
3714626SN/A    }
3724626SN/A    sc_signal<sc_dt::sc_logic, WRITER_POLICY> &
3734626SN/A    operator = (const sc_dt::sc_logic &l)
3744626SN/A    {
3754626SN/A        write(l);
3764626SN/A        return *this;
3774626SN/A    }
3784626SN/A    sc_signal<sc_dt::sc_logic, WRITER_POLICY> &
3794626SN/A    operator = (const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &s)
3804626SN/A    {
3814626SN/A        write(s.read());
3824626SN/A        return *this;
3834626SN/A    }
3844626SN/A
3854626SN/A    virtual const sc_event &
3864626SN/A    default_event() const
3874626SN/A    {
3884626SN/A        return value_changed_event();
3894626SN/A    }
3904626SN/A
3914626SN/A    virtual const sc_event &
3924626SN/A    value_changed_event() const
3934626SN/A    {
3944871SN/A        return _valueChangedEvent;
3954626SN/A    }
3964626SN/A    virtual const sc_event &
3974626SN/A    posedge_event() const
3984626SN/A    {
3994626SN/A        return _posedgeEvent;
4004626SN/A    }
4014871SN/A    virtual const sc_event &
4024626SN/A    negedge_event() const
4034626SN/A    {
4044626SN/A        return _negedgeEvent;
4054626SN/A    }
4064626SN/A
4074626SN/A    virtual bool
4084626SN/A    event() const
4094626SN/A    {
4104626SN/A        return _changeStamp == ::sc_gem5::getChangeStamp();
4114626SN/A    }
4124626SN/A    virtual bool
4134626SN/A    posedge() const
4144626SN/A    {
4154626SN/A        return _posStamp == ::sc_gem5::getChangeStamp();
4164626SN/A    }
4174626SN/A    virtual bool
4184626SN/A    negedge() const
4194626SN/A    {
4204626SN/A        return _negStamp == ::sc_gem5::getChangeStamp();
4214871SN/A    }
4224626SN/A
4234626SN/A    virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; }
4244626SN/A    virtual void
4254626SN/A    dump(std::ostream &os=std::cout) const
4264626SN/A    {
4274626SN/A        os << "     name = " << name() << ::std::endl;
4284871SN/A        os << "    value = " << m_cur_val << ::std::endl;
4294626SN/A        os << "new value = " << m_new_val << ::std::endl;
4304626SN/A    }
4314626SN/A    virtual const char *kind() const { return "sc_signal"; }
4324626SN/A
4334626SN/A  protected:
4344626SN/A    virtual void
4354626SN/A    update()
4364626SN/A    {
4374626SN/A        if (m_new_val == m_cur_val)
4384626SN/A            return;
4394626SN/A
4404626SN/A        m_cur_val = m_new_val;
4414626SN/A        _valueChangedEvent.notify(SC_ZERO_TIME);
4424626SN/A        if (m_cur_val == sc_dt::SC_LOGIC_1)
4434626SN/A            _posedgeEvent.notify(SC_ZERO_TIME);
4444626SN/A        else if (m_cur_val == sc_dt::SC_LOGIC_0)
4454626SN/A            _negedgeEvent.notify(SC_ZERO_TIME);
4464626SN/A    }
4474626SN/A
4484871SN/A    sc_dt::sc_logic m_cur_val;
4494626SN/A    sc_dt::sc_logic m_new_val;
4504626SN/A
4514626SN/A  private:
4524626SN/A    sc_event _valueChangedEvent;
4534626SN/A    sc_event _posedgeEvent;
4544626SN/A    sc_event _negedgeEvent;
4554871SN/A
4564871SN/A    uint64_t _changeStamp;
4574626SN/A    uint64_t _posStamp;
4584626SN/A    uint64_t _negStamp;
4594626SN/A
4604626SN/A    // Disabled
4614626SN/A    sc_signal(const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &) :
4624626SN/A            sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel("")
4634626SN/A    {}
4644626SN/A};
4654626SN/A
4664626SN/A} // namespace sc_core
4674626SN/A
4684626SN/A#endif  //__SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__
4694626SN/A