init.cc revision 7823:dac01f14f20f
1/*
2 * Copyright (c) 2000-2005 The Regents of The University of Michigan
3 * Copyright (c) 2008 The Hewlett-Packard Development Company
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Authors: Nathan Binkert
30 */
31
32#include <Python.h>
33#include <marshal.h>
34#include <signal.h>
35
36#include <list>
37#include <iostream>
38#include <string>
39#include <zlib.h>
40
41#include "base/cprintf.hh"
42#include "base/misc.hh"
43#include "base/types.hh"
44#include "sim/async.hh"
45#include "sim/core.hh"
46#include "sim/init.hh"
47
48using namespace std;
49
50/// Stats signal handler.
51void
52dumpStatsHandler(int sigtype)
53{
54    async_event = true;
55    async_statdump = true;
56}
57
58void
59dumprstStatsHandler(int sigtype)
60{
61    async_event = true;
62    async_statdump = true;
63    async_statreset = true;
64}
65
66/// Exit signal handler.
67void
68exitNowHandler(int sigtype)
69{
70    async_event = true;
71    async_exit = true;
72}
73
74/// Abort signal handler.
75void
76abortHandler(int sigtype)
77{
78    ccprintf(cerr, "Program aborted at cycle %d\n", curTick());
79}
80
81/*
82 * M5 can do several special things when various signals are sent.
83 * None are mandatory.
84 */
85void
86initSignals()
87{
88    // Floating point exceptions may happen on misspeculated paths, so
89    // ignore them
90    signal(SIGFPE, SIG_IGN);
91
92    // We use SIGTRAP sometimes for debugging
93    signal(SIGTRAP, SIG_IGN);
94
95    // Dump intermediate stats
96    signal(SIGUSR1, dumpStatsHandler);
97
98    // Dump intermediate stats and reset them
99    signal(SIGUSR2, dumprstStatsHandler);
100
101    // Exit cleanly on Interrupt (Ctrl-C)
102    signal(SIGINT, exitNowHandler);
103
104    // Print out cycle number on abort
105    signal(SIGABRT, abortHandler);
106}
107
108// The python library is totally messed up with respect to constness,
109// so make a simple macro to make life a little easier
110#define PyCC(x) (const_cast<char *>(x))
111
112EmbeddedPython *EmbeddedPython::importer = NULL;
113PyObject *EmbeddedPython::importerModule = NULL;
114EmbeddedPython::EmbeddedPython(const char *filename, const char *abspath,
115    const char *modpath, const char *code, int zlen, int len)
116    : filename(filename), abspath(abspath), modpath(modpath), code(code),
117      zlen(zlen), len(len)
118{
119    // if we've added the importer keep track of it because we need it
120    // to bootstrap.
121    if (string(modpath) == string("importer"))
122        importer = this;
123    else
124        getList().push_back(this);
125}
126
127list<EmbeddedPython *> &
128EmbeddedPython::getList()
129{
130    static list<EmbeddedPython *> the_list;
131    return the_list;
132}
133
134/*
135 * Uncompress and unmarshal the code object stored in the
136 * EmbeddedPython
137 */
138PyObject *
139EmbeddedPython::getCode() const
140{
141    Bytef marshalled[len];
142    uLongf unzlen = len;
143    int ret = uncompress(marshalled, &unzlen, (const Bytef *)code, zlen);
144    if (ret != Z_OK)
145        panic("Could not uncompress code: %s\n", zError(ret));
146    assert(unzlen == (uLongf)len);
147
148    return PyMarshal_ReadObjectFromString((char *)marshalled, len);
149}
150
151bool
152EmbeddedPython::addModule() const
153{
154    PyObject *code = getCode();
155    PyObject *result = PyObject_CallMethod(importerModule, PyCC("add_module"),
156        PyCC("sssO"), filename, abspath, modpath, code);
157    if (!result) {
158        PyErr_Print();
159        return false;
160    }
161
162    Py_DECREF(result);
163    return true;
164}
165
166/*
167 * Load and initialize all of the python parts of M5, including Swig
168 * and the embedded module importer.
169 */
170int
171EmbeddedPython::initAll()
172{
173    // Load the importer module
174    PyObject *code = importer->getCode();
175    importerModule = PyImport_ExecCodeModule(PyCC("importer"), code);
176    if (!importerModule) {
177        PyErr_Print();
178        return 1;
179    }
180
181    // Load the rest of the embedded python files into the embedded
182    // python importer
183    list<EmbeddedPython *>::iterator i = getList().begin();
184    list<EmbeddedPython *>::iterator end = getList().end();
185    for (; i != end; ++i)
186        if (!(*i)->addModule())
187            return 1;
188
189    return 0;
190}
191
192EmbeddedSwig::EmbeddedSwig(void (*init_func)())
193    : initFunc(init_func)
194{
195    getList().push_back(this);
196}
197
198list<EmbeddedSwig *> &
199EmbeddedSwig::getList()
200{
201    static list<EmbeddedSwig *> the_list;
202    return the_list;
203}
204
205void
206EmbeddedSwig::initAll()
207{
208    // initialize SWIG modules.  initSwig() is autogenerated and calls
209    // all of the individual swig initialization functions.
210    list<EmbeddedSwig *>::iterator i = getList().begin();
211    list<EmbeddedSwig *>::iterator end = getList().end();
212    for (; i != end; ++i)
213        (*i)->initFunc();
214}
215
216int
217initM5Python()
218{
219    EmbeddedSwig::initAll();
220    return EmbeddedPython::initAll();
221}
222
223/*
224 * Start up the M5 simulator.  This mostly vectors into the python
225 * main function.
226 */
227int
228m5Main(int argc, char **argv)
229{
230    PySys_SetArgv(argc, argv);
231
232    // We have to set things up in the special __main__ module
233    PyObject *module = PyImport_AddModule(PyCC("__main__"));
234    if (module == NULL)
235        panic("Could not import __main__");
236    PyObject *dict = PyModule_GetDict(module);
237
238    // import the main m5 module
239    PyObject *result;
240    result = PyRun_String("import m5", Py_file_input, dict, dict);
241    if (!result) {
242        PyErr_Print();
243        return 1;
244    }
245    Py_DECREF(result);
246
247    // Start m5
248    result = PyRun_String("m5.main()", Py_file_input, dict, dict);
249    if (!result) {
250        PyErr_Print();
251        return 1;
252    }
253    Py_DECREF(result);
254
255    return 0;
256}
257
258PyMODINIT_FUNC
259initm5(void)
260{
261    initM5Python();
262    PyImport_ImportModule(PyCC("m5"));
263}
264