diff options
-rw-r--r-- | src/systemc/core/SConscript | 1 | ||||
-rw-r--r-- | src/systemc/core/kernel.cc | 11 | ||||
-rw-r--r-- | src/systemc/core/kernel.hh | 3 | ||||
-rw-r--r-- | src/systemc/core/sc_main.cc | 96 | ||||
-rw-r--r-- | src/systemc/core/sc_main_fiber.cc | 82 | ||||
-rw-r--r-- | src/systemc/core/sc_main_fiber.hh | 70 | ||||
-rw-r--r-- | src/systemc/core/scheduler.cc | 18 | ||||
-rw-r--r-- | src/systemc/core/scheduler.hh | 3 |
8 files changed, 186 insertions, 98 deletions
diff --git a/src/systemc/core/SConscript b/src/systemc/core/SConscript index 1f5498b93..41abba417 100644 --- a/src/systemc/core/SConscript +++ b/src/systemc/core/SConscript @@ -50,6 +50,7 @@ if env['USE_SYSTEMC']: Source('sc_interface.cc') Source('sc_join.cc') Source('sc_main.cc') + Source('sc_main_fiber.cc') Source('sc_module.cc') Source('sc_module_name.cc') Source('sc_object.cc') diff --git a/src/systemc/core/kernel.cc b/src/systemc/core/kernel.cc index 11292c4a5..2fd3027da 100644 --- a/src/systemc/core/kernel.cc +++ b/src/systemc/core/kernel.cc @@ -33,6 +33,7 @@ #include "systemc/core/channel.hh" #include "systemc/core/module.hh" #include "systemc/core/port.hh" +#include "systemc/core/sc_main_fiber.hh" #include "systemc/core/scheduler.hh" namespace sc_gem5 @@ -41,7 +42,6 @@ namespace sc_gem5 namespace { -bool scMainDone = false; bool stopAfterCallbacks = false; bool startComplete = false; bool endComplete = false; @@ -53,9 +53,6 @@ sc_core::sc_status _status = sc_core::SC_ELABORATION; bool Kernel::startOfSimulationComplete() { return startComplete; } bool Kernel::endOfSimulationComplete() { return endComplete; } -bool Kernel::scMainFinished() { return scMainDone; } -void Kernel::scMainFinished(bool finished) { scMainDone = finished; } - sc_core::sc_status Kernel::status() { return _status; } void Kernel::status(sc_core::sc_status s) { _status = s; } @@ -69,7 +66,7 @@ Kernel::Kernel(Params *params) : void Kernel::init() { - if (scMainDone) + if (scMainFiber.finished()) return; if (stopAfterCallbacks) @@ -89,7 +86,7 @@ Kernel::init() void Kernel::regStats() { - if (scMainDone || stopAfterCallbacks) + if (scMainFiber.finished() || stopAfterCallbacks) return; try { @@ -113,7 +110,7 @@ Kernel::regStats() void Kernel::startup() { - if (scMainDone) + if (scMainFiber.finished()) return; schedule(t0Event, curTick()); diff --git a/src/systemc/core/kernel.hh b/src/systemc/core/kernel.hh index e0808fe47..b9a37d00a 100644 --- a/src/systemc/core/kernel.hh +++ b/src/systemc/core/kernel.hh @@ -64,9 +64,6 @@ class Kernel : public SimObject static bool startOfSimulationComplete(); static bool endOfSimulationComplete(); - static bool scMainFinished(); - static void scMainFinished(bool); - private: static void stopWork(); diff --git a/src/systemc/core/sc_main.cc b/src/systemc/core/sc_main.cc index a5e0366b9..e2f69bb58 100644 --- a/src/systemc/core/sc_main.cc +++ b/src/systemc/core/sc_main.cc @@ -38,119 +38,67 @@ #include "sim/init.hh" #include "systemc/core/kernel.hh" #include "systemc/core/python.hh" +#include "systemc/core/sc_main_fiber.hh" #include "systemc/core/scheduler.hh" #include "systemc/ext/core/messages.hh" #include "systemc/ext/core/sc_main.hh" #include "systemc/ext/utils/sc_report_handler.hh" #include "systemc/utils/report.hh" -// A weak symbol to detect if sc_main has been defined, and if so where it is. -[[gnu::weak]] int sc_main(int argc, char *argv[]); - namespace sc_core { namespace { -bool scMainCalled = false; - -int _argc = 0; -char **_argv = NULL; - -class ScMainFiber : public Fiber -{ - public: - std::string resultStr; - int resultInt; - - ScMainFiber() : resultInt(1) {} - - void - main() - { - if (::sc_main) { - try { - resultInt = ::sc_main(_argc, _argv); - if (resultInt) - resultStr = "sc_main returned non-zero"; - else - resultStr = "sc_main finished"; - // Make sure no systemc events/notifications are scheduled - // after sc_main returns. - } catch (const sc_report &r) { - // There was an exception nobody caught. - resultStr = "uncaught sc_report"; - sc_gem5::reportHandlerProc( - r, sc_report_handler::get_catch_actions()); - } catch (...) { - // There was some other type of exception we need to wrap. - resultStr = "uncaught exception"; - sc_gem5::reportHandlerProc( - ::sc_gem5::reportifyException(), - sc_report_handler::get_catch_actions()); - } - ::sc_gem5::Kernel::scMainFinished(true); - ::sc_gem5::scheduler.clear(); - } else { - // If python tries to call sc_main but no sc_main was defined... - fatal("sc_main called but not defined.\n"); - } - } -}; - -ScMainFiber scMainFiber; - // This wrapper adapts the python version of sc_main to the c++ version. void sc_main(pybind11::args args) { - panic_if(scMainCalled, "sc_main called more than once."); + panic_if(::sc_gem5::scMainFiber.called(), + "sc_main called more than once."); - _argc = args.size(); - _argv = new char *[_argc]; + int argc = args.size(); + char **argv = new char *[argc]; - // Initialize all the _argvs to NULL so we can delete [] them + // Initialize all the argvs to NULL so we can delete [] them // unconditionally. - for (int idx = 0; idx < _argc; idx++) - _argv[idx] = NULL; + for (int idx = 0; idx < argc; idx++) + argv[idx] = NULL; // Attempt to convert all the arguments to strings. If that fails, clean // up after ourselves. Also don't count this as a call to sc_main since // we never got to the c++ version of that function. try { - for (int idx = 0; idx < _argc; idx++) { + for (int idx = 0; idx < argc; idx++) { std::string arg = args[idx].cast<std::string>(); - _argv[idx] = new char[arg.length() + 1]; - strcpy(_argv[idx], arg.c_str()); + argv[idx] = new char[arg.length() + 1]; + strcpy(argv[idx], arg.c_str()); } } catch (...) { // If that didn't work for some reason (probably a conversion error) - // blow away _argv and _argc and pass on the exception. - for (int idx = 0; idx < _argc; idx++) - delete [] _argv[idx]; - delete [] _argv; - _argc = 0; + // blow away argv and argc and pass on the exception. + for (int idx = 0; idx < argc; idx++) + delete [] argv[idx]; + delete [] argv; + argc = 0; throw; } - // At this point we're going to call the c++ sc_main, so we can't try - // again later. - scMainCalled = true; - - scMainFiber.run(); + ::sc_gem5::scMainFiber.setArgs(argc, argv); + ::sc_gem5::scMainFiber.run(); } int sc_main_result_code() { - return scMainFiber.resultInt; + return ::sc_gem5::scMainFiber.resultInt(); } std::string sc_main_result_str() { - return scMainFiber.resultStr; + return ::sc_gem5::scMainFiber.resultStr(); } // Make our sc_main wrapper available in the internal _m5 python module under @@ -174,13 +122,13 @@ sc_stop_mode _stop_mode = SC_STOP_FINISH_DELTA; int sc_argc() { - return _argc; + return ::sc_gem5::scMainFiber.argc(); } const char *const * sc_argv() { - return _argv; + return ::sc_gem5::scMainFiber.argv(); } void diff --git a/src/systemc/core/sc_main_fiber.cc b/src/systemc/core/sc_main_fiber.cc new file mode 100644 index 000000000..aa10c19c4 --- /dev/null +++ b/src/systemc/core/sc_main_fiber.cc @@ -0,0 +1,82 @@ +/* + * 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/sc_main_fiber.hh" + +#include <cstring> +#include <string> + +#include "systemc/core/kernel.hh" +#include "systemc/core/scheduler.hh" +#include "systemc/ext/core/messages.hh" +#include "systemc/ext/core/sc_main.hh" +#include "systemc/ext/utils/sc_report_handler.hh" +#include "systemc/utils/report.hh" + +// A weak symbol to detect if sc_main has been defined, and if so where it is. +[[gnu::weak]] int sc_main(int argc, char *argv[]); + +namespace sc_gem5 +{ + +void +ScMainFiber::main() +{ + _called = true; + + if (::sc_main) { + try { + _resultInt = ::sc_main(_argc, _argv); + if (_resultInt) + _resultStr = "sc_main returned non-zero"; + else + _resultStr = "sc_main finished"; + // Make sure no systemc events/notifications are scheduled + // after sc_main returns. + } catch (const ::sc_core::sc_report &r) { + // There was an exception nobody caught. + _resultStr = "uncaught sc_report"; + reportHandlerProc( + r, ::sc_core::sc_report_handler::get_catch_actions()); + } catch (...) { + // There was some other type of exception we need to wrap. + _resultStr = "uncaught exception"; + reportHandlerProc(reportifyException(), + ::sc_core::sc_report_handler::get_catch_actions()); + } + scheduler.clear(); + } else { + // If python tries to call sc_main but no sc_main was defined... + fatal("sc_main called but not defined.\n"); + } +} + +ScMainFiber scMainFiber; + +} // namespace sc_gem5 diff --git a/src/systemc/core/sc_main_fiber.hh b/src/systemc/core/sc_main_fiber.hh new file mode 100644 index 000000000..2e89f11df --- /dev/null +++ b/src/systemc/core/sc_main_fiber.hh @@ -0,0 +1,70 @@ +/* + * 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_SC_MAIN_FIBER_HH__ +#define __SYSTEMC_CORE_SC_MAIN_FIBER_HH__ + +#include "base/fiber.hh" +#include "base/logging.hh" + +namespace sc_gem5 +{ + +class ScMainFiber : public Fiber +{ + private: + int _argc = 0; + char **_argv = NULL; + std::string _resultStr; + int _resultInt = 1; + + bool _called = false; + + public: + int argc() { return _argc; } + const char *const *argv() { return _argv; } + std::string resultStr() { return _resultStr; } + int resultInt() { return _resultInt; } + bool called() { return _called; } + + void + setArgs(int new_argc, char **new_argv) + { + _argc = new_argc; + _argv = new_argv; + } + + void main() override; +}; + +extern ScMainFiber scMainFiber; + +} // namespace sc_gem5 + +#endif // __SYSTEMC_CORE_SC_MAIN_FIBER_HH__ diff --git a/src/systemc/core/scheduler.cc b/src/systemc/core/scheduler.cc index 5e96a47d5..a2e52f0ca 100644 --- a/src/systemc/core/scheduler.cc +++ b/src/systemc/core/scheduler.cc @@ -33,6 +33,7 @@ #include "base/logging.hh" #include "sim/eventq.hh" #include "systemc/core/kernel.hh" +#include "systemc/core/sc_main_fiber.hh" #include "systemc/ext/core/messages.hh" #include "systemc/ext/core/sc_main.hh" #include "systemc/ext/utils/sc_report.hh" @@ -46,8 +47,7 @@ namespace sc_gem5 Scheduler::Scheduler() : eq(nullptr), readyEvent(this, false, ReadyPriority), pauseEvent(this, false, PausePriority), - stopEvent(this, false, StopPriority), - scMain(nullptr), _throwToScMain(nullptr), + stopEvent(this, false, StopPriority), _throwToScMain(nullptr), starvationEvent(this, false, StarvationPriority), _elaborationDone(false), _started(false), _stopNow(false), _status(StatusOther), maxTickEvent(this, false, MaxTickPriority), @@ -349,8 +349,8 @@ Scheduler::pause() status(StatusPaused); kernel->status(::sc_core::SC_PAUSED); runOnce = false; - if (scMain && !scMain->finished()) - scMain->run(); + if (scMainFiber.called() && !scMainFiber.finished()) + scMainFiber.run(); } void @@ -362,17 +362,13 @@ Scheduler::stop() clear(); runOnce = false; - if (scMain && !scMain->finished()) - scMain->run(); + if (scMainFiber.called() && !scMainFiber.finished()) + scMainFiber.run(); } void Scheduler::start(Tick max_tick, bool run_to_time) { - // We should be running from sc_main. Keep track of that Fiber to return - // to later. - scMain = Fiber::currentFiber(); - _started = true; status(StatusOther); runToTime = run_to_time; @@ -431,7 +427,7 @@ Scheduler::throwToScMain() ::sc_core::sc_report report = reportifyException(); _throwToScMain = &report; status(StatusOther); - scMain->run(); + scMainFiber.run(); } void diff --git a/src/systemc/core/scheduler.hh b/src/systemc/core/scheduler.hh index 2ae03ea1b..64841086d 100644 --- a/src/systemc/core/scheduler.hh +++ b/src/systemc/core/scheduler.hh @@ -333,8 +333,6 @@ class Scheduler // Run delta events. void runDelta(); - void setScMainFiber(Fiber *sc_main) { scMain = sc_main; } - void start(Tick max_tick, bool run_to_time); void oneCycle(); @@ -426,7 +424,6 @@ class Scheduler EventWrapper<Scheduler, &Scheduler::pause> pauseEvent; EventWrapper<Scheduler, &Scheduler::stop> stopEvent; - Fiber *scMain; const ::sc_core::sc_report *_throwToScMain; bool |