| /* | |
| * 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/module.hh" | |
| #include <cassert> | |
| #include "base/logging.hh" | |
| #include "systemc/ext/core/messages.hh" | |
| #include "systemc/ext/core/sc_export.hh" | |
| #include "systemc/ext/core/sc_port.hh" | |
| #include "systemc/ext/utils/sc_report_handler.hh" | |
| namespace sc_gem5 | |
| { | |
| namespace | |
| { | |
| std::list<Module *> _modules; | |
| Module *_new_module; | |
| } // anonymous namespace | |
| UniqueNameGen globalNameGen; | |
| Module::Module(const char *name) : | |
| _name(name), _sc_mod(nullptr), _obj(nullptr), _ended(false), | |
| _deprecatedConstructor(false), bindingIndex(0) | |
| { | |
| using namespace gem5; | |
| panic_if(_new_module, "Previous module not finished.\n"); | |
| _new_module = this; | |
| } | |
| Module::~Module() | |
| { | |
| // Aborted module construction? | |
| if (_new_module == this) | |
| _new_module = nullptr; | |
| // Attempt to pop now in case we're at the top of the stack, so that | |
| // a stale pointer to us isn't left floating around for somebody to trip | |
| // on. | |
| pop(); | |
| allModules.remove(this); | |
| } | |
| void | |
| Module::finish(Object *this_obj) | |
| { | |
| assert(!_obj); | |
| _obj = this_obj; | |
| _modules.push_back(this); | |
| pushParentModule(this); | |
| try { | |
| _new_module = nullptr; | |
| // This is called from the constructor of this_obj, so it can't use | |
| // dynamic cast. | |
| sc_mod(static_cast<::sc_core::sc_module *>(this_obj->sc_obj())); | |
| allModules.emplace_back(this); | |
| } catch (...) { | |
| popParentModule(); | |
| throw; | |
| } | |
| } | |
| void | |
| Module::pop() | |
| { | |
| if (_modules.empty() || _modules.back() != this) | |
| return; | |
| using namespace gem5; | |
| panic_if(_new_module, "Pop with unfinished module.\n"); | |
| _modules.pop_back(); | |
| popParentModule(); | |
| } | |
| void | |
| Module::bindPorts(std::vector<const ::sc_core::sc_bind_proxy *> &proxies) | |
| { | |
| using namespace gem5; | |
| panic_if(proxies.size() > ports.size(), | |
| "Trying to bind %d interfaces/ports to %d ports.\n", | |
| proxies.size(), ports.size()); | |
| auto proxyIt = proxies.begin(); | |
| auto portIt = ports.begin(); | |
| portIt += bindingIndex; | |
| for (; proxyIt != proxies.end(); proxyIt++, portIt++) { | |
| auto proxy = *proxyIt; | |
| auto port = *portIt; | |
| if (proxy->interface()) | |
| port->vbind(*proxy->interface()); | |
| else | |
| port->vbind(*proxy->port()); | |
| } | |
| bindingIndex += proxies.size(); | |
| } | |
| void | |
| Module::beforeEndOfElaboration() | |
| { | |
| pushParentModule(this); | |
| try { | |
| _sc_mod->before_end_of_elaboration(); | |
| for (auto e: exports) | |
| e->before_end_of_elaboration(); | |
| } catch (...) { | |
| popParentModule(); | |
| throw; | |
| } | |
| popParentModule(); | |
| } | |
| void | |
| Module::endOfElaboration() | |
| { | |
| if (_deprecatedConstructor && !_ended) { | |
| std::string msg = gem5::csprintf("module '%s'", name()); | |
| SC_REPORT_WARNING(sc_core::SC_ID_END_MODULE_NOT_CALLED_, msg.c_str()); | |
| } | |
| pushParentModule(this); | |
| try { | |
| _sc_mod->end_of_elaboration(); | |
| for (auto e: exports) | |
| e->end_of_elaboration(); | |
| } catch (...) { | |
| popParentModule(); | |
| throw; | |
| } | |
| popParentModule(); | |
| } | |
| void | |
| Module::startOfSimulation() | |
| { | |
| pushParentModule(this); | |
| try { | |
| _sc_mod->start_of_simulation(); | |
| for (auto e: exports) | |
| e->start_of_simulation(); | |
| } catch (...) { | |
| popParentModule(); | |
| throw; | |
| } | |
| popParentModule(); | |
| } | |
| void | |
| Module::endOfSimulation() | |
| { | |
| pushParentModule(this); | |
| try { | |
| _sc_mod->end_of_simulation(); | |
| for (auto e: exports) | |
| e->end_of_simulation(); | |
| } catch(...) { | |
| popParentModule(); | |
| throw; | |
| } | |
| popParentModule(); | |
| } | |
| Module * | |
| currentModule() | |
| { | |
| if (_modules.empty()) | |
| return nullptr; | |
| return _modules.back(); | |
| } | |
| Module * | |
| newModuleChecked() | |
| { | |
| if (!_new_module) | |
| SC_REPORT_ERROR(sc_core::SC_ID_MODULE_NAME_STACK_EMPTY_, ""); | |
| return _new_module; | |
| } | |
| Module * | |
| newModule() | |
| { | |
| return _new_module; | |
| } | |
| std::list<Module *> allModules; | |
| } // namespace sc_gem5 |