| /* |
| * 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) |
| { |
| 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; |
| |
| 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) |
| { |
| 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 = 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 |