From d737358ac643ff5bdc3984138cc3ae08c7b57ff7 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 14 Sep 2018 18:33:16 -0700 Subject: [PATCH] systemc: Rework how delayed sensitivities are handled. Make BindInfo into a more general purpose Port class which mirrors sc_module and Module, sc_object and Object, etc. This tracks multiple bindings internally, and also pending sensitivities. Keep a global list of ports which are added in reverse order to match Accellera, and which is iterated over to finalize binding and for phase callbacks. This is as opposed to doing it one module at a time, and is to better match Accellera's ordering for the regressions. Also the sensitivity classes are now built with factory functions, which gets around problems calling virtual functions from their constructors or forgetting to having to have extra boilerplate each place they're constructed. The port class also now finalizes port or event finder sensitivities when its binding is completed, unless it's already complete in which case it does so immediately. Change-Id: I1b01689715c425b94e0f68cf0271f5c1565d8c61 Reviewed-on: https://gem5-review.googlesource.com/c/12806 Reviewed-by: Gabe Black Maintainer: Gabe Black --- src/systemc/core/SConscript | 1 + src/systemc/core/kernel.cc | 14 +- src/systemc/core/module.cc | 8 -- src/systemc/core/{bindinfo.hh => port.cc} | 78 ++++++++--- src/systemc/core/port.hh | 150 +++++++++++++++++++++ src/systemc/core/process.cc | 9 -- src/systemc/core/process.hh | 3 - src/systemc/core/sc_module.cc | 24 ++-- src/systemc/core/sc_port.cc | 50 ++----- src/systemc/core/sc_sensitive.cc | 12 +- src/systemc/core/sc_spawn.cc | 10 +- src/systemc/core/scheduler.cc | 3 - src/systemc/core/sensitivity.cc | 154 ++++++++++++++-------- src/systemc/core/sensitivity.hh | 151 +++++++++++---------- src/systemc/ext/core/sc_port.hh | 16 +-- 15 files changed, 442 insertions(+), 241 deletions(-) rename src/systemc/core/{bindinfo.hh => port.cc} (55%) create mode 100644 src/systemc/core/port.hh diff --git a/src/systemc/core/SConscript b/src/systemc/core/SConscript index 1d291ef4d..0aa59944d 100644 --- a/src/systemc/core/SConscript +++ b/src/systemc/core/SConscript @@ -35,6 +35,7 @@ if env['USE_SYSTEMC']: Source('kernel.cc') Source('module.cc') Source('object.cc') + Source('port.cc') Source('process.cc') Source('process_types.cc') Source('python.cc') diff --git a/src/systemc/core/kernel.cc b/src/systemc/core/kernel.cc index ca99e1932..ff8e24e6a 100644 --- a/src/systemc/core/kernel.cc +++ b/src/systemc/core/kernel.cc @@ -32,6 +32,7 @@ #include "base/logging.hh" #include "systemc/core/channel.hh" #include "systemc/core/module.hh" +#include "systemc/core/port.hh" #include "systemc/core/scheduler.hh" namespace sc_gem5 @@ -75,6 +76,8 @@ Kernel::init() fatal("Simulation called sc_stop during elaboration.\n"); status(::sc_core::SC_BEFORE_END_OF_ELABORATION); + for (auto p: allPorts) + p->sc_port_base()->before_end_of_elaboration(); for (auto m: sc_gem5::allModules) m->beforeEndOfElaboration(); for (auto c: sc_gem5::allChannels) @@ -88,11 +91,12 @@ Kernel::regStats() return; try { - for (auto m: sc_gem5::allModules) - for (auto p: m->ports) - p->_gem5Finalize(); + for (auto p: allPorts) + p->finalize(); status(::sc_core::SC_END_OF_ELABORATION); + for (auto p: allPorts) + p->sc_port_base()->end_of_elaboration(); for (auto m: sc_gem5::allModules) m->endOfElaboration(); for (auto c: sc_gem5::allChannels) @@ -117,6 +121,8 @@ Kernel::startup() try { status(::sc_core::SC_START_OF_SIMULATION); + for (auto p: allPorts) + p->sc_port_base()->start_of_simulation(); for (auto m: sc_gem5::allModules) m->startOfSimulation(); for (auto c: sc_gem5::allChannels) @@ -147,6 +153,8 @@ Kernel::stopWork() { status(::sc_core::SC_END_OF_SIMULATION); try { + for (auto p: allPorts) + p->sc_port_base()->end_of_simulation(); for (auto m: sc_gem5::allModules) m->endOfSimulation(); for (auto c: sc_gem5::allChannels) diff --git a/src/systemc/core/module.cc b/src/systemc/core/module.cc index dcd6faa53..afc3bf241 100644 --- a/src/systemc/core/module.cc +++ b/src/systemc/core/module.cc @@ -113,8 +113,6 @@ Module::beforeEndOfElaboration() { callbackModule(this); _sc_mod->before_end_of_elaboration(); - for (auto p: ports) - p->before_end_of_elaboration(); for (auto e: exports) e->before_end_of_elaboration(); callbackModule(nullptr); @@ -131,8 +129,6 @@ Module::endOfElaboration() } callbackModule(this); _sc_mod->end_of_elaboration(); - for (auto p: ports) - p->end_of_elaboration(); for (auto e: exports) e->end_of_elaboration(); callbackModule(nullptr); @@ -143,8 +139,6 @@ Module::startOfSimulation() { callbackModule(this); _sc_mod->start_of_simulation(); - for (auto p: ports) - p->start_of_simulation(); for (auto e: exports) e->start_of_simulation(); callbackModule(nullptr); @@ -155,8 +149,6 @@ Module::endOfSimulation() { callbackModule(this); _sc_mod->end_of_simulation(); - for (auto p: ports) - p->end_of_simulation(); for (auto e: exports) e->end_of_simulation(); callbackModule(nullptr); diff --git a/src/systemc/core/bindinfo.hh b/src/systemc/core/port.cc similarity index 55% rename from src/systemc/core/bindinfo.hh rename to src/systemc/core/port.cc index 9e636a696..af6ecd125 100644 --- a/src/systemc/core/bindinfo.hh +++ b/src/systemc/core/port.cc @@ -27,29 +27,75 @@ * Authors: Gabe Black */ -#ifndef __SYSTEMC_CORE_BINDINFO_HH__ -#define __SYSTEMC_CORE_BINDINFO_HH__ +#include "systemc/core/port.hh" -#include "systemc/ext/core/sc_interface.hh" +#include "systemc/core/sensitivity.hh" namespace sc_gem5 { -class BindInfo +void +Port::finalizePort(StaticSensitivityPort *port) { - public: - BindInfo(::sc_core::sc_interface *interface) : - interface(interface), port(nullptr) - {} + for (int i = 0; i < size(); i++) + port->addEvent(&getInterface(i)->default_event()); +} - BindInfo(::sc_core::sc_port_base *port) : - interface(nullptr), port(port) - {} +void +Port::finalizeFinder(StaticSensitivityFinder *finder) +{ + for (int i = 0; i < size(); i++) + finder->addEvent(&finder->find(getInterface(i))); +} - ::sc_core::sc_interface *interface; - ::sc_core::sc_port_base *port; -}; +void +Port::sensitive(StaticSensitivityPort *port) +{ + if (finalized) + finalizePort(port); + else + sensitivities.push_back(new Sensitivity(port)); +} -} // namespace sc_gem5 +void +Port::sensitive(StaticSensitivityFinder *finder) +{ + if (finalized) + finalizeFinder(finder); + else + sensitivities.push_back(new Sensitivity(finder)); +} + +void +Port::finalize() +{ + if (finalized) + return; + finalized = true; -#endif // __SYSTEMC_CORE_BINDINFO_HH__ + for (auto &b: bindings) { + if (b->interface) { + addInterface(b->interface); + } else { + b->port->_gem5Port->finalize(); + addInterfaces(b->port); + } + delete b; + } + + bindings.clear(); + + for (auto &s: sensitivities) { + if (s->port) + finalizePort(s->port); + else + finalizeFinder(s->finder); + delete s; + } + + sensitivities.clear(); +} + +std::list allPorts; + +} // namespace sc_gem5 diff --git a/src/systemc/core/port.hh b/src/systemc/core/port.hh new file mode 100644 index 000000000..15e7bbed1 --- /dev/null +++ b/src/systemc/core/port.hh @@ -0,0 +1,150 @@ +/* + * 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_PORT_HH__ +#define __SYSTEMC_CORE_PORT_HH__ + +#include +#include + +#include "systemc/ext/core/sc_interface.hh" +#include "systemc/ext/core/sc_port.hh" + +namespace sc_gem5 +{ + +class StaticSensitivityPort; +class StaticSensitivityFinder; + +class Port; + +extern std::list allPorts; + +class Port +{ + private: + ::sc_core::sc_port_base *portBase; + + bool finalized; + int _maxSize; + int _size; + + void finalizePort(StaticSensitivityPort *port); + void finalizeFinder(StaticSensitivityFinder *finder); + + void + addInterface(::sc_core::sc_interface *i) + { + _size++; + portBase->_gem5AddInterface(i); + } + + void + addInterfaces(::sc_core::sc_port_base *pb) + { + for (int i = 0; i < pb->size(); i++) + addInterface(pb->_gem5Interface(i)); + } + + ::sc_core::sc_interface * + getInterface(int i) + { + return portBase->_gem5Interface(i); + } + + struct Binding + { + explicit Binding(::sc_core::sc_interface *interface) : + interface(interface), port(nullptr) + {} + + explicit Binding(::sc_core::sc_port_base *port) : + interface(nullptr), port(port) + {} + + ::sc_core::sc_interface *interface; + ::sc_core::sc_port_base *port; + }; + + struct Sensitivity + { + Sensitivity(StaticSensitivityPort *port) : + port(port), finder(nullptr) + {} + + Sensitivity(StaticSensitivityFinder *finder) : + port(nullptr), finder(finder) + {} + + StaticSensitivityPort *port; + StaticSensitivityFinder *finder; + }; + + std::vector bindings; + std::vector sensitivities; + + public: + static Port * + fromPort(const ::sc_core::sc_port_base *pb) + { + return pb->_gem5Port; + } + + ::sc_core::sc_port_base *sc_port_base() { return portBase; } + + Port(::sc_core::sc_port_base *port_base, int max) : + portBase(port_base), finalized(false), _maxSize(max), _size(0) + { + allPorts.push_front(this); + } + + void + bind(::sc_core::sc_interface *interface) + { + bindings.push_back(new Binding(interface)); + } + + void + bind(::sc_core::sc_port_base *port) + { + bindings.push_back(new Binding(port)); + } + + void sensitive(StaticSensitivityPort *port); + void sensitive(StaticSensitivityFinder *finder); + + void finalize(); + + int size() { return _size; } + int maxSize() { return _maxSize; } +}; + +} // namespace sc_gem5 + +#endif // __SYSTEMC_CORE_PORT_HH__ diff --git a/src/systemc/core/process.cc b/src/systemc/core/process.cc index e977713f4..45c01e916 100644 --- a/src/systemc/core/process.cc +++ b/src/systemc/core/process.cc @@ -235,13 +235,6 @@ Process::syncResetOff(bool inc_kids) _syncReset = false; } -void -Process::finalize() -{ - for (auto s: staticSensitivities) - s->finalize(); -}; - void Process::run() { @@ -276,8 +269,6 @@ Process::setDynamic(DynamicSensitivity *s) delete dynamicSensitivity; } dynamicSensitivity = s; - if (dynamicSensitivity) - dynamicSensitivity->finalize(); } void diff --git a/src/systemc/core/process.hh b/src/systemc/core/process.hh index 0a312e28e..4266c2d7d 100644 --- a/src/systemc/core/process.hh +++ b/src/systemc/core/process.hh @@ -35,7 +35,6 @@ #include #include "base/fiber.hh" -#include "systemc/core/bindinfo.hh" #include "systemc/core/list.hh" #include "systemc/core/object.hh" #include "systemc/core/sched_event.hh" @@ -96,8 +95,6 @@ class Process : public ::sc_core::sc_process_b, public ListNode void setStackSize(size_t size) { stackSize = size; } - void finalize(); - void run(); void addStatic(StaticSensitivity *); diff --git a/src/systemc/core/sc_module.cc b/src/systemc/core/sc_module.cc index 3e900f658..32d1c979a 100644 --- a/src/systemc/core/sc_module.cc +++ b/src/systemc/core/sc_module.cc @@ -505,7 +505,7 @@ next_trigger(const sc_event &e) { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->cancelTimeout(); - p->setDynamic(new ::sc_gem5::DynamicSensitivityEvent(p, &e)); + ::sc_gem5::newDynamicSensitivityEvent(p, &e); } void @@ -513,7 +513,7 @@ next_trigger(const sc_event_or_list &eol) { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->cancelTimeout(); - p->setDynamic(new ::sc_gem5::DynamicSensitivityEventOrList(p, &eol)); + ::sc_gem5::newDynamicSensitivityEventOrList(p, &eol); } void @@ -521,7 +521,7 @@ next_trigger(const sc_event_and_list &eal) { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->cancelTimeout(); - p->setDynamic(new ::sc_gem5::DynamicSensitivityEventAndList(p, &eal)); + ::sc_gem5::newDynamicSensitivityEventAndList(p, &eal); } void @@ -543,7 +543,7 @@ next_trigger(const sc_time &t, const sc_event &e) { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->setTimeout(t); - p->setDynamic(new ::sc_gem5::DynamicSensitivityEvent(p, &e)); + ::sc_gem5::newDynamicSensitivityEvent(p, &e); } void @@ -557,7 +557,7 @@ next_trigger(const sc_time &t, const sc_event_or_list &eol) { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->setTimeout(t); - p->setDynamic(new ::sc_gem5::DynamicSensitivityEventOrList(p, &eol)); + ::sc_gem5::newDynamicSensitivityEventOrList(p, &eol); } void @@ -571,7 +571,7 @@ next_trigger(const sc_time &t, const sc_event_and_list &eal) { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->setTimeout(t); - p->setDynamic(new ::sc_gem5::DynamicSensitivityEventAndList(p, &eal)); + ::sc_gem5::newDynamicSensitivityEventAndList(p, &eal); } void @@ -616,7 +616,7 @@ wait(const sc_event &e) { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->cancelTimeout(); - p->setDynamic(new ::sc_gem5::DynamicSensitivityEvent(p, &e)); + ::sc_gem5::newDynamicSensitivityEvent(p, &e); sc_gem5::scheduler.yield(); } @@ -625,7 +625,7 @@ wait(const sc_event_or_list &eol) { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->cancelTimeout(); - p->setDynamic(new ::sc_gem5::DynamicSensitivityEventOrList(p, &eol)); + ::sc_gem5::newDynamicSensitivityEventOrList(p, &eol); sc_gem5::scheduler.yield(); } @@ -634,7 +634,7 @@ wait(const sc_event_and_list &eal) { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->cancelTimeout(); - p->setDynamic(new ::sc_gem5::DynamicSensitivityEventAndList(p, &eal)); + ::sc_gem5::newDynamicSensitivityEventAndList(p, &eal); sc_gem5::scheduler.yield(); } @@ -658,7 +658,7 @@ wait(const sc_time &t, const sc_event &e) { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->setTimeout(t); - p->setDynamic(new ::sc_gem5::DynamicSensitivityEvent(p, &e)); + ::sc_gem5::newDynamicSensitivityEvent(p, &e); sc_gem5::scheduler.yield(); } @@ -673,7 +673,7 @@ wait(const sc_time &t, const sc_event_or_list &eol) { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->setTimeout(t); - p->setDynamic(new ::sc_gem5::DynamicSensitivityEventOrList(p, &eol)); + ::sc_gem5::newDynamicSensitivityEventOrList(p, &eol); sc_gem5::scheduler.yield(); } @@ -688,7 +688,7 @@ wait(const sc_time &t, const sc_event_and_list &eal) { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->setTimeout(t); - p->setDynamic(new ::sc_gem5::DynamicSensitivityEventAndList(p, &eal)); + ::sc_gem5::newDynamicSensitivityEventAndList(p, &eal); sc_gem5::scheduler.yield(); } diff --git a/src/systemc/core/sc_port.cc b/src/systemc/core/sc_port.cc index c822e966e..52f66b70d 100644 --- a/src/systemc/core/sc_port.cc +++ b/src/systemc/core/sc_port.cc @@ -28,8 +28,8 @@ */ #include "base/logging.hh" -#include "systemc/core/bindinfo.hh" #include "systemc/core/module.hh" +#include "systemc/core/port.hh" #include "systemc/core/scheduler.hh" #include "systemc/ext/core/sc_main.hh" #include "systemc/ext/core/sc_port.hh" @@ -56,7 +56,7 @@ reportError(const char *id, const char *add_msg, } sc_port_base::sc_port_base(const char *name, int n, sc_port_policy p) : - sc_object(name), _maxSize(n), _size(0), finalized(false) + sc_object(name), _gem5Port(new ::sc_gem5::Port(this, n)) { if (sc_is_running()) { reportError("(E110) insert port failed", "simulation running", @@ -76,51 +76,21 @@ sc_port_base::sc_port_base(const char *name, int n, sc_port_policy p) : } } -void -sc_port_base::warn_unimpl(const char *func) const -{ - warn("%s not implemented.\n", func); -} - -int sc_port_base::maxSize() const { return _maxSize; } -int sc_port_base::size() const { return _size; } - -void -sc_port_base::bind(sc_interface &i) +sc_port_base::~sc_port_base() { - _gem5BindInfo.push_back(new ::sc_gem5::BindInfo(&i)); + delete _gem5Port; } void -sc_port_base::bind(sc_port_base &p) +sc_port_base::warn_unimpl(const char *func) const { - _gem5BindInfo.push_back(new ::sc_gem5::BindInfo(&p)); + warn("%s not implemented.\n", func); } -void -sc_port_base::_gem5Finalize() -{ - if (finalized) - return; - finalized = true; +int sc_port_base::maxSize() const { return _gem5Port->maxSize(); } +int sc_port_base::size() const { return _gem5Port->size(); } - for (auto &bi: _gem5BindInfo) { - if (bi->interface) { - _size++; - _gem5AddInterface(bi->interface); - } else { - sc_port_base *port = bi->port; - port->_gem5Finalize(); - int size = port->size(); - for (int i = 0; i < size; i++) { - _size++; - _gem5AddInterface(port->_gem5Interface(i)); - } - } - delete bi; - } - - _gem5BindInfo.clear(); -} +void sc_port_base::bind(sc_interface &i) { _gem5Port->bind(&i); } +void sc_port_base::bind(sc_port_base &p) { _gem5Port->bind(&p); } } // namespace sc_core diff --git a/src/systemc/core/sc_sensitive.cc b/src/systemc/core/sc_sensitive.cc index 93b460a4b..b254f6861 100644 --- a/src/systemc/core/sc_sensitive.cc +++ b/src/systemc/core/sc_sensitive.cc @@ -40,32 +40,28 @@ sc_sensitive::sc_sensitive() : currentProcess(nullptr) {} sc_sensitive & sc_sensitive::operator << (const sc_event &e) { - currentProcess->addStatic( - new sc_gem5::StaticSensitivityEvent(currentProcess, &e)); + sc_gem5::newStaticSensitivityEvent(currentProcess, &e); return *this; } sc_sensitive & sc_sensitive::operator << (const sc_interface &i) { - currentProcess->addStatic( - new sc_gem5::StaticSensitivityInterface(currentProcess, &i)); + sc_gem5::newStaticSensitivityInterface(currentProcess, &i); return *this; } sc_sensitive & sc_sensitive::operator << (const sc_port_base &b) { - currentProcess->addStatic( - new sc_gem5::StaticSensitivityPort(currentProcess, &b)); + sc_gem5::newStaticSensitivityPort(currentProcess, &b); return *this; } sc_sensitive & sc_sensitive::operator << (sc_event_finder &f) { - currentProcess->addStatic( - new sc_gem5::StaticSensitivityFinder(currentProcess, &f)); + sc_gem5::newStaticSensitivityFinder(currentProcess, &f); return *this; } diff --git a/src/systemc/core/sc_spawn.cc b/src/systemc/core/sc_spawn.cc index 02f1fa6c9..8c936bfe9 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 StaticSensitivityEvent(proc, e)); + newStaticSensitivityEvent(proc, e); for (auto p: opts->_ports) - proc->addStatic(new StaticSensitivityPort(proc, p)); + newStaticSensitivityPort(proc, p); for (auto e: opts->_exports) - proc->addStatic(new StaticSensitivityExport(proc, e)); + newStaticSensitivityExport(proc, e); for (auto i: opts->_interfaces) - proc->addStatic(new StaticSensitivityInterface(proc, i)); + newStaticSensitivityInterface(proc, i); for (auto f: opts->_finders) - proc->addStatic(new StaticSensitivityFinder(proc, f)); + newStaticSensitivityFinder(proc, f); } if (opts && opts->_dontInitialize && diff --git a/src/systemc/core/scheduler.cc b/src/systemc/core/scheduler.cc index a0695a395..8a796bb5b 100644 --- a/src/systemc/core/scheduler.cc +++ b/src/systemc/core/scheduler.cc @@ -104,7 +104,6 @@ void Scheduler::initPhase() { for (Process *p = initList.getNext(); p; p = initList.getNext()) { - p->finalize(); p->popListNode(); if (p->dontInitialize()) { @@ -141,8 +140,6 @@ void Scheduler::reg(Process *p) { if (initDone) { - // If we're past initialization, finalize static sensitivity. - p->finalize(); // If not marked as dontInitialize, mark as ready. if (!p->dontInitialize()) p->ready(); diff --git a/src/systemc/core/sensitivity.cc b/src/systemc/core/sensitivity.cc index 77aacb56a..740090cd9 100644 --- a/src/systemc/core/sensitivity.cc +++ b/src/systemc/core/sensitivity.cc @@ -30,6 +30,7 @@ #include "systemc/core/sensitivity.hh" #include "systemc/core/event.hh" +#include "systemc/core/port.hh" #include "systemc/core/scheduler.hh" #include "systemc/ext/core/sc_export.hh" #include "systemc/ext/core/sc_interface.hh" @@ -38,6 +39,10 @@ namespace sc_gem5 { +/* + * Common sensitivity interface. + */ + void Sensitivity::satisfy() { @@ -53,6 +58,10 @@ Sensitivity::notify(Event *e) } +/* + * Dynamic vs. static sensitivity. + */ + void DynamicSensitivity::addToEvent(const ::sc_core::sc_event *e) { @@ -77,106 +86,139 @@ StaticSensitivity::delFromEvent(const ::sc_core::sc_event *e) Event::getFromScEvent(e)->delSensitivity(this); } + +/* + * Static sensitivities. + */ + void -StaticSensitivityInterface::finalize() +newStaticSensitivityEvent(Process *p, const sc_core::sc_event *e) { - event = &interface->default_event(); - SensitivityEvent::finalize(); + auto s = new StaticSensitivityEvent(p, e); + s->addToEvent(s->event); + p->addStatic(s); } void -StaticSensitivityPort::finalize() +newStaticSensitivityInterface(Process *p, const sc_core::sc_interface *i) { - for (int i = 0; i < port->size(); i++) { - const ::sc_core::sc_event *event = - &port->_gem5Interface(i)->default_event(); - events.insert(event); - addToEvent(event); - } + auto s = new StaticSensitivityInterface(p, i); + s->addToEvent(s->event); + p->addStatic(s); } void -StaticSensitivityExport::finalize() +newStaticSensitivityPort(Process *p, const sc_core::sc_port_base *pb) { - event = &exp->get_interface()->default_event(); - SensitivityEvent::finalize(); + auto s = new StaticSensitivityPort(p); + Port *port = Port::fromPort(pb); + port->sensitive(s); + p->addStatic(s); } void -StaticSensitivityFinder::finalize() +newStaticSensitivityExport(Process *p, const sc_core::sc_export_base *exp) { - 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); - } + auto s = new StaticSensitivityExport(p, exp); + s->addToEvent(s->event); + p->addStatic(s); } -bool -DynamicSensitivityEventOrList::notifyWork(Event *e) +void +newStaticSensitivityFinder(Process *p, const sc_core::sc_event_finder *f) { - events.erase(e->sc_event()); + auto s = new StaticSensitivityFinder(p, f); + Port *port = Port::fromPort(f->port()); + port->sensitive(s); + p->addStatic(s); +} - // 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; -} +StaticSensitivityInterface::StaticSensitivityInterface( + Process *p, const sc_core::sc_interface *i) : + Sensitivity(p), StaticSensitivity(p), + SensitivityEvent(p, &i->default_event()) +{} -DynamicSensitivityEventOrList::DynamicSensitivityEventOrList( - Process *p, const sc_core::sc_event_or_list *eol) : - Sensitivity(p), DynamicSensitivity(p), events(eol->events) +StaticSensitivityExport::StaticSensitivityExport( + Process *p, const sc_core::sc_export_base *exp) : + Sensitivity(p), StaticSensitivity(p), + SensitivityEvent(p, &exp->get_interface()->default_event()) {} +const ::sc_core::sc_event & +StaticSensitivityFinder::find(::sc_core::sc_interface *i) +{ + return finder->find_event(i); +} + + +/* + * Dynamic sensitivities. + */ + void -DynamicSensitivityEventOrList::finalize() +newDynamicSensitivityEvent(Process *p, const sc_core::sc_event *e) { - for (auto e: events) - addToEvent(e); + auto s = new DynamicSensitivityEvent(p, e); + s->addToEvent(s->event); + p->setDynamic(s); } void -DynamicSensitivityEventOrList::clear() +newDynamicSensitivityEventOrList( + Process *p, const sc_core::sc_event_or_list *eol) +{ + auto s = new DynamicSensitivityEventOrList(p, eol); + for (auto event: s->events) + s->addToEvent(event); + p->setDynamic(s); +} + +void newDynamicSensitivityEventAndList( + Process *p, const sc_core::sc_event_and_list *eal) { - for (auto e: events) - delFromEvent(e); + auto s = new DynamicSensitivityEventAndList(p, eal); + for (auto event: s->events) + s->addToEvent(event); + p->setDynamic(s); } + +DynamicSensitivityEventOrList::DynamicSensitivityEventOrList( + Process *p, const sc_core::sc_event_or_list *eol) : + Sensitivity(p), DynamicSensitivity(p), SensitivityEvents(p, eol->events) +{} + bool -DynamicSensitivityEventAndList::notifyWork(Event *e) +DynamicSensitivityEventOrList::notifyWork(Event *e) { events.erase(e->sc_event()); - // This sensitivity is satisfied if all events have triggered. - if (events.empty()) - satisfy(); + // 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; } DynamicSensitivityEventAndList::DynamicSensitivityEventAndList( Process *p, const sc_core::sc_event_and_list *eal) : - Sensitivity(p), DynamicSensitivity(p), events(eal->events) + Sensitivity(p), DynamicSensitivity(p), SensitivityEvents(p, eal->events) {} -void -DynamicSensitivityEventAndList::finalize() +bool +DynamicSensitivityEventAndList::notifyWork(Event *e) { - for (auto e: events) - addToEvent(e); -} + events.erase(e->sc_event()); -void -DynamicSensitivityEventAndList::clear() -{ - for (auto e: events) - delFromEvent(e); + // This sensitivity is satisfied if all events have triggered. + if (events.empty()) + satisfy(); + + return true; } } // namespace sc_gem5 diff --git a/src/systemc/core/sensitivity.hh b/src/systemc/core/sensitivity.hh index f032630ec..b3f9a2e49 100644 --- a/src/systemc/core/sensitivity.hh +++ b/src/systemc/core/sensitivity.hh @@ -79,7 +79,6 @@ class Sensitivity } public: - virtual void finalize() = 0; virtual void clear() = 0; void satisfy(); @@ -124,7 +123,7 @@ typedef std::vector StaticSensitivities; /* - * Sensitivity to events, which can be static or dynamic. + * Sensitivity to an event or events, which can be static or dynamic. */ class SensitivityEvent : virtual public Sensitivity @@ -137,19 +136,57 @@ class SensitivityEvent : virtual public Sensitivity {} public: - void finalize() override { addToEvent(event); } void clear() override { delFromEvent(event); } }; +class SensitivityEvents : virtual public Sensitivity +{ + protected: + std::set events; + + SensitivityEvents(Process *p) : Sensitivity(p) {} + SensitivityEvents( + Process *p, const std::set &s) : + Sensitivity(p), events(s) + {} + + public: + void + clear() override + { + for (auto event: events) + delFromEvent(event); + } + + void + addEvent(const ::sc_core::sc_event *event) + { + events.insert(event); + addToEvent(event); + } +}; + /* * Static sensitivities. */ +void newStaticSensitivityEvent(Process *p, const sc_core::sc_event *e); +void newStaticSensitivityInterface(Process *p, const sc_core::sc_interface *i); +void newStaticSensitivityPort(Process *p, const sc_core::sc_port_base *pb); +void newStaticSensitivityExport( + Process *p, const sc_core::sc_export_base *exp); +void newStaticSensitivityFinder( + Process *p, const sc_core::sc_event_finder *f); + + class StaticSensitivityEvent : public StaticSensitivity, public SensitivityEvent { - public: + friend void newStaticSensitivityEvent( + Process *p, const sc_core::sc_event *e); + + protected: StaticSensitivityEvent(Process *p, const sc_core::sc_event *e) : Sensitivity(p), StaticSensitivity(p), SensitivityEvent(p, e) {} @@ -158,71 +195,50 @@ class StaticSensitivityEvent : 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; + friend void newStaticSensitivityInterface( + Process *p, const sc_core::sc_interface *i); + protected: + StaticSensitivityInterface(Process *p, const sc_core::sc_interface *i); }; -class StaticSensitivityPort : public StaticSensitivity +class StaticSensitivityPort : + public StaticSensitivity, public SensitivityEvents { - private: - const ::sc_core::sc_port_base *port; - std::set events; + friend void newStaticSensitivityPort( + Process *p, const sc_core::sc_port_base *pb); - public: - StaticSensitivityPort(Process *p, const sc_core::sc_port_base *pb) : - Sensitivity(p), StaticSensitivity(p), port(pb) + protected: + StaticSensitivityPort(Process *p) : + Sensitivity(p), StaticSensitivity(p), SensitivityEvents(p) {} - - 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) - {} + friend void newStaticSensitivityExport( + Process *p, const sc_core::sc_export_base *exp); - void finalize() override; + StaticSensitivityExport(Process *p, const sc_core::sc_export_base *exp); }; -class StaticSensitivityFinder : public StaticSensitivity + +class StaticSensitivityFinder : + public StaticSensitivity, public SensitivityEvents { private: - const ::sc_core::sc_event_finder *finder; - std::set events; + const sc_core::sc_event_finder *finder; + + friend void newStaticSensitivityFinder( + Process *p, const sc_core::sc_event_finder *f); - public: StaticSensitivityFinder(Process *p, const sc_core::sc_event_finder *f) : - Sensitivity(p), StaticSensitivity(p), finder(f) + Sensitivity(p), StaticSensitivity(p), SensitivityEvents(p), finder(f) {} - void finalize() override; - - void - clear() override - { - for (auto event: events) - delFromEvent(event); - } + public: + const ::sc_core::sc_event &find(::sc_core::sc_interface *i); }; @@ -230,48 +246,51 @@ class StaticSensitivityFinder : public StaticSensitivity * Dynamic sensitivities. */ +void newDynamicSensitivityEvent(Process *p, const sc_core::sc_event *e); +void newDynamicSensitivityEventOrList( + Process *p, const sc_core::sc_event_or_list *eol); +void newDynamicSensitivityEventAndList( + Process *p, const sc_core::sc_event_and_list *eal); + class DynamicSensitivityEvent : public DynamicSensitivity, public SensitivityEvent { - public: + private: + friend void newDynamicSensitivityEvent( + Process *p, const sc_core::sc_event *e); + DynamicSensitivityEvent(Process *p, const sc_core::sc_event *e) : Sensitivity(p), DynamicSensitivity(p), SensitivityEvent(p, e) {} }; -class DynamicSensitivityEventOrList : public DynamicSensitivity +class DynamicSensitivityEventOrList : + public DynamicSensitivity, public SensitivityEvents { private: - std::set events; - - protected: - bool notifyWork(Event *e) override; + friend void newDynamicSensitivityEventOrList( + Process *p, const sc_core::sc_event_or_list *eol); - public: DynamicSensitivityEventOrList( Process *p, const sc_core::sc_event_or_list *eol); - void finalize() override; - void clear() override; + bool notifyWork(Event *e) 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 +class DynamicSensitivityEventAndList : + public DynamicSensitivity, public SensitivityEvents { private: - std::set events; - - protected: - bool notifyWork(Event *e) override; + friend void newDynamicSensitivityEventAndList( + Process *p, const sc_core::sc_event_and_list *eal); - public: DynamicSensitivityEventAndList( Process *p, const sc_core::sc_event_and_list *eal); - void finalize() override; - void clear() override; + bool notifyWork(Event *e) override; }; } // namespace sc_gem5 diff --git a/src/systemc/ext/core/sc_port.hh b/src/systemc/ext/core/sc_port.hh index de26f5ae5..c9d436ec3 100644 --- a/src/systemc/ext/core/sc_port.hh +++ b/src/systemc/ext/core/sc_port.hh @@ -39,10 +39,7 @@ namespace sc_gem5 { -class BindInfo; -class Module; -class StaticSensitivityPort; -class StaticSensitivityFinder; +class Port; }; @@ -62,6 +59,7 @@ class sc_port_base : public sc_object { public: sc_port_base(const char *name, int n, sc_port_policy p); + virtual ~sc_port_base(); void warn_unimpl(const char *func) const; @@ -87,19 +85,13 @@ class sc_port_base : public sc_object virtual void end_of_simulation() = 0; private: - friend class ::sc_gem5::StaticSensitivityPort; - friend class ::sc_gem5::StaticSensitivityFinder; + friend class ::sc_gem5::Port; friend class ::sc_gem5::Kernel; - void _gem5Finalize(); - virtual sc_interface *_gem5Interface(int n) const = 0; virtual void _gem5AddInterface(sc_interface *i) = 0; - std::vector<::sc_gem5::BindInfo *> _gem5BindInfo; - int _maxSize; - int _size; - bool finalized; + ::sc_gem5::Port *_gem5Port; }; template -- 2.30.2