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