summaryrefslogtreecommitdiff
path: root/src/systemc/core/scheduler.hh
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.hh
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.hh')
-rw-r--r--src/systemc/core/scheduler.hh60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/systemc/core/scheduler.hh b/src/systemc/core/scheduler.hh
index aa8ec9aa4..5db5556ae 100644
--- a/src/systemc/core/scheduler.hh
+++ b/src/systemc/core/scheduler.hh
@@ -32,11 +32,14 @@
#include <vector>
+#include "base/logging.hh"
#include "sim/eventq.hh"
#include "systemc/core/channel.hh"
#include "systemc/core/list.hh"
#include "systemc/core/process.hh"
+class Fiber;
+
namespace sc_gem5
{
@@ -105,6 +108,32 @@ typedef NodeList<Channel> ChannelList;
* will all happen together since the readyEvent priority is lower,
* potentially marking new processes as ready. Once these events finish, the
* readyEvent may run, starting the next delta cycle.
+ *
+ * PAUSE/STOP
+ *
+ * To inject a pause from sc_pause which should happen after the current delta
+ * cycle's delta notification phase, an event is scheduled with a lower than
+ * normal priority, but higher than the readyEvent. That ensures that any
+ * delta notifications which are scheduled with normal priority will happen
+ * first, since those are part of the current delta cycle. Then the pause
+ * event will happen before the next readyEvent which would start the next
+ * delta cycle. All of these events are scheduled for the current time, and so
+ * would happen before any timed notifications went off.
+ *
+ * To inject a stop from sc_stop, the delta cycles should stop before even the
+ * delta notifications have happened, but after the evaluate and update phases.
+ * For that, a stop event with slightly higher than normal priority will be
+ * scheduled so that it happens before any of the delta notification events
+ * which are at normal priority.
+ *
+ * MAX RUN TIME
+ *
+ * When sc_start is called, it's possible to pass in a maximum time the
+ * simulation should run to, at which point sc_pause is implicitly called.
+ * That's implemented by scheduling an event at the max time with a priority
+ * which is lower than all the others so that it happens only if time would
+ * advance. When that event triggers, it calls the same function as the pause
+ * event.
*/
class Scheduler
@@ -156,13 +185,44 @@ class Scheduler
// Run scheduled channel updates.
void update();
+ void setScMainFiber(Fiber *sc_main) { scMain = sc_main; }
+
+ void start(Tick max_tick, bool run_to_time);
+
+ void schedulePause();
+ void scheduleStop(bool finish_delta);
+
+ bool paused() { return _paused; }
+ bool stopped() { return _stopped; }
+
private:
+ typedef const EventBase::Priority Priority;
+ static Priority DefaultPriority = EventBase::Default_Pri;
+
+ static Priority StopPriority = DefaultPriority - 1;
+ static Priority PausePriority = DefaultPriority + 1;
+ static Priority ReadyPriority = DefaultPriority + 2;
+ static Priority MaxTickPriority = DefaultPriority + 3;
+
EventQueue *eq;
void runReady();
EventWrapper<Scheduler, &Scheduler::runReady> readyEvent;
void scheduleReadyEvent();
+ void pause();
+ void stop();
+ EventWrapper<Scheduler, &Scheduler::pause> pauseEvent;
+ EventWrapper<Scheduler, &Scheduler::stop> stopEvent;
+ Fiber *scMain;
+
+ bool _started;
+ bool _paused;
+ bool _stopped;
+
+ Tick maxTick;
+ EventWrapper<Scheduler, &Scheduler::pause> maxTickEvent;
+
uint64_t _numCycles;
Process *_current;