summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/systemc/core/SConscript2
-rw-r--r--src/systemc/core/kernel.cc13
-rw-r--r--src/systemc/core/kernel.hh7
-rw-r--r--src/systemc/core/list.hh113
-rw-r--r--src/systemc/core/object.cc6
-rw-r--r--src/systemc/core/process.cc38
-rw-r--r--src/systemc/core/process.hh74
-rw-r--r--src/systemc/core/process_types.cc46
-rw-r--r--src/systemc/core/process_types.hh118
-rw-r--r--src/systemc/core/sc_module.cc8
-rw-r--r--src/systemc/core/sc_process_handle.cc4
-rw-r--r--src/systemc/core/scheduler.cc102
-rw-r--r--src/systemc/core/scheduler.hh101
13 files changed, 559 insertions, 73 deletions
diff --git a/src/systemc/core/SConscript b/src/systemc/core/SConscript
index f4d65060f..045300478 100644
--- a/src/systemc/core/SConscript
+++ b/src/systemc/core/SConscript
@@ -34,6 +34,8 @@ if env['USE_SYSTEMC']:
Source('module.cc')
Source('object.cc')
Source('process.cc')
+ Source('process_types.cc')
+ Source('scheduler.cc')
Source('sc_attr.cc')
Source('sc_event.cc')
diff --git a/src/systemc/core/kernel.cc b/src/systemc/core/kernel.cc
index 288a037cc..82281c085 100644
--- a/src/systemc/core/kernel.cc
+++ b/src/systemc/core/kernel.cc
@@ -28,12 +28,23 @@
*/
#include "systemc/core/kernel.hh"
+#include "systemc/core/scheduler.hh"
namespace SystemC
{
-Kernel::Kernel(Params *params) : SimObject(params)
+Kernel::Kernel(Params *params) : SimObject(params), t0Event(this) {}
+
+void
+Kernel::startup()
+{
+ schedule(t0Event, curTick());
+}
+
+void
+Kernel::t0Handler()
{
+ ::sc_gem5::scheduler.initialize();
}
} // namespace SystemC
diff --git a/src/systemc/core/kernel.hh b/src/systemc/core/kernel.hh
index 9a81d9db4..8cbf4fb3b 100644
--- a/src/systemc/core/kernel.hh
+++ b/src/systemc/core/kernel.hh
@@ -48,6 +48,13 @@ class Kernel : public SimObject
public:
typedef SystemC_KernelParams Params;
Kernel(Params *params);
+
+ void startup() override;
+
+ void t0Handler();
+
+ private:
+ EventWrapper<Kernel, &Kernel::t0Handler> t0Event;
};
} // namespace SystemC
diff --git a/src/systemc/core/list.hh b/src/systemc/core/list.hh
new file mode 100644
index 000000000..65eada27d
--- /dev/null
+++ b/src/systemc/core/list.hh
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2018 Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#ifndef __SYSTEMC_CORE_LIST_HH__
+#define __SYSTEMC_CORE_LIST_HH__
+
+#include <functional>
+
+#include "base/fiber.hh"
+#include "systemc/core/object.hh"
+#include "systemc/ext/core/sc_event.hh"
+#include "systemc/ext/core/sc_module.hh"
+#include "systemc/ext/core/sc_process_handle.hh"
+
+namespace sc_gem5
+{
+
+struct ListNode
+{
+ ListNode() : nextListNode(nullptr), prevListNode(nullptr) {}
+ virtual ~ListNode() {}
+
+ ListNode *nextListNode;
+ ListNode *prevListNode;
+
+ void
+ popListNode()
+ {
+ if (nextListNode)
+ nextListNode->prevListNode = prevListNode;
+ if (prevListNode)
+ prevListNode->nextListNode = nextListNode;
+ nextListNode = nullptr;
+ prevListNode = nullptr;
+ }
+};
+
+template <typename T>
+struct NodeList : public ListNode
+{
+ NodeList()
+ {
+ nextListNode = this;
+ prevListNode = this;
+ }
+
+ void
+ pushFirst(T *t)
+ {
+ // Make sure this node isn't currently in a different list.
+ t->popListNode();
+
+ // The node behind t is whoever used to be first.
+ t->nextListNode = nextListNode;
+ // The node that used to be first is behind t.
+ nextListNode->prevListNode = t;
+
+ // Nobody is in front of t.
+ t->prevListNode = this;
+ // The first node is t.
+ nextListNode = t;
+ }
+
+ void
+ pushLast(T *t)
+ {
+ // Make sure this node isn't currently in a different list.
+ t->popListNode();
+
+ // The node in front of t is whoever used to be last.
+ t->prevListNode = prevListNode;
+ // The node that used to be last is in front of t.
+ prevListNode->nextListNode = t;
+
+ // Nobody is behind t.
+ t->nextListNode = this;
+ // The last node is t.
+ prevListNode = t;
+ }
+
+ T *getNext() { return dynamic_cast<T *>(nextListNode); }
+ bool empty() { return getNext() == nullptr; }
+};
+
+} // namespace sc_gem5
+
+#endif //__SYSTEMC_CORE_LIST_HH__
diff --git a/src/systemc/core/object.cc b/src/systemc/core/object.cc
index cfd4c5e93..2bc6804e2 100644
--- a/src/systemc/core/object.cc
+++ b/src/systemc/core/object.cc
@@ -31,6 +31,7 @@
#include "base/logging.hh"
#include "systemc/core/module.hh"
+#include "systemc/core/scheduler.hh"
namespace sc_gem5
{
@@ -87,8 +88,9 @@ Object::Object(sc_core::sc_object *sc_obj, const char *obj_name) :
// constructor is running.
parent = p->obj()->sc_obj;
addObject(&parent->_gem5_object->children, sc_obj);
- } else if (false /* TODO Check if a process is running */) {
- // The process is our parent.
+ } else if (scheduler.current()) {
+ // Our parent is the currently running process.
+ parent = scheduler.current();
} else {
// We're a top level object.
addObject(&topLevelObjects, sc_obj);
diff --git a/src/systemc/core/process.cc b/src/systemc/core/process.cc
index 4597d8b60..26cfb7ecd 100644
--- a/src/systemc/core/process.cc
+++ b/src/systemc/core/process.cc
@@ -28,6 +28,7 @@
*/
#include "systemc/core/process.hh"
+#include "systemc/core/scheduler.hh"
namespace sc_gem5
{
@@ -79,8 +80,9 @@ Process::suspend(bool inc_kids)
//TODO Suspend this process.
}
- if (procKind() != ::sc_core::SC_METHOD_PROC_ /* && we're running */) {
- // We suspended this thread or cthread. Stop running.
+ if (procKind() != ::sc_core::SC_METHOD_PROC_ &&
+ scheduler.current() == this) {
+ scheduler.yield();
}
}
@@ -189,16 +191,34 @@ Process::syncResetOff(bool inc_kids)
}
void
-Thread::throw_it(ExceptionWrapperBase &exc, bool inc_kids)
-{
- Process::throw_it(exc, inc_kids);
-
- if (_terminated)
- return;
+Process::run()
+{
+ _running = true;
+ bool reset;
+ do {
+ reset = false;
+ try {
+ func->call();
+ } catch(::sc_core::sc_unwind_exception exc) {
+ reset = exc.is_reset();
+ }
+ } while (reset);
+ _running = false;
+}
- injectException(exc);
+Process::Process(const char *name, ProcessFuncWrapper *func, bool _dynamic) :
+ ::sc_core::sc_object(name), excWrapper(nullptr), func(func),
+ _running(false), _dynamic(_dynamic), _isUnwinding(false),
+ _terminated(false), _suspended(false), _disabled(false),
+ _syncReset(false), refCount(0), stackSize(::Fiber::DefaultStackSize)
+{
+ _newest = this;
+ if (!_dynamic)
+ scheduler.init(this);
}
+Process *Process::_newest;
+
void
throw_it_wrapper(Process *p, ExceptionWrapperBase &exc, bool inc_kids)
{
diff --git a/src/systemc/core/process.hh b/src/systemc/core/process.hh
index 07ef97c5e..bb9a9c60c 100644
--- a/src/systemc/core/process.hh
+++ b/src/systemc/core/process.hh
@@ -33,6 +33,7 @@
#include <functional>
#include "base/fiber.hh"
+#include "systemc/core/list.hh"
#include "systemc/core/object.hh"
#include "systemc/ext/core/sc_event.hh"
#include "systemc/ext/core/sc_module.hh"
@@ -41,10 +42,11 @@
namespace sc_gem5
{
-class Process : public ::sc_core::sc_object
+class Process : public ::sc_core::sc_object, public ListNode
{
public:
virtual ::sc_core::sc_curr_proc_kind procKind() const = 0;
+ bool running() const { return _running; }
bool dynamic() const { return _dynamic; }
bool isUnwinding() const { return _isUnwinding; }
bool terminated() const { return _terminated; }
@@ -75,12 +77,21 @@ class Process : public ::sc_core::sc_object
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() { popListNode(); }
+
+ void setStackSize(size_t size) { stackSize = size; }
+
+ void run();
+
+ virtual Fiber *fiber() { return Fiber::primaryFiber(); }
+
+ static Process *newest() { return _newest; }
+
protected:
- Process(const char *name, ProcessFuncWrapper *func, bool _dynamic) :
- ::sc_core::sc_object(name), func(func), _dynamic(_dynamic),
- _isUnwinding(false), _terminated(false), _suspended(false),
- _disabled(false), _syncReset(false), refCount(0)
- {}
+ Process(const char *name, ProcessFuncWrapper *func, bool _dynamic);
+
+ static Process *_newest;
virtual ~Process() { delete func; }
@@ -89,6 +100,7 @@ class Process : public ::sc_core::sc_object
ProcessFuncWrapper *func;
sc_core::sc_curr_proc_kind _procKind;
+ bool _running;
bool _dynamic;
bool _isUnwinding;
bool _terminated;
@@ -99,56 +111,8 @@ class Process : public ::sc_core::sc_object
bool _syncReset;
int refCount;
-};
-
-class Method : public Process
-{
- public:
- Method(const char *name, ProcessFuncWrapper *func, bool _dynamic=false) :
- Process(name, func, _dynamic)
- {}
-
- const char *kind() const override { return "sc_method_process"; }
-
- sc_core::sc_curr_proc_kind
- procKind() const override
- {
- return sc_core::SC_METHOD_PROC_;
- }
-};
-
-class Thread : public Process
-{
- public:
- Thread(const char *name, ProcessFuncWrapper *func, bool _dynamic=false) :
- Process(name, func, _dynamic)
- {}
-
- const char *kind() const override { return "sc_thread_process"; }
-
- void throw_it(ExceptionWrapperBase &exc, bool inc_kids) override;
-
- sc_core::sc_curr_proc_kind
- procKind() const override
- {
- return sc_core::SC_THREAD_PROC_;
- }
-};
-
-class CThread : public Thread
-{
- public:
- CThread(const char *name, ProcessFuncWrapper *func, bool _dynamic=false) :
- Thread(name, func, _dynamic)
- {}
-
- const char *kind() const override { return "sc_cthread_process"; }
- sc_core::sc_curr_proc_kind
- procKind() const override
- {
- return sc_core::SC_CTHREAD_PROC_;
- }
+ size_t stackSize;
};
} // namespace sc_gem5
diff --git a/src/systemc/core/process_types.cc b/src/systemc/core/process_types.cc
new file mode 100644
index 000000000..188225c02
--- /dev/null
+++ b/src/systemc/core/process_types.cc
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2018 Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#include "systemc/core/process_types.hh"
+
+namespace sc_gem5
+{
+
+void
+Thread::throw_it(ExceptionWrapperBase &exc, bool inc_kids)
+{
+ Process::throw_it(exc, inc_kids);
+
+ if (_terminated)
+ return;
+
+ injectException(exc);
+}
+
+} // namespace sc_gem5
diff --git a/src/systemc/core/process_types.hh b/src/systemc/core/process_types.hh
new file mode 100644
index 000000000..6d13592b6
--- /dev/null
+++ b/src/systemc/core/process_types.hh
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2018 Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#ifndef __SYSTEMC_CORE_PROCESS_TYPES_HH__
+#define __SYSTEMC_CORE_PROCESS_TYPES_HH__
+
+#include "systemc/core/process.hh"
+#include "systemc/core/scheduler.hh"
+
+namespace sc_gem5
+{
+
+class Method : public Process
+{
+ public:
+ Method(const char *name, ProcessFuncWrapper *func, bool _dynamic=false) :
+ Process(name, func, _dynamic)
+ {}
+
+ const char *kind() const override { return "sc_method_process"; }
+
+ sc_core::sc_curr_proc_kind
+ procKind() const override
+ {
+ return sc_core::SC_METHOD_PROC_;
+ }
+};
+
+class Thread : public Process
+{
+ public:
+ Thread(const char *name, ProcessFuncWrapper *func, bool _dynamic=false) :
+ Process(name, func, _dynamic), ctx(nullptr)
+ {}
+
+ ~Thread() { delete ctx; }
+
+ const char *kind() const override { return "sc_thread_process"; }
+
+ void throw_it(ExceptionWrapperBase &exc, bool inc_kids) override;
+
+ sc_core::sc_curr_proc_kind
+ procKind() const override
+ {
+ return sc_core::SC_THREAD_PROC_;
+ }
+
+ Fiber *
+ fiber() override
+ {
+ if (!ctx)
+ ctx = new Context(this, stackSize);
+ return ctx;
+ }
+
+ private:
+ class Context : public Fiber
+ {
+ public:
+ Context(Thread *thread, size_t size) : Fiber(size), thread(thread) {}
+
+ private:
+ Thread *thread;
+
+ void main() override { thread->run(); }
+ };
+
+ Context *ctx;
+};
+
+class CThread : public Thread
+{
+ public:
+ CThread(const char *name, ProcessFuncWrapper *func, bool _dynamic=false) :
+ Thread(name, func, _dynamic)
+ {
+ // We'll be in the initialization list now, but we shouldn't be.
+ popListNode();
+ }
+
+ const char *kind() const override { return "sc_cthread_process"; }
+
+ sc_core::sc_curr_proc_kind
+ procKind() const override
+ {
+ return sc_core::SC_CTHREAD_PROC_;
+ }
+};
+
+} // namespace sc_gem5
+
+#endif //__SYSTEMC_CORE_PROCESS_TYPES_HH__
diff --git a/src/systemc/core/sc_module.cc b/src/systemc/core/sc_module.cc
index 44369d751..90139a166 100644
--- a/src/systemc/core/sc_module.cc
+++ b/src/systemc/core/sc_module.cc
@@ -32,7 +32,7 @@
#include "base/logging.hh"
#include "systemc/core/module.hh"
-#include "systemc/core/process.hh"
+#include "systemc/core/process_types.hh"
#include "systemc/ext/core/sc_module.hh"
#include "systemc/ext/core/sc_module_name.hh"
@@ -221,13 +221,13 @@ sc_module::async_reset_signal_is(const sc_signal_in_if<bool> &, bool)
void
sc_module::dont_initialize()
{
- warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+ ::sc_gem5::Process::newest()->dontInitialize();
}
void
-sc_module::set_stack_size(size_t)
+sc_module::set_stack_size(size_t size)
{
- warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+ ::sc_gem5::Process::newest()->setStackSize(size);
}
diff --git a/src/systemc/core/sc_process_handle.cc b/src/systemc/core/sc_process_handle.cc
index eff2490ba..c4014b747 100644
--- a/src/systemc/core/sc_process_handle.cc
+++ b/src/systemc/core/sc_process_handle.cc
@@ -29,6 +29,7 @@
#include "base/logging.hh"
#include "systemc/core/process.hh"
+#include "systemc/core/scheduler.hh"
#include "systemc/ext/core/sc_process_handle.hh"
namespace sc_core
@@ -291,8 +292,7 @@ sc_process_handle::sync_reset_off(
sc_process_handle
sc_get_current_process_handle()
{
- warn("%s not implemented.\n", __PRETTY_FUNCTION__);
- return sc_process_handle(nullptr /* Current process pointer */);
+ return sc_process_handle(::sc_gem5::scheduler.current());
}
bool
diff --git a/src/systemc/core/scheduler.cc b/src/systemc/core/scheduler.cc
new file mode 100644
index 000000000..41c64f876
--- /dev/null
+++ b/src/systemc/core/scheduler.cc
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2018 Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#include "systemc/core/scheduler.hh"
+
+#include "base/fiber.hh"
+
+namespace sc_gem5
+{
+
+Scheduler::Scheduler() : _numCycles(0), _current(nullptr) {}
+
+void
+Scheduler::initialize()
+{
+ update();
+
+ while (!initList.empty())
+ ready(initList.getNext());
+
+ delta();
+}
+
+void
+Scheduler::runCycles()
+{
+ while (!readyList.empty()) {
+ evaluate();
+ update();
+ delta();
+ }
+}
+
+void
+Scheduler::yield()
+{
+ _current = readyList.getNext();
+ if (!_current) {
+ // There are no more processes, so return control to evaluate.
+ Fiber::primaryFiber()->run();
+ } else {
+ _current->popListNode();
+ // 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())
+ _current->run();
+ }
+}
+
+void
+Scheduler::evaluate()
+{
+ if (!readyList.empty())
+ _numCycles++;
+
+ do {
+ yield();
+ } while (!readyList.empty());
+}
+
+void
+Scheduler::update()
+{
+}
+
+void
+Scheduler::delta()
+{
+}
+
+Scheduler scheduler;
+
+} // namespace sc_gem5
diff --git a/src/systemc/core/scheduler.hh b/src/systemc/core/scheduler.hh
new file mode 100644
index 000000000..a7216231a
--- /dev/null
+++ b/src/systemc/core/scheduler.hh
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2018 Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#ifndef __SYSTEMC_CORE_SCHEDULER_HH__
+#define __SYSTEMC_CORE_SCHEDULER_HH__
+
+#include "systemc/core/list.hh"
+#include "systemc/core/process.hh"
+
+namespace sc_gem5
+{
+
+typedef NodeList<Process> ProcessList;
+
+class Scheduler
+{
+ public:
+ Scheduler();
+
+ uint64_t numCycles() { return _numCycles; }
+ Process *current() { return _current; }
+
+ // Run the initialization phase.
+ void initialize();
+
+ // Run delta cycles until time needs to advance.
+ void runCycles();
+
+ // Put a process on the list of processes to be initialized.
+ void init(Process *p) { initList.pushLast(p); }
+
+ // Run the next process, if there is one.
+ void yield();
+
+ // Put a process on the ready list.
+ void
+ ready(Process *p)
+ {
+ // Clump methods together to minimize context switching.
+ if (p->procKind() == ::sc_core::SC_METHOD_PROC_)
+ readyList.pushFirst(p);
+ else
+ readyList.pushLast(p);
+ }
+
+ // Run the given process immediately, preempting whatever may be running.
+ void
+ runNow(Process *p)
+ {
+ // If a process is running, schedule it/us to run again.
+ if (_current)
+ readyList.pushFirst(_current);
+ // Schedule p to run first.
+ readyList.pushFirst(p);
+ yield();
+ }
+
+ private:
+ uint64_t _numCycles;
+
+ Process *_current;
+
+ ProcessList initList;
+ ProcessList readyList;
+
+ void evaluate();
+ void update();
+ void delta();
+};
+
+extern Scheduler scheduler;
+
+} // namespace sc_gem5
+
+#endif // __SYSTEMC_CORE_SCHEDULER_H__