diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/systemc/core/SConscript | 1 | ||||
-rw-r--r-- | src/systemc/core/event.cc | 13 | ||||
-rw-r--r-- | src/systemc/core/event.hh | 41 | ||||
-rw-r--r-- | src/systemc/core/process.cc | 154 | ||||
-rw-r--r-- | src/systemc/core/process.hh | 277 | ||||
-rw-r--r-- | src/systemc/core/sc_module.cc | 52 | ||||
-rw-r--r-- | src/systemc/core/sc_sensitive.cc | 8 | ||||
-rw-r--r-- | src/systemc/core/sc_spawn.cc | 10 | ||||
-rw-r--r-- | src/systemc/core/sensitivity.cc | 182 | ||||
-rw-r--r-- | src/systemc/core/sensitivity.hh | 279 | ||||
-rw-r--r-- | src/systemc/ext/core/sc_event.hh | 8 | ||||
-rw-r--r-- | src/systemc/ext/core/sc_port.hh | 8 |
12 files changed, 633 insertions, 400 deletions
diff --git a/src/systemc/core/SConscript b/src/systemc/core/SConscript index 4814e6afa..1d291ef4d 100644 --- a/src/systemc/core/SConscript +++ b/src/systemc/core/SConscript @@ -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') diff --git a/src/systemc/core/event.cc b/src/systemc/core/event.cc index 61fa80c8b..0daca12e1 100644 --- a/src/systemc/core/event.cc +++ b/src/systemc/core/event.cc @@ -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 diff --git a/src/systemc/core/event.hh b/src/systemc/core/event.hh index c39053be8..bb1d0a0d6 100644 --- a/src/systemc/core/event.hh +++ b/src/systemc/core/event.hh @@ -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; diff --git a/src/systemc/core/process.cc b/src/systemc/core/process.cc index 1c7a9d72e..e977713f4 100644 --- a/src/systemc/core/process.cc +++ b/src/systemc/core/process.cc @@ -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(); diff --git a/src/systemc/core/process.hh b/src/systemc/core/process.hh index d399d7a3d..0a312e28e 100644 --- a/src/systemc/core/process.hh +++ b/src/systemc/core/process.hh @@ -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__ diff --git a/src/systemc/core/sc_module.cc b/src/systemc/core/sc_module.cc index e695f7697..3e900f658 100644 --- a/src/systemc/core/sc_module.cc +++ b/src/systemc/core/sc_module.cc @@ -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(); } diff --git a/src/systemc/core/sc_sensitive.cc b/src/systemc/core/sc_sensitive.cc index 25bc1bb08..93b460a4b 100644 --- a/src/systemc/core/sc_sensitive.cc +++ b/src/systemc/core/sc_sensitive.cc @@ -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; } diff --git a/src/systemc/core/sc_spawn.cc b/src/systemc/core/sc_spawn.cc index 9e2b4c83a..02f1fa6c9 100644 --- a/src/systemc/core/sc_spawn.cc +++ b/src/systemc/core/sc_spawn.cc @@ -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 && diff --git a/src/systemc/core/sensitivity.cc b/src/systemc/core/sensitivity.cc new file mode 100644 index 000000000..77aacb56a --- /dev/null +++ b/src/systemc/core/sensitivity.cc @@ -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 diff --git a/src/systemc/core/sensitivity.hh b/src/systemc/core/sensitivity.hh new file mode 100644 index 000000000..f032630ec --- /dev/null +++ b/src/systemc/core/sensitivity.hh @@ -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__ diff --git a/src/systemc/ext/core/sc_event.hh b/src/systemc/ext/core/sc_event.hh index e9748cb95..f70951d6a 100644 --- a/src/systemc/ext/core/sc_event.hh +++ b/src/systemc/ext/core/sc_event.hh @@ -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); diff --git a/src/systemc/ext/core/sc_port.hh b/src/systemc/ext/core/sc_port.hh index 88745cc2e..de26f5ae5 100644 --- a/src/systemc/ext/core/sc_port.hh +++ b/src/systemc/ext/core/sc_port.hh @@ -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(); |