From 4bd389c9d0370d67464c2a508381abe326de3bdf Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 29 Jun 2018 16:46:52 -0700 Subject: systemc: Fill out sc_process_handle and create Process classes. The sc_process_handle class now primarily delegates to a Process object it points at. The Process object does book keeping as far as its internal state, but doesn't yet have a way to run its target function or to schedule itself or inject exceptions into its context of execution. Change-Id: I98389778abe29aa26e3e3a91bf02e6721acc8a9c Reviewed-on: https://gem5-review.googlesource.com/11613 Reviewed-by: Gabe Black Maintainer: Gabe Black --- src/systemc/core/SConscript | 1 + src/systemc/core/object.cc | 2 +- src/systemc/core/process.cc | 208 ++++++++++++++++++++++++++++++ src/systemc/core/process.hh | 156 ++++++++++++++++++++++ src/systemc/core/sc_module.cc | 26 +++- src/systemc/core/sc_process_handle.cc | 166 ++++++++++++------------ src/systemc/core/sc_sensitive.cc | 9 ++ src/systemc/ext/core/sc_module.hh | 37 +++++- src/systemc/ext/core/sc_process_handle.hh | 48 ++++++- src/systemc/ext/core/sc_sensitive.hh | 22 ++++ 10 files changed, 581 insertions(+), 94 deletions(-) create mode 100644 src/systemc/core/process.cc create mode 100644 src/systemc/core/process.hh diff --git a/src/systemc/core/SConscript b/src/systemc/core/SConscript index a07c02683..f4d65060f 100644 --- a/src/systemc/core/SConscript +++ b/src/systemc/core/SConscript @@ -33,6 +33,7 @@ if env['USE_SYSTEMC']: Source('kernel.cc') Source('module.cc') Source('object.cc') + Source('process.cc') Source('sc_attr.cc') Source('sc_event.cc') diff --git a/src/systemc/core/object.cc b/src/systemc/core/object.cc index 8d2b73545..cfd4c5e93 100644 --- a/src/systemc/core/object.cc +++ b/src/systemc/core/object.cc @@ -100,7 +100,7 @@ Object::Object(sc_core::sc_object *sc_obj, const char *obj_name) : sc_core::sc_object *sc_p = parent; while (sc_p) { _name = std::string(sc_p->basename()) + std::string(".") + _name; - sc_p = get_parent_object(); + sc_p = sc_p->get_parent_object(); } } diff --git a/src/systemc/core/process.cc b/src/systemc/core/process.cc new file mode 100644 index 000000000..4597d8b60 --- /dev/null +++ b/src/systemc/core/process.cc @@ -0,0 +1,208 @@ +/* + * 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.hh" + +namespace sc_gem5 +{ + +class UnwindExceptionReset : public ::sc_core::sc_unwind_exception +{ + public: + const char *what() const throw() override { return "RESET"; } + bool is_reset() const override { return true; } +}; + +class UnwindExceptionKill : public ::sc_core::sc_unwind_exception +{ + public: + const char *what() const throw() override { return "KILL"; } + bool is_reset() const override { return false; } +}; + +template +struct BuiltinExceptionWrapper : public ExceptionWrapperBase +{ + public: + T t; + void throw_it() override { throw t; } +}; + +BuiltinExceptionWrapper resetException; +BuiltinExceptionWrapper killException; + + +void +Process::forEachKid(const std::function &work) +{ + for (auto &kid: get_child_objects()) { + Process *p_kid = dynamic_cast(kid); + if (p_kid) + work(p_kid); + } +} + +void +Process::suspend(bool inc_kids) +{ + if (inc_kids) + forEachKid([](Process *p) { p->suspend(true); }); + + if (!_suspended) { + _suspended = true; + //TODO Suspend this process. + } + + if (procKind() != ::sc_core::SC_METHOD_PROC_ /* && we're running */) { + // We suspended this thread or cthread. Stop running. + } +} + +void +Process::resume(bool inc_kids) +{ + if (inc_kids) + forEachKid([](Process *p) { p->resume(true); }); + + if (_suspended) { + _suspended = false; + //TODO Resume this process. + } +} + +void +Process::disable(bool inc_kids) +{ + if (inc_kids) + forEachKid([](Process *p) { p->disable(true); }); + + _disabled = true; +} + +void +Process::enable(bool inc_kids) +{ + + if (inc_kids) + forEachKid([](Process *p) { p->enable(true); }); + + _disabled = false; +} + +void +Process::kill(bool inc_kids) +{ + // Update our state. + _terminated = true; + _isUnwinding = true; + + // Propogate the kill to our children no matter what happens to us. + if (inc_kids) + forEachKid([](Process *p) { p->kill(true); }); + + // If we're in the middle of unwinding, ignore the kill request. + if (_isUnwinding) + return; + + // Inject the kill exception into this process. + injectException(killException); + + _terminatedEvent.notify(); +} + +void +Process::reset(bool inc_kids) +{ + // Update our state. + _isUnwinding = true; + + // Propogate the reset to our children no matter what happens to us. + if (inc_kids) + forEachKid([](Process *p) { p->reset(true); }); + + // If we're in the middle of unwinding, ignore the reset request. + if (_isUnwinding) + return; + + // Inject the reset exception into this process. + injectException(resetException); + + _resetEvent.notify(); +} + +void +Process::throw_it(ExceptionWrapperBase &exc, bool inc_kids) +{ + if (inc_kids) + forEachKid([&exc](Process *p) { p->throw_it(exc, true); }); +} + +void +Process::injectException(ExceptionWrapperBase &exc) +{ + excWrapper = &exc; + // Let this process preempt us. +}; + +void +Process::syncResetOn(bool inc_kids) +{ + if (inc_kids) + forEachKid([](Process *p) { p->syncResetOn(true); }); + + _syncReset = true; +} + +void +Process::syncResetOff(bool inc_kids) +{ + if (inc_kids) + forEachKid([](Process *p) { p->syncResetOff(true); }); + + _syncReset = false; +} + +void +Thread::throw_it(ExceptionWrapperBase &exc, bool inc_kids) +{ + Process::throw_it(exc, inc_kids); + + if (_terminated) + return; + + injectException(exc); +} + +void +throw_it_wrapper(Process *p, ExceptionWrapperBase &exc, bool inc_kids) +{ + p->throw_it(exc, inc_kids); +} + +} // namespace sc_gem5 diff --git a/src/systemc/core/process.hh b/src/systemc/core/process.hh new file mode 100644 index 000000000..07ef97c5e --- /dev/null +++ b/src/systemc/core/process.hh @@ -0,0 +1,156 @@ +/* + * 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_HH__ +#define __SYSTEMC_CORE_PROCESS_HH__ + +#include + +#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 +{ + +class Process : public ::sc_core::sc_object +{ + public: + virtual ::sc_core::sc_curr_proc_kind procKind() const = 0; + bool dynamic() const { return _dynamic; } + bool isUnwinding() const { return _isUnwinding; } + bool terminated() const { return _terminated; } + + void forEachKid(const std::function &work); + + bool suspended() const { return _suspended; } + bool disabled() const { return _disabled; } + + void suspend(bool inc_kids); + void resume(bool inc_kids); + void disable(bool inc_kids); + void enable(bool inc_kids); + + void kill(bool inc_kids); + void reset(bool inc_kids); + virtual void throw_it(ExceptionWrapperBase &exc, bool inc_kids); + + void injectException(ExceptionWrapperBase &exc); + ExceptionWrapperBase *excWrapper; + + void syncResetOn(bool inc_kids); + void syncResetOff(bool inc_kids); + + void incref() { refCount++; } + void decref() { refCount--; } + + const ::sc_core::sc_event &resetEvent() { return _resetEvent; } + const ::sc_core::sc_event &terminatedEvent() { return _terminatedEvent; } + + 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) + {} + + virtual ~Process() { delete func; } + + ::sc_core::sc_event _resetEvent; + ::sc_core::sc_event _terminatedEvent; + + ProcessFuncWrapper *func; + sc_core::sc_curr_proc_kind _procKind; + bool _dynamic; + bool _isUnwinding; + bool _terminated; + + bool _suspended; + bool _disabled; + + 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_; + } +}; + +} // namespace sc_gem5 + +#endif //__SYSTEMC_CORE_PROCESS_HH__ diff --git a/src/systemc/core/sc_module.cc b/src/systemc/core/sc_module.cc index 89f74c7f2..44369d751 100644 --- a/src/systemc/core/sc_module.cc +++ b/src/systemc/core/sc_module.cc @@ -32,9 +32,33 @@ #include "base/logging.hh" #include "systemc/core/module.hh" +#include "systemc/core/process.hh" #include "systemc/ext/core/sc_module.hh" #include "systemc/ext/core/sc_module_name.hh" +namespace sc_gem5 +{ + +Process * +newMethodProcess(const char *name, ProcessFuncWrapper *func) +{ + return new Method(name, func); +} + +Process * +newThreadProcess(const char *name, ProcessFuncWrapper *func) +{ + return new Thread(name, func); +} + +Process * +newCThreadProcess(const char *name, ProcessFuncWrapper *func) +{ + return new CThread(name, func); +} + +} // namespace sc_gem5 + namespace sc_core { @@ -134,7 +158,7 @@ sc_module::get_child_events() const } sc_module::sc_module() : - sc_object(sc_gem5::currentModule()->name()), + sc_object(sc_gem5::newModule()->name()), _gem5_module(sc_gem5::currentModule()) {} diff --git a/src/systemc/core/sc_process_handle.cc b/src/systemc/core/sc_process_handle.cc index cf81f9ff5..eff2490ba 100644 --- a/src/systemc/core/sc_process_handle.cc +++ b/src/systemc/core/sc_process_handle.cc @@ -28,6 +28,7 @@ */ #include "base/logging.hh" +#include "systemc/core/process.hh" #include "systemc/ext/core/sc_process_handle.hh" namespace sc_core @@ -36,31 +37,18 @@ namespace sc_core const char * sc_unwind_exception::what() const throw() { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return ""; + panic("%s for base class called.\n", __PRETTY_FUNCTION__); } bool sc_unwind_exception::is_reset() const { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return false; -} - -sc_unwind_exception::sc_unwind_exception() -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); -} - -sc_unwind_exception::sc_unwind_exception(const sc_unwind_exception &) -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + panic("%s for base class called.\n", __PRETTY_FUNCTION__); } -sc_unwind_exception::~sc_unwind_exception() throw() -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); -} +sc_unwind_exception::sc_unwind_exception() {} +sc_unwind_exception::sc_unwind_exception(const sc_unwind_exception &) {} +sc_unwind_exception::~sc_unwind_exception() throw() {} const char * @@ -86,183 +74,198 @@ sc_get_curr_process_handle() } -sc_process_handle::sc_process_handle() -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); -} +sc_process_handle::sc_process_handle() : _gem5_process(nullptr) {} -sc_process_handle::sc_process_handle(const sc_process_handle &) +sc_process_handle::sc_process_handle(const sc_process_handle &handle) : + _gem5_process(handle._gem5_process) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + if (_gem5_process) + _gem5_process->incref(); } -sc_process_handle::sc_process_handle(sc_object *) +sc_process_handle::sc_process_handle(sc_object *obj) : + _gem5_process(dynamic_cast<::sc_gem5::Process *>(obj)) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + if (_gem5_process) + _gem5_process->incref(); } sc_process_handle::~sc_process_handle() { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + if (_gem5_process) + _gem5_process->decref(); } bool sc_process_handle::valid() const { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return false; + return _gem5_process != nullptr; } sc_process_handle & -sc_process_handle::operator = (const sc_process_handle &) +sc_process_handle::operator = (const sc_process_handle &handle) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + if (_gem5_process) + _gem5_process->decref(); + _gem5_process = handle._gem5_process; + if (_gem5_process) + _gem5_process->incref(); return *this; } bool -sc_process_handle::operator == (const sc_process_handle &) const +sc_process_handle::operator == (const sc_process_handle &handle) const { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return true; + return _gem5_process && handle._gem5_process && + (_gem5_process == handle._gem5_process); } bool -sc_process_handle::operator != (const sc_process_handle &) const +sc_process_handle::operator != (const sc_process_handle &handle) const { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return false; + return !(handle == *this); } bool -sc_process_handle::operator < (const sc_process_handle &) const +sc_process_handle::operator < (const sc_process_handle &other) const { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return false; + return _gem5_process < other._gem5_process; } -bool -sc_process_handle::swap(sc_process_handle &) +void +sc_process_handle::swap(sc_process_handle &handle) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return false; + ::sc_gem5::Process *temp = handle._gem5_process; + handle._gem5_process = _gem5_process; + _gem5_process = temp; } const char * sc_process_handle::name() const { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return ""; + return _gem5_process ? _gem5_process->name() : ""; } sc_curr_proc_kind sc_process_handle::proc_kind() const { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return SC_NO_PROC_; + return _gem5_process ? _gem5_process->procKind() : SC_NO_PROC_; } const std::vector & sc_process_handle::get_child_objects() const { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return *(const std::vector *)nullptr; + static const std::vector empty; + return _gem5_process ? _gem5_process->get_child_objects() : empty; } const std::vector & sc_process_handle::get_child_events() const { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return *(const std::vector *)nullptr; + static const std::vector empty; + return _gem5_process ? _gem5_process->get_child_events() : empty; } sc_object * sc_process_handle::get_parent_object() const { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return (sc_object *)nullptr; + return _gem5_process ? _gem5_process->get_parent_object() : nullptr; } sc_object * sc_process_handle::get_process_object() const { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return (sc_object *)nullptr; + return _gem5_process; } bool sc_process_handle::dynamic() const { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return false; + return _gem5_process ? _gem5_process->dynamic() : false; } bool sc_process_handle::terminated() const { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return false; + return _gem5_process ? _gem5_process->terminated() : false; } const sc_event & sc_process_handle::terminated_event() const { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return *(sc_event *)nullptr; + static sc_event non_event; + return _gem5_process ? _gem5_process->terminatedEvent() : non_event; } void sc_process_handle::suspend(sc_descendent_inclusion_info include_descendants) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + if (!_gem5_process) + return; + _gem5_process->suspend(include_descendants == SC_INCLUDE_DESCENDANTS); } void sc_process_handle::resume(sc_descendent_inclusion_info include_descendants) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + if (!_gem5_process) + return; + _gem5_process->resume(include_descendants == SC_INCLUDE_DESCENDANTS); } void sc_process_handle::disable(sc_descendent_inclusion_info include_descendants) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + if (!_gem5_process) + return; + _gem5_process->disable(include_descendants == SC_INCLUDE_DESCENDANTS); } void sc_process_handle::enable(sc_descendent_inclusion_info include_descendants) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + if (!_gem5_process) + return; + _gem5_process->enable(include_descendants == SC_INCLUDE_DESCENDANTS); } void sc_process_handle::kill(sc_descendent_inclusion_info include_descendants) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + if (!_gem5_process) + return; + _gem5_process->kill(include_descendants == SC_INCLUDE_DESCENDANTS); } void sc_process_handle::reset(sc_descendent_inclusion_info include_descendants) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + if (!_gem5_process) + return; + _gem5_process->reset(include_descendants == SC_INCLUDE_DESCENDANTS); } bool sc_process_handle::is_unwinding() { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return false; + if (!_gem5_process) { + //TODO This should generate a systemc style warning if the handle is + //invalid. + return false; + } else { + return _gem5_process->isUnwinding(); + } } const sc_event & sc_process_handle::reset_event() const { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return *(sc_event *)nullptr; + static sc_event non_event; + return _gem5_process ? _gem5_process->resetEvent() : non_event; } @@ -270,20 +273,18 @@ void sc_process_handle::sync_reset_on( sc_descendent_inclusion_info include_descendants) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + if (!_gem5_process) + return; + _gem5_process->syncResetOn(include_descendants == SC_INCLUDE_DESCENDANTS); } void sc_process_handle::sync_reset_off( sc_descendent_inclusion_info include_descendants) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); -} - -void -sc_process_handle::warn_unimpl(const char *func) -{ - warn("%s not implemented.\n", func); + if (!_gem5_process) + return; + _gem5_process->syncResetOff(include_descendants == SC_INCLUDE_DESCENDANTS); } @@ -291,14 +292,13 @@ sc_process_handle sc_get_current_process_handle() { warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return sc_process_handle(); + return sc_process_handle(nullptr /* Current process pointer */); } bool sc_is_unwinding() { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return false; + return sc_get_current_process_handle().is_unwinding(); } bool sc_allow_process_control_corners; diff --git a/src/systemc/core/sc_sensitive.cc b/src/systemc/core/sc_sensitive.cc index e182fa003..d233cda6a 100644 --- a/src/systemc/core/sc_sensitive.cc +++ b/src/systemc/core/sc_sensitive.cc @@ -33,6 +33,8 @@ namespace sc_core { +sc_sensitive::sc_sensitive() : currentProcess(nullptr) {} + sc_sensitive & sc_sensitive::operator << (const sc_event &) { @@ -61,4 +63,11 @@ sc_sensitive::operator << (sc_event_finder &) return *this; } +sc_sensitive & +sc_sensitive::operator << (::sc_gem5::Process *p) +{ + currentProcess = p; + return *this; +} + } // namespace sc_core diff --git a/src/systemc/ext/core/sc_module.hh b/src/systemc/ext/core/sc_module.hh index fd4a802b1..746e0c71e 100644 --- a/src/systemc/ext/core/sc_module.hh +++ b/src/systemc/ext/core/sc_module.hh @@ -47,6 +47,12 @@ namespace sc_gem5 { class Module; +class Process; +struct ProcessFuncWrapper; + +Process *newMethodProcess(const char *name, ProcessFuncWrapper *func); +Process *newThreadProcess(const char *name, ProcessFuncWrapper *func); +Process *newCThreadProcess(const char *name, ProcessFuncWrapper *func); } // namespace sc_gem5 @@ -271,9 +277,34 @@ bool timed_out(); #define SC_HAS_PROCESS(name) typedef name SC_CURRENT_USER_MODULE -#define SC_METHOD(name) /* Implementation defined */ -#define SC_THREAD(name) /* Implementation defined */ -#define SC_CTHREAD(name, clk) /* Implementation defined */ +#define SC_METHOD(name) \ + { \ + ::sc_gem5::Process *p = \ + ::sc_gem5::newMethodProcess( \ + #name, new ::sc_gem5::ProcessMemberFuncWrapper< \ + SC_CURRENT_USER_MODULE>(this, \ + &SC_CURRENT_USER_MODULE::name)); \ + this->sensitive << p; \ + } +#define SC_THREAD(name) \ + { \ + ::sc_gem5::Process *p = \ + ::sc_gem5::newThreadProcess( \ + #name, new ::sc_gem5::ProcessMemberFuncWrapper< \ + SC_CURRENT_USER_MODULE>(this, \ + &SC_CURRENT_USER_MODULE::name)); \ + this->sensitive << p; \ + } +#define SC_CTHREAD(name, clk) \ + { \ + ::sc_gem5::Process *p = \ + ::sc_gem5::newCThreadProcess( \ + #name, new ::sc_gem5::ProcessMemberFuncWrapper< \ + SC_CURRENT_USER_MODULE>(this, \ + &SC_CURRENT_USER_MODULE::name)); \ + this->sensitive << p; \ + this->sensitive << clk; \ + } // Nonstandard // Documentation for this is very scarce, but it looks like it's supposed to diff --git a/src/systemc/ext/core/sc_process_handle.hh b/src/systemc/ext/core/sc_process_handle.hh index e577b9e47..2db553b7a 100644 --- a/src/systemc/ext/core/sc_process_handle.hh +++ b/src/systemc/ext/core/sc_process_handle.hh @@ -38,6 +38,40 @@ namespace sc_gem5 class Process; +struct ProcessFuncWrapper +{ + virtual void call() = 0; + virtual ~ProcessFuncWrapper() {} +}; + +template +struct ProcessMemberFuncWrapper : public ProcessFuncWrapper +{ + typedef void (T::*TFunc)(); + T *t; + TFunc func; + + ProcessMemberFuncWrapper(T *t, TFunc func) : t(t), func(func) {} + + void call() override { (t->*func)(); } +}; + +struct ExceptionWrapperBase +{ + virtual void throw_it() = 0; +}; + +template +struct ExceptionWrapper : public ExceptionWrapperBase +{ + const T &t; + ExceptionWrapper(const T &t) : t(t) {} + + void throw_it() { throw t; } +}; + +void throw_it_wrapper(Process *p, ExceptionWrapperBase &exc, bool inc_kids); + } // namespace sc_gem5 namespace sc_core @@ -133,7 +167,7 @@ class sc_process_handle bool operator == (const sc_process_handle &) const; bool operator != (const sc_process_handle &) const; bool operator < (const sc_process_handle &) const; - bool swap(sc_process_handle &); + void swap(sc_process_handle &); const char *name() const; sc_curr_proc_kind proc_kind() const; @@ -165,13 +199,15 @@ class sc_process_handle void sync_reset_off(sc_descendent_inclusion_info include_descendants= SC_NO_DESCENDANTS); - void warn_unimpl(const char *func); template - void throw_it(const T &user_defined_exception, - sc_descendent_inclusion_info include_descendants= - SC_NO_DESCENDANTS) + void + throw_it(const T &user_defined_exception, + sc_descendent_inclusion_info include_descendants= + SC_NO_DESCENDANTS) { - warn_unimpl(__PRETTY_FUNCTION__); + ::sc_gem5::ExceptionWrapper exc(user_defined_exception); + ::sc_gem5::throw_it_wrapper(_gem5_process, exc, + include_descendants == SC_INCLUDE_DESCENDANTS); } }; diff --git a/src/systemc/ext/core/sc_sensitive.hh b/src/systemc/ext/core/sc_sensitive.hh index 62f18b6d2..72d401f68 100644 --- a/src/systemc/ext/core/sc_sensitive.hh +++ b/src/systemc/ext/core/sc_sensitive.hh @@ -30,12 +30,20 @@ #ifndef __SYSTEMC_EXT_CORE_SC_SENSITIVE_HH__ #define __SYSTEMC_EXT_CORE_SC_SENSITIVE_HH__ +namespace sc_gem5 +{ + +class Process; + +} // namespace sc_gem5 + namespace sc_core { class sc_event; class sc_event_finder; class sc_interface; +class sc_module; class sc_port_base; class sc_sensitive @@ -45,6 +53,20 @@ class sc_sensitive sc_sensitive &operator << (const sc_interface &); sc_sensitive &operator << (const sc_port_base &); sc_sensitive &operator << (sc_event_finder &); + + sc_sensitive &operator << (::sc_gem5::Process *p); + + private: + friend class sc_module; + + // Install all the static events which may not have been ready at + // construction time, like the default_event of the peer of an unbound + // port. + void finalize(); + + sc_sensitive(); + + ::sc_gem5::Process *currentProcess; }; } // namespace sc_core -- cgit v1.2.3