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