/* * 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 #include #include #include "systemc/core/event.hh" #include "systemc/core/kernel.hh" #include "systemc/core/module.hh" #include "systemc/core/object.hh" #include "systemc/core/port.hh" #include "systemc/core/process_types.hh" #include "systemc/core/sensitivity.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/channel/sc_signal_in_if.hh" #include "systemc/ext/core/messages.hh" #include "systemc/ext/core/sc_module.hh" #include "systemc/ext/core/sc_module_name.hh" #include "systemc/ext/dt/bit/sc_logic.hh" #include "systemc/ext/utils/sc_report_handler.hh" namespace sc_gem5 { Process * newMethodProcess(const char *name, ProcessFuncWrapper *func) { Method *p = new Method(name, func); if (::sc_core::sc_is_running()) { std::string name = p->name(); delete p; SC_REPORT_ERROR(sc_core::SC_ID_MODULE_METHOD_AFTER_START_, name.c_str()); return nullptr; } scheduler.reg(p); return p; } Process * newThreadProcess(const char *name, ProcessFuncWrapper *func) { Thread *p = new Thread(name, func); if (::sc_core::sc_is_running()) { std::string name = p->name(); delete p; SC_REPORT_ERROR(sc_core::SC_ID_MODULE_THREAD_AFTER_START_, name.c_str()); return nullptr; } scheduler.reg(p); return p; } Process * newCThreadProcess(const char *name, ProcessFuncWrapper *func) { CThread *p = new CThread(name, func); if (::sc_core::sc_is_running()) { std::string name = p->name(); delete p; SC_REPORT_ERROR(sc_core::SC_ID_MODULE_CTHREAD_AFTER_START_, name.c_str()); return nullptr; } scheduler.reg(p); p->dontInitialize(true); return p; } } // namespace sc_gem5 namespace sc_core { sc_bind_proxy::sc_bind_proxy(sc_interface &_interface) : _interface(&_interface), _port(nullptr) {} sc_bind_proxy::sc_bind_proxy(sc_port_base &_port) : _interface(nullptr), _port(&_port) {} const sc_bind_proxy SC_BIND_PROXY_NUL(*(sc_port_base *)nullptr); sc_module::~sc_module() { delete _gem5_module; } const sc_bind_proxy SC_BIND_PROXY_NIL(*(sc_port_base *)nullptr); void sc_module::operator () (const sc_bind_proxy &p001, const sc_bind_proxy &p002, const sc_bind_proxy &p003, const sc_bind_proxy &p004, const sc_bind_proxy &p005, const sc_bind_proxy &p006, const sc_bind_proxy &p007, const sc_bind_proxy &p008, const sc_bind_proxy &p009, const sc_bind_proxy &p010, const sc_bind_proxy &p011, const sc_bind_proxy &p012, const sc_bind_proxy &p013, const sc_bind_proxy &p014, const sc_bind_proxy &p015, const sc_bind_proxy &p016, const sc_bind_proxy &p017, const sc_bind_proxy &p018, const sc_bind_proxy &p019, const sc_bind_proxy &p020, const sc_bind_proxy &p021, const sc_bind_proxy &p022, const sc_bind_proxy &p023, const sc_bind_proxy &p024, const sc_bind_proxy &p025, const sc_bind_proxy &p026, const sc_bind_proxy &p027, const sc_bind_proxy &p028, const sc_bind_proxy &p029, const sc_bind_proxy &p030, const sc_bind_proxy &p031, const sc_bind_proxy &p032, const sc_bind_proxy &p033, const sc_bind_proxy &p034, const sc_bind_proxy &p035, const sc_bind_proxy &p036, const sc_bind_proxy &p037, const sc_bind_proxy &p038, const sc_bind_proxy &p039, const sc_bind_proxy &p040, const sc_bind_proxy &p041, const sc_bind_proxy &p042, const sc_bind_proxy &p043, const sc_bind_proxy &p044, const sc_bind_proxy &p045, const sc_bind_proxy &p046, const sc_bind_proxy &p047, const sc_bind_proxy &p048, const sc_bind_proxy &p049, const sc_bind_proxy &p050, const sc_bind_proxy &p051, const sc_bind_proxy &p052, const sc_bind_proxy &p053, const sc_bind_proxy &p054, const sc_bind_proxy &p055, const sc_bind_proxy &p056, const sc_bind_proxy &p057, const sc_bind_proxy &p058, const sc_bind_proxy &p059, const sc_bind_proxy &p060, const sc_bind_proxy &p061, const sc_bind_proxy &p062, const sc_bind_proxy &p063, const sc_bind_proxy &p064) { std::vector proxies; auto insert = [&proxies](const ::sc_core::sc_bind_proxy &p) -> bool { if (!p.port() && !p.interface()) return false; proxies.push_back(&p); return true; }; insert(p001) && insert(p002) && insert(p003) && insert(p004) && insert(p005) && insert(p006) && insert(p007) && insert(p008) && insert(p009) && insert(p010) && insert(p011) && insert(p012) && insert(p013) && insert(p014) && insert(p015) && insert(p016) && insert(p017) && insert(p018) && insert(p019) && insert(p020) && insert(p021) && insert(p022) && insert(p023) && insert(p024) && insert(p025) && insert(p026) && insert(p027) && insert(p028) && insert(p029) && insert(p030) && insert(p031) && insert(p032) && insert(p033) && insert(p034) && insert(p035) && insert(p036) && insert(p037) && insert(p038) && insert(p039) && insert(p040) && insert(p041) && insert(p042) && insert(p043) && insert(p044) && insert(p045) && insert(p046) && insert(p047) && insert(p048) && insert(p049) && insert(p050) && insert(p051) && insert(p052) && insert(p053) && insert(p054) && insert(p055) && insert(p056) && insert(p057) && insert(p058) && insert(p059) && insert(p060) && insert(p061) && insert(p062) && insert(p063) && insert(p064); _gem5_module->bindPorts(proxies); } sc_module & sc_module::operator << (sc_interface &iface) { (*this)(iface); return *this; } sc_module & sc_module::operator << (sc_port_base &pb) { (*this)(pb); return *this; } sc_module & sc_module::operator , (sc_interface &iface) { (*this)(iface); return *this; } sc_module & sc_module::operator , (sc_port_base &pb) { (*this)(pb); return *this; } const std::vector & sc_module::get_child_objects() const { return _gem5_module->obj()->get_child_objects(); } const std::vector & sc_module::get_child_events() const { return _gem5_module->obj()->get_child_events(); } sc_module::sc_module() : sc_object(sc_gem5::newModuleChecked()->name()), _gem5_module(sc_gem5::currentModule()) { if (sc_is_running()) SC_REPORT_ERROR(SC_ID_INSERT_MODULE_, "simulation running"); if (::sc_gem5::scheduler.elaborationDone()) SC_REPORT_ERROR(SC_ID_INSERT_MODULE_, "elaboration done"); } sc_module::sc_module(const sc_module_name &) : sc_module() {} sc_module::sc_module(const char *_name) : sc_module(sc_module_name(_name)) { _gem5_module->deprecatedConstructor(); SC_REPORT_WARNING(SC_ID_BAD_SC_MODULE_CONSTRUCTOR_, _name); } sc_module::sc_module(const std::string &_name) : sc_module(sc_module_name(_name.c_str())) { _gem5_module->deprecatedConstructor(); SC_REPORT_WARNING(SC_ID_BAD_SC_MODULE_CONSTRUCTOR_, _name.c_str()); } void sc_module::end_module() { _gem5_module->endModule(); } void sc_module::reset_signal_is(const sc_in &port, bool val) { ::sc_gem5::newReset(&port, ::sc_gem5::Process::newest(), true, val); } void sc_module::reset_signal_is(const sc_inout &port, bool val) { ::sc_gem5::newReset(&port, ::sc_gem5::Process::newest(), true, val); } void sc_module::reset_signal_is(const sc_out &port, bool val) { ::sc_gem5::newReset(&port, ::sc_gem5::Process::newest(), true, val); } void sc_module::reset_signal_is(const sc_signal_in_if &signal, bool val) { ::sc_gem5::newReset(&signal, ::sc_gem5::Process::newest(), true, val); } void sc_module::async_reset_signal_is(const sc_in &port, bool val) { ::sc_gem5::newReset(&port, ::sc_gem5::Process::newest(), false, val); } void sc_module::async_reset_signal_is(const sc_inout &port, bool val) { ::sc_gem5::newReset(&port, ::sc_gem5::Process::newest(), false, val); } void sc_module::async_reset_signal_is(const sc_out &port, bool val) { ::sc_gem5::newReset(&port, ::sc_gem5::Process::newest(), false, val); } void sc_module::async_reset_signal_is(const sc_signal_in_if &signal, bool val) { ::sc_gem5::newReset(&signal, ::sc_gem5::Process::newest(), false, val); } void sc_module::dont_initialize() { ::sc_gem5::Process *p = ::sc_gem5::Process::newest(); if (p->procKind() == SC_CTHREAD_PROC_) SC_REPORT_WARNING(SC_ID_DONT_INITIALIZE_, ""); p->dontInitialize(true); } void sc_module::set_stack_size(size_t size) { ::sc_gem5::Process::newest()->setStackSize(size); } void sc_module::next_trigger() { ::sc_core::next_trigger(); } void sc_module::next_trigger(const sc_event &e) { ::sc_core::next_trigger(e); } void sc_module::next_trigger(const sc_event_or_list &eol) { ::sc_core::next_trigger(eol); } void sc_module::next_trigger(const sc_event_and_list &eal) { ::sc_core::next_trigger(eal); } void sc_module::next_trigger(const sc_time &t) { ::sc_core::next_trigger(t); } void sc_module::next_trigger(double d, sc_time_unit u) { ::sc_core::next_trigger(d, u); } void sc_module::next_trigger(const sc_time &t, const sc_event &e) { ::sc_core::next_trigger(t, e); } void sc_module::next_trigger(double d, sc_time_unit u, const sc_event &e) { ::sc_core::next_trigger(d, u, e); } void sc_module::next_trigger(const sc_time &t, const sc_event_or_list &eol) { ::sc_core::next_trigger(t, eol); } void sc_module::next_trigger(double d, sc_time_unit u, const sc_event_or_list &eol) { ::sc_core::next_trigger(d, u, eol); } void sc_module::next_trigger(const sc_time &t, const sc_event_and_list &eal) { ::sc_core::next_trigger(t, eal); } void sc_module::next_trigger(double d, sc_time_unit u, const sc_event_and_list &eal) { ::sc_core::next_trigger(d, u, eal); } bool sc_module::timed_out() { return ::sc_core::timed_out(); } void sc_module::wait() { ::sc_core::wait(); } void sc_module::wait(int i) { ::sc_core::wait(i); } void sc_module::wait(const sc_event &e) { ::sc_core::wait(e); } void sc_module::wait(const sc_event_or_list &eol) { ::sc_core::wait(eol); } void sc_module::wait(const sc_event_and_list &eal) { ::sc_core::wait(eal); } void sc_module::wait(const sc_time &t) { ::sc_core::wait(t); } void sc_module::wait(double d, sc_time_unit u) { ::sc_core::wait(d, u); } void sc_module::wait(const sc_time &t, const sc_event &e) { ::sc_core::wait(t, e); } void sc_module::wait(double d, sc_time_unit u, const sc_event &e) { ::sc_core::wait(d, u, e); } void sc_module::wait(const sc_time &t, const sc_event_or_list &eol) { ::sc_core::wait(t, eol); } void sc_module::wait(double d, sc_time_unit u, const sc_event_or_list &eol) { ::sc_core::wait(d, u, eol); } void sc_module::wait(const sc_time &t, const sc_event_and_list &eal) { ::sc_core::wait(t, eal); } void sc_module::wait(double d, sc_time_unit u, const sc_event_and_list &eal) { ::sc_core::wait(d, u, eal); } void sc_module::halt() { ::sc_core::halt(); } void sc_module::at_posedge(const sc_signal_in_if &s) { ::sc_core::at_posedge(s); } void sc_module::at_posedge(const sc_signal_in_if &s) { ::sc_core::at_posedge(s); } void sc_module::at_negedge(const sc_signal_in_if &s) { ::sc_core::at_negedge(s); } void sc_module::at_negedge(const sc_signal_in_if &s) { ::sc_core::at_negedge(s); } void next_trigger() { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->cancelTimeout(); p->clearDynamic(); } void next_trigger(const sc_event &e) { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->cancelTimeout(); ::sc_gem5::newDynamicSensitivityEvent(p, &e); } void next_trigger(const sc_event_or_list &eol) { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->cancelTimeout(); ::sc_gem5::newDynamicSensitivityEventOrList(p, &eol); } void next_trigger(const sc_event_and_list &eal) { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->cancelTimeout(); ::sc_gem5::newDynamicSensitivityEventAndList(p, &eal); } void next_trigger(const sc_time &t) { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->setTimeout(t); p->clearDynamic(); } void next_trigger(double d, sc_time_unit u) { next_trigger(sc_time(d, u)); } void next_trigger(const sc_time &t, const sc_event &e) { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->setTimeout(t); ::sc_gem5::newDynamicSensitivityEvent(p, &e); } void next_trigger(double d, sc_time_unit u, const sc_event &e) { next_trigger(sc_time(d, u), e); } void next_trigger(const sc_time &t, const sc_event_or_list &eol) { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->setTimeout(t); ::sc_gem5::newDynamicSensitivityEventOrList(p, &eol); } void next_trigger(double d, sc_time_unit u, const sc_event_or_list &eol) { next_trigger(sc_time(d, u), eol); } void next_trigger(const sc_time &t, const sc_event_and_list &eal) { sc_gem5::Process *p = sc_gem5::scheduler.current(); p->setTimeout(t); ::sc_gem5::newDynamicSensitivityEventAndList(p, &eal); } void next_trigger(double d, sc_time_unit u, const sc_event_and_list &eal) { next_trigger(sc_time(d, u), eal); } bool timed_out() { ::sc_gem5::Process *p = sc_gem5::scheduler.current(); if (!p) return false; else return p->timedOut(); } namespace { bool waitErrorCheck(sc_gem5::Process *p) { if (p->procKind() == SC_METHOD_PROC_) { SC_REPORT_ERROR(SC_ID_WAIT_NOT_ALLOWED_, "\n in SC_METHODs use next_trigger() instead"); return true; } return false; } } // anonymous namespace void wait() { sc_gem5::Process *p = sc_gem5::scheduler.current(); if (waitErrorCheck(p)) return; p->cancelTimeout(); p->clearDynamic(); sc_gem5::scheduler.yield(); } void wait(int n) { if (n <= 0) { std::string msg = csprintf("n = %d", n); SC_REPORT_ERROR(SC_ID_WAIT_N_INVALID_, msg.c_str()); } sc_gem5::Process *p = sc_gem5::scheduler.current(); p->waitCount(n - 1); wait(); } void wait(const sc_event &e) { sc_gem5::Process *p = sc_gem5::scheduler.current(); if (waitErrorCheck(p)) return; p->cancelTimeout(); ::sc_gem5::newDynamicSensitivityEvent(p, &e); sc_gem5::scheduler.yield(); } void wait(const sc_event_or_list &eol) { sc_gem5::Process *p = sc_gem5::scheduler.current(); if (waitErrorCheck(p)) return; p->cancelTimeout(); ::sc_gem5::newDynamicSensitivityEventOrList(p, &eol); sc_gem5::scheduler.yield(); } void wait(const sc_event_and_list &eal) { sc_gem5::Process *p = sc_gem5::scheduler.current(); if (waitErrorCheck(p)) return; p->cancelTimeout(); ::sc_gem5::newDynamicSensitivityEventAndList(p, &eal); sc_gem5::scheduler.yield(); } void wait(const sc_time &t) { sc_gem5::Process *p = sc_gem5::scheduler.current(); if (waitErrorCheck(p)) return; p->setTimeout(t); p->clearDynamic(); sc_gem5::scheduler.yield(); } void wait(double d, sc_time_unit u) { wait(sc_time(d, u)); } void wait(const sc_time &t, const sc_event &e) { sc_gem5::Process *p = sc_gem5::scheduler.current(); if (waitErrorCheck(p)) return; p->setTimeout(t); ::sc_gem5::newDynamicSensitivityEvent(p, &e); sc_gem5::scheduler.yield(); } void wait(double d, sc_time_unit u, const sc_event &e) { wait(sc_time(d, u), e); } void wait(const sc_time &t, const sc_event_or_list &eol) { sc_gem5::Process *p = sc_gem5::scheduler.current(); if (waitErrorCheck(p)) return; p->setTimeout(t); ::sc_gem5::newDynamicSensitivityEventOrList(p, &eol); sc_gem5::scheduler.yield(); } void wait(double d, sc_time_unit u, const sc_event_or_list &eol) { wait(sc_time(d, u), eol); } void wait(const sc_time &t, const sc_event_and_list &eal) { sc_gem5::Process *p = sc_gem5::scheduler.current(); if (waitErrorCheck(p)) return; p->setTimeout(t); ::sc_gem5::newDynamicSensitivityEventAndList(p, &eal); sc_gem5::scheduler.yield(); } void wait(double d, sc_time_unit u, const sc_event_and_list &eal) { wait(sc_time(d, u), eal); } void halt() { ::sc_core::wait(); throw ::sc_gem5::ScHalt(); } void at_posedge(const sc_signal_in_if &s) { while (s.read()) wait(); while (!s.read()) wait(); } void at_posedge(const sc_signal_in_if &s) { while (s.read() == sc_dt::Log_1) wait(); while (s.read() == sc_dt::Log_0) wait(); } void at_negedge(const sc_signal_in_if &s) { while (!s.read()) wait(); while (s.read()) wait(); } void at_negedge(const sc_signal_in_if &s) { while (s.read() == sc_dt::Log_0) wait(); while (s.read() == sc_dt::Log_1) wait(); } const char * sc_gen_unique_name(const char *seed) { if (!seed || seed[0] == '\0') { SC_REPORT_ERROR(SC_ID_GEN_UNIQUE_NAME_, ""); seed = "unnamed"; } auto mod = sc_gem5::pickParentModule(); if (mod) return mod->uniqueName(seed); sc_gem5::Process *p = sc_gem5::scheduler.current(); if (p) return p->uniqueName(seed); return ::sc_gem5::globalNameGen.gen(seed); } bool sc_hierarchical_name_exists(const char *name) { return sc_gem5::findEvent(name) != sc_gem5::allEvents.end() || ::sc_gem5::findObject(name, sc_gem5::allObjects); } bool sc_start_of_simulation_invoked() { return ::sc_gem5::kernel->startOfSimulationComplete(); } bool sc_end_of_simulation_invoked() { return ::sc_gem5::kernel->endOfSimulationComplete(); } sc_module * sc_module_sc_new(sc_module *mod) { static std::vector > modules; modules.emplace_back(mod); return mod; } } // namespace sc_core