systemc: Keep all pre-init processes on a single list.

We were keeping track of processes which should be initialized and
those which shouldn't on two different lists, and then processing
each list one after the other. This could reorder processes from the
order they were created, and so cause spurious differences which cause
the Accellera tests to fail.

This does make the scheduler slightly simpler, so it's not all bad.

Change-Id: I63306a41ce7bea91fa9ff2f6774ce9150134ce48
Reviewed-on: https://gem5-review.googlesource.com/c/12613
Reviewed-by: Gabe Black <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>
This commit is contained in:
Gabe Black
2018-09-10 17:25:00 -07:00
parent e4ab67f717
commit 86d82dff58
7 changed files with 30 additions and 59 deletions

View File

@@ -66,8 +66,8 @@ class ClockTick : public ScEvent
createProcess()
{
p = new Method(name.c_str(), &funcWrapper, true);
p->dontInitialize(true);
scheduler.reg(p);
scheduler.dontInitialize(p);
}
~ClockTick()

View File

@@ -313,12 +313,6 @@ Process::syncResetOff(bool inc_kids)
_syncReset = false;
}
void
Process::dontInitialize()
{
scheduler.dontInitialize(this);
}
void
Process::finalize()
{
@@ -400,9 +394,9 @@ Process::lastReport(::sc_core::sc_report *report)
Process::Process(const char *name, ProcessFuncWrapper *func, bool internal) :
::sc_core::sc_process_b(name), excWrapper(nullptr), func(func),
_internal(internal), _timedOut(false), _needsStart(true),
_isUnwinding(false), _terminated(false), _suspended(false),
_disabled(false), _syncReset(false), refCount(0),
_internal(internal), _timedOut(false), _dontInitialize(false),
_needsStart(true), _isUnwinding(false), _terminated(false),
_suspended(false), _disabled(false), _syncReset(false), refCount(0),
stackSize(::Fiber::DefaultStackSize), dynamicSensitivity(nullptr)
{
_dynamic =

View File

@@ -319,9 +319,6 @@ class Process : public ::sc_core::sc_process_b, public ListNode
const ::sc_core::sc_event &resetEvent() { return _resetEvent; }
const ::sc_core::sc_event &terminatedEvent() { return _terminatedEvent; }
// This should only be called before initialization.
void dontInitialize();
void setStackSize(size_t size) { stackSize = size; }
void finalize();
@@ -347,6 +344,9 @@ class Process : public ::sc_core::sc_process_b, public ListNode
bool timedOut() { return _timedOut; }
void timedOut(bool to) { _timedOut = to; }
bool dontInitialize() { return _dontInitialize; }
void dontInitialize(bool di) { _dontInitialize = di; }
protected:
Process(const char *name, ProcessFuncWrapper *func, bool internal=false);
@@ -371,6 +371,8 @@ class Process : public ::sc_core::sc_process_b, public ListNode
// Needed to support the deprecated "timed_out" function.
bool _timedOut;
bool _dontInitialize;
bool _needsStart;
bool _dynamic;
bool _isUnwinding;

View File

@@ -86,7 +86,7 @@ newCThreadProcess(const char *name, ProcessFuncWrapper *func)
return nullptr;
}
scheduler.reg(p);
p->dontInitialize();
p->dontInitialize(true);
return p;
}
@@ -296,7 +296,7 @@ sc_module::async_reset_signal_is(const sc_signal_in_if<bool> &, bool)
void
sc_module::dont_initialize()
{
::sc_gem5::Process::newest()->dontInitialize();
::sc_gem5::Process::newest()->dontInitialize(true);
}
void

View File

@@ -66,6 +66,8 @@ spawnWork(ProcessFuncWrapper *func, const char *name,
else
proc = new Thread(name, func);
proc->dontInitialize(dontInitialize);
if (opts) {
for (auto e: opts->_events)
proc->addStatic(new PendingSensitivityEvent(proc, e));
@@ -95,9 +97,6 @@ spawnWork(ProcessFuncWrapper *func, const char *name,
scheduler.reg(proc);
if (dontInitialize)
scheduler.dontInitialize(proc);
return proc;
}

View File

@@ -88,8 +88,6 @@ Scheduler::clear()
deschedule(&maxTickEvent);
Process *p;
while ((p = toFinalize.getNext()))
p->popListNode();
while ((p = initList.getNext()))
p->popListNode();
while ((p = readyListMethods.getNext()))
@@ -105,22 +103,20 @@ Scheduler::clear()
void
Scheduler::initPhase()
{
for (Process *p = toFinalize.getNext(); p; p = toFinalize.getNext()) {
p->finalize();
p->popListNode();
if (!p->hasStaticSensitivities() && !p->internal()) {
SC_REPORT_WARNING(
"(W558) disable() or dont_initialize() called on process "
"with no static sensitivity, it will be orphaned",
p->name());
}
}
for (Process *p = initList.getNext(); p; p = initList.getNext()) {
p->finalize();
p->popListNode();
p->ready();
if (p->dontInitialize()) {
if (!p->hasStaticSensitivities() && !p->internal()) {
SC_REPORT_WARNING(
"(W558) disable() or dont_initialize() called on "
"process with no static sensitivity, it will be "
"orphaned", p->name());
}
} else {
p->ready();
}
}
runUpdate();
@@ -147,8 +143,9 @@ Scheduler::reg(Process *p)
if (initDone) {
// If we're past initialization, finalize static sensitivity.
p->finalize();
// Mark the process as ready.
p->ready();
// If not marked as dontInitialize, mark as ready.
if (!p->dontInitialize())
p->ready();
} else {
// Otherwise, record that this process should be initialized once we
// get there.
@@ -156,20 +153,6 @@ Scheduler::reg(Process *p)
}
}
void
Scheduler::dontInitialize(Process *p)
{
if (initDone) {
// Pop this process off of the ready list.
p->popListNode();
} else {
// Push this process onto the list of processes which still need
// their static sensitivity to be finalized. That implicitly pops it
// off the list of processes to be initialized/marked ready.
toFinalize.pushLast(p);
}
}
void
Scheduler::yield()
{
@@ -240,15 +223,12 @@ Scheduler::suspend(Process *p)
{
bool was_ready;
if (initDone) {
// After initialization, the only list we can be on is the ready list.
// After initialization, check if we're on a ready list.
was_ready = (p->nextListNode != nullptr);
p->popListNode();
} else {
// Check the ready lists to see if we find this process.
was_ready = listContains(&readyListMethods, p) ||
listContains(&readyListThreads, p);
if (was_ready)
toFinalize.pushLast(p);
// Nothing is ready before init.
was_ready = false;
}
return was_ready;
}

View File

@@ -173,9 +173,6 @@ class Scheduler
// Register a process with the scheduler.
void reg(Process *p);
// Tell the scheduler not to initialize a process.
void dontInitialize(Process *p);
// Run the next process, if there is one.
void yield();
@@ -439,7 +436,6 @@ class Scheduler
bool runOnce;
ProcessList initList;
ProcessList toFinalize;
ProcessList *readyList;
ProcessList readyListMethods;