systemc: Fill out sc_process_handle and create Process classes.
authorGabe Black <gabeblack@google.com>
Fri, 29 Jun 2018 23:46:52 +0000 (16:46 -0700)
committerGabe Black <gabeblack@google.com>
Wed, 5 Sep 2018 06:02:51 +0000 (06:02 +0000)
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 <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>

src/systemc/core/SConscript
src/systemc/core/object.cc
src/systemc/core/process.cc [new file with mode: 0644]
src/systemc/core/process.hh [new file with mode: 0644]
src/systemc/core/sc_module.cc
src/systemc/core/sc_process_handle.cc
src/systemc/core/sc_sensitive.cc
src/systemc/ext/core/sc_module.hh
src/systemc/ext/core/sc_process_handle.hh
src/systemc/ext/core/sc_sensitive.hh

index a07c026830a6658ee51ce9f337a65d92d6d0e7a4..f4d65060fb355374a03ec9a3d1d04bb19fa78683 100644 (file)
@@ -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')
index 8d2b73545d056a1b4d28ae9d3f622dbe3297b015..cfd4c5e93fa3248f1f7c4cd6142e034cd6c25938 100644 (file)
@@ -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 (file)
index 0000000..4597d8b
--- /dev/null
@@ -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 <typename T>
+struct BuiltinExceptionWrapper : public ExceptionWrapperBase
+{
+  public:
+    T t;
+    void throw_it() override { throw t; }
+};
+
+BuiltinExceptionWrapper<UnwindExceptionReset> resetException;
+BuiltinExceptionWrapper<UnwindExceptionKill> killException;
+
+
+void
+Process::forEachKid(const std::function<void(Process *)> &work)
+{
+    for (auto &kid: get_child_objects()) {
+        Process *p_kid = dynamic_cast<Process *>(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 (file)
index 0000000..07ef97c
--- /dev/null
@@ -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 <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
+{
+
+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<void(Process *)> &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__
index 89f74c7f2d7bdfc5193171c869b0f2a2e5910349..44369d751209d29262b25d18253e76643b8db1e9 100644 (file)
 
 #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())
 {}
 
index cf81f9ff5526513ed0923e3533bf2acf0705b95e..eff2490ba2be9c6423e2ce6c76c7f03b860623ee 100644 (file)
@@ -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_object *> &
 sc_process_handle::get_child_objects() const
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return *(const std::vector<sc_object *> *)nullptr;
+    static const std::vector<sc_object *> empty;
+    return _gem5_process ? _gem5_process->get_child_objects() : empty;
 }
 
 const std::vector<sc_event *> &
 sc_process_handle::get_child_events() const
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return *(const std::vector<sc_event *> *)nullptr;
+    static const std::vector<sc_event *> 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;
index e182fa003af0bc84143c752e8b95b8a9b1b99508..d233cda6aaf5d68496f0d6870c15ad889b7c268b 100644 (file)
@@ -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
index fd4a802b14bf3646190890bd3666b13ca07d15a4..746e0c71e86454c254dc90ba54a562c86f1993c3 100644 (file)
@@ -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
index e577b9e47af8bf8d1979b55a1ea05c4ec69155c6..2db553b7a1d121b611cdc89c42adfcef1e00b6de 100644 (file)
@@ -38,6 +38,40 @@ namespace sc_gem5
 
 class Process;
 
+struct ProcessFuncWrapper
+{
+    virtual void call() = 0;
+    virtual ~ProcessFuncWrapper() {}
+};
+
+template <typename T>
+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 <typename T>
+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 <typename T>
-    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<T> exc(user_defined_exception);
+        ::sc_gem5::throw_it_wrapper(_gem5_process, exc,
+                include_descendants == SC_INCLUDE_DESCENDANTS);
     }
 };
 
index 62f18b6d25e13dd2c8b02a713850a1ffd2225dfd..72d401f683ae66bfbf4e24634ffb4f6802704cbe 100644 (file)
 #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