summaryrefslogtreecommitdiff
path: root/src/systemc/core/scheduler.hh
diff options
context:
space:
mode:
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;