systemc: Implement much of sc_spawn.
authorGabe Black <gabeblack@google.com>
Sat, 21 Jul 2018 02:27:27 +0000 (19:27 -0700)
committerGabe Black <gabeblack@google.com>
Tue, 11 Sep 2018 21:45:43 +0000 (21:45 +0000)
This doesn't implement reset signals, although those aren't implemented
for static processes either yet.

Change-Id: I748a7f75b9b91774c91d969bc1ff5b07e1711aa3
Reviewed-on: https://gem5-review.googlesource.com/12044
Reviewed-by: Gabe Black <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>

src/systemc/core/process.cc
src/systemc/core/sc_module.cc
src/systemc/core/sc_spawn.cc
src/systemc/ext/core/sc_spawn.hh

index ad297a23c789c2c7d36decc6d597326361547a96..678cb04dbc1d3b76fc61748e0e14563005cbd8f9 100644 (file)
@@ -338,10 +338,6 @@ Process::Process(const char *name, ProcessFuncWrapper *func,
     dynamicSensitivity(nullptr)
 {
     _newest = this;
-    if (_dynamic)
-        finalize();
-    else
-        scheduler.reg(this);
 }
 
 Process *Process::_newest;
index 499a741ce5ba20e05e5684d639f1d6f8c2e66d9e..bd0b2e1472546eec02f49445cc34fb3c87f9e34e 100644 (file)
@@ -43,19 +43,25 @@ namespace sc_gem5
 Process *
 newMethodProcess(const char *name, ProcessFuncWrapper *func)
 {
-    return new Method(name, func);
+    Process *p = new Method(name, func);
+    scheduler.reg(p);
+    return p;
 }
 
 Process *
 newThreadProcess(const char *name, ProcessFuncWrapper *func)
 {
-    return new Thread(name, func);
+    Process *p = new Thread(name, func);
+    scheduler.reg(p);
+    return p;
 }
 
 Process *
 newCThreadProcess(const char *name, ProcessFuncWrapper *func)
 {
-    return new CThread(name, func);
+    Process *p = new CThread(name, func);
+    scheduler.reg(p);
+    return p;
 }
 
 } // namespace sc_gem5
index fd7dc0ad04bd856477e1bd447d3fcad42dace26f..ecb0bbc3fdc5848209be25d98b9ed896856ee322 100644 (file)
  */
 
 #include "base/logging.hh"
+#include "systemc/core/process.hh"
+#include "systemc/core/process_types.hh"
+#include "systemc/core/scheduler.hh"
+#include "systemc/ext/core/sc_module.hh"
 #include "systemc/ext/core/sc_spawn.hh"
 
-namespace sc_core
+namespace sc_gem5
 {
 
-sc_spawn_options::sc_spawn_options()
+Process *
+spawnWork(ProcessFuncWrapper *func, const char *name,
+          const ::sc_core::sc_spawn_options *opts)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    bool method = false;
+    bool dontInitialize = false;
+    if (opts) {
+        if (opts->_spawnMethod)
+            method = true;
+        if (opts->_dontInitialize)
+            dontInitialize = true;
+        if (opts->_stackSize != -1)
+            warn("Ignoring request to set stack size.\n");
+    }
+
+    if (!name || name[0] == '\0') {
+        if (method)
+            name = ::sc_core::sc_gen_unique_name("method_p");
+        else
+            name = ::sc_core::sc_gen_unique_name("thread_p");
+    }
+
+    Process *proc;
+    if (method)
+        proc = new Method(name, func, true);
+    else
+        proc = new Thread(name, func, true);
+
+    if (opts) {
+        for (auto e: opts->_events)
+            proc->addStatic(new PendingSensitivityEvent(proc, e));
+
+        for (auto p: opts->_ports)
+            proc->addStatic(new PendingSensitivityPort(proc, p));
+
+        for (auto e: opts->_exports)
+            proc->addStatic(new PendingSensitivityExport(proc, e));
+
+        for (auto i: opts->_interfaces)
+            proc->addStatic(new PendingSensitivityInterface(proc, i));
+
+        for (auto f: opts->_finders)
+            proc->addStatic(new PendingSensitivityFinder(proc, f));
+    }
+
+    scheduler.reg(proc);
+
+    if (dontInitialize)
+        scheduler.dontInitialize(proc);
+
+    return proc;
 }
 
+} // namespace sc_gem5
+
+namespace sc_core
+{
+
+sc_spawn_options::sc_spawn_options() :
+    _spawnMethod(false), _dontInitialize(false), _stackSize(-1)
+{}
+
 
 void
 sc_spawn_options::spawn_method()
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    _spawnMethod = true;
 }
 
 void
 sc_spawn_options::dont_initialize()
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    _dontInitialize = true;
 }
 
 void
-sc_spawn_options::set_stack_size(int)
+sc_spawn_options::set_stack_size(int ss)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    _stackSize = ss;
 }
 
 
 void
-sc_spawn_options::set_sensitivity(const sc_event *)
+sc_spawn_options::set_sensitivity(const sc_event *e)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    _events.push_back(e);
 }
 
 void
-sc_spawn_options::set_sensitivity(sc_port_base *)
+sc_spawn_options::set_sensitivity(sc_port_base *p)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    _ports.push_back(p);
 }
 
 void
-sc_spawn_options::set_sensitivity(sc_export_base *)
+sc_spawn_options::set_sensitivity(sc_export_base *e)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    _exports.push_back(e);
 }
 
 void
-sc_spawn_options::set_sensitivity(sc_interface *)
+sc_spawn_options::set_sensitivity(sc_interface *i)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    _interfaces.push_back(i);
 }
 
 void
-sc_spawn_options::set_sensitivity(sc_event_finder *)
+sc_spawn_options::set_sensitivity(sc_event_finder *f)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    _finders.push_back(f);
 }
 
 
index 0463dc133e7a1a2bfde06d785468c4f46ae527b1..82851542dddce63c6bb8d5b857a3a733e486d483 100644 (file)
 #ifndef __SYSTEMC_EXT_CORE_SC_SPAWN_HH__
 #define __SYSTEMC_EXT_CORE_SC_SPAWN_HH__
 
+#include <vector>
+
 #include "sc_process_handle.hh"
 
 namespace sc_core
 {
 
+class sc_spawn_options;
+
+} // namespace sc_core
+
+namespace sc_gem5
+{
+
+class Process;
+
+template <typename T>
+struct ProcessObjFuncWrapper : public ProcessFuncWrapper
+{
+    T t;
+
+    ProcessObjFuncWrapper(T t) : t(t) {}
+
+    void call() override { t(); }
+};
+
+template <typename T, typename R>
+struct ProcessObjRetFuncWrapper : public ProcessFuncWrapper
+{
+    T t;
+    R *r;
+
+    ProcessObjRetFuncWrapper(T t, R *r) : t(t), r(r) {}
+
+    void call() override { *r = t(); }
+};
+
+Process *spawnWork(ProcessFuncWrapper *func, const char *name,
+                   const ::sc_core::sc_spawn_options *);
+
+} // namespace sc_gem5
+
+namespace sc_core
+{
+
 template <class T>
 class sc_in;
 template <class T>
@@ -53,6 +93,10 @@ class sc_port_base;
 class sc_spawn_options
 {
   public:
+    friend ::sc_gem5::Process *::sc_gem5::spawnWork(
+            ::sc_gem5::ProcessFuncWrapper *, const char *,
+            const sc_spawn_options *);
+
     sc_spawn_options();
 
     void spawn_method();
@@ -76,6 +120,15 @@ class sc_spawn_options
     void async_reset_signal_is(const sc_signal_in_if<bool> &, bool);
 
   private:
+    bool _spawnMethod;
+    bool _dontInitialize;
+    int _stackSize;
+    std::vector<const sc_event *> _events;
+    std::vector<sc_port_base *> _ports;
+    std::vector<sc_export_base *> _exports;
+    std::vector<sc_interface *> _interfaces;
+    std::vector<sc_event_finder *> _finders;
+
     // Disabled
     sc_spawn_options(const sc_spawn_options &) {}
     sc_spawn_options &operator = (const sc_spawn_options &) { return *this; }
@@ -88,8 +141,9 @@ sc_process_handle
 sc_spawn(T object, const char *name_p=nullptr,
          const sc_spawn_options *opt_p=nullptr)
 {
-    sc_spawn_warn_unimpl(__PRETTY_FUNCTION__);
-    return sc_process_handle();
+    auto func = new ::sc_gem5::ProcessObjFuncWrapper<T>(object);
+    ::sc_gem5::Process *p = spawnWork(func, name_p, opt_p);
+    return sc_process_handle() = p;
 }
 
 template <typename T>
@@ -97,8 +151,10 @@ sc_process_handle
 sc_spawn(typename T::result_type *r_p, T object, const char *name_p=nullptr,
          const sc_spawn_options *opt_p=nullptr)
 {
-    sc_spawn_warn_unimpl(__PRETTY_FUNCTION__);
-    return sc_process_handle();
+    auto func = new ::sc_gem5::ProcessObjRetFuncWrapper<
+        T, typename T::result_type>(object, r_p);
+    ::sc_gem5::Process *p = spawnWork(func, name_p, opt_p);
+    return sc_process_handle() = p;
 }
 
 #define sc_bind boost::bind