systemc: Implement the SC_EXIT_ON_STARVATION exit mode.
This mode implies checking whether there's any activity left either before starting a delta cycle, or processing delta or timed notification or timeout. Change-Id: I0780a1f720cf63f3d2907b8dd28685266b52d6b4 Reviewed-on: https://gem5-review.googlesource.com/12038 Reviewed-by: Gabe Black <gabeblack@google.com> Maintainer: Gabe Black <gabeblack@google.com>
This commit is contained in:
@@ -42,7 +42,9 @@ Scheduler::Scheduler() :
|
||||
eq(nullptr), readyEvent(this, false, ReadyPriority),
|
||||
pauseEvent(this, false, PausePriority),
|
||||
stopEvent(this, false, StopPriority),
|
||||
scMain(nullptr), _started(false), _paused(false), _stopped(false),
|
||||
scMain(nullptr),
|
||||
starvationEvent(this, false, StarvationPriority),
|
||||
_started(false), _paused(false), _stopped(false),
|
||||
maxTickEvent(this, false, MaxTickPriority),
|
||||
_numCycles(0), _current(nullptr), initReady(false)
|
||||
{}
|
||||
@@ -143,6 +145,20 @@ Scheduler::scheduleReadyEvent()
|
||||
if (!readyEvent.scheduled()) {
|
||||
panic_if(!eq, "Need to schedule ready, but no event manager.\n");
|
||||
eq->schedule(&readyEvent, eq->getCurTick());
|
||||
if (starvationEvent.scheduled())
|
||||
eq->deschedule(&starvationEvent);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Scheduler::scheduleStarvationEvent()
|
||||
{
|
||||
if (!starvationEvent.scheduled()) {
|
||||
panic_if(!eq, "Need to schedule starvation event, "
|
||||
"but no event manager.\n");
|
||||
eq->schedule(&starvationEvent, eq->getCurTick());
|
||||
if (readyEvent.scheduled())
|
||||
eq->deschedule(&readyEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,6 +178,9 @@ Scheduler::runReady()
|
||||
// The update phase.
|
||||
update();
|
||||
|
||||
if (starved() && !runToTime)
|
||||
scheduleStarvationEvent();
|
||||
|
||||
// The delta phase will happen naturally through the event queue.
|
||||
}
|
||||
|
||||
@@ -202,9 +221,13 @@ Scheduler::start(Tick max_tick, bool run_to_time)
|
||||
_started = true;
|
||||
_paused = false;
|
||||
_stopped = false;
|
||||
runToTime = run_to_time;
|
||||
|
||||
maxTick = max_tick;
|
||||
|
||||
if (starved() && !runToTime)
|
||||
return;
|
||||
|
||||
if (initReady) {
|
||||
kernel->status(::sc_core::SC_RUNNING);
|
||||
eq->schedule(&maxTickEvent, maxTick);
|
||||
@@ -219,6 +242,8 @@ Scheduler::start(Tick max_tick, bool run_to_time)
|
||||
eq->deschedule(&stopEvent);
|
||||
if (maxTickEvent.scheduled())
|
||||
eq->deschedule(&maxTickEvent);
|
||||
if (starvationEvent.scheduled())
|
||||
eq->deschedule(&starvationEvent);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -215,6 +215,9 @@ class Scheduler
|
||||
auto it = pendingTicks.begin();
|
||||
if (--it->second == 0)
|
||||
pendingTicks.erase(it);
|
||||
|
||||
if (starved() && !runToTime)
|
||||
scheduleStarvationEvent();
|
||||
}
|
||||
|
||||
// Pending activity ignores gem5 activity, much like how a systemc
|
||||
@@ -277,6 +280,7 @@ class Scheduler
|
||||
static Priority StopPriority = DefaultPriority - 1;
|
||||
static Priority PausePriority = DefaultPriority + 1;
|
||||
static Priority ReadyPriority = DefaultPriority + 2;
|
||||
static Priority StarvationPriority = ReadyPriority;
|
||||
static Priority MaxTickPriority = DefaultPriority + 3;
|
||||
|
||||
EventQueue *eq;
|
||||
@@ -292,6 +296,17 @@ class Scheduler
|
||||
EventWrapper<Scheduler, &Scheduler::stop> stopEvent;
|
||||
Fiber *scMain;
|
||||
|
||||
bool
|
||||
starved()
|
||||
{
|
||||
return (readyList.empty() && updateList.empty() &&
|
||||
(pendingTicks.empty() ||
|
||||
pendingTicks.begin()->first > maxTick) &&
|
||||
initList.empty());
|
||||
}
|
||||
EventWrapper<Scheduler, &Scheduler::pause> starvationEvent;
|
||||
void scheduleStarvationEvent();
|
||||
|
||||
bool _started;
|
||||
bool _paused;
|
||||
bool _stopped;
|
||||
@@ -304,6 +319,7 @@ class Scheduler
|
||||
Process *_current;
|
||||
|
||||
bool initReady;
|
||||
bool runToTime;
|
||||
|
||||
ProcessList initList;
|
||||
ProcessList toFinalize;
|
||||
|
||||
Reference in New Issue
Block a user