systemc: Implement SC_FORK, SC_JOIN, and SC_CJOIN.
authorGabe Black <gabeblack@google.com>
Tue, 11 Sep 2018 05:01:47 +0000 (22:01 -0700)
committerGabe Black <gabeblack@google.com>
Tue, 9 Oct 2018 21:45:46 +0000 (21:45 +0000)
SC_CJOIN is non-standard, but relied on by the Accellera tests.

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

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

index 553f332d3c7d6c7aa1884f53a37f01fe26bfe49a..1c7a9d72ea33b0fd2c6063a7327eade7f71def33 100644 (file)
@@ -32,6 +32,7 @@
 #include "base/logging.hh"
 #include "systemc/core/event.hh"
 #include "systemc/core/scheduler.hh"
+#include "systemc/ext/core/sc_join.hh"
 #include "systemc/ext/core/sc_main.hh"
 #include "systemc/ext/core/sc_process_handle.hh"
 #include "systemc/ext/utils/sc_report_handler.hh"
@@ -419,6 +420,10 @@ Process::terminate()
     staticSensitivities.clear();
 
     _terminatedEvent.notify();
+
+    for (auto jw: joinWaiters)
+        jw->signal();
+    joinWaiters.clear();
 }
 
 Process *Process::_newest;
index 4d88e27b841bf8a0fbf3f91ee24251975ba1a516..d399d7a3d4aabd3fa5743e8b950b832b24b43984 100644 (file)
 #include "systemc/ext/core/sc_process_handle.hh"
 #include "systemc/ext/utils/sc_report.hh"
 
+namespace sc_core
+{
+
+class sc_join;
+
+} // namespace sc_core
+
 namespace sc_gem5
 {
 
@@ -347,6 +354,8 @@ class Process : public ::sc_core::sc_process_b, public ListNode
     bool dontInitialize() { return _dontInitialize; }
     void dontInitialize(bool di) { _dontInitialize = di; }
 
+    void joinWait(::sc_core::sc_join *join) { joinWaiters.push_back(join); }
+
   protected:
     Process(const char *name, ProcessFuncWrapper *func, bool internal=false);
 
@@ -396,6 +405,8 @@ class Process : public ::sc_core::sc_process_b, public ListNode
     Sensitivity *dynamicSensitivity;
 
     std::unique_ptr<::sc_core::sc_report> _lastReport;
+
+    std::vector<::sc_core::sc_join *> joinWaiters;
 };
 
 inline void
index 4d531433ab5a6bb6ec5fe6d7cfe6aaca0fe8af98..3e4c6eec432cc75c35b17c5204bc9a509fc85142 100644 (file)
  */
 
 #include "base/logging.hh"
+#include "systemc/core/process.hh"
+#include "systemc/ext/core/sc_event.hh"
 #include "systemc/ext/core/sc_join.hh"
+#include "systemc/ext/core/sc_module.hh"
 
 namespace sc_core
 {
 
-sc_join::sc_join()
-{
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-}
+sc_join::sc_join() : remaining(0) {}
 
 void
-sc_join::add_process(sc_process_handle)
-{
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-}
-
-int
-sc_join::process_count()
+sc_join::add_process(sc_process_handle h)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return 0;
-}
+    auto p = (::sc_gem5::Process *)h;
+    assert(p);
 
-void
-sc_join::signal(sc_thread_handle thread_p, int type)
-{
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    remaining++;
+    p->joinWait(this);
 }
 
-void
-sc_join::wait()
-{
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-}
-
-void
-sc_join::wait_clocked()
-{
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-}
+int sc_join::process_count() { return remaining; }
+void sc_join::signal() { if (!--remaining) joinEvent.notify(); }
+void sc_join::wait() { ::sc_core::wait(joinEvent); }
+void sc_join::wait_clocked() { do { ::sc_core::wait(); } while (remaining); }
 
 } // namespace sc_core
index 18119ae3d95d871dfb3735b77ceb7061130d8b6d..49e54ceeeb81a0129546e44f2bd943367fe86eeb 100644 (file)
@@ -30,6 +30,7 @@
 #ifndef __SYSTEMC_EXT_CORE_SC_JOIN_HH__
 #define __SYSTEMC_EXT_CORE_SC_JOIN_HH__
 
+#include "sc_event.hh"
 #include "sc_process_handle.hh"
 
 namespace sc_core
@@ -43,11 +44,16 @@ class sc_join
 {
   public:
     sc_join();
+
     void add_process(sc_process_handle);
     int process_count();
-    virtual void signal(sc_thread_handle thread_p, int type);
+    void signal();
     void wait();
     void wait_clocked();
+
+  private:
+    sc_event joinEvent;
+    int remaining;
 };
 
 } // namespace sc_core
index 82851542dddce63c6bb8d5b857a3a733e486d483..d97883035d53851473666c1cba1310a750aa42a6 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <vector>
 
+#include "sc_join.hh"
 #include "sc_process_handle.hh"
 
 namespace sc_core
@@ -166,11 +167,22 @@ sc_spawn(typename T::result_type *r_p, T object, const char *name_p=nullptr,
     ::sc_core::sc_process_handle forkees[] = {
 
 #define SC_JOIN \
-    }; /* TODO wait for the forkees. */ \
+    }; \
+    ::sc_core::sc_join join; \
+    for (int i = 0; i < sizeof(forkees) / sizeof(forkees[0]); i++) \
+        join.add_process(forkees[i]); \
+    join.wait(); \
 }
 
 // Non-standard
-#define SC_CJOIN SC_JOIN
+#define SC_CJOIN \
+    }; \
+    ::sc_core::sc_join join; \
+    for (int i = 0; i < sizeof(forkees) / sizeof(forkees[0]); i++) \
+        join.add_process(forkees[i]); \
+    join.wait_clocked(); \
+}
+
 
 } // namespace sc_core