systemc: Refactor sensitivities.

Dynamic and Static sensitivities used to be represented by the same
classes, even though they're (almost) disjoint in how they worked. Also
timeouts, which can be used alongside dynamic sensitivities, were
handled by the sensitivities themselves. That meant that the
sensitivity mechanism had to mix in more types of behaviors,
increasing complexity. Also, the non-standard timed_out function
Accellera includes is harder to implement if the path for timeouts and
regular sensitivities are mixed together.

This change splits up dynamic and static sensitivities and splits out
timeouts. It also immitates the ordering Accellera uses when going
through sensitivities for an event. Static sensitivities are triggered
first in reverse order (why?), and then dynamic sensitivities are
triggered in what amounts to reverse order. To delete a sensitivity
which has been handled, it's swapped with the one in the last position,
and then the vector is truncated to drop it at the end. This has the
net effect of stirring the dynamic sensitivities, and isn't easily
immitated using a different approach, even if other approaches would
be more straightforward.

Double check addSensitivity for event.hh

Change-Id: I1e73dce386b95f68e9d6737deb8bed70ef717e0d
Reviewed-on: https://gem5-review.googlesource.com/c/12805
Reviewed-by: Gabe Black <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>
This commit is contained in:
Gabe Black
2018-09-14 00:04:22 -07:00
parent 8817e547e5
commit 7bc110ce5c
12 changed files with 633 additions and 400 deletions

View File

@@ -40,6 +40,7 @@ if env['USE_SYSTEMC']:
Source('python.cc')
Source('scheduler.cc')
Source('sched_event.cc')
Source('sensitivity.cc')
Source('sc_attr.cc')
Source('sc_event.cc')

View File

@@ -145,9 +145,18 @@ Event::notify()
if (delayedNotify.scheduled())
scheduler.deschedule(&delayedNotify);
auto local_sensitivities = sensitivities;
for (auto s: local_sensitivities)
for (auto s: staticSensitivities)
s->notify(this);
DynamicSensitivities &ds = dynamicSensitivities;
int size = ds.size();
int pos = 0;
while (pos < size) {
if (ds[pos]->notify(this))
ds[pos] = ds[--size];
else
pos++;
}
ds.resize(size);
}
void

View File

@@ -37,7 +37,9 @@
#include "sim/eventq.hh"
#include "systemc/core/list.hh"
#include "systemc/core/object.hh"
#include "systemc/core/process.hh"
#include "systemc/core/sched_event.hh"
#include "systemc/core/sensitivity.hh"
#include "systemc/ext/core/sc_prim.hh"
#include "systemc/ext/core/sc_time.hh"
@@ -93,8 +95,40 @@ class Event
return e->_gem5_event;
}
void addSensitivity(Sensitivity *s) const { sensitivities.push_back(s); }
void delSensitivity(Sensitivity *s) const { sensitivities.remove(s); }
void
addSensitivity(StaticSensitivity *s) const
{
// Insert static sensitivities in reverse order to match Accellera's
// implementation.
staticSensitivities.insert(staticSensitivities.begin(), s);
}
void
delSensitivity(StaticSensitivity *s) const
{
for (auto &t: staticSensitivities) {
if (t == s) {
t = staticSensitivities.back();
staticSensitivities.pop_back();
break;
}
}
}
void
addSensitivity(DynamicSensitivity *s) const
{
dynamicSensitivities.push_back(s);
}
void
delSensitivity(DynamicSensitivity *s) const
{
for (auto &t: dynamicSensitivities) {
if (t == s) {
t = dynamicSensitivities.back();
dynamicSensitivities.pop_back();
break;
}
}
}
private:
sc_core::sc_event *_sc_event;
@@ -107,7 +141,8 @@ class Event
ScEvent delayedNotify;
mutable std::list<Sensitivity *> sensitivities;
mutable StaticSensitivities staticSensitivities;
mutable DynamicSensitivities dynamicSensitivities;
};
extern Events topLevelEvents;

View File

@@ -40,85 +40,6 @@
namespace sc_gem5
{
SensitivityTimeout::SensitivityTimeout(Process *p, ::sc_core::sc_time t) :
Sensitivity(p), timeoutEvent([this]() { this->timeout(); })
{
scheduler.schedule(&timeoutEvent, t);
}
SensitivityTimeout::~SensitivityTimeout()
{
if (timeoutEvent.scheduled())
scheduler.deschedule(&timeoutEvent);
}
void
SensitivityTimeout::timeout()
{
notify();
}
SensitivityEvent::SensitivityEvent(
Process *p, const ::sc_core::sc_event *e) : Sensitivity(p), event(e)
{
Event::getFromScEvent(event)->addSensitivity(this);
}
SensitivityEvent::~SensitivityEvent()
{
Event::getFromScEvent(event)->delSensitivity(this);
}
SensitivityEventAndList::SensitivityEventAndList(
Process *p, const ::sc_core::sc_event_and_list *list) :
Sensitivity(p), list(list), count(0)
{
for (auto e: list->events)
Event::getFromScEvent(e)->addSensitivity(this);
}
SensitivityEventAndList::~SensitivityEventAndList()
{
for (auto e: list->events)
Event::getFromScEvent(e)->delSensitivity(this);
}
void
SensitivityEventAndList::notifyWork(Event *e)
{
e->delSensitivity(this);
count++;
if (count == list->events.size())
satisfy();
}
SensitivityEventOrList::SensitivityEventOrList(
Process *p, const ::sc_core::sc_event_or_list *list) :
Sensitivity(p), list(list)
{
for (auto e: list->events)
Event::getFromScEvent(e)->addSensitivity(this);
}
SensitivityEventOrList::~SensitivityEventOrList()
{
for (auto e: list->events)
Event::getFromScEvent(e)->delSensitivity(this);
}
void
SensitivityTimeoutAndEventAndList::notifyWork(Event *e)
{
if (e) {
// An event went off which must be part of the sc_event_and_list.
SensitivityEventAndList::notifyWork(e);
} else {
// There's no inciting event, so this must be a timeout.
satisfy(true);
}
}
class UnwindExceptionReset : public ::sc_core::sc_unwind_exception
{
public:
@@ -195,7 +116,7 @@ Process::disable(bool inc_kids)
forEachKid([](Process *p) { p->disable(true); });
if (!::sc_core::sc_allow_process_control_corners &&
dynamic_cast<SensitivityTimeout *>(dynamicSensitivity)) {
timeoutEvent.scheduled()) {
std::string message("attempt to disable a thread with timeout wait: ");
message += name();
SC_REPORT_ERROR("Undefined process control interaction",
@@ -317,12 +238,8 @@ Process::syncResetOff(bool inc_kids)
void
Process::finalize()
{
for (auto &s: pendingStaticSensitivities) {
s->finalize(staticSensitivities);
delete s;
s = nullptr;
}
pendingStaticSensitivities.clear();
for (auto s: staticSensitivities)
s->finalize();
};
void
@@ -346,26 +263,66 @@ Process::run()
}
void
Process::addStatic(PendingSensitivity *s)
Process::addStatic(StaticSensitivity *s)
{
pendingStaticSensitivities.push_back(s);
staticSensitivities.push_back(s);
}
void
Process::setDynamic(Sensitivity *s)
Process::setDynamic(DynamicSensitivity *s)
{
delete dynamicSensitivity;
if (dynamicSensitivity) {
dynamicSensitivity->clear();
delete dynamicSensitivity;
}
dynamicSensitivity = s;
if (dynamicSensitivity)
dynamicSensitivity->finalize();
}
void
Process::cancelTimeout()
{
if (timeoutEvent.scheduled())
scheduler.deschedule(&timeoutEvent);
}
void
Process::setTimeout(::sc_core::sc_time t)
{
cancelTimeout();
scheduler.schedule(&timeoutEvent, t);
}
void
Process::timeout()
{
// A process is considered timed_out only if it was also waiting for an
// event but got a timeout instead.
_timedOut = (dynamicSensitivity != nullptr);
setDynamic(nullptr);
if (disabled())
return;
ready();
}
void
Process::satisfySensitivity(Sensitivity *s)
{
// If there's a dynamic sensitivity and this wasn't it, ignore.
if (dynamicSensitivity && dynamicSensitivity != s)
if ((dynamicSensitivity || timeoutEvent.scheduled()) &&
dynamicSensitivity != s) {
return;
}
setDynamic(nullptr);
_timedOut = false;
// This sensitivity should already be cleared by this point, or the event
// which triggered it will take care of it.
delete dynamicSensitivity;
dynamicSensitivity = nullptr;
cancelTimeout();
ready();
}
@@ -394,8 +351,9 @@ Process::lastReport(::sc_core::sc_report *report)
::sc_core::sc_report *Process::lastReport() const { return _lastReport.get(); }
Process::Process(const char *name, ProcessFuncWrapper *func, bool internal) :
::sc_core::sc_process_b(name), excWrapper(nullptr), func(func),
_internal(internal), _timedOut(false), _dontInitialize(false),
::sc_core::sc_process_b(name), excWrapper(nullptr),
timeoutEvent([this]() { this->timeout(); }),
func(func), _internal(internal), _timedOut(false), _dontInitialize(false),
_needsStart(true), _isUnwinding(false), _terminated(false),
_suspended(false), _disabled(false), _syncReset(false), refCount(0),
stackSize(::Fiber::DefaultStackSize), dynamicSensitivity(nullptr)
@@ -413,10 +371,12 @@ Process::terminate()
_suspendedReady = false;
_suspended = false;
_syncReset = false;
delete dynamicSensitivity;
dynamicSensitivity = nullptr;
for (auto s: staticSensitivities)
clearDynamic();
cancelTimeout();
for (auto s: staticSensitivities) {
s->clear();
delete s;
}
staticSensitivities.clear();
_terminatedEvent.notify();

View File

@@ -35,19 +35,14 @@
#include <vector>
#include "base/fiber.hh"
#include "sim/eventq.hh"
#include "systemc/core/bindinfo.hh"
#include "systemc/core/event.hh"
#include "systemc/core/list.hh"
#include "systemc/core/object.hh"
#include "systemc/core/sched_event.hh"
#include "systemc/core/sensitivity.hh"
#include "systemc/ext/core/sc_event.hh"
#include "systemc/ext/core/sc_export.hh"
#include "systemc/ext/core/sc_interface.hh"
#include "systemc/ext/core/sc_module.hh"
#include "systemc/ext/core/sc_port.hh"
#include "systemc/ext/core/sc_process_handle.hh"
#include "systemc/ext/utils/sc_report.hh"
namespace sc_core
{
@@ -62,233 +57,6 @@ namespace sc_gem5
class ScHalt
{};
class Sensitivity
{
protected:
Process *process;
public:
Sensitivity(Process *p) : process(p) {}
virtual ~Sensitivity() {}
void satisfy(bool timedOut=false);
virtual void notifyWork(Event *e) { satisfy(); }
void notify(Event *e);
void notify() { notify(nullptr); }
const std::string name();
};
class SensitivityTimeout : virtual public Sensitivity
{
private:
void timeout();
ScEvent timeoutEvent;
public:
SensitivityTimeout(Process *p, ::sc_core::sc_time t);
~SensitivityTimeout();
};
class SensitivityEvent : virtual public Sensitivity
{
private:
const ::sc_core::sc_event *event;
public:
SensitivityEvent(Process *p, const ::sc_core::sc_event *e);
~SensitivityEvent();
};
//XXX This sensitivity can't be reused. To reset it, it has to be deleted and
//recreated. That works for dynamic sensitivities, but not for static.
//Fortunately processes can't be statically sensitive to sc_event_and_lists.
class SensitivityEventAndList : virtual public Sensitivity
{
private:
const ::sc_core::sc_event_and_list *list;
int count;
public:
SensitivityEventAndList(
Process *p, const ::sc_core::sc_event_and_list *list);
~SensitivityEventAndList();
void notifyWork(Event *e) override;
};
class SensitivityEventOrList : virtual public Sensitivity
{
private:
const ::sc_core::sc_event_or_list *list;
public:
SensitivityEventOrList(
Process *p, const ::sc_core::sc_event_or_list *list);
~SensitivityEventOrList();
};
// Combined sensitivities. These trigger when any of their parts do.
class SensitivityTimeoutAndEvent :
public SensitivityTimeout, public SensitivityEvent
{
public:
SensitivityTimeoutAndEvent(
Process *p, ::sc_core::sc_time t, const ::sc_core::sc_event *e) :
Sensitivity(p), SensitivityTimeout(p, t), SensitivityEvent(p, e)
{}
void notifyWork(Event *e) override { satisfy(e == nullptr); }
};
class SensitivityTimeoutAndEventAndList :
public SensitivityTimeout, public SensitivityEventAndList
{
public:
SensitivityTimeoutAndEventAndList(
Process *p, ::sc_core::sc_time t,
const ::sc_core::sc_event_and_list *eal) :
Sensitivity(p), SensitivityTimeout(p, t),
SensitivityEventAndList(p, eal)
{}
void notifyWork(Event *e) override;
};
class SensitivityTimeoutAndEventOrList :
public SensitivityTimeout, public SensitivityEventOrList
{
public:
SensitivityTimeoutAndEventOrList(
Process *p, ::sc_core::sc_time t,
const ::sc_core::sc_event_or_list *eol) :
Sensitivity(p), SensitivityTimeout(p, t),
SensitivityEventOrList(p, eol)
{}
void notifyWork(Event *e) override { satisfy(e == nullptr); }
};
typedef std::vector<Sensitivity *> Sensitivities;
/*
* Pending sensitivities. These are records of sensitivities to install later,
* once all the information to configure them is available.
*/
class PendingSensitivity
{
protected:
Process *process;
public:
virtual void finalize(Sensitivities &s) = 0;
PendingSensitivity(Process *p) : process(p) {}
virtual ~PendingSensitivity() {}
};
class PendingSensitivityEvent : public PendingSensitivity
{
private:
const sc_core::sc_event *event;
public:
PendingSensitivityEvent(Process *p, const sc_core::sc_event *e) :
PendingSensitivity(p), event(e) {}
void
finalize(Sensitivities &s) override
{
s.push_back(new SensitivityEvent(process, event));
}
};
class PendingSensitivityInterface : public PendingSensitivity
{
private:
const sc_core::sc_interface *interface;
public:
PendingSensitivityInterface(Process *p, const sc_core::sc_interface *i) :
PendingSensitivity(p), interface(i)
{}
void
finalize(Sensitivities &s) override
{
s.push_back(new SensitivityEvent(process,
&interface->default_event()));
}
};
class PendingSensitivityPort : public PendingSensitivity
{
private:
const sc_core::sc_port_base *port;
public:
PendingSensitivityPort(Process *p, const sc_core::sc_port_base *pb) :
PendingSensitivity(p), port(pb)
{}
void
finalize(Sensitivities &s) override
{
for (int i = 0; i < port->size(); i++) {
const ::sc_core::sc_event *e =
&port->_gem5Interface(i)->default_event();
s.push_back(new SensitivityEvent(process, e));
}
}
};
class PendingSensitivityExport : public PendingSensitivity
{
private:
const sc_core::sc_export_base *exp;
public:
PendingSensitivityExport(Process *p, const sc_core::sc_export_base *exp) :
PendingSensitivity(p), exp(exp)
{}
void
finalize(Sensitivities &s) override
{
s.push_back(new SensitivityEvent(process,
&exp->get_interface()->default_event()));
}
};
class PendingSensitivityFinder : public PendingSensitivity
{
private:
const sc_core::sc_event_finder *finder;
public:
PendingSensitivityFinder(Process *p, const sc_core::sc_event_finder *f) :
PendingSensitivity(p), finder(f)
{}
void
finalize(Sensitivities &s) override
{
const ::sc_core::sc_port_base *port = finder->port();
int size = port->size();
for (int i = 0; i < size; i++) {
::sc_core::sc_interface *interface = port->_gem5Interface(i);
const ::sc_core::sc_event *event = &finder->find_event(interface);
s.push_back(new SensitivityEvent(process, event));
}
}
};
typedef std::vector<PendingSensitivity *> PendingSensitivities;
class Process : public ::sc_core::sc_process_b, public ListNode
{
public:
@@ -332,8 +100,13 @@ class Process : public ::sc_core::sc_process_b, public ListNode
void run();
void addStatic(PendingSensitivity *);
void setDynamic(Sensitivity *);
void addStatic(StaticSensitivity *);
void setDynamic(DynamicSensitivity *);
void clearDynamic() { setDynamic(nullptr); }
ScEvent timeoutEvent;
void setTimeout(::sc_core::sc_time t);
void cancelTimeout();
void satisfySensitivity(Sensitivity *);
@@ -349,7 +122,6 @@ class Process : public ::sc_core::sc_process_b, public ListNode
bool hasStaticSensitivities() { return !staticSensitivities.empty(); }
bool internal() { return _internal; }
bool timedOut() { return _timedOut; }
void timedOut(bool to) { _timedOut = to; }
bool dontInitialize() { return _dontInitialize; }
void dontInitialize(bool di) { _dontInitialize = di; }
@@ -357,6 +129,8 @@ class Process : public ::sc_core::sc_process_b, public ListNode
void joinWait(::sc_core::sc_join *join) { joinWaiters.push_back(join); }
protected:
void timeout();
Process(const char *name, ProcessFuncWrapper *func, bool internal=false);
static Process *_newest;
@@ -365,8 +139,11 @@ class Process : public ::sc_core::sc_process_b, public ListNode
{
popListNode();
delete func;
for (auto s: staticSensitivities)
for (auto s: staticSensitivities) {
s->clear();
delete s;
}
clearDynamic();
}
::sc_core::sc_event _resetEvent;
@@ -399,36 +176,14 @@ class Process : public ::sc_core::sc_process_b, public ListNode
size_t stackSize;
Sensitivities staticSensitivities;
PendingSensitivities pendingStaticSensitivities;
Sensitivity *dynamicSensitivity;
StaticSensitivities staticSensitivities;
DynamicSensitivity *dynamicSensitivity;
std::unique_ptr<::sc_core::sc_report> _lastReport;
std::vector<::sc_core::sc_join *> joinWaiters;
};
inline void
Sensitivity::satisfy(bool timedOut)
{
process->timedOut(timedOut);
process->satisfySensitivity(this);
}
inline void
Sensitivity::notify(Event *e)
{
if (!process->disabled())
notifyWork(e);
}
inline const std::string
Sensitivity::name()
{
return std::string(process->name()) + ".timeout";
}
} // namespace sc_gem5
#endif //__SYSTEMC_CORE_PROCESS_HH__

View File

@@ -496,35 +496,40 @@ void
next_trigger()
{
sc_gem5::Process *p = sc_gem5::scheduler.current();
p->setDynamic(nullptr);
p->cancelTimeout();
p->clearDynamic();
}
void
next_trigger(const sc_event &e)
{
sc_gem5::Process *p = sc_gem5::scheduler.current();
p->setDynamic(new ::sc_gem5::SensitivityEvent(p, &e));
p->cancelTimeout();
p->setDynamic(new ::sc_gem5::DynamicSensitivityEvent(p, &e));
}
void
next_trigger(const sc_event_or_list &eol)
{
sc_gem5::Process *p = sc_gem5::scheduler.current();
p->setDynamic(new ::sc_gem5::SensitivityEventOrList(p, &eol));
p->cancelTimeout();
p->setDynamic(new ::sc_gem5::DynamicSensitivityEventOrList(p, &eol));
}
void
next_trigger(const sc_event_and_list &eal)
{
sc_gem5::Process *p = sc_gem5::scheduler.current();
p->setDynamic(new ::sc_gem5::SensitivityEventAndList(p, &eal));
p->cancelTimeout();
p->setDynamic(new ::sc_gem5::DynamicSensitivityEventAndList(p, &eal));
}
void
next_trigger(const sc_time &t)
{
sc_gem5::Process *p = sc_gem5::scheduler.current();
p->setDynamic(new ::sc_gem5::SensitivityTimeout(p, t));
p->setTimeout(t);
p->clearDynamic();
}
void
@@ -537,7 +542,8 @@ void
next_trigger(const sc_time &t, const sc_event &e)
{
sc_gem5::Process *p = sc_gem5::scheduler.current();
p->setDynamic(new ::sc_gem5::SensitivityTimeoutAndEvent(p, t, &e));
p->setTimeout(t);
p->setDynamic(new ::sc_gem5::DynamicSensitivityEvent(p, &e));
}
void
@@ -550,8 +556,8 @@ void
next_trigger(const sc_time &t, const sc_event_or_list &eol)
{
sc_gem5::Process *p = sc_gem5::scheduler.current();
p->setDynamic(
new ::sc_gem5::SensitivityTimeoutAndEventOrList(p, t, &eol));
p->setTimeout(t);
p->setDynamic(new ::sc_gem5::DynamicSensitivityEventOrList(p, &eol));
}
void
@@ -564,8 +570,8 @@ void
next_trigger(const sc_time &t, const sc_event_and_list &eal)
{
sc_gem5::Process *p = sc_gem5::scheduler.current();
p->setDynamic(
new ::sc_gem5::SensitivityTimeoutAndEventAndList(p, t, &eal));
p->setTimeout(t);
p->setDynamic(new ::sc_gem5::DynamicSensitivityEventAndList(p, &eal));
}
void
@@ -589,7 +595,8 @@ void
wait()
{
sc_gem5::Process *p = sc_gem5::scheduler.current();
p->setDynamic(nullptr);
p->cancelTimeout();
p->clearDynamic();
sc_gem5::scheduler.yield();
}
@@ -608,7 +615,8 @@ void
wait(const sc_event &e)
{
sc_gem5::Process *p = sc_gem5::scheduler.current();
p->setDynamic(new ::sc_gem5::SensitivityEvent(p, &e));
p->cancelTimeout();
p->setDynamic(new ::sc_gem5::DynamicSensitivityEvent(p, &e));
sc_gem5::scheduler.yield();
}
@@ -616,7 +624,8 @@ void
wait(const sc_event_or_list &eol)
{
sc_gem5::Process *p = sc_gem5::scheduler.current();
p->setDynamic(new ::sc_gem5::SensitivityEventOrList(p, &eol));
p->cancelTimeout();
p->setDynamic(new ::sc_gem5::DynamicSensitivityEventOrList(p, &eol));
sc_gem5::scheduler.yield();
}
@@ -624,7 +633,8 @@ void
wait(const sc_event_and_list &eal)
{
sc_gem5::Process *p = sc_gem5::scheduler.current();
p->setDynamic(new ::sc_gem5::SensitivityEventAndList(p, &eal));
p->cancelTimeout();
p->setDynamic(new ::sc_gem5::DynamicSensitivityEventAndList(p, &eal));
sc_gem5::scheduler.yield();
}
@@ -632,7 +642,8 @@ void
wait(const sc_time &t)
{
sc_gem5::Process *p = sc_gem5::scheduler.current();
p->setDynamic(new ::sc_gem5::SensitivityTimeout(p, t));
p->setTimeout(t);
p->clearDynamic();
sc_gem5::scheduler.yield();
}
@@ -646,7 +657,8 @@ void
wait(const sc_time &t, const sc_event &e)
{
sc_gem5::Process *p = sc_gem5::scheduler.current();
p->setDynamic(new ::sc_gem5::SensitivityTimeoutAndEvent(p, t, &e));
p->setTimeout(t);
p->setDynamic(new ::sc_gem5::DynamicSensitivityEvent(p, &e));
sc_gem5::scheduler.yield();
}
@@ -660,8 +672,8 @@ void
wait(const sc_time &t, const sc_event_or_list &eol)
{
sc_gem5::Process *p = sc_gem5::scheduler.current();
p->setDynamic(
new ::sc_gem5::SensitivityTimeoutAndEventOrList(p, t, &eol));
p->setTimeout(t);
p->setDynamic(new ::sc_gem5::DynamicSensitivityEventOrList(p, &eol));
sc_gem5::scheduler.yield();
}
@@ -675,8 +687,8 @@ void
wait(const sc_time &t, const sc_event_and_list &eal)
{
sc_gem5::Process *p = sc_gem5::scheduler.current();
p->setDynamic(
new ::sc_gem5::SensitivityTimeoutAndEventAndList(p, t, &eal));
p->setTimeout(t);
p->setDynamic(new ::sc_gem5::DynamicSensitivityEventAndList(p, &eal));
sc_gem5::scheduler.yield();
}

View File

@@ -41,7 +41,7 @@ sc_sensitive &
sc_sensitive::operator << (const sc_event &e)
{
currentProcess->addStatic(
new sc_gem5::PendingSensitivityEvent(currentProcess, &e));
new sc_gem5::StaticSensitivityEvent(currentProcess, &e));
return *this;
}
@@ -49,7 +49,7 @@ sc_sensitive &
sc_sensitive::operator << (const sc_interface &i)
{
currentProcess->addStatic(
new sc_gem5::PendingSensitivityInterface(currentProcess, &i));
new sc_gem5::StaticSensitivityInterface(currentProcess, &i));
return *this;
}
@@ -57,7 +57,7 @@ sc_sensitive &
sc_sensitive::operator << (const sc_port_base &b)
{
currentProcess->addStatic(
new sc_gem5::PendingSensitivityPort(currentProcess, &b));
new sc_gem5::StaticSensitivityPort(currentProcess, &b));
return *this;
}
@@ -65,7 +65,7 @@ sc_sensitive &
sc_sensitive::operator << (sc_event_finder &f)
{
currentProcess->addStatic(
new sc_gem5::PendingSensitivityFinder(currentProcess, &f));
new sc_gem5::StaticSensitivityFinder(currentProcess, &f));
return *this;
}

View File

@@ -70,19 +70,19 @@ spawnWork(ProcessFuncWrapper *func, const char *name,
if (opts) {
for (auto e: opts->_events)
proc->addStatic(new PendingSensitivityEvent(proc, e));
proc->addStatic(new StaticSensitivityEvent(proc, e));
for (auto p: opts->_ports)
proc->addStatic(new PendingSensitivityPort(proc, p));
proc->addStatic(new StaticSensitivityPort(proc, p));
for (auto e: opts->_exports)
proc->addStatic(new PendingSensitivityExport(proc, e));
proc->addStatic(new StaticSensitivityExport(proc, e));
for (auto i: opts->_interfaces)
proc->addStatic(new PendingSensitivityInterface(proc, i));
proc->addStatic(new StaticSensitivityInterface(proc, i));
for (auto f: opts->_finders)
proc->addStatic(new PendingSensitivityFinder(proc, f));
proc->addStatic(new StaticSensitivityFinder(proc, f));
}
if (opts && opts->_dontInitialize &&

View File

@@ -0,0 +1,182 @@
/*
* 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/sensitivity.hh"
#include "systemc/core/event.hh"
#include "systemc/core/scheduler.hh"
#include "systemc/ext/core/sc_export.hh"
#include "systemc/ext/core/sc_interface.hh"
#include "systemc/ext/core/sc_port.hh"
namespace sc_gem5
{
void
Sensitivity::satisfy()
{
process->satisfySensitivity(this);
}
bool
Sensitivity::notify(Event *e)
{
if (process->disabled())
return false;
return notifyWork(e);
}
void
DynamicSensitivity::addToEvent(const ::sc_core::sc_event *e)
{
Event::getFromScEvent(e)->addSensitivity(this);
}
void
DynamicSensitivity::delFromEvent(const ::sc_core::sc_event *e)
{
Event::getFromScEvent(e)->delSensitivity(this);
}
void
StaticSensitivity::addToEvent(const ::sc_core::sc_event *e)
{
Event::getFromScEvent(e)->addSensitivity(this);
}
void
StaticSensitivity::delFromEvent(const ::sc_core::sc_event *e)
{
Event::getFromScEvent(e)->delSensitivity(this);
}
void
StaticSensitivityInterface::finalize()
{
event = &interface->default_event();
SensitivityEvent::finalize();
}
void
StaticSensitivityPort::finalize()
{
for (int i = 0; i < port->size(); i++) {
const ::sc_core::sc_event *event =
&port->_gem5Interface(i)->default_event();
events.insert(event);
addToEvent(event);
}
}
void
StaticSensitivityExport::finalize()
{
event = &exp->get_interface()->default_event();
SensitivityEvent::finalize();
}
void
StaticSensitivityFinder::finalize()
{
const ::sc_core::sc_port_base *port = finder->port();
int size = port->size();
for (int i = 0; i < size; i++) {
::sc_core::sc_interface *interface = port->_gem5Interface(i);
const ::sc_core::sc_event *event = &finder->find_event(interface);
events.insert(event);
addToEvent(event);
}
}
bool
DynamicSensitivityEventOrList::notifyWork(Event *e)
{
events.erase(e->sc_event());
// All the other events need this deleted from their lists since this
// sensitivity has been satisfied without them triggering.
for (auto le: events)
delFromEvent(le);
satisfy();
return true;
}
DynamicSensitivityEventOrList::DynamicSensitivityEventOrList(
Process *p, const sc_core::sc_event_or_list *eol) :
Sensitivity(p), DynamicSensitivity(p), events(eol->events)
{}
void
DynamicSensitivityEventOrList::finalize()
{
for (auto e: events)
addToEvent(e);
}
void
DynamicSensitivityEventOrList::clear()
{
for (auto e: events)
delFromEvent(e);
}
bool
DynamicSensitivityEventAndList::notifyWork(Event *e)
{
events.erase(e->sc_event());
// This sensitivity is satisfied if all events have triggered.
if (events.empty())
satisfy();
return true;
}
DynamicSensitivityEventAndList::DynamicSensitivityEventAndList(
Process *p, const sc_core::sc_event_and_list *eal) :
Sensitivity(p), DynamicSensitivity(p), events(eal->events)
{}
void
DynamicSensitivityEventAndList::finalize()
{
for (auto e: events)
addToEvent(e);
}
void
DynamicSensitivityEventAndList::clear()
{
for (auto e: events)
delFromEvent(e);
}
} // namespace sc_gem5

View File

@@ -0,0 +1,279 @@
/*
* 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_SENSITIVITY_HH__
#define __SYSTEMC_CORE_SENSITIVITY_HH__
#include <set>
#include <vector>
#include "sim/eventq.hh"
#include "systemc/core/sched_event.hh"
#include "systemc/ext/core/sc_module.hh"
namespace sc_core
{
class sc_event;
class sc_event_and_list;
class sc_event_or_list;
class sc_event_finder;
class sc_export_base;
class sc_interface;
class sc_port_base;
} // namespace sc_core
namespace sc_gem5
{
class Process;
class Event;
/*
* Common sensitivity interface.
*/
class Sensitivity
{
protected:
Process *process;
Sensitivity(Process *p) : process(p) {}
virtual ~Sensitivity() {}
virtual void addToEvent(const ::sc_core::sc_event *e) = 0;
virtual void delFromEvent(const ::sc_core::sc_event *e) = 0;
virtual bool
notifyWork(Event *e)
{
satisfy();
return true;
}
public:
virtual void finalize() = 0;
virtual void clear() = 0;
void satisfy();
bool notify(Event *e);
virtual bool dynamic() = 0;
};
/*
* Dynamic vs. static sensitivity.
*/
class DynamicSensitivity : virtual public Sensitivity
{
protected:
DynamicSensitivity(Process *p) : Sensitivity(p) {}
void addToEvent(const ::sc_core::sc_event *e) override;
void delFromEvent(const ::sc_core::sc_event *e) override;
public:
bool dynamic() override { return true; }
};
typedef std::vector<DynamicSensitivity *> DynamicSensitivities;
class StaticSensitivity : virtual public Sensitivity
{
protected:
StaticSensitivity(Process *p) : Sensitivity(p) {}
void addToEvent(const ::sc_core::sc_event *e) override;
void delFromEvent(const ::sc_core::sc_event *e) override;
public:
bool dynamic() override { return false; }
};
typedef std::vector<StaticSensitivity *> StaticSensitivities;
/*
* Sensitivity to events, which can be static or dynamic.
*/
class SensitivityEvent : virtual public Sensitivity
{
protected:
const ::sc_core::sc_event *event;
SensitivityEvent(Process *p, const ::sc_core::sc_event *e=nullptr) :
Sensitivity(p), event(e)
{}
public:
void finalize() override { addToEvent(event); }
void clear() override { delFromEvent(event); }
};
/*
* Static sensitivities.
*/
class StaticSensitivityEvent :
public StaticSensitivity, public SensitivityEvent
{
public:
StaticSensitivityEvent(Process *p, const sc_core::sc_event *e) :
Sensitivity(p), StaticSensitivity(p), SensitivityEvent(p, e)
{}
};
class StaticSensitivityInterface :
public StaticSensitivity, public SensitivityEvent
{
private:
const sc_core::sc_interface *interface;
public:
StaticSensitivityInterface(Process *p, const sc_core::sc_interface *i) :
Sensitivity(p), StaticSensitivity(p), SensitivityEvent(p), interface(i)
{}
void finalize() override;
};
class StaticSensitivityPort : public StaticSensitivity
{
private:
const ::sc_core::sc_port_base *port;
std::set<const ::sc_core::sc_event *> events;
public:
StaticSensitivityPort(Process *p, const sc_core::sc_port_base *pb) :
Sensitivity(p), StaticSensitivity(p), port(pb)
{}
void finalize() override;
void
clear() override
{
for (auto event: events)
delFromEvent(event);
}
};
class StaticSensitivityExport :
public StaticSensitivity, public SensitivityEvent
{
private:
const sc_core::sc_export_base *exp;
public:
StaticSensitivityExport(Process *p, const sc_core::sc_export_base *exp) :
Sensitivity(p), StaticSensitivity(p), SensitivityEvent(p), exp(exp)
{}
void finalize() override;
};
class StaticSensitivityFinder : public StaticSensitivity
{
private:
const ::sc_core::sc_event_finder *finder;
std::set<const ::sc_core::sc_event *> events;
public:
StaticSensitivityFinder(Process *p, const sc_core::sc_event_finder *f) :
Sensitivity(p), StaticSensitivity(p), finder(f)
{}
void finalize() override;
void
clear() override
{
for (auto event: events)
delFromEvent(event);
}
};
/*
* Dynamic sensitivities.
*/
class DynamicSensitivityEvent :
public DynamicSensitivity, public SensitivityEvent
{
public:
DynamicSensitivityEvent(Process *p, const sc_core::sc_event *e) :
Sensitivity(p), DynamicSensitivity(p), SensitivityEvent(p, e)
{}
};
class DynamicSensitivityEventOrList : public DynamicSensitivity
{
private:
std::set<const ::sc_core::sc_event *> events;
protected:
bool notifyWork(Event *e) override;
public:
DynamicSensitivityEventOrList(
Process *p, const sc_core::sc_event_or_list *eol);
void finalize() override;
void clear() override;
};
//XXX This sensitivity can't be reused. To reset it, it has to be deleted and
//recreated. That works for dynamic sensitivities, but not for static.
//Fortunately processes can't be statically sensitive to sc_event_and_lists.
class DynamicSensitivityEventAndList : public DynamicSensitivity
{
private:
std::set<const ::sc_core::sc_event *> events;
protected:
bool notifyWork(Event *e) override;
public:
DynamicSensitivityEventAndList(
Process *p, const sc_core::sc_event_and_list *eal);
void finalize() override;
void clear() override;
};
} // namespace sc_gem5
#endif //__SYSTEMC_CORE_SENSITIVITY_HH__

View File

@@ -41,8 +41,8 @@ namespace sc_gem5
{
class Event;
class SensitivityEventAndList;
class SensitivityEventOrList;
class DynamicSensitivityEventAndList;
class DynamicSensitivityEventOrList;
}
@@ -116,7 +116,7 @@ class sc_event_and_list
private:
friend class sc_event_and_expr;
friend class sc_gem5::SensitivityEventAndList;
friend class sc_gem5::DynamicSensitivityEventAndList;
explicit sc_event_and_list(bool auto_delete);
@@ -148,7 +148,7 @@ class sc_event_or_list
private:
friend class sc_event_or_expr;
friend class sc_gem5::SensitivityEventOrList;
friend class sc_gem5::DynamicSensitivityEventOrList;
explicit sc_event_or_list(bool auto_delete);

View File

@@ -41,8 +41,8 @@ namespace sc_gem5
class BindInfo;
class Module;
class PendingSensitivityPort;
class PendingSensitivityFinder;
class StaticSensitivityPort;
class StaticSensitivityFinder;
};
@@ -87,8 +87,8 @@ class sc_port_base : public sc_object
virtual void end_of_simulation() = 0;
private:
friend class ::sc_gem5::PendingSensitivityPort;
friend class ::sc_gem5::PendingSensitivityFinder;
friend class ::sc_gem5::StaticSensitivityPort;
friend class ::sc_gem5::StaticSensitivityFinder;
friend class ::sc_gem5::Kernel;
void _gem5Finalize();