diff options
Diffstat (limited to 'src/systemc/core')
-rw-r--r-- | src/systemc/core/SConscript | 2 | ||||
-rw-r--r-- | src/systemc/core/kernel.cc | 13 | ||||
-rw-r--r-- | src/systemc/core/kernel.hh | 7 | ||||
-rw-r--r-- | src/systemc/core/list.hh | 113 | ||||
-rw-r--r-- | src/systemc/core/object.cc | 6 | ||||
-rw-r--r-- | src/systemc/core/process.cc | 38 | ||||
-rw-r--r-- | src/systemc/core/process.hh | 74 | ||||
-rw-r--r-- | src/systemc/core/process_types.cc | 46 | ||||
-rw-r--r-- | src/systemc/core/process_types.hh | 118 | ||||
-rw-r--r-- | src/systemc/core/sc_module.cc | 8 | ||||
-rw-r--r-- | src/systemc/core/sc_process_handle.cc | 4 | ||||
-rw-r--r-- | src/systemc/core/scheduler.cc | 102 | ||||
-rw-r--r-- | src/systemc/core/scheduler.hh | 101 |
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__ |