summaryrefslogtreecommitdiff
path: root/src/systemc
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemc')
-rw-r--r--src/systemc/core/process.cc2
-rw-r--r--src/systemc/core/process_types.hh8
-rw-r--r--src/systemc/core/sc_main.cc4
-rw-r--r--src/systemc/core/scheduler.cc73
-rw-r--r--src/systemc/core/scheduler.hh6
-rw-r--r--src/systemc/ext/utils/sc_report_handler.hh4
-rwxr-xr-xsrc/systemc/tests/config.py7
-rw-r--r--src/systemc/utils/sc_report_handler.cc6
8 files changed, 101 insertions, 9 deletions
diff --git a/src/systemc/core/process.cc b/src/systemc/core/process.cc
index 317e8c3a2..cc2eff512 100644
--- a/src/systemc/core/process.cc
+++ b/src/systemc/core/process.cc
@@ -343,6 +343,8 @@ Process::run()
} catch(const ::sc_core::sc_unwind_exception &exc) {
reset = exc.is_reset();
_isUnwinding = false;
+ } catch (...) {
+ throw;
}
} while (reset);
needsStart(true);
diff --git a/src/systemc/core/process_types.hh b/src/systemc/core/process_types.hh
index 6f603e73f..748c24914 100644
--- a/src/systemc/core/process_types.hh
+++ b/src/systemc/core/process_types.hh
@@ -92,7 +92,13 @@ class Thread : public Process
main() override
{
thread->_needsStart = false;
- thread->run();
+ try {
+ thread->run();
+ } catch (...) {
+ thread->terminate();
+ scheduler.throwToScMain();
+ return;
+ }
thread->terminate();
scheduler.yield();
}
diff --git a/src/systemc/core/sc_main.cc b/src/systemc/core/sc_main.cc
index 2637cef0e..5e1cd4fe6 100644
--- a/src/systemc/core/sc_main.cc
+++ b/src/systemc/core/sc_main.cc
@@ -79,6 +79,10 @@ class ScMainFiber : public Fiber
} catch (const sc_report &r) {
// There was an exception nobody caught.
resultStr = r.what();
+ } catch (...) {
+ // There was some other type of exception we need to wrap.
+ const sc_report *r = ::sc_gem5::reportifyException();
+ resultStr = r->what();
}
::sc_gem5::Kernel::scMainFinished(true);
::sc_gem5::scheduler.clear();
diff --git a/src/systemc/core/scheduler.cc b/src/systemc/core/scheduler.cc
index 4c98b68aa..5348e6665 100644
--- a/src/systemc/core/scheduler.cc
+++ b/src/systemc/core/scheduler.cc
@@ -34,6 +34,8 @@
#include "sim/eventq.hh"
#include "systemc/core/kernel.hh"
#include "systemc/ext/core/sc_main.hh"
+#include "systemc/ext/utils/sc_report.hh"
+#include "systemc/ext/utils/sc_report_handler.hh"
namespace sc_gem5
{
@@ -42,7 +44,7 @@ Scheduler::Scheduler() :
eq(nullptr), readyEvent(this, false, ReadyPriority),
pauseEvent(this, false, PausePriority),
stopEvent(this, false, StopPriority),
- scMain(nullptr),
+ scMain(nullptr), _throwToScMain(nullptr),
starvationEvent(this, false, StarvationPriority),
_started(false), _paused(false), _stopped(false), _stopNow(false),
maxTickEvent(this, false, MaxTickPriority),
@@ -184,7 +186,11 @@ Scheduler::yield()
// If the current process needs to be manually started, start it.
if (_current && _current->needsStart()) {
_current->needsStart(false);
- _current->run();
+ try {
+ _current->run();
+ } catch (...) {
+ throwToScMain();
+ }
}
}
if (_current && _current->excWrapper) {
@@ -336,7 +342,8 @@ Scheduler::pause()
_paused = true;
kernel->status(::sc_core::SC_PAUSED);
runOnce = false;
- scMain->run();
+ if (scMain && !scMain->finished())
+ scMain->run();
}
void
@@ -348,7 +355,8 @@ Scheduler::stop()
clear();
runOnce = false;
- scMain->run();
+ if (scMain && !scMain->finished())
+ scMain->run();
}
void
@@ -385,6 +393,12 @@ Scheduler::start(Tick max_tick, bool run_to_time)
deschedule(&maxTickEvent);
if (starvationEvent.scheduled())
deschedule(&starvationEvent);
+
+ if (_throwToScMain) {
+ const ::sc_core::sc_report *to_throw = _throwToScMain;
+ _throwToScMain = nullptr;
+ throw *to_throw;
+ }
}
void
@@ -405,6 +419,15 @@ Scheduler::schedulePause()
}
void
+Scheduler::throwToScMain(const ::sc_core::sc_report *r)
+{
+ if (!r)
+ r = reportifyException();
+ _throwToScMain = r;
+ scMain->run();
+}
+
+void
Scheduler::scheduleStop(bool finish_delta)
{
if (stopEvent.scheduled())
@@ -421,4 +444,46 @@ Scheduler::scheduleStop(bool finish_delta)
Scheduler scheduler;
+namespace {
+
+void
+throwingReportHandler(const ::sc_core::sc_report &r,
+ const ::sc_core::sc_actions &)
+{
+ throw r;
+}
+
+} // anonymous namespace
+
+const ::sc_core::sc_report *
+reportifyException()
+{
+ ::sc_core::sc_report_handler_proc old_handler =
+ ::sc_core::sc_report_handler::get_handler();
+ ::sc_core::sc_report_handler::set_handler(&throwingReportHandler);
+
+ try {
+ try {
+ // Rethrow the current exception so we can catch it and throw an
+ // sc_report instead if it's not a type we recognize/can handle.
+ throw;
+ } catch (const ::sc_core::sc_report &) {
+ // It's already a sc_report, so nothing to do.
+ throw;
+ } catch (const ::sc_core::sc_unwind_exception &) {
+ panic("Kill/reset exception escaped a Process::run()");
+ } catch (const std::exception &e) {
+ SC_REPORT_ERROR("uncaught exception", e.what());
+ } catch (const char *msg) {
+ SC_REPORT_ERROR("uncaught exception", msg);
+ } catch (...) {
+ SC_REPORT_ERROR("uncaught exception", "UNKNOWN EXCEPTION");
+ }
+ } catch (const ::sc_core::sc_report &r) {
+ ::sc_core::sc_report_handler::set_handler(old_handler);
+ return &r;
+ }
+ panic("No exception thrown in reportifyException.");
+}
+
} // namespace sc_gem5
diff --git a/src/systemc/core/scheduler.hh b/src/systemc/core/scheduler.hh
index 29501bc24..dda483f0c 100644
--- a/src/systemc/core/scheduler.hh
+++ b/src/systemc/core/scheduler.hh
@@ -333,6 +333,8 @@ class Scheduler
uint64_t changeStamp() { return _changeStamp; }
+ void throwToScMain(const ::sc_core::sc_report *r=nullptr);
+
private:
typedef const EventBase::Priority Priority;
static Priority DefaultPriority = EventBase::Default_Pri;
@@ -377,7 +379,9 @@ class Scheduler
void stop();
EventWrapper<Scheduler, &Scheduler::pause> pauseEvent;
EventWrapper<Scheduler, &Scheduler::stop> stopEvent;
+
Fiber *scMain;
+ const ::sc_core::sc_report *_throwToScMain;
bool
starved()
@@ -437,6 +441,8 @@ Scheduler::TimeSlot::process()
scheduler.completeTimeSlot(this);
}
+const ::sc_core::sc_report *reportifyException();
+
} // namespace sc_gem5
#endif // __SYSTEMC_CORE_SCHEDULER_H__
diff --git a/src/systemc/ext/utils/sc_report_handler.hh b/src/systemc/ext/utils/sc_report_handler.hh
index f65b32cca..6ce20afb4 100644
--- a/src/systemc/ext/utils/sc_report_handler.hh
+++ b/src/systemc/ext/utils/sc_report_handler.hh
@@ -105,6 +105,10 @@ class sc_report_handler
static void set_handler(sc_report_handler_proc);
static void default_handler(const sc_report &, const sc_actions &);
static sc_actions get_new_action_id();
+ // Nonstandard
+ // Returns the current handler so it can be restored if it needs to be
+ // changed temporarily.
+ static sc_report_handler_proc get_handler();
static sc_report *get_cached_report();
static void clear_cached_report();
diff --git a/src/systemc/tests/config.py b/src/systemc/tests/config.py
index 439a6828c..d9ae74994 100755
--- a/src/systemc/tests/config.py
+++ b/src/systemc/tests/config.py
@@ -31,6 +31,7 @@ import argparse
import m5
import os
import re
+import sys
from m5.objects import SystemC_Kernel, Root
@@ -58,7 +59,5 @@ if result.code != 0:
# generate errors, and as long as their output matches that's still
# considered correct. A "real" systemc config should expect sc_main
# (if present) not to fail.
- scrubbed = re.sub(r'In file: .*$',
- 'In file: <removed by verify.pl>',
- result.message)
- print('\n' + scrubbed)
+ print('\n' + result.message)
+ sys.exit(int(result.code))
diff --git a/src/systemc/utils/sc_report_handler.cc b/src/systemc/utils/sc_report_handler.cc
index e08ad6624..1ca9d975d 100644
--- a/src/systemc/utils/sc_report_handler.cc
+++ b/src/systemc/utils/sc_report_handler.cc
@@ -341,6 +341,12 @@ sc_report_handler::get_new_action_id()
return maxAction;
}
+sc_report_handler_proc
+sc_report_handler::get_handler()
+{
+ return reportHandlerProc;
+}
+
sc_report *
sc_report_handler::get_cached_report()
{