1/* 2 * Copyright 2018 Google, Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer; 8 * redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution; 11 * neither the name of the copyright holders nor the names of its 12 * contributors may be used to endorse or promote products derived from 13 * this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 * Authors: Gabe Black 28 */ 29 30#include "systemc/core/module.hh" 31 32#include <cassert> 33 34#include "base/logging.hh" 35#include "systemc/ext/core/messages.hh" 36#include "systemc/ext/core/sc_export.hh" 37#include "systemc/ext/core/sc_port.hh" 38#include "systemc/ext/utils/sc_report_handler.hh" 39 40namespace sc_gem5 41{ 42 43namespace 44{ 45 46std::list<Module *> _modules; 47Module *_new_module; 48 49} // anonymous namespace 50 51UniqueNameGen globalNameGen; 52 53Module::Module(const char *name) : 54 _name(name), _sc_mod(nullptr), _obj(nullptr), _ended(false), 55 _deprecatedConstructor(false), bindingIndex(0) 56{ 57 panic_if(_new_module, "Previous module not finished.\n"); 58 _new_module = this; 59} 60 61Module::~Module() 62{ 63 // Aborted module construction? 64 if (_new_module == this) 65 _new_module = nullptr; 66 67 // Attempt to pop now in case we're at the top of the stack, so that 68 // a stale pointer to us isn't left floating around for somebody to trip 69 // on. 70 pop(); 71 72 allModules.remove(this); 73} 74 75void 76Module::finish(Object *this_obj) 77{ 78 assert(!_obj); 79 _obj = this_obj; 80 _modules.push_back(this); 81 pushParentModule(this); 82 try { 83 _new_module = nullptr; 84 // This is called from the constructor of this_obj, so it can't use 85 // dynamic cast. 86 sc_mod(static_cast<::sc_core::sc_module *>(this_obj->sc_obj())); 87 allModules.emplace_back(this); 88 } catch (...) { 89 popParentModule(); 90 throw; 91 } 92} 93 94void 95Module::pop() 96{ 97 if (_modules.empty() || _modules.back() != this) 98 return; 99 100 panic_if(_new_module, "Pop with unfinished module.\n"); 101 102 _modules.pop_back(); 103 popParentModule(); 104} 105 106void 107Module::bindPorts(std::vector<const ::sc_core::sc_bind_proxy *> &proxies) 108{ 109 panic_if(proxies.size() > ports.size(), 110 "Trying to bind %d interfaces/ports to %d ports.\n", 111 proxies.size(), ports.size()); 112 113 auto proxyIt = proxies.begin(); 114 auto portIt = ports.begin(); 115 portIt += bindingIndex; 116 for (; proxyIt != proxies.end(); proxyIt++, portIt++) { 117 auto proxy = *proxyIt; 118 auto port = *portIt; 119 if (proxy->interface()) 120 port->vbind(*proxy->interface()); 121 else 122 port->vbind(*proxy->port()); 123 } 124 bindingIndex += proxies.size(); 125} 126 127void 128Module::beforeEndOfElaboration() 129{ 130 pushParentModule(this); 131 try { 132 _sc_mod->before_end_of_elaboration(); 133 for (auto e: exports) 134 e->before_end_of_elaboration(); 135 } catch (...) { 136 popParentModule(); 137 throw; 138 } 139 popParentModule(); 140} 141 142void 143Module::endOfElaboration() 144{ 145 if (_deprecatedConstructor && !_ended) { 146 std::string msg = csprintf("module '%s'", name()); 147 SC_REPORT_WARNING(sc_core::SC_ID_END_MODULE_NOT_CALLED_, msg.c_str()); 148 } 149 pushParentModule(this); 150 try { 151 _sc_mod->end_of_elaboration(); 152 for (auto e: exports) 153 e->end_of_elaboration(); 154 } catch (...) { 155 popParentModule(); 156 throw; 157 } 158 popParentModule(); 159} 160 161void 162Module::startOfSimulation() 163{ 164 pushParentModule(this); 165 try { 166 _sc_mod->start_of_simulation(); 167 for (auto e: exports) 168 e->start_of_simulation(); 169 } catch (...) { 170 popParentModule(); 171 throw; 172 } 173 popParentModule(); 174} 175 176void 177Module::endOfSimulation() 178{ 179 pushParentModule(this); 180 try { 181 _sc_mod->end_of_simulation(); 182 for (auto e: exports) 183 e->end_of_simulation(); 184 } catch(...) { 185 popParentModule(); 186 throw; 187 } 188 popParentModule(); 189} 190 191Module * 192currentModule() 193{ 194 if (_modules.empty()) 195 return nullptr; 196 return _modules.back(); 197} 198 199Module * 200newModuleChecked() 201{ 202 if (!_new_module) 203 SC_REPORT_ERROR(sc_core::SC_ID_MODULE_NAME_STACK_EMPTY_, ""); 204 return _new_module; 205} 206 207Module * 208newModule() 209{ 210 return _new_module; 211} 212 213std::list<Module *> allModules; 214 215} // namespace sc_gem5 216