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