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