From 960c3500532a0ca28e4192f838e81eeb7c29860c Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Mon, 10 Sep 2018 22:01:47 -0700 Subject: [PATCH] systemc: Implement SC_FORK, SC_JOIN, and SC_CJOIN. 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 Maintainer: Gabe Black --- src/systemc/core/process.cc | 5 ++++ src/systemc/core/process.hh | 11 +++++++++ src/systemc/core/sc_join.cc | 42 ++++++++++---------------------- src/systemc/ext/core/sc_join.hh | 8 +++++- src/systemc/ext/core/sc_spawn.hh | 16 ++++++++++-- 5 files changed, 50 insertions(+), 32 deletions(-) diff --git a/src/systemc/core/process.cc b/src/systemc/core/process.cc index 553f332d3..1c7a9d72e 100644 --- a/src/systemc/core/process.cc +++ b/src/systemc/core/process.cc @@ -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; diff --git a/src/systemc/core/process.hh b/src/systemc/core/process.hh index 4d88e27b8..d399d7a3d 100644 --- a/src/systemc/core/process.hh +++ b/src/systemc/core/process.hh @@ -49,6 +49,13 @@ #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 diff --git a/src/systemc/core/sc_join.cc b/src/systemc/core/sc_join.cc index 4d531433a..3e4c6eec4 100644 --- a/src/systemc/core/sc_join.cc +++ b/src/systemc/core/sc_join.cc @@ -28,45 +28,29 @@ */ #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 diff --git a/src/systemc/ext/core/sc_join.hh b/src/systemc/ext/core/sc_join.hh index 18119ae3d..49e54ceee 100644 --- a/src/systemc/ext/core/sc_join.hh +++ b/src/systemc/ext/core/sc_join.hh @@ -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 diff --git a/src/systemc/ext/core/sc_spawn.hh b/src/systemc/ext/core/sc_spawn.hh index 82851542d..d97883035 100644 --- a/src/systemc/ext/core/sc_spawn.hh +++ b/src/systemc/ext/core/sc_spawn.hh @@ -32,6 +32,7 @@ #include +#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 -- 2.30.2