summaryrefslogtreecommitdiff
path: root/src/systemc/core/scheduler.cc
diff options
context:
space:
mode:
authorGabe Black <gabeblack@google.com>2018-07-17 00:09:59 -0700
committerGabe Black <gabeblack@google.com>2018-09-05 06:08:22 +0000
commit91a6b128198515a7a29ee766715c9a1fe1bf7b0c (patch)
tree22980516f87d12af1df372ddfabe57e45f4acc5a /src/systemc/core/scheduler.cc
parent746c1eaa72dbce46899459f988336485190897c2 (diff)
downloadgem5-91a6b128198515a7a29ee766715c9a1fe1bf7b0c.tar.xz
systemc: Implement sc_pause, sc_stop, and re-sc_start-ing.
This change further modifies the scheduler to implement the sc_pause and sc_stop functions, and to ensure that calling sc_start again works. Also, some small changes were made to how processes and contexts are hooked up. Now, rather than checking whether a process is running to determine wether it started on its own or needs to be started manually, there's a bool which explicitly tracks whether it needs this step. The problem was that once a thread finished, it wasn't considered running any more. In that case it had run but finished, but that was indistinguishable from it needing to run but not having been started. Change-Id: I3aefb5493f91d9efa1a1382586196339b67925fe Reviewed-on: https://gem5-review.googlesource.com/12031 Reviewed-by: Gabe Black <gabeblack@google.com> Maintainer: Gabe Black <gabeblack@google.com>
Diffstat (limited to 'src/systemc/core/scheduler.cc')
-rw-r--r--src/systemc/core/scheduler.cc84
1 files changed, 80 insertions, 4 deletions
diff --git a/src/systemc/core/scheduler.cc b/src/systemc/core/scheduler.cc
index 230ed0af2..e3d275bb1 100644
--- a/src/systemc/core/scheduler.cc
+++ b/src/systemc/core/scheduler.cc
@@ -37,7 +37,12 @@ namespace sc_gem5
{
Scheduler::Scheduler() :
- eq(nullptr), readyEvent(this, false, EventBase::Default_Pri + 1),
+ eq(nullptr), _pendingCurr(0), _pendingFuture(0),
+ readyEvent(this, false, ReadyPriority),
+ pauseEvent(this, false, PausePriority),
+ stopEvent(this, false, StopPriority),
+ scMain(nullptr), _started(false), _paused(false), _stopped(false),
+ maxTickEvent(this, false, MaxTickPriority),
_numCycles(0), _current(nullptr), initReady(false)
{}
@@ -54,6 +59,9 @@ Scheduler::prepareForInit()
p->ready();
}
+ if (_started)
+ eq->schedule(&maxTickEvent, maxTick);
+
initReady = true;
}
@@ -98,9 +106,8 @@ Scheduler::yield()
// Switch to whatever Fiber is supposed to run this process. All
// Fibers which aren't running should be parked at this line.
_current->fiber()->run();
- // If the current process hasn't been started yet, start it. This
- // should always be true for methods, but may not be true for threads.
- if (_current && !_current->running())
+ // If the current process needs to be manually started, start it.
+ if (_current && _current->needsStart())
_current->run();
}
}
@@ -164,6 +171,75 @@ Scheduler::update()
}
}
+void
+Scheduler::pause()
+{
+ _paused = true;
+ scMain->run();
+}
+
+void
+Scheduler::stop()
+{
+ _stopped = true;
+ scMain->run();
+}
+
+void
+Scheduler::start(Tick max_tick, bool run_to_time)
+{
+ // We should be running from sc_main. Keep track of that Fiber to return
+ // to later.
+ scMain = Fiber::currentFiber();
+
+ _started = true;
+ _paused = false;
+ _stopped = false;
+
+ maxTick = max_tick;
+
+ if (initReady)
+ eq->schedule(&maxTickEvent, maxTick);
+
+ // Return to gem5 to let it run events, etc.
+ Fiber::primaryFiber()->run();
+
+ if (pauseEvent.scheduled())
+ eq->deschedule(&pauseEvent);
+ if (stopEvent.scheduled())
+ eq->deschedule(&stopEvent);
+ if (maxTickEvent.scheduled())
+ eq->deschedule(&maxTickEvent);
+}
+
+void
+Scheduler::schedulePause()
+{
+ if (pauseEvent.scheduled())
+ return;
+
+ eq->schedule(&pauseEvent, eq->getCurTick());
+}
+
+void
+Scheduler::scheduleStop(bool finish_delta)
+{
+ if (stopEvent.scheduled())
+ return;
+
+ if (!finish_delta) {
+ // If we're not supposed to finish the delta cycle, flush the list
+ // of ready processes and scheduled updates.
+ Process *p;
+ while ((p = readyList.getNext()))
+ p->popListNode();
+ Channel *c;
+ while ((c = updateList.getNext()))
+ c->popListNode();
+ }
+ eq->schedule(&stopEvent, eq->getCurTick());
+}
+
Scheduler scheduler;
} // namespace sc_gem5