summaryrefslogtreecommitdiff
path: root/src/systemc/core/scheduler.cc
diff options
context:
space:
mode:
authorGabe Black <gabeblack@google.com>2018-07-04 22:41:29 -0700
committerGabe Black <gabeblack@google.com>2018-09-05 06:04:19 +0000
commit7088d69ab5fc70fca4890e0d0169fadd2b19bab8 (patch)
treec74b56e47f903c7fb8e722393e86a28410ae2c21 /src/systemc/core/scheduler.cc
parent0aec777bf2fff0ac61cd36b7c0358dbe9350c784 (diff)
downloadgem5-7088d69ab5fc70fca4890e0d0169fadd2b19bab8.tar.xz
systemc: Implement channel updates and rework the scheduler.
This change implements channel updates, and also reworks the scheduler to delegate more to the gem5 event queue by taking advantage of event priorities to ensure things happen in the right order. There's a lengthy comment in scheduler.hh describes how that all works. Change-Id: I5dee71b86b2e612bb720a4429f3a72e4b7c6d01f Reviewed-on: https://gem5-review.googlesource.com/11710 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.cc77
1 files changed, 53 insertions, 24 deletions
diff --git a/src/systemc/core/scheduler.cc b/src/systemc/core/scheduler.cc
index 41c64f876..17e7dc43e 100644
--- a/src/systemc/core/scheduler.cc
+++ b/src/systemc/core/scheduler.cc
@@ -30,31 +30,22 @@
#include "systemc/core/scheduler.hh"
#include "base/fiber.hh"
+#include "base/logging.hh"
+#include "sim/eventq.hh"
namespace sc_gem5
{
-Scheduler::Scheduler() : _numCycles(0), _current(nullptr) {}
+Scheduler::Scheduler() :
+ eq(nullptr), readyEvent(this, false, EventBase::Default_Pri + 1),
+ _numCycles(0), _current(nullptr)
+{}
void
-Scheduler::initialize()
+Scheduler::initToReady()
{
- update();
-
while (!initList.empty())
ready(initList.getNext());
-
- delta();
-}
-
-void
-Scheduler::runCycles()
-{
- while (!readyList.empty()) {
- evaluate();
- update();
- delta();
- }
}
void
@@ -77,24 +68,62 @@ Scheduler::yield()
}
void
-Scheduler::evaluate()
+Scheduler::ready(Process *p)
{
- if (!readyList.empty())
- _numCycles++;
+ // Clump methods together to minimize context switching.
+ if (p->procKind() == ::sc_core::SC_METHOD_PROC_)
+ readyList.pushFirst(p);
+ else
+ readyList.pushLast(p);
- do {
- yield();
- } while (!readyList.empty());
+ scheduleReadyEvent();
}
void
-Scheduler::update()
+Scheduler::requestUpdate(Channel *c)
{
+ updateList.pushLast(c);
+ scheduleReadyEvent();
}
void
-Scheduler::delta()
+Scheduler::scheduleReadyEvent()
{
+ // Schedule the evaluate and update phases.
+ if (!readyEvent.scheduled()) {
+ panic_if(!eq, "Need to schedule ready, but no event manager.\n");
+ eq->schedule(&readyEvent, eq->getCurTick());
+ }
+}
+
+void
+Scheduler::runReady()
+{
+ bool empty = readyList.empty();
+
+ // The evaluation phase.
+ do {
+ yield();
+ } while (!readyList.empty());
+
+ if (!empty)
+ _numCycles++;
+
+ // The update phase.
+ update();
+
+ // The delta phase will happen naturally through the event queue.
+}
+
+void
+Scheduler::update()
+{
+ Channel *channel = updateList.getNext();
+ while (channel) {
+ channel->popListNode();
+ channel->update();
+ channel = updateList.getNext();
+ }
}
Scheduler scheduler;