init.cc revision 8946
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>
338229Snate@binkert.org
345522Snate@binkert.org#include <marshal.h>
358229Snate@binkert.org#include <zlib.h>
365522Snate@binkert.org
378229Snate@binkert.org#include <csignal>
388229Snate@binkert.org#include <iostream>
397674Snate@binkert.org#include <list>
405522Snate@binkert.org#include <string>
415522Snate@binkert.org
425522Snate@binkert.org#include "base/cprintf.hh"
435522Snate@binkert.org#include "base/misc.hh"
446216Snate@binkert.org#include "base/types.hh"
455522Snate@binkert.org#include "sim/async.hh"
465522Snate@binkert.org#include "sim/core.hh"
475522Snate@binkert.org#include "sim/init.hh"
485522Snate@binkert.org
495522Snate@binkert.orgusing namespace std;
505522Snate@binkert.org
515522Snate@binkert.org/// Stats signal handler.
525522Snate@binkert.orgvoid
535522Snate@binkert.orgdumpStatsHandler(int sigtype)
545522Snate@binkert.org{
555522Snate@binkert.org    async_event = true;
565522Snate@binkert.org    async_statdump = true;
575522Snate@binkert.org}
585522Snate@binkert.org
595522Snate@binkert.orgvoid
605522Snate@binkert.orgdumprstStatsHandler(int sigtype)
615522Snate@binkert.org{
625522Snate@binkert.org    async_event = true;
635522Snate@binkert.org    async_statdump = true;
645522Snate@binkert.org    async_statreset = true;
655522Snate@binkert.org}
665522Snate@binkert.org
675522Snate@binkert.org/// Exit signal handler.
685522Snate@binkert.orgvoid
695522Snate@binkert.orgexitNowHandler(int sigtype)
705522Snate@binkert.org{
715522Snate@binkert.org    async_event = true;
725522Snate@binkert.org    async_exit = true;
735522Snate@binkert.org}
745522Snate@binkert.org
755522Snate@binkert.org/// Abort signal handler.
765522Snate@binkert.orgvoid
775522Snate@binkert.orgabortHandler(int sigtype)
785522Snate@binkert.org{
797823Ssteve.reinhardt@amd.com    ccprintf(cerr, "Program aborted at cycle %d\n", curTick());
805522Snate@binkert.org}
815522Snate@binkert.org
825522Snate@binkert.org/*
835522Snate@binkert.org * M5 can do several special things when various signals are sent.
845522Snate@binkert.org * None are mandatory.
855522Snate@binkert.org */
865522Snate@binkert.orgvoid
875522Snate@binkert.orginitSignals()
885522Snate@binkert.org{
895522Snate@binkert.org    // Floating point exceptions may happen on misspeculated paths, so
905522Snate@binkert.org    // ignore them
915522Snate@binkert.org    signal(SIGFPE, SIG_IGN);
925522Snate@binkert.org
935522Snate@binkert.org    // We use SIGTRAP sometimes for debugging
945522Snate@binkert.org    signal(SIGTRAP, SIG_IGN);
955522Snate@binkert.org
965522Snate@binkert.org    // Dump intermediate stats
975522Snate@binkert.org    signal(SIGUSR1, dumpStatsHandler);
985522Snate@binkert.org
995522Snate@binkert.org    // Dump intermediate stats and reset them
1005522Snate@binkert.org    signal(SIGUSR2, dumprstStatsHandler);
1015522Snate@binkert.org
1025522Snate@binkert.org    // Exit cleanly on Interrupt (Ctrl-C)
1035522Snate@binkert.org    signal(SIGINT, exitNowHandler);
1045522Snate@binkert.org
1055522Snate@binkert.org    // Print out cycle number on abort
1065522Snate@binkert.org    signal(SIGABRT, abortHandler);
1075522Snate@binkert.org}
1085522Snate@binkert.org
1095522Snate@binkert.org// The python library is totally messed up with respect to constness,
1105522Snate@binkert.org// so make a simple macro to make life a little easier
1115522Snate@binkert.org#define PyCC(x) (const_cast<char *>(x))
1125522Snate@binkert.org
1137674Snate@binkert.orgEmbeddedPython *EmbeddedPython::importer = NULL;
1147674Snate@binkert.orgPyObject *EmbeddedPython::importerModule = NULL;
1157674Snate@binkert.orgEmbeddedPython::EmbeddedPython(const char *filename, const char *abspath,
1168946Sandreas.hansson@arm.com    const char *modpath, const unsigned char *code, int zlen, int len)
1177674Snate@binkert.org    : filename(filename), abspath(abspath), modpath(modpath), code(code),
1187674Snate@binkert.org      zlen(zlen), len(len)
1197674Snate@binkert.org{
1207674Snate@binkert.org    // if we've added the importer keep track of it because we need it
1217674Snate@binkert.org    // to bootstrap.
1227674Snate@binkert.org    if (string(modpath) == string("importer"))
1237674Snate@binkert.org        importer = this;
1247674Snate@binkert.org    else
1257674Snate@binkert.org        getList().push_back(this);
1267674Snate@binkert.org}
1277674Snate@binkert.org
1287674Snate@binkert.orglist<EmbeddedPython *> &
1297674Snate@binkert.orgEmbeddedPython::getList()
1307674Snate@binkert.org{
1317674Snate@binkert.org    static list<EmbeddedPython *> the_list;
1327674Snate@binkert.org    return the_list;
1337674Snate@binkert.org}
1347674Snate@binkert.org
1357674Snate@binkert.org/*
1367674Snate@binkert.org * Uncompress and unmarshal the code object stored in the
1377674Snate@binkert.org * EmbeddedPython
1387674Snate@binkert.org */
1397674Snate@binkert.orgPyObject *
1407674Snate@binkert.orgEmbeddedPython::getCode() const
1417674Snate@binkert.org{
1427674Snate@binkert.org    Bytef marshalled[len];
1437674Snate@binkert.org    uLongf unzlen = len;
1447674Snate@binkert.org    int ret = uncompress(marshalled, &unzlen, (const Bytef *)code, zlen);
1457674Snate@binkert.org    if (ret != Z_OK)
1467674Snate@binkert.org        panic("Could not uncompress code: %s\n", zError(ret));
1477674Snate@binkert.org    assert(unzlen == (uLongf)len);
1487674Snate@binkert.org
1497674Snate@binkert.org    return PyMarshal_ReadObjectFromString((char *)marshalled, len);
1507674Snate@binkert.org}
1517674Snate@binkert.org
1527674Snate@binkert.orgbool
1537674Snate@binkert.orgEmbeddedPython::addModule() const
1547674Snate@binkert.org{
1557674Snate@binkert.org    PyObject *code = getCode();
1567674Snate@binkert.org    PyObject *result = PyObject_CallMethod(importerModule, PyCC("add_module"),
1577674Snate@binkert.org        PyCC("sssO"), filename, abspath, modpath, code);
1587674Snate@binkert.org    if (!result) {
1597674Snate@binkert.org        PyErr_Print();
1607674Snate@binkert.org        return false;
1617674Snate@binkert.org    }
1627674Snate@binkert.org
1637674Snate@binkert.org    Py_DECREF(result);
1647674Snate@binkert.org    return true;
1657674Snate@binkert.org}
1667674Snate@binkert.org
1675522Snate@binkert.org/*
1685522Snate@binkert.org * Load and initialize all of the python parts of M5, including Swig
1695522Snate@binkert.org * and the embedded module importer.
1705522Snate@binkert.org */
1715522Snate@binkert.orgint
1727674Snate@binkert.orgEmbeddedPython::initAll()
1735522Snate@binkert.org{
1745522Snate@binkert.org    // Load the importer module
1757674Snate@binkert.org    PyObject *code = importer->getCode();
1767674Snate@binkert.org    importerModule = PyImport_ExecCodeModule(PyCC("importer"), code);
1777674Snate@binkert.org    if (!importerModule) {
1785522Snate@binkert.org        PyErr_Print();
1795522Snate@binkert.org        return 1;
1805522Snate@binkert.org    }
1815522Snate@binkert.org
1825522Snate@binkert.org    // Load the rest of the embedded python files into the embedded
1835522Snate@binkert.org    // python importer
1847674Snate@binkert.org    list<EmbeddedPython *>::iterator i = getList().begin();
1857674Snate@binkert.org    list<EmbeddedPython *>::iterator end = getList().end();
1867674Snate@binkert.org    for (; i != end; ++i)
1877674Snate@binkert.org        if (!(*i)->addModule())
1885522Snate@binkert.org            return 1;
1895522Snate@binkert.org
1905522Snate@binkert.org    return 0;
1915522Snate@binkert.org}
1925522Snate@binkert.org
1937674Snate@binkert.orgEmbeddedSwig::EmbeddedSwig(void (*init_func)())
1947674Snate@binkert.org    : initFunc(init_func)
1957674Snate@binkert.org{
1967674Snate@binkert.org    getList().push_back(this);
1977674Snate@binkert.org}
1987674Snate@binkert.org
1997674Snate@binkert.orglist<EmbeddedSwig *> &
2007674Snate@binkert.orgEmbeddedSwig::getList()
2017674Snate@binkert.org{
2027674Snate@binkert.org    static list<EmbeddedSwig *> the_list;
2037674Snate@binkert.org    return the_list;
2047674Snate@binkert.org}
2057674Snate@binkert.org
2067674Snate@binkert.orgvoid
2077674Snate@binkert.orgEmbeddedSwig::initAll()
2087674Snate@binkert.org{
2097674Snate@binkert.org    // initialize SWIG modules.  initSwig() is autogenerated and calls
2107674Snate@binkert.org    // all of the individual swig initialization functions.
2117674Snate@binkert.org    list<EmbeddedSwig *>::iterator i = getList().begin();
2127674Snate@binkert.org    list<EmbeddedSwig *>::iterator end = getList().end();
2137674Snate@binkert.org    for (; i != end; ++i)
2147674Snate@binkert.org        (*i)->initFunc();
2157674Snate@binkert.org}
2167674Snate@binkert.org
2177674Snate@binkert.orgint
2187674Snate@binkert.orginitM5Python()
2197674Snate@binkert.org{
2207674Snate@binkert.org    EmbeddedSwig::initAll();
2217674Snate@binkert.org    return EmbeddedPython::initAll();
2227674Snate@binkert.org}
2237674Snate@binkert.org
2245522Snate@binkert.org/*
2258234Snate@binkert.org * Make the commands array weak so that they can be overridden (used
2268234Snate@binkert.org * by unit tests to specify a different python main function.
2278234Snate@binkert.org */
2288234Snate@binkert.orgconst char * __attribute__((weak)) m5MainCommands[] = {
2298234Snate@binkert.org    "import m5",
2308234Snate@binkert.org    "m5.main()",
2318234Snate@binkert.org    0 // sentinel is required
2328234Snate@binkert.org};
2338234Snate@binkert.org
2348234Snate@binkert.org/*
2355522Snate@binkert.org * Start up the M5 simulator.  This mostly vectors into the python
2365522Snate@binkert.org * main function.
2375522Snate@binkert.org */
2385522Snate@binkert.orgint
2395522Snate@binkert.orgm5Main(int argc, char **argv)
2405522Snate@binkert.org{
2415522Snate@binkert.org    PySys_SetArgv(argc, argv);
2425522Snate@binkert.org
2435522Snate@binkert.org    // We have to set things up in the special __main__ module
2445522Snate@binkert.org    PyObject *module = PyImport_AddModule(PyCC("__main__"));
2455522Snate@binkert.org    if (module == NULL)
2465522Snate@binkert.org        panic("Could not import __main__");
2475522Snate@binkert.org    PyObject *dict = PyModule_GetDict(module);
2485522Snate@binkert.org
2495522Snate@binkert.org    // import the main m5 module
2505522Snate@binkert.org    PyObject *result;
2518234Snate@binkert.org    const char **command = m5MainCommands;
2528234Snate@binkert.org
2538234Snate@binkert.org    // evaluate each command in the m5MainCommands array (basically a
2548234Snate@binkert.org    // bunch of python statements.
2558234Snate@binkert.org    while (*command) {
2568234Snate@binkert.org        result = PyRun_String(*command, Py_file_input, dict, dict);
2578234Snate@binkert.org        if (!result) {
2588234Snate@binkert.org            PyErr_Print();
2598234Snate@binkert.org            return 1;
2608234Snate@binkert.org        }
2618234Snate@binkert.org        Py_DECREF(result);
2628234Snate@binkert.org
2638234Snate@binkert.org        command++;
2645522Snate@binkert.org    }
2655522Snate@binkert.org
2665522Snate@binkert.org    return 0;
2675522Snate@binkert.org}
2685601Snate@binkert.org
2695601Snate@binkert.orgPyMODINIT_FUNC
2705601Snate@binkert.orginitm5(void)
2715601Snate@binkert.org{
2725601Snate@binkert.org    initM5Python();
2735601Snate@binkert.org    PyImport_ImportModule(PyCC("m5"));
2745601Snate@binkert.org}
275