Event::Event(sc_core::sc_event *_sc_event) : Event(_sc_event, "") {}
Event::Event(sc_core::sc_event *_sc_event, const char *_basename) :
- _sc_event(_sc_event), _basename(_basename), delayedNotify(this)
+ _sc_event(_sc_event), _basename(_basename), delayedNotifyEvent(this)
{
Module *p = currentModule();
s->notify(this);
}
+void
+Event::delayedNotify()
+{
+ scheduler.eventHappened();
+ notify();
+}
+
void
Event::notify(const sc_core::sc_time &t)
{
//XXX We're assuming the systemc time resolution is in ps.
- Tick new_tick = t.value() * SimClock::Int::ps +
- scheduler.eventQueue().getCurTick();
- if (delayedNotify.scheduled()) {
- Tick old_tick = delayedNotify.when();
+ Tick new_tick = t.value() * SimClock::Int::ps + scheduler.getCurTick();
+ if (delayedNotifyEvent.scheduled()) {
+ Tick old_tick = delayedNotifyEvent.when();
if (new_tick >= old_tick)
return;
- scheduler.eventQueue().deschedule(&delayedNotify);
+ scheduler.deschedule(&delayedNotifyEvent);
}
- scheduler.eventQueue().schedule(&delayedNotify, new_tick);
+ scheduler.schedule(&delayedNotifyEvent, new_tick);
}
void
Event::cancel()
{
- if (delayedNotify.scheduled())
- scheduler.eventQueue().deschedule(&delayedNotify);
+ if (delayedNotifyEvent.scheduled())
+ scheduler.deschedule(&delayedNotifyEvent);
}
bool
sc_core::sc_object *parent;
EventsIt parentIt;
- EventWrapper<Event, &Event::notify> delayedNotify;
+ void delayedNotify();
+ EventWrapper<Event, &Event::delayedNotify> delayedNotifyEvent;
mutable std::set<Sensitivity *> sensitivities;
};
{
SensitivityTimeout::SensitivityTimeout(Process *p, ::sc_core::sc_time t) :
- Sensitivity(p), timeoutEvent(this), timeout(t)
+ Sensitivity(p), timeoutEvent(this), time(t)
{
- Tick when = scheduler.eventQueue().getCurTick() + timeout.value();
- scheduler.eventQueue().schedule(&timeoutEvent, when);
+ Tick when = scheduler.getCurTick() + time.value();
+ scheduler.schedule(&timeoutEvent, when);
}
SensitivityTimeout::~SensitivityTimeout()
{
if (timeoutEvent.scheduled())
- scheduler.eventQueue().deschedule(&timeoutEvent);
+ scheduler.deschedule(&timeoutEvent);
+}
+
+void
+SensitivityTimeout::timeout()
+{
+ scheduler.eventHappened();
+ notify();
}
SensitivityEvent::SensitivityEvent(
class SensitivityTimeout : virtual public Sensitivity
{
private:
- EventWrapper<Sensitivity, &Sensitivity::notify> timeoutEvent;
- ::sc_core::sc_time timeout;
+ void timeout();
+ EventWrapper<SensitivityTimeout,
+ &SensitivityTimeout::timeout> timeoutEvent;
+ ::sc_core::sc_time time;
public:
SensitivityTimeout(Process *p, ::sc_core::sc_time t);
Process *p, const ::sc_core::sc_event_and_list *list);
~SensitivityEventAndList();
- virtual void notifyWork(Event *e) override;
+ void notifyWork(Event *e) override;
};
class SensitivityEventOrList : virtual public Sensitivity
void
sc_start()
{
- Tick now = curEventQueue() ? curEventQueue()->getCurTick() : 0;
+ Tick now = ::sc_gem5::scheduler.getCurTick();
sc_start(sc_time::from_value(MaxTick - now), SC_EXIT_ON_STARVATION);
}
{
_status = SC_RUNNING;
- Tick now = curEventQueue() ? curEventQueue()->getCurTick() : 0;
+ Tick now = ::sc_gem5::scheduler.getCurTick();
::sc_gem5::scheduler.start(now + time.value(), p == SC_RUN_TO_TIME);
if (::sc_gem5::scheduler.paused())
sc_time_stamp()
{
static sc_time tstamp;
- Tick tick = sc_gem5::scheduler.eventQueue().getCurTick();
+ Tick tick = ::sc_gem5::scheduler.getCurTick();
//XXX We're assuming the systemc time resolution is in ps.
tstamp = sc_time::from_value(tick / SimClock::Int::ps);
return tstamp;
bool
sc_pending_activity_at_current_time()
{
- warn("%s not implemented.\n", __PRETTY_FUNCTION__);
- return false;
+ return ::sc_gem5::scheduler.pendingCurr();
}
bool
sc_pending_activity_at_future_time()
{
- warn("%s not implemented.\n", __PRETTY_FUNCTION__);
- return false;
+ return ::sc_gem5::scheduler.pendingFuture();
}
bool
sc_time
sc_time_to_pending_activity()
{
- warn("%s not implemented.\n", __PRETTY_FUNCTION__);
- return sc_time();
+ return sc_time::from_value(::sc_gem5::scheduler.timeToPending());
}
sc_status
{
Scheduler::Scheduler() :
- eq(nullptr), _pendingCurr(0), _pendingFuture(0),
- readyEvent(this, false, ReadyPriority),
+ eq(nullptr), readyEvent(this, false, ReadyPriority),
pauseEvent(this, false, PausePriority),
stopEvent(this, false, StopPriority),
scMain(nullptr), _started(false), _paused(false), _stopped(false),
// Set an event queue for scheduling events.
void setEventQueue(EventQueue *_eq) { eq = _eq; }
- // Retrieve the event queue.
- EventQueue &eventQueue() const { return *eq; }
+ // Get the current time according to gem5.
+ Tick getCurTick() { return eq ? eq->getCurTick() : 0; }
+
+ // For scheduling delayed/timed notifications/timeouts.
+ void
+ schedule(::Event *event, Tick tick)
+ {
+ pendingTicks[tick]++;
+ eq->schedule(event, tick);
+ }
+
+ // For descheduling delayed/timed notifications/timeouts.
+ void
+ deschedule(::Event *event)
+ {
+ auto it = pendingTicks.find(event->when());
+ if (--it->second == 0)
+ pendingTicks.erase(it);
+ eq->deschedule(event);
+ }
+
+ // Tell the scheduler than an event fired for bookkeeping purposes.
+ void
+ eventHappened()
+ {
+ auto it = pendingTicks.begin();
+ if (--it->second == 0)
+ pendingTicks.erase(it);
+ }
+
+ // Pending activity ignores gem5 activity, much like how a systemc
+ // simulation wouldn't know about asynchronous external events (socket IO
+ // for instance) that might happen before time advances in a pure
+ // systemc simulation. Also the spec lists what specific types of pending
+ // activity needs to be counted, which obviously doesn't include gem5
+ // events.
+
+ // Return whether there's pending systemc activity at this time.
+ bool
+ pendingCurr()
+ {
+ if (!readyList.empty() || !updateList.empty())
+ return true;
+ return pendingTicks.size() &&
+ pendingTicks.begin()->first == getCurTick();
+ }
+
+ // Return whether there are pending timed notifications or timeouts.
+ bool
+ pendingFuture()
+ {
+ switch (pendingTicks.size()) {
+ case 0: return false;
+ case 1: return pendingTicks.begin()->first > getCurTick();
+ default: return true;
+ }
+ }
+
+ // Return how many ticks there are until the first pending event, if any.
+ Tick
+ timeToPending()
+ {
+ if (!readyList.empty() || !updateList.empty())
+ return 0;
+ else if (pendingTicks.size())
+ return pendingTicks.begin()->first - getCurTick();
+ else
+ return MaxTick - getCurTick();
+ }
// Run scheduled channel updates.
void update();
static Priority MaxTickPriority = DefaultPriority + 3;
EventQueue *eq;
+ std::map<Tick, int> pendingTicks;
void runReady();
EventWrapper<Scheduler, &Scheduler::runReady> readyEvent;