Source('python.cc')
Source('scheduler.cc')
Source('sched_event.cc')
+ Source('sensitivity.cc')
Source('sc_attr.cc')
Source('sc_event.cc')
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
#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"
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;
ScEvent delayedNotify;
- mutable std::list<Sensitivity *> sensitivities;
+ mutable StaticSensitivities staticSensitivities;
+ mutable DynamicSensitivities dynamicSensitivities;
};
extern Events topLevelEvents;
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:
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",
void
Process::finalize()
{
- for (auto &s: pendingStaticSensitivities) {
- s->finalize(staticSensitivities);
- delete s;
- s = nullptr;
- }
- pendingStaticSensitivities.clear();
+ for (auto s: staticSensitivities)
+ s->finalize();
};
void
}
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();
}
::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)
_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();
#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
{
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:
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 *);
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; }
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;
{
popListNode();
delete func;
- for (auto s: staticSensitivities)
+ for (auto s: staticSensitivities) {
+ s->clear();
delete s;
+ }
+ clearDynamic();
}
::sc_core::sc_event _resetEvent;
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__
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
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
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
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
wait()
{
sc_gem5::Process *p = sc_gem5::scheduler.current();
- p->setDynamic(nullptr);
+ p->cancelTimeout();
+ p->clearDynamic();
sc_gem5::scheduler.yield();
}
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();
}
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();
}
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();
}
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();
}
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();
}
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();
}
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();
}
sc_sensitive::operator << (const sc_event &e)
{
currentProcess->addStatic(
- new sc_gem5::PendingSensitivityEvent(currentProcess, &e));
+ new sc_gem5::StaticSensitivityEvent(currentProcess, &e));
return *this;
}
sc_sensitive::operator << (const sc_interface &i)
{
currentProcess->addStatic(
- new sc_gem5::PendingSensitivityInterface(currentProcess, &i));
+ new sc_gem5::StaticSensitivityInterface(currentProcess, &i));
return *this;
}
sc_sensitive::operator << (const sc_port_base &b)
{
currentProcess->addStatic(
- new sc_gem5::PendingSensitivityPort(currentProcess, &b));
+ new sc_gem5::StaticSensitivityPort(currentProcess, &b));
return *this;
}
sc_sensitive::operator << (sc_event_finder &f)
{
currentProcess->addStatic(
- new sc_gem5::PendingSensitivityFinder(currentProcess, &f));
+ new sc_gem5::StaticSensitivityFinder(currentProcess, &f));
return *this;
}
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 &&
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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__
{
class Event;
-class SensitivityEventAndList;
-class SensitivityEventOrList;
+class DynamicSensitivityEventAndList;
+class DynamicSensitivityEventOrList;
}
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);
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);
class BindInfo;
class Module;
-class PendingSensitivityPort;
-class PendingSensitivityFinder;
+class StaticSensitivityPort;
+class StaticSensitivityFinder;
};
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();