--- /dev/null
+/*
+ * Copyright 2018 Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#include <sstream>
+
+#include "systemc/core/scheduler.hh"
+#include "systemc/ext/channel/sc_signal.hh"
+#include "systemc/ext/core/sc_main.hh"
+
+namespace sc_gem5
+{
+
+ScSignalBase::ScSignalBase(const char *name) :
+ sc_core::sc_prim_channel(name), _changeStamp(~0ULL),
+ _gem5WriterPort(nullptr)
+{}
+
+ScSignalBase::~ScSignalBase() {}
+
+const sc_core::sc_event &
+ScSignalBase::defaultEvent() const
+{
+ return valueChangedEvent();
+}
+
+const sc_core::sc_event &
+ScSignalBase::valueChangedEvent() const
+{
+ return _valueChangedEvent;
+}
+
+bool
+ScSignalBase::event() const
+{
+ return _changeStamp == getChangeStamp();
+}
+
+void
+ScSignalBase::_signalChange()
+{
+ _changeStamp = getChangeStamp();
+ _valueChangedEvent.notify(sc_core::SC_ZERO_TIME);
+}
+
+namespace
+{
+
+void
+reportSignalError(ScSignalBase *sig, sc_core::sc_object *first,
+ sc_core::sc_object *second, bool delta_conflict=false)
+{
+ std::ostringstream ss;
+ ss << "\n signal " << "`" << sig->name() << "' (" << sig->kind() << ")";
+ ss << "\n first driver `" << first->name() << "' (" <<
+ first->kind() << ")";
+ ss << "\n second driver `" << second->name() << "' (" <<
+ second->kind() << ")";
+ if (delta_conflict) {
+ ss << "\n conflicting write in delta cycle " <<
+ sc_core::sc_delta_count();
+ }
+ SC_REPORT_ERROR(
+ "(E115) sc_signal<T> cannot have more than one driver",
+ ss.str().c_str());
+}
+
+} // anonymous namespace
+
+WriteChecker<sc_core::SC_ONE_WRITER>::WriteChecker(ScSignalBase *_sig) :
+ sig(_sig), firstPort(nullptr), proc(nullptr), writeStamp(~0ULL)
+{}
+
+void
+WriteChecker<sc_core::SC_ONE_WRITER>::checkPort(sc_core::sc_port_base &port,
+ std::string iface_type_name, std::string out_name)
+{
+ if (iface_type_name == out_name) {
+ if (firstPort)
+ reportSignalError(sig, firstPort, &port);
+ firstPort = &port;
+ }
+}
+
+void
+WriteChecker<sc_core::SC_ONE_WRITER>::checkWriter()
+{
+ Process *p = scheduler.current();
+ if (!p)
+ return;
+ uint64_t stamp = getChangeStamp();
+ if (proc && proc != p)
+ reportSignalError(sig, proc, p);
+ proc = p;
+ writeStamp = stamp;
+}
+
+WriteChecker<sc_core::SC_MANY_WRITERS>::WriteChecker(ScSignalBase *_sig) :
+ sig(_sig), proc(nullptr), writeStamp(~0ULL)
+{}
+
+void
+WriteChecker<sc_core::SC_MANY_WRITERS>::checkPort(sc_core::sc_port_base &port,
+ std::string iface_type_name, std::string out_name)
+{
+ return;
+}
+
+void
+WriteChecker<sc_core::SC_MANY_WRITERS>::checkWriter()
+{
+ Process *p = scheduler.current();
+ if (!p)
+ return;
+ uint64_t stamp = getChangeStamp();
+ if (writeStamp == stamp && proc && proc != p)
+ reportSignalError(sig, proc, p, writeStamp == stamp);
+ proc = p;
+ writeStamp = stamp;
+}
+
+ScSignalBaseBinary::ScSignalBaseBinary(const char *_name) :
+ ScSignalBase(_name), _posStamp(~0ULL), _negStamp(~0ULL)
+{}
+
+const sc_core::sc_event &
+ScSignalBaseBinary::posedgeEvent() const
+{
+ return _posedgeEvent;
+}
+
+const sc_core::sc_event &
+ScSignalBaseBinary::negedgeEvent() const
+{
+ return _negedgeEvent;
+}
+
+bool
+ScSignalBaseBinary::posedge() const
+{
+ return _posStamp == getChangeStamp();
+}
+bool
+
+ScSignalBaseBinary::negedge() const
+{
+ return _negStamp == getChangeStamp();
+}
+
+} // namespace sc_gem5
#define __SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__
#include <iostream>
-#include <sstream>
#include <string>
#include <vector>
class sc_port_base;
-template <class T, sc_writer_policy WRITER_POLICY=SC_ONE_WRITER>
-class sc_signal : public sc_signal_inout_if<T>,
- public sc_prim_channel
+} // namespace sc_core
+
+namespace sc_gem5
+{
+
+class Process;
+
+class ScSignalBase : public sc_core::sc_prim_channel
{
public:
- sc_signal() : sc_signal_inout_if<T>(),
- sc_prim_channel(sc_gen_unique_name("signal")),
- m_cur_val(T()), m_new_val(T()), _changeStamp(~0ULL),
- _gem5Writer(NULL)
- {}
- explicit sc_signal(const char *name) :
- sc_signal_inout_if<T>(), sc_prim_channel(name),
- m_cur_val(T()), m_new_val(T()), _changeStamp(~0ULL),
- _gem5Writer(NULL)
+ virtual const char *kind() const { return "sc_signal"; }
+
+ protected:
+ ScSignalBase(const char *_name);
+ virtual ~ScSignalBase();
+
+ const sc_core::sc_event &defaultEvent() const;
+ const sc_core::sc_event &valueChangedEvent() const;
+
+ bool event() const;
+
+ void _signalChange();
+
+ virtual sc_core::sc_writer_policy get_writer_policy() const = 0;
+
+ sc_core::sc_event _valueChangedEvent;
+ uint64_t _changeStamp;
+ sc_core::sc_port_base *_gem5WriterPort;
+};
+
+class ScSignalBaseBinary : public ScSignalBase
+{
+ protected:
+ ScSignalBaseBinary(const char *_name);
+
+ const sc_core::sc_event &posedgeEvent() const;
+ const sc_core::sc_event &negedgeEvent() const;
+
+ bool posedge() const;
+ bool negedge() const;
+
+ sc_core::sc_event _posedgeEvent;
+ sc_core::sc_event _negedgeEvent;
+
+ uint64_t _posStamp;
+ uint64_t _negStamp;
+};
+
+template <class T>
+class ScSignalBasePicker : public ScSignalBase
+{
+ protected:
+ ScSignalBasePicker(const char *_name) : ScSignalBase(_name) {}
+};
+
+template <>
+class ScSignalBasePicker<bool> : public ScSignalBaseBinary
+{
+ protected:
+ ScSignalBasePicker(const char *_name) : ScSignalBaseBinary(_name) {}
+};
+
+template <>
+class ScSignalBasePicker<sc_dt::sc_logic> : public ScSignalBaseBinary
+{
+ protected:
+ ScSignalBasePicker(const char *_name) : ScSignalBaseBinary(_name) {}
+};
+
+template <sc_core::sc_writer_policy WRITER_POLICY>
+class WriteChecker;
+
+template <>
+class WriteChecker<sc_core::SC_ONE_WRITER>
+{
+ public:
+ WriteChecker(ScSignalBase *_sig);
+
+ void checkPort(sc_core::sc_port_base &port,
+ std::string iface_type_name, std::string out_name);
+ void checkWriter();
+
+ private:
+ ScSignalBase *sig;
+ sc_core::sc_port_base *firstPort;
+ Process *proc;
+ uint64_t writeStamp;
+};
+
+template <>
+class WriteChecker<sc_core::SC_MANY_WRITERS>
+{
+ public:
+ WriteChecker(ScSignalBase *_sig);
+
+ void checkPort(sc_core::sc_port_base &port,
+ std::string iface_type_name, std::string out_name);
+ void checkWriter();
+
+ private:
+ ScSignalBase *sig;
+ Process *proc;
+ uint64_t writeStamp;
+};
+
+template <class T, sc_core::sc_writer_policy WRITER_POLICY>
+class ScSignalBaseT :
+ public ScSignalBasePicker<T>, public sc_core::sc_signal_inout_if<T>
+{
+ public:
+ ScSignalBaseT(const char *_name) :
+ ScSignalBasePicker<T>(_name), m_cur_val(T()), m_new_val(T()),
+ _checker(this)
{}
- explicit sc_signal(const char *name, const T &initial_value) :
- sc_signal_inout_if<T>(), sc_prim_channel(name),
- m_cur_val(initial_value), m_new_val(initial_value),
- _changeStamp(~0ULL), _gem5Writer(NULL)
+ ScSignalBaseT(const char *_name, const T &initial_value) :
+ ScSignalBasePicker<T>(_name), m_cur_val(initial_value),
+ m_new_val(initial_value), _checker(this)
{}
- virtual ~sc_signal() {}
+ virtual ~ScSignalBaseT() {}
virtual void
- register_port(sc_port_base &port, const char *iface_type_name)
+ register_port(sc_core::sc_port_base &port, const char *iface_type_name)
{
- if (WRITER_POLICY == SC_ONE_WRITER &&
- std::string(iface_type_name) ==
- typeid(sc_signal_inout_if<T>).name()) {
- if (_gem5Writer) {
- std::ostringstream ss;
- ss << "\n signal " << "`" << name() << "' (" <<
- kind() << ")";
- ss << "\n first driver `" << _gem5Writer->name() << "' (" <<
- _gem5Writer->kind() << ")";
- ss << "\n second driver `" << port.name() << "' (" <<
- port.kind() << ")";
- SC_REPORT_ERROR(
- "(E115) sc_signal<T> cannot have more than one driver",
- ss.str().c_str());
- }
- _gem5Writer = &port;
+# if !defined(SC_NO_WRITE_CHECK)
+ {
+ _checker.checkPort(port, iface_type_name,
+ typeid(sc_core::sc_signal_inout_if<T>).name());
}
+# endif
}
virtual const T &read() const { return m_cur_val; }
operator const T&() const { return read(); }
- virtual sc_writer_policy
- get_writer_policy() const
- {
- return WRITER_POLICY;
- }
virtual void
write(const T &t)
{
+# if !defined(SC_NO_WRITE_CHECK)
+ {
+ _checker.checkWriter();
+ }
+# endif
m_new_val = t;
bool changed = !(m_cur_val == m_new_val);
- //TODO check whether this write follows the write policy.
if (changed)
- request_update();
- }
- sc_signal<T, WRITER_POLICY> &
- operator = (const T &t)
- {
- write(t);
- return *this;
- }
- sc_signal<T, WRITER_POLICY> &
- operator = (const sc_signal<T, WRITER_POLICY> &s)
- {
- write(s.read());
- return *this;
+ this->request_update();
}
- virtual const sc_event &
+ virtual const sc_core::sc_event &
default_event() const
{
- return value_changed_event();
+ return ScSignalBase::defaultEvent();
}
- virtual const sc_event &
+
+ virtual const sc_core::sc_event &
value_changed_event() const
{
- return _valueChangedEvent;
- }
- virtual bool
- event() const
- {
- return _changeStamp == ::sc_gem5::getChangeStamp();
+ return ScSignalBase::valueChangedEvent();
}
virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; }
virtual void
dump(std::ostream &os=std::cout) const
{
- os << " name = " << name() << ::std::endl;
+ os << " name = " << this->name() << ::std::endl;
os << " value = " << m_cur_val << ::std::endl;
os << "new value = " << m_new_val << ::std::endl;
}
- virtual const char *kind() const { return "sc_signal"; }
-
- protected:
- virtual void
- update()
- {
- if (m_new_val == m_cur_val)
- return;
- m_cur_val = m_new_val;
- _signalChange();
- _changeStamp = ::sc_gem5::getChangeStamp();
- _valueChangedEvent.notify(SC_ZERO_TIME);
- }
+ virtual bool event() const { return ScSignalBase::event(); }
- void
- _signalChange()
+ virtual sc_core::sc_writer_policy
+ get_writer_policy() const
{
- _changeStamp = ::sc_gem5::getChangeStamp();
- _valueChangedEvent.notify(SC_ZERO_TIME);
+ return WRITER_POLICY;
}
+ protected:
// These members which store the current and future value of the signal
// are not specified in the standard but are referred to directly by one
// of the tests.
T m_cur_val;
T m_new_val;
- private:
- sc_event _valueChangedEvent;
- uint64_t _changeStamp;
- sc_port_base *_gem5Writer;
+ WriteChecker<WRITER_POLICY> _checker;
+};
- // Disabled
- sc_signal(const sc_signal<T, WRITER_POLICY> &) :
- sc_signal_inout_if<T>(), sc_prim_channel("")
+template <typename T, sc_core::sc_writer_policy WRITER_POLICY>
+class ScSignalBinary : public ScSignalBaseT<T, WRITER_POLICY>
+{
+ public:
+ ScSignalBinary(const char *_name) : ScSignalBaseT<T, WRITER_POLICY>(_name)
+ {}
+ ScSignalBinary(const char *_name, const T& initial_value) :
+ ScSignalBaseT<T, WRITER_POLICY>(_name, initial_value)
{}
+
+ const sc_core::sc_event &
+ posedge_event() const
+ {
+ return ScSignalBaseBinary::posedgeEvent();
+ }
+ const sc_core::sc_event &
+ negedge_event() const
+ {
+ return ScSignalBaseBinary::negedgeEvent();
+ }
+
+ bool posedge() const { return ScSignalBaseBinary::posedge(); }
+ bool negedge() const { return ScSignalBaseBinary::negedge(); }
+};
+
+} // namespace sc_gem5
+
+namespace sc_core
+{
+
+template <class T, sc_writer_policy WRITER_POLICY=SC_ONE_WRITER>
+class sc_signal : public sc_gem5::ScSignalBaseT<T, WRITER_POLICY>
+{
+ public:
+ sc_signal() : sc_gem5::ScSignalBaseT<T, WRITER_POLICY>(
+ sc_gen_unique_name("signal"))
+ {}
+ explicit sc_signal(const char *name) :
+ sc_gem5::ScSignalBaseT<T, WRITER_POLICY>(name)
+ {}
+ explicit sc_signal(const char *name, const T &initial_value) :
+ sc_gem5::ScSignalBaseT<T, WRITER_POLICY>(name, initial_value)
+ {}
+ virtual ~sc_signal() {}
+
+ sc_signal<T, WRITER_POLICY> &
+ operator = (const T &t)
+ {
+ this->write(t);
+ return *this;
+ }
+ sc_signal<T, WRITER_POLICY> &
+ operator = (const sc_signal<T, WRITER_POLICY> &s)
+ {
+ this->write(s.read());
+ return *this;
+ }
+
+ protected:
+ virtual void
+ update()
+ {
+ if (this->m_new_val == this->m_cur_val)
+ return;
+
+ this->m_cur_val = this->m_new_val;
+ this->_signalChange();
+ }
+
+ private:
+ // Disabled
+ sc_signal(const sc_signal<T, WRITER_POLICY> &);
};
template <class T, sc_writer_policy WRITER_POLICY>
template <sc_writer_policy WRITER_POLICY>
class sc_signal<bool, WRITER_POLICY> :
- public sc_signal_inout_if<bool>, public sc_prim_channel
+ public sc_gem5::ScSignalBinary<bool, WRITER_POLICY>
{
public:
- sc_signal() : sc_signal_inout_if<bool>(),
- sc_prim_channel(sc_gen_unique_name("signal")),
- m_cur_val(bool()), m_new_val(bool()),
- _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL),
- _gem5Writer(NULL)
+ sc_signal() :
+ sc_gem5::ScSignalBinary<bool, WRITER_POLICY>(
+ sc_gen_unique_name("signal"))
{}
explicit sc_signal(const char *name) :
- sc_signal_inout_if<bool>(), sc_prim_channel(name),
- m_cur_val(bool()), m_new_val(bool()),
- _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL),
- _gem5Writer(NULL)
+ sc_gem5::ScSignalBinary<bool, WRITER_POLICY>(name)
{}
explicit sc_signal(const char *name, const bool &initial_value) :
- sc_signal_inout_if<bool>(), sc_prim_channel(name),
- m_cur_val(initial_value), m_new_val(initial_value),
- _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL),
- _gem5Writer(NULL)
+ sc_gem5::ScSignalBinary<bool, WRITER_POLICY>(name, initial_value)
{}
virtual ~sc_signal() {}
- virtual void
- register_port(sc_port_base &port, const char *iface_type_name)
- {
- if (WRITER_POLICY == SC_ONE_WRITER &&
- std::string(iface_type_name) ==
- typeid(sc_signal_inout_if<bool>).name()) {
- if (_gem5Writer) {
- std::ostringstream ss;
- ss << "\n signal " << "`" << name() << "' (" <<
- kind() << ")";
- ss << "\n first driver `" << _gem5Writer->name() << "' (" <<
- _gem5Writer->kind() << ")";
- ss << "\n second driver `" << port.name() << "' (" <<
- port.kind() << ")";
- SC_REPORT_ERROR(
- "(E115) sc_signal<T> cannot have more than one driver",
- ss.str().c_str());
- }
- _gem5Writer = &port;
- }
- }
-
- virtual const bool &read() const { return m_cur_val; }
- operator const bool &() const { return read(); }
-
- virtual sc_writer_policy
- get_writer_policy() const
- {
- return WRITER_POLICY;
- }
- virtual void
- write(const bool &b)
- {
- m_new_val = b;
- bool changed = !(m_cur_val == m_new_val);
- //TODO check whether this write follows the write policy.
- if (changed)
- request_update();
- }
sc_signal<bool, WRITER_POLICY> &
operator = (const bool &b)
{
- write(b);
+ this->write(b);
return *this;
}
sc_signal<bool, WRITER_POLICY> &
operator = (const sc_signal<bool, WRITER_POLICY> &s)
{
- write(s.read());
+ this->write(s.read());
return *this;
}
- virtual const sc_event &
- default_event() const
- {
- return value_changed_event();
- }
-
- virtual const sc_event &
- value_changed_event() const
- {
- return _valueChangedEvent;
- }
- virtual const sc_event &
- posedge_event() const
- {
- return _posedgeEvent;
- }
- virtual const sc_event &
- negedge_event() const
- {
- return _negedgeEvent;
- }
-
- virtual bool
- event() const
- {
- return _changeStamp == ::sc_gem5::getChangeStamp();
- }
- virtual bool
- posedge() const
- {
- return _posStamp == ::sc_gem5::getChangeStamp();
- }
- virtual bool
- negedge() const
- {
- return _negStamp == ::sc_gem5::getChangeStamp();
- }
-
- virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; }
- virtual void
- dump(std::ostream &os=std::cout) const
- {
- os << " name = " << name() << ::std::endl;
- os << " value = " << m_cur_val << ::std::endl;
- os << "new value = " << m_new_val << ::std::endl;
- }
- virtual const char *kind() const { return "sc_signal"; }
-
protected:
virtual void
update()
{
- if (m_new_val == m_cur_val)
+ if (this->m_new_val == this->m_cur_val)
return;
- m_cur_val = m_new_val;
- _signalChange();
- if (m_cur_val) {
- _posStamp = ::sc_gem5::getChangeStamp();
- _posedgeEvent.notify(SC_ZERO_TIME);
+ this->m_cur_val = this->m_new_val;
+ this->_signalChange();
+ if (this->m_cur_val) {
+ this->_posStamp = ::sc_gem5::getChangeStamp();
+ this->_posedgeEvent.notify(SC_ZERO_TIME);
} else {
- _negStamp = ::sc_gem5::getChangeStamp();
- _negedgeEvent.notify(SC_ZERO_TIME);
+ this->_negStamp = ::sc_gem5::getChangeStamp();
+ this->_negedgeEvent.notify(SC_ZERO_TIME);
}
}
- void
- _signalChange()
- {
- _changeStamp = ::sc_gem5::getChangeStamp();
- _valueChangedEvent.notify(SC_ZERO_TIME);
- }
-
- bool m_cur_val;
- bool m_new_val;
-
private:
- sc_event _valueChangedEvent;
- sc_event _posedgeEvent;
- sc_event _negedgeEvent;
-
- uint64_t _changeStamp;
- uint64_t _posStamp;
- uint64_t _negStamp;
-
- sc_port_base *_gem5Writer;
-
// Disabled
- sc_signal(const sc_signal<bool, WRITER_POLICY> &) :
- sc_signal_inout_if<bool>(), sc_prim_channel("")
- {}
+ sc_signal(const sc_signal<bool, WRITER_POLICY> &);
};
template <sc_writer_policy WRITER_POLICY>
class sc_signal<sc_dt::sc_logic, WRITER_POLICY> :
- public sc_signal_inout_if<sc_dt::sc_logic>, public sc_prim_channel
+ public sc_gem5::ScSignalBinary<sc_dt::sc_logic, WRITER_POLICY>
{
public:
- sc_signal() : sc_signal_inout_if<sc_dt::sc_logic>(),
- sc_prim_channel(sc_gen_unique_name("signal")),
- m_cur_val(sc_dt::sc_logic()), m_new_val(sc_dt::sc_logic()),
- _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL),
- _gem5Writer(NULL)
+ sc_signal() :
+ sc_gem5::ScSignalBinary<sc_dt::sc_logic, WRITER_POLICY>(
+ sc_gen_unique_name("signal"))
{}
explicit sc_signal(const char *name) :
- sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel(name),
- m_cur_val(sc_dt::sc_logic()), m_new_val(sc_dt::sc_logic()),
- _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL),
- _gem5Writer(NULL)
+ sc_gem5::ScSignalBinary<sc_dt::sc_logic, WRITER_POLICY>(name)
{}
explicit sc_signal(const char *name,
const sc_dt::sc_logic &initial_value) :
- sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel(name),
- m_cur_val(initial_value), m_new_val(initial_value),
- _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL),
- _gem5Writer(NULL)
+ sc_gem5::ScSignalBinary<sc_dt::sc_logic, WRITER_POLICY>(
+ name, initial_value)
{}
virtual ~sc_signal() {}
- virtual void
- register_port(sc_port_base &port, const char *iface_type_name)
- {
- if (WRITER_POLICY == SC_ONE_WRITER &&
- std::string(iface_type_name) ==
- typeid(sc_signal_inout_if<sc_dt::sc_logic>).name()) {
- if (_gem5Writer) {
- std::ostringstream ss;
- ss << "\n signal " << "`" << name() << "' (" <<
- kind() << ")";
- ss << "\n first driver `" << _gem5Writer->name() << "' (" <<
- _gem5Writer->kind() << ")";
- ss << "\n second driver `" << port.name() << "' (" <<
- port.kind() << ")";
- SC_REPORT_ERROR(
- "(E115) sc_signal<T> cannot have more than one driver",
- ss.str().c_str());
- }
- _gem5Writer = &port;
- }
- }
-
- virtual const sc_dt::sc_logic &read() const { return m_cur_val; }
- operator const sc_dt::sc_logic &() const { return read(); }
-
- virtual sc_writer_policy
- get_writer_policy() const
- {
- return WRITER_POLICY;
- }
- virtual void
- write(const sc_dt::sc_logic &l)
- {
- m_new_val = l;
- bool changed = !(m_cur_val == m_new_val);
- //TODO check whether this write follows the write policy.
- if (changed)
- request_update();
- }
sc_signal<sc_dt::sc_logic, WRITER_POLICY> &
operator = (const sc_dt::sc_logic &l)
{
- write(l);
+ this->write(l);
return *this;
}
sc_signal<sc_dt::sc_logic, WRITER_POLICY> &
operator = (const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &s)
{
- write(s.read());
+ this->write(s.read());
return *this;
}
- virtual const sc_event &
- default_event() const
- {
- return value_changed_event();
- }
-
- virtual const sc_event &
- value_changed_event() const
- {
- return _valueChangedEvent;
- }
- virtual const sc_event &
- posedge_event() const
- {
- return _posedgeEvent;
- }
- virtual const sc_event &
- negedge_event() const
- {
- return _negedgeEvent;
- }
-
- virtual bool
- event() const
- {
- return _changeStamp == ::sc_gem5::getChangeStamp();
- }
- virtual bool
- posedge() const
- {
- return _posStamp == ::sc_gem5::getChangeStamp();
- }
- virtual bool
- negedge() const
- {
- return _negStamp == ::sc_gem5::getChangeStamp();
- }
-
- virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; }
- virtual void
- dump(std::ostream &os=std::cout) const
- {
- os << " name = " << name() << ::std::endl;
- os << " value = " << m_cur_val << ::std::endl;
- os << "new value = " << m_new_val << ::std::endl;
- }
- virtual const char *kind() const { return "sc_signal"; }
-
protected:
virtual void
update()
{
- if (m_new_val == m_cur_val)
+ if (this->m_new_val == this->m_cur_val)
return;
- m_cur_val = m_new_val;
- _signalChange();
- if (m_cur_val == sc_dt::SC_LOGIC_1) {
- _posStamp = ::sc_gem5::getChangeStamp();
- _posedgeEvent.notify(SC_ZERO_TIME);
- } else if (m_cur_val == sc_dt::SC_LOGIC_0) {
- _negStamp = ::sc_gem5::getChangeStamp();
- _negedgeEvent.notify(SC_ZERO_TIME);
+ this->m_cur_val = this->m_new_val;
+ this->_signalChange();
+ if (this->m_cur_val == sc_dt::SC_LOGIC_1) {
+ this->_posStamp = ::sc_gem5::getChangeStamp();
+ this->_posedgeEvent.notify(SC_ZERO_TIME);
+ } else if (this->m_cur_val == sc_dt::SC_LOGIC_0) {
+ this->_negStamp = ::sc_gem5::getChangeStamp();
+ this->_negedgeEvent.notify(SC_ZERO_TIME);
}
}
- void
- _signalChange()
- {
- _changeStamp = ::sc_gem5::getChangeStamp();
- _valueChangedEvent.notify(SC_ZERO_TIME);
- }
-
- sc_dt::sc_logic m_cur_val;
- sc_dt::sc_logic m_new_val;
-
private:
- sc_event _valueChangedEvent;
- sc_event _posedgeEvent;
- sc_event _negedgeEvent;
-
- uint64_t _changeStamp;
- uint64_t _posStamp;
- uint64_t _negStamp;
-
- sc_port_base *_gem5Writer;
-
// Disabled
- sc_signal(const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &) :
- sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel("")
- {}
+ sc_signal(const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &);
};
} // namespace sc_core