summaryrefslogtreecommitdiff
path: root/src/systemc/core/sensitivity.cc
diff options
context:
space:
mode:
authorGabe Black <gabeblack@google.com>2018-09-26 03:20:09 -0700
committerGabe Black <gabeblack@google.com>2018-10-16 00:35:50 +0000
commit0cfce458003c377878aad3b15cf5fa2860a5f8e7 (patch)
treef99966a70759fde8d40b8a2e95939a4f7c3b2412 /src/systemc/core/sensitivity.cc
parentf4ab64a588771391c2eebd9b1c8b089aa33cda67 (diff)
downloadgem5-0cfce458003c377878aad3b15cf5fa2860a5f8e7.tar.xz
systemc: Implement signal based resets.
The implementation is based on sc_event sensitivities. Also of note is that the way reset works in the Accellera implementation isn't consistent with the spec. That says that wait(int n) is supposed to be equivalent to calling wait() n times, assuming n is greater than 0. Instead, Accellera stores that count and then doesn't wake up the process until the count is 0, decrementing it otherwise. That means that when the process is in reset, it won't actually reset for those intermediate wait()s which it would if wait() was called repeatedly. Also, oddly, when a reset becomes asserted, it will clear the count to 0 explicitly. That may have been an attempt to make the behavior of wait(int n) match the spec, but it doesn't handle cases where the reset is already set when wait(int n) is called. Change-Id: I92f8e9a128e6618af94dc048ce570a4436e17e4b Reviewed-on: https://gem5-review.googlesource.com/c/13186 Reviewed-by: Gabe Black <gabeblack@google.com> Maintainer: Gabe Black <gabeblack@google.com>
Diffstat (limited to 'src/systemc/core/sensitivity.cc')
-rw-r--r--src/systemc/core/sensitivity.cc82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/systemc/core/sensitivity.cc b/src/systemc/core/sensitivity.cc
index 2bd0b5fcb..b0709ee91 100644
--- a/src/systemc/core/sensitivity.cc
+++ b/src/systemc/core/sensitivity.cc
@@ -33,6 +33,9 @@
#include "systemc/core/port.hh"
#include "systemc/core/process.hh"
#include "systemc/core/scheduler.hh"
+#include "systemc/ext/channel/sc_in.hh"
+#include "systemc/ext/channel/sc_inout.hh"
+#include "systemc/ext/channel/sc_out.hh"
#include "systemc/ext/core/sc_export.hh"
#include "systemc/ext/core/sc_interface.hh"
#include "systemc/ext/core/sc_port.hh"
@@ -93,6 +96,18 @@ StaticSensitivity::delFromEvent(const ::sc_core::sc_event *e)
Event::getFromScEvent(e)->delSensitivity(this);
}
+void
+ResetSensitivity::addToEvent(const ::sc_core::sc_event *e)
+{
+ Event::getFromScEvent(e)->addSensitivity(this);
+}
+
+void
+ResetSensitivity::delFromEvent(const ::sc_core::sc_event *e)
+{
+ Event::getFromScEvent(e)->delSensitivity(this);
+}
+
/*
* Static sensitivities.
@@ -228,4 +243,71 @@ DynamicSensitivityEventAndList::notifyWork(Event *e)
return true;
}
+/*
+ * Reset sensitivities.
+ */
+
+void
+newResetSensitivitySignal(
+ Process *p, const sc_core::sc_signal_in_if<bool> *signal,
+ bool val, bool sync)
+{
+ auto s = new ResetSensitivitySignal(p, signal, val, sync);
+ s->addToEvent(s->event);
+ p->addReset(s);
+}
+
+void
+newResetSensitivityPort(Process *p, const sc_core::sc_in<bool> *port,
+ bool val, bool sync)
+{
+ auto s = new ResetSensitivityPort(p, port, val, sync);
+ Port::fromPort(port)->sensitive(s);
+ p->addReset(s);
+}
+void
+newResetSensitivityPort(Process *p, const sc_core::sc_inout<bool> *port,
+ bool val, bool sync)
+{
+ auto s = new ResetSensitivityPort(p, port, val, sync);
+ Port::fromPort(port)->sensitive(s);
+ p->addReset(s);
+}
+void
+newResetSensitivityPort(Process *p, const sc_core::sc_out<bool> *port,
+ bool val, bool sync)
+{
+ auto s = new ResetSensitivityPort(p, port, val, sync);
+ Port::fromPort(port)->sensitive(s);
+ p->addReset(s);
+}
+
+ResetSensitivitySignal::ResetSensitivitySignal(
+ Process *p, const sc_core::sc_signal_in_if<bool> *signal,
+ bool _val, bool _sync) :
+ Sensitivity(p), ResetSensitivity(p, _val, _sync),
+ SensitivityEvent(p, signal ? &signal->value_changed_event() : nullptr),
+ _signal(signal)
+{
+ if (signal && signal->read() == val())
+ process->signalReset(true, sync());
+}
+
+bool
+ResetSensitivitySignal::notifyWork(Event *e)
+{
+ process->signalReset(_signal->read() == val(), sync());
+ return true;
+}
+
+void
+ResetSensitivityPort::setSignal(const ::sc_core::sc_signal_in_if<bool> *signal)
+{
+ _signal = signal;
+ event = &_signal->value_changed_event();
+ addToEvent(event);
+ if (signal->read() == val())
+ process->signalReset(true, sync());
+}
+
} // namespace sc_gem5