| /* |
| * 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. |
| */ |
| |
| #include "systemc/core/sensitivity.hh" |
| |
| #include "systemc/core/event.hh" |
| #include "systemc/core/port.hh" |
| #include "systemc/core/process.hh" |
| #include "systemc/core/scheduler.hh" |
| #include "systemc/ext/channel/sc_in.hh" |
| #include "systemc/ext/channel/sc_inout.hh" |
| #include "systemc/ext/channel/sc_out.hh" |
| #include "systemc/ext/core/messages.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 |
| { |
| |
| /* |
| * Common sensitivity interface. |
| */ |
| |
| void |
| Sensitivity::satisfy() |
| { |
| process->satisfySensitivity(this); |
| } |
| |
| bool |
| Sensitivity::notifyWork(Event *e) |
| { |
| satisfy(); |
| return true; |
| } |
| |
| bool |
| Sensitivity::notify(Event *e) |
| { |
| if (scheduler.current() == process) { |
| static bool warned = false; |
| if (!warned) { |
| SC_REPORT_WARNING(sc_core::SC_ID_IMMEDIATE_SELF_NOTIFICATION_, |
| process->name()); |
| warned = true; |
| } |
| return false; |
| } |
| |
| if (process->disabled()) |
| return false; |
| |
| return notifyWork(e); |
| } |
| |
| bool |
| Sensitivity::ofMethod() |
| { |
| return process->procKind() == sc_core::SC_METHOD_PROC_; |
| } |
| |
| |
| /* |
| * Dynamic vs. static sensitivity. |
| */ |
| |
| 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); |
| } |
| |
| |
| /* |
| * Static sensitivities. |
| */ |
| |
| void |
| newStaticSensitivityEvent(Process *p, const sc_core::sc_event *e) |
| { |
| auto s = new StaticSensitivityEvent(p, e); |
| s->addToEvent(s->event); |
| p->addStatic(s); |
| } |
| |
| void |
| newStaticSensitivityInterface(Process *p, const sc_core::sc_interface *i) |
| { |
| auto s = new StaticSensitivityInterface(p, i); |
| s->addToEvent(s->event); |
| p->addStatic(s); |
| } |
| |
| void |
| newStaticSensitivityPort(Process *p, const sc_core::sc_port_base *pb) |
| { |
| auto s = new StaticSensitivityPort(p); |
| Port *port = Port::fromPort(pb); |
| port->sensitive(s); |
| p->addStatic(s); |
| } |
| |
| void |
| newStaticSensitivityExport(Process *p, const sc_core::sc_export_base *exp) |
| { |
| auto s = new StaticSensitivityExport(p, exp); |
| s->addToEvent(s->event); |
| p->addStatic(s); |
| } |
| |
| void |
| newStaticSensitivityFinder(Process *p, const sc_core::sc_event_finder *f) |
| { |
| auto s = new StaticSensitivityFinder(p, f); |
| Port *port = Port::fromPort(f->port()); |
| port->sensitive(s); |
| p->addStatic(s); |
| } |
| |
| |
| StaticSensitivityInterface::StaticSensitivityInterface( |
| Process *p, const sc_core::sc_interface *i) : |
| Sensitivity(p), StaticSensitivity(p), |
| SensitivityEvent(p, &i->default_event()) |
| {} |
| |
| 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 |
| newDynamicSensitivityEvent(Process *p, const sc_core::sc_event *e) |
| { |
| auto s = new DynamicSensitivityEvent(p, e); |
| s->addToEvent(s->event); |
| p->setDynamic(s); |
| } |
| |
| void |
| 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) |
| { |
| 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), |
| list(eol) |
| {} |
| |
| DynamicSensitivityEventOrList::~DynamicSensitivityEventOrList() |
| { |
| if (list->autoDelete) { |
| panic_if(list->busy, |
| "sc_event_or_list can never be busy in gem5 implementation"); |
| delete list; |
| } |
| } |
| |
| 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; |
| } |
| |
| DynamicSensitivityEventAndList::DynamicSensitivityEventAndList( |
| Process *p, const sc_core::sc_event_and_list *eal) : |
| Sensitivity(p), |
| DynamicSensitivity(p), |
| SensitivityEvents(p, eal->events), |
| list(eal) |
| {} |
| |
| DynamicSensitivityEventAndList::~DynamicSensitivityEventAndList() |
| { |
| if (list->autoDelete) { |
| panic_if(list->busy, |
| "sc_event_and_list can never be busy in gem5 implementation"); |
| delete list; |
| } |
| } |
| |
| 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; |
| } |
| |
| } // namespace sc_gem5 |