diff options
-rw-r--r-- | src/systemc/channel/sc_clock.cc | 151 | ||||
-rw-r--r-- | src/systemc/ext/channel/sc_clock.hh | 22 |
2 files changed, 120 insertions, 53 deletions
diff --git a/src/systemc/channel/sc_clock.cc b/src/systemc/channel/sc_clock.cc index 65f1f100d..6736e57cf 100644 --- a/src/systemc/channel/sc_clock.cc +++ b/src/systemc/channel/sc_clock.cc @@ -28,94 +28,141 @@ */ #include "base/logging.hh" +#include "base/types.hh" +#include "sim/core.hh" +#include "sim/eventq.hh" +#include "systemc/core/kernel.hh" +#include "systemc/core/sched_event.hh" +#include "systemc/core/scheduler.hh" #include "systemc/ext/channel/sc_clock.hh" #include "systemc/ext/core/sc_module.hh" // for sc_gen_unique_name -namespace sc_core +namespace sc_gem5 { -sc_clock::sc_clock() : - sc_interface(), sc_signal<bool>(sc_gen_unique_name("clock")) +class ClockTick : public ScEvent { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); -} + private: + ::sc_core::sc_clock *clock; + ::sc_core::sc_time _period; + std::string _name; + Process *p; + ProcessMemberFuncWrapper<::sc_core::sc_clock> funcWrapper; + std::string _procName; + + public: + ClockTick(::sc_core::sc_clock *clock, bool to, + ::sc_core::sc_time _period) : + ScEvent([this]() { tick(); }), + clock(clock), _period(_period), _name(clock->name()), + funcWrapper(clock, to ? &::sc_core::sc_clock::tickUp : + &::sc_core::sc_clock::tickDown) + { + _name += (to ? ".up_tick" : ".down_tick"); + _procName = _name + ".p"; + p = newMethodProcess(_procName.c_str(), &funcWrapper); + scheduler.dontInitialize(p); + } + + ~ClockTick() + { + if (scheduled()) + scheduler.deschedule(this); + p->popListNode(); + } + + void + tick() + { + scheduler.schedule(this, _period); + p->ready(); + } +}; + +}; -sc_clock::sc_clock(const char *name) : sc_interface(), sc_signal<bool>(name) +namespace sc_core { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); -} + +sc_clock::sc_clock() : + sc_clock(sc_gen_unique_name("clock"), sc_time(1.0, SC_NS), + 0.5, SC_ZERO_TIME, true) +{} + +sc_clock::sc_clock(const char *name) : + sc_clock(name, sc_time(1.0, SC_NS), 0.5, SC_ZERO_TIME, true) +{} sc_clock::sc_clock(const char *name, const sc_time &period, double duty_cycle, const sc_time &start_time, - bool posedge_first) + bool posedge_first) : + sc_interface(), sc_signal<bool>(name, posedge_first ? false : true), + _period(period), _dutyCycle(duty_cycle), _startTime(start_time), + _posedgeFirst(posedge_first) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + _gem5UpEdge = new ::sc_gem5::ClockTick(this, true, period); + _gem5DownEdge = new ::sc_gem5::ClockTick(this, false, period); } sc_clock::sc_clock(const char *name, double period_v, sc_time_unit period_tu, - double duty_cycle) -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); -} + double duty_cycle) : + sc_clock(name, sc_time(period_v, period_tu), duty_cycle, SC_ZERO_TIME, + true) +{} sc_clock::sc_clock(const char *name, double period_v, sc_time_unit period_tu, double duty_cycle, double start_time_v, - sc_time_unit start_time_tu, bool posedge_first) -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); -} + sc_time_unit start_time_tu, bool posedge_first) : + sc_clock(name, sc_time(period_v, period_tu), duty_cycle, + sc_time(start_time_v, start_time_tu), posedge_first) +{} sc_clock::sc_clock(const char *name, double period, double duty_cycle, - double start_time, bool posedge_first) + double start_time, bool posedge_first) : + sc_clock(name, sc_time(period, true), duty_cycle, + sc_time(start_time, true), posedge_first) +{} + +sc_clock::~sc_clock() { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + if (_gem5UpEdge->scheduled()) + ::sc_gem5::scheduler.deschedule(_gem5UpEdge); + if (_gem5DownEdge->scheduled()) + ::sc_gem5::scheduler.deschedule(_gem5DownEdge); + delete _gem5UpEdge; + delete _gem5DownEdge; } -sc_clock::~sc_clock() {} - void sc_clock::write(const bool &) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); -} - -const sc_time & -sc_clock::period() const -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return *(const sc_time *)nullptr; + panic("write() called on sc_clock."); } -double -sc_clock::duty_cycle() const -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return 0.0; -} +const sc_time &sc_clock::period() const { return _period; } +double sc_clock::duty_cycle() const { return _dutyCycle; } +const sc_time &sc_clock::start_time() const { return _startTime; } +bool sc_clock::posedge_first() const { return _posedgeFirst; } const sc_time & -sc_clock::start_time() const +sc_clock::time_stamp() { warn("%s not implemented.\n", __PRETTY_FUNCTION__); return *(const sc_time *)nullptr; } -bool -sc_clock::posedge_first() const -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return false; -} - -const sc_time & -sc_clock::time_stamp() +void +sc_clock::before_end_of_elaboration() { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return *(const sc_time *)nullptr; + if (_posedgeFirst) { + ::sc_gem5::scheduler.schedule(_gem5UpEdge, _startTime); + ::sc_gem5::scheduler.schedule(_gem5DownEdge, + _startTime + _period * _dutyCycle); + } else { + ::sc_gem5::scheduler.schedule(_gem5DownEdge, _startTime); + ::sc_gem5::scheduler.schedule(_gem5UpEdge, + _startTime + _period * (1.0 - _dutyCycle)); + } } -const char *sc_clock::kind() const { return "sc_clock"; } - -void sc_clock::before_end_of_elaboration() {} - } // namespace sc_core diff --git a/src/systemc/ext/channel/sc_clock.hh b/src/systemc/ext/channel/sc_clock.hh index 30895ced2..3713394b6 100644 --- a/src/systemc/ext/channel/sc_clock.hh +++ b/src/systemc/ext/channel/sc_clock.hh @@ -33,6 +33,13 @@ #include "../core/sc_time.hh" #include "sc_signal.hh" +namespace sc_gem5 +{ + +class ClockTick; + +} // namespace sc_gem5 + namespace sc_core { @@ -74,15 +81,28 @@ class sc_clock : public sc_signal<bool> // Nonstandard static const sc_time &time_stamp(); - virtual const char *kind() const; + virtual const char *kind() const { return "sc_clock"; } protected: virtual void before_end_of_elaboration(); private: + friend class ::sc_gem5::ClockTick; + // Disabled sc_clock(const sc_clock &) : sc_interface(), sc_signal<bool>() {} sc_clock &operator = (const sc_clock &) { return *this; } + + sc_time _period; + double _dutyCycle; + sc_time _startTime; + bool _posedgeFirst; + + ::sc_gem5::ClockTick *_gem5UpEdge; + ::sc_gem5::ClockTick *_gem5DownEdge; + + void tickUp() { sc_signal<bool>::write(true); } + void tickDown() { sc_signal<bool>::write(false); } }; typedef sc_in<bool> sc_in_clk; |