init.cc revision 7674
15522Snate@binkert.org/*
25522Snate@binkert.org * Copyright (c) 2000-2005 The Regents of The University of Michigan
35522Snate@binkert.org * Copyright (c) 2008 The Hewlett-Packard Development Company
45522Snate@binkert.org * All rights reserved.
55522Snate@binkert.org *
65522Snate@binkert.org * Redistribution and use in source and binary forms, with or without
75522Snate@binkert.org * modification, are permitted provided that the following conditions are
85522Snate@binkert.org * met: redistributions of source code must retain the above copyright
95522Snate@binkert.org * notice, this list of conditions and the following disclaimer;
105522Snate@binkert.org * redistributions in binary form must reproduce the above copyright
115522Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
125522Snate@binkert.org * documentation and/or other materials provided with the distribution;
135522Snate@binkert.org * neither the name of the copyright holders nor the names of its
145522Snate@binkert.org * contributors may be used to endorse or promote products derived from
155522Snate@binkert.org * this software without specific prior written permission.
165522Snate@binkert.org *
175522Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
185522Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
195522Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
205522Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
215522Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
225522Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
235522Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
245522Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
255522Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
265522Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
275522Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
285522Snate@binkert.org *
295522Snate@binkert.org * Authors: Nathan Binkert
305522Snate@binkert.org */
315522Snate@binkert.org
325522Snate@binkert.org#include <Python.h>
335522Snate@binkert.org#include <marshal.h>
345522Snate@binkert.org#include <signal.h>
355522Snate@binkert.org
367674Snate@binkert.org#include <list>
375522Snate@binkert.org#include <iostream>
385522Snate@binkert.org#include <string>
395522Snate@binkert.org#include <zlib.h>
405522Snate@binkert.org
415522Snate@binkert.org#include "base/cprintf.hh"
425522Snate@binkert.org#include "base/misc.hh"
436216Snate@binkert.org#include "base/types.hh"
445522Snate@binkert.org#include "sim/async.hh"
455522Snate@binkert.org#include "sim/core.hh"
465522Snate@binkert.org#include "sim/init.hh"
475522Snate@binkert.org
485522Snate@binkert.orgusing namespace std;
495522Snate@binkert.org
505522Snate@binkert.org/// Stats signal handler.
515522Snate@binkert.orgvoid
525522Snate@binkert.orgdumpStatsHandler(int sigtype)
535522Snate@binkert.org{
545522Snate@binkert.org    async_event = true;
555522Snate@binkert.org    async_statdump = true;
565522Snate@binkert.org}
575522Snate@binkert.org
585522Snate@binkert.orgvoid
595522Snate@binkert.orgdumprstStatsHandler(int sigtype)
605522Snate@binkert.org{
615522Snate@binkert.org    async_event = true;
625522Snate@binkert.org    async_statdump = true;
635522Snate@binkert.org    async_statreset = true;
645522Snate@binkert.org}
655522Snate@binkert.org
665522Snate@binkert.org/// Exit signal handler.
675522Snate@binkert.orgvoid
685522Snate@binkert.orgexitNowHandler(int sigtype)
695522Snate@binkert.org{
705522Snate@binkert.org    async_event = true;
715522Snate@binkert.org    async_exit = true;
725522Snate@binkert.org}
735522Snate@binkert.org
745522Snate@binkert.org/// Abort signal handler.
755522Snate@binkert.orgvoid
765522Snate@binkert.orgabortHandler(int sigtype)
775522Snate@binkert.org{
785522Snate@binkert.org    ccprintf(cerr, "Program aborted at cycle %d\n", curTick);
795522Snate@binkert.org}
805522Snate@binkert.org
815522Snate@binkert.org/*
825522Snate@binkert.org * M5 can do several special things when various signals are sent.
835522Snate@binkert.org * None are mandatory.
845522Snate@binkert.org */
855522Snate@binkert.orgvoid
865522Snate@binkert.orginitSignals()
875522Snate@binkert.org{
885522Snate@binkert.org    // Floating point exceptions may happen on misspeculated paths, so
895522Snate@binkert.org    // ignore them
905522Snate@binkert.org    signal(SIGFPE, SIG_IGN);
915522Snate@binkert.org
925522Snate@binkert.org    // We use SIGTRAP sometimes for debugging
935522Snate@binkert.org    signal(SIGTRAP, SIG_IGN);
945522Snate@binkert.org
955522Snate@binkert.org    // Dump intermediate stats
965522Snate@binkert.org    signal(SIGUSR1, dumpStatsHandler);
975522Snate@binkert.org
985522Snate@binkert.org    // Dump intermediate stats and reset them
995522Snate@binkert.org    signal(SIGUSR2, dumprstStatsHandler);
1005522Snate@binkert.org
1015522Snate@binkert.org    // Exit cleanly on Interrupt (Ctrl-C)
1025522Snate@binkert.org    signal(SIGINT, exitNowHandler);
1035522Snate@binkert.org
1045522Snate@binkert.org    // Print out cycle number on abort
1055522Snate@binkert.org    signal(SIGABRT, abortHandler);
1065522Snate@binkert.org}
1075522Snate@binkert.org
1085522Snate@binkert.org// The python library is totally messed up with respect to constness,
1095522Snate@binkert.org// so make a simple macro to make life a little easier
1105522Snate@binkert.org#define PyCC(x) (const_cast<char *>(x))
1115522Snate@binkert.org
1127674Snate@binkert.orgEmbeddedPython *EmbeddedPython::importer = NULL;
1137674Snate@binkert.orgPyObject *EmbeddedPython::importerModule = NULL;
1147674Snate@binkert.orgEmbeddedPython::EmbeddedPython(const char *filename, const char *abspath,
1157674Snate@binkert.org    const char *modpath, const char *code, int zlen, int len)
1167674Snate@binkert.org    : filename(filename), abspath(abspath), modpath(modpath), code(code),
1177674Snate@binkert.org      zlen(zlen), len(len)
1187674Snate@binkert.org{
1197674Snate@binkert.org    // if we've added the importer keep track of it because we need it
1207674Snate@binkert.org    // to bootstrap.
1217674Snate@binkert.org    if (string(modpath) == string("importer"))
1227674Snate@binkert.org        importer = this;
1237674Snate@binkert.org    else
1247674Snate@binkert.org        getList().push_back(this);
1257674Snate@binkert.org}
1267674Snate@binkert.org
1277674Snate@binkert.orglist<EmbeddedPython *> &
1287674Snate@binkert.orgEmbeddedPython::getList()
1297674Snate@binkert.org{
1307674Snate@binkert.org    static list<EmbeddedPython *> the_list;
1317674Snate@binkert.org    return the_list;
1327674Snate@binkert.org}
1337674Snate@binkert.org
1347674Snate@binkert.org/*
1357674Snate@binkert.org * Uncompress and unmarshal the code object stored in the
1367674Snate@binkert.org * EmbeddedPython
1377674Snate@binkert.org */
1387674Snate@binkert.orgPyObject *
1397674Snate@binkert.orgEmbeddedPython::getCode() const
1407674Snate@binkert.org{
1417674Snate@binkert.org    Bytef marshalled[len];
1427674Snate@binkert.org    uLongf unzlen = len;
1437674Snate@binkert.org    int ret = uncompress(marshalled, &unzlen, (const Bytef *)code, zlen);
1447674Snate@binkert.org    if (ret != Z_OK)
1457674Snate@binkert.org        panic("Could not uncompress code: %s\n", zError(ret));
1467674Snate@binkert.org    assert(unzlen == (uLongf)len);
1477674Snate@binkert.org
1487674Snate@binkert.org    return PyMarshal_ReadObjectFromString((char *)marshalled, len);
1497674Snate@binkert.org}
1507674Snate@binkert.org
1517674Snate@binkert.orgbool
1527674Snate@binkert.orgEmbeddedPython::addModule() const
1537674Snate@binkert.org{
1547674Snate@binkert.org    PyObject *code = getCode();
1557674Snate@binkert.org    PyObject *result = PyObject_CallMethod(importerModule, PyCC("add_module"),
1567674Snate@binkert.org        PyCC("sssO"), filename, abspath, modpath, code);
1577674Snate@binkert.org    if (!result) {
1587674Snate@binkert.org        PyErr_Print();
1597674Snate@binkert.org        return false;
1607674Snate@binkert.org    }
1617674Snate@binkert.org
1627674Snate@binkert.org    Py_DECREF(result);
1637674Snate@binkert.org    return true;
1647674Snate@binkert.org}
1657674Snate@binkert.org
1665522Snate@binkert.org/*
1675522Snate@binkert.org * Load and initialize all of the python parts of M5, including Swig
1685522Snate@binkert.org * and the embedded module importer.
1695522Snate@binkert.org */
1705522Snate@binkert.orgint
1717674Snate@binkert.orgEmbeddedPython::initAll()
1725522Snate@binkert.org{
1735522Snate@binkert.org    // Load the importer module
1747674Snate@binkert.org    PyObject *code = importer->getCode();
1757674Snate@binkert.org    importerModule = PyImport_ExecCodeModule(PyCC("importer"), code);
1767674Snate@binkert.org    if (!importerModule) {
1775522Snate@binkert.org        PyErr_Print();
1785522Snate@binkert.org        return 1;
1795522Snate@binkert.org    }
1805522Snate@binkert.org
1815522Snate@binkert.org    // Load the rest of the embedded python files into the embedded
1825522Snate@binkert.org    // python importer
1837674Snate@binkert.org    list<EmbeddedPython *>::iterator i = getList().begin();
1847674Snate@binkert.org    list<EmbeddedPython *>::iterator end = getList().end();
1857674Snate@binkert.org    for (; i != end; ++i)
1867674Snate@binkert.org        if (!(*i)->addModule())
1875522Snate@binkert.org            return 1;
1885522Snate@binkert.org
1895522Snate@binkert.org    return 0;
1905522Snate@binkert.org}
1915522Snate@binkert.org
1927674Snate@binkert.orgEmbeddedSwig::EmbeddedSwig(void (*init_func)())
1937674Snate@binkert.org    : initFunc(init_func)
1947674Snate@binkert.org{
1957674Snate@binkert.org    getList().push_back(this);
1967674Snate@binkert.org}
1977674Snate@binkert.org
1987674Snate@binkert.orglist<EmbeddedSwig *> &
1997674Snate@binkert.orgEmbeddedSwig::getList()
2007674Snate@binkert.org{
2017674Snate@binkert.org    static list<EmbeddedSwig *> the_list;
2027674Snate@binkert.org    return the_list;
2037674Snate@binkert.org}
2047674Snate@binkert.org
2057674Snate@binkert.orgvoid
2067674Snate@binkert.orgEmbeddedSwig::initAll()
2077674Snate@binkert.org{
2087674Snate@binkert.org    // initialize SWIG modules.  initSwig() is autogenerated and calls
2097674Snate@binkert.org    // all of the individual swig initialization functions.
2107674Snate@binkert.org    list<EmbeddedSwig *>::iterator i = getList().begin();
2117674Snate@binkert.org    list<EmbeddedSwig *>::iterator end = getList().end();
2127674Snate@binkert.org    for (; i != end; ++i)
2137674Snate@binkert.org        (*i)->initFunc();
2147674Snate@binkert.org}
2157674Snate@binkert.org
2167674Snate@binkert.orgint
2177674Snate@binkert.orginitM5Python()
2187674Snate@binkert.org{
2197674Snate@binkert.org    EmbeddedSwig::initAll();
2207674Snate@binkert.org    return EmbeddedPython::initAll();
2217674Snate@binkert.org}
2227674Snate@binkert.org
2235522Snate@binkert.org/*
2245522Snate@binkert.org * Start up the M5 simulator.  This mostly vectors into the python
2255522Snate@binkert.org * main function.
2265522Snate@binkert.org */
2275522Snate@binkert.orgint
2285522Snate@binkert.orgm5Main(int argc, char **argv)
2295522Snate@binkert.org{
2305522Snate@binkert.org    PySys_SetArgv(argc, argv);
2315522Snate@binkert.org
2325522Snate@binkert.org    // We have to set things up in the special __main__ module
2335522Snate@binkert.org    PyObject *module = PyImport_AddModule(PyCC("__main__"));
2345522Snate@binkert.org    if (module == NULL)
2355522Snate@binkert.org        panic("Could not import __main__");
2365522Snate@binkert.org    PyObject *dict = PyModule_GetDict(module);
2375522Snate@binkert.org
2385522Snate@binkert.org    // import the main m5 module
2395522Snate@binkert.org    PyObject *result;
2405522Snate@binkert.org    result = PyRun_String("import m5", Py_file_input, dict, dict);
2415522Snate@binkert.org    if (!result) {
2425522Snate@binkert.org        PyErr_Print();
2435522Snate@binkert.org        return 1;
2445522Snate@binkert.org    }
2455522Snate@binkert.org    Py_DECREF(result);
2465522Snate@binkert.org
2475522Snate@binkert.org    // Start m5
2485522Snate@binkert.org    result = PyRun_String("m5.main()", Py_file_input, dict, dict);
2495522Snate@binkert.org    if (!result) {
2505522Snate@binkert.org        PyErr_Print();
2515522Snate@binkert.org        return 1;
2525522Snate@binkert.org    }
2535522Snate@binkert.org    Py_DECREF(result);
2545522Snate@binkert.org
2555522Snate@binkert.org    return 0;
2565522Snate@binkert.org}
2575601Snate@binkert.org
2585601Snate@binkert.orgPyMODINIT_FUNC
2595601Snate@binkert.orginitm5(void)
2605601Snate@binkert.org{
2615601Snate@binkert.org    initM5Python();
2625601Snate@binkert.org    PyImport_ImportModule(PyCC("m5"));
2635601Snate@binkert.org}
264