module.cc revision 13268:9802f3e0a6ae
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/sc_export.hh"
36#include "systemc/ext/core/sc_port.hh"
37#include "systemc/ext/utils/sc_report_handler.hh"
38
39namespace sc_gem5
40{
41
42namespace
43{
44
45std::list<Module *> _modules;
46Module *_new_module;
47
48} // anonymous namespace
49
50Module::Module(const char *name) :
51    _name(name), _sc_mod(nullptr), _obj(nullptr), _ended(false),
52    _deprecatedConstructor(false)
53{
54    panic_if(_new_module, "Previous module not finished.\n");
55    _new_module = this;
56}
57
58Module::~Module()
59{
60    // Aborted module construction?
61    if (_new_module == this)
62        _new_module = nullptr;
63
64    // Attempt to pop now in case we're at the top of the stack, so that
65    // a stale pointer to us isn't left floating around for somebody to trip
66    // on.
67    pop();
68
69    allModules.remove(this);
70}
71
72void
73Module::finish(Object *this_obj)
74{
75    assert(!_obj);
76    _obj = this_obj;
77    _modules.push_back(this);
78    pushParentModule(this);
79    try {
80        _new_module = nullptr;
81        // This is called from the constructor of this_obj, so it can't use
82        // dynamic cast.
83        sc_mod(static_cast<::sc_core::sc_module *>(this_obj->sc_obj()));
84        allModules.emplace_back(this);
85    } catch (...) {
86        popParentModule();
87        throw;
88    }
89}
90
91void
92Module::pop()
93{
94    if (_modules.empty() || _modules.back() != this)
95        return;
96
97    panic_if(_new_module, "Pop with unfinished module.\n");
98
99    _modules.pop_back();
100    popParentModule();
101}
102
103void
104Module::bindPorts(std::vector<const ::sc_core::sc_bind_proxy *> &proxies)
105{
106    panic_if(proxies.size() > ports.size(),
107            "Trying to bind %d interfaces/ports to %d ports.\n",
108            proxies.size(), ports.size());
109
110    auto proxyIt = proxies.begin();
111    auto portIt = ports.begin();
112    for (; proxyIt != proxies.end(); proxyIt++, portIt++) {
113        auto proxy = *proxyIt;
114        auto port = *portIt;
115        if (proxy->interface())
116            port->vbind(*proxy->interface());
117        else
118            port->vbind(*proxy->port());
119    }
120}
121
122void
123Module::beforeEndOfElaboration()
124{
125    pushParentModule(this);
126    try {
127        _sc_mod->before_end_of_elaboration();
128        for (auto e: exports)
129            e->before_end_of_elaboration();
130    } catch (...) {
131        popParentModule();
132        throw;
133    }
134    popParentModule();
135}
136
137void
138Module::endOfElaboration()
139{
140    if (_deprecatedConstructor && !_ended) {
141        std::string msg = csprintf("module '%s'", name());
142        SC_REPORT_WARNING("(W509) module construction not properly completed: "
143                "did you forget to add a sc_module_name parameter to "
144                "your module constructor?", msg.c_str());
145    }
146    pushParentModule(this);
147    try {
148        _sc_mod->end_of_elaboration();
149        for (auto e: exports)
150            e->end_of_elaboration();
151    } catch (...) {
152        popParentModule();
153        throw;
154    }
155    popParentModule();
156}
157
158void
159Module::startOfSimulation()
160{
161    pushParentModule(this);
162    try {
163        _sc_mod->start_of_simulation();
164        for (auto e: exports)
165            e->start_of_simulation();
166    } catch (...) {
167        popParentModule();
168        throw;
169    }
170    popParentModule();
171}
172
173void
174Module::endOfSimulation()
175{
176    pushParentModule(this);
177    try {
178        _sc_mod->end_of_simulation();
179        for (auto e: exports)
180            e->end_of_simulation();
181    } catch(...) {
182        popParentModule();
183        throw;
184    }
185    popParentModule();
186}
187
188Module *
189currentModule()
190{
191    if (_modules.empty())
192        return nullptr;
193    return _modules.back();
194}
195
196Module *
197newModuleChecked()
198{
199    if (!_new_module) {
200        SC_REPORT_ERROR("(E533) module name stack is empty: "
201                "did you forget to add a sc_module_name parameter to "
202                "your module constructor?", nullptr);
203    }
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