systemc: Implement a significant portion of sc_clock.
Change-Id: Ic195f46ac13b46a02c86a5fc8d90ba66a415a9c8 Reviewed-on: https://gem5-review.googlesource.com/12215 Reviewed-by: Gabe Black <gabeblack@google.com> Maintainer: Gabe Black <gabeblack@google.com>
This commit is contained in:
@@ -28,84 +28,121 @@
|
||||
*/
|
||||
|
||||
#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_gem5
|
||||
{
|
||||
|
||||
class ClockTick : public ScEvent
|
||||
{
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
namespace sc_core
|
||||
{
|
||||
|
||||
sc_clock::sc_clock() :
|
||||
sc_interface(), sc_signal<bool>(sc_gen_unique_name("clock"))
|
||||
{
|
||||
warn("%s not implemented.\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
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_interface(), sc_signal<bool>(name)
|
||||
{
|
||||
warn("%s not implemented.\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
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)
|
||||
{
|
||||
warn("%s not implemented.\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
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() {}
|
||||
sc_clock::~sc_clock()
|
||||
{
|
||||
if (_gem5UpEdge->scheduled())
|
||||
::sc_gem5::scheduler.deschedule(_gem5UpEdge);
|
||||
if (_gem5DownEdge->scheduled())
|
||||
::sc_gem5::scheduler.deschedule(_gem5DownEdge);
|
||||
delete _gem5UpEdge;
|
||||
delete _gem5DownEdge;
|
||||
}
|
||||
|
||||
void
|
||||
sc_clock::write(const bool &)
|
||||
{
|
||||
warn("%s not implemented.\n", __PRETTY_FUNCTION__);
|
||||
panic("write() called on sc_clock.");
|
||||
}
|
||||
|
||||
const sc_time &
|
||||
sc_clock::period() const
|
||||
{
|
||||
warn("%s not implemented.\n", __PRETTY_FUNCTION__);
|
||||
return *(const sc_time *)nullptr;
|
||||
}
|
||||
|
||||
double
|
||||
sc_clock::duty_cycle() const
|
||||
{
|
||||
warn("%s not implemented.\n", __PRETTY_FUNCTION__);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
const sc_time &
|
||||
sc_clock::start_time() const
|
||||
{
|
||||
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::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::time_stamp()
|
||||
@@ -114,8 +151,18 @@ sc_clock::time_stamp()
|
||||
return *(const sc_time *)nullptr;
|
||||
}
|
||||
|
||||
const char *sc_clock::kind() const { return "sc_clock"; }
|
||||
|
||||
void sc_clock::before_end_of_elaboration() {}
|
||||
void
|
||||
sc_clock::before_end_of_elaboration()
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sc_core
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user