init.cc revision 11808
15522Snate@binkert.org/* 29397Sandreas.hansson@arm.com * Copyright (c) 2012 ARM Limited 39397Sandreas.hansson@arm.com * All rights reserved 49397Sandreas.hansson@arm.com * 59397Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 69397Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 79397Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 89397Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 99397Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 109397Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 119397Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 129397Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 139397Sandreas.hansson@arm.com * 145522Snate@binkert.org * Copyright (c) 2000-2005 The Regents of The University of Michigan 155522Snate@binkert.org * Copyright (c) 2008 The Hewlett-Packard Development Company 165522Snate@binkert.org * All rights reserved. 175522Snate@binkert.org * 185522Snate@binkert.org * Redistribution and use in source and binary forms, with or without 195522Snate@binkert.org * modification, are permitted provided that the following conditions are 205522Snate@binkert.org * met: redistributions of source code must retain the above copyright 215522Snate@binkert.org * notice, this list of conditions and the following disclaimer; 225522Snate@binkert.org * redistributions in binary form must reproduce the above copyright 235522Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 245522Snate@binkert.org * documentation and/or other materials provided with the distribution; 255522Snate@binkert.org * neither the name of the copyright holders nor the names of its 265522Snate@binkert.org * contributors may be used to endorse or promote products derived from 275522Snate@binkert.org * this software without specific prior written permission. 285522Snate@binkert.org * 295522Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 305522Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 315522Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 325522Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 335522Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 345522Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 355522Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 365522Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 375522Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 385522Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 395522Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 405522Snate@binkert.org * 415522Snate@binkert.org * Authors: Nathan Binkert 425522Snate@binkert.org */ 435522Snate@binkert.org 4411808Sandreas.sandberg@arm.com#include <Python.h> 4511808Sandreas.sandberg@arm.com 4611793Sbrandon.potter@amd.com#include "sim/init.hh" 4711793Sbrandon.potter@amd.com 485522Snate@binkert.org#include <marshal.h> 498229Snate@binkert.org#include <zlib.h> 505522Snate@binkert.org 518229Snate@binkert.org#include <iostream> 527674Snate@binkert.org#include <list> 535522Snate@binkert.org#include <string> 545522Snate@binkert.org 555522Snate@binkert.org#include "base/cprintf.hh" 565522Snate@binkert.org#include "base/misc.hh" 576216Snate@binkert.org#include "base/types.hh" 589397Sandreas.hansson@arm.com#include "config/have_protobuf.hh" 595522Snate@binkert.org#include "sim/async.hh" 605522Snate@binkert.org#include "sim/core.hh" 615522Snate@binkert.org 629397Sandreas.hansson@arm.com#if HAVE_PROTOBUF 639397Sandreas.hansson@arm.com#include <google/protobuf/stubs/common.h> 6411793Sbrandon.potter@amd.com 659397Sandreas.hansson@arm.com#endif 669397Sandreas.hansson@arm.com 675522Snate@binkert.orgusing namespace std; 685522Snate@binkert.org 695522Snate@binkert.org// The python library is totally messed up with respect to constness, 705522Snate@binkert.org// so make a simple macro to make life a little easier 715522Snate@binkert.org#define PyCC(x) (const_cast<char *>(x)) 725522Snate@binkert.org 737674Snate@binkert.orgEmbeddedPython *EmbeddedPython::importer = NULL; 747674Snate@binkert.orgPyObject *EmbeddedPython::importerModule = NULL; 757674Snate@binkert.orgEmbeddedPython::EmbeddedPython(const char *filename, const char *abspath, 768946Sandreas.hansson@arm.com const char *modpath, const unsigned char *code, int zlen, int len) 777674Snate@binkert.org : filename(filename), abspath(abspath), modpath(modpath), code(code), 787674Snate@binkert.org zlen(zlen), len(len) 797674Snate@binkert.org{ 807674Snate@binkert.org // if we've added the importer keep track of it because we need it 817674Snate@binkert.org // to bootstrap. 827674Snate@binkert.org if (string(modpath) == string("importer")) 837674Snate@binkert.org importer = this; 847674Snate@binkert.org else 857674Snate@binkert.org getList().push_back(this); 867674Snate@binkert.org} 877674Snate@binkert.org 887674Snate@binkert.orglist<EmbeddedPython *> & 897674Snate@binkert.orgEmbeddedPython::getList() 907674Snate@binkert.org{ 917674Snate@binkert.org static list<EmbeddedPython *> the_list; 927674Snate@binkert.org return the_list; 937674Snate@binkert.org} 947674Snate@binkert.org 957674Snate@binkert.org/* 967674Snate@binkert.org * Uncompress and unmarshal the code object stored in the 977674Snate@binkert.org * EmbeddedPython 987674Snate@binkert.org */ 997674Snate@binkert.orgPyObject * 1007674Snate@binkert.orgEmbeddedPython::getCode() const 1017674Snate@binkert.org{ 1027674Snate@binkert.org Bytef marshalled[len]; 1037674Snate@binkert.org uLongf unzlen = len; 1047674Snate@binkert.org int ret = uncompress(marshalled, &unzlen, (const Bytef *)code, zlen); 1057674Snate@binkert.org if (ret != Z_OK) 1067674Snate@binkert.org panic("Could not uncompress code: %s\n", zError(ret)); 1077674Snate@binkert.org assert(unzlen == (uLongf)len); 1087674Snate@binkert.org 1097674Snate@binkert.org return PyMarshal_ReadObjectFromString((char *)marshalled, len); 1107674Snate@binkert.org} 1117674Snate@binkert.org 1127674Snate@binkert.orgbool 1137674Snate@binkert.orgEmbeddedPython::addModule() const 1147674Snate@binkert.org{ 1157674Snate@binkert.org PyObject *code = getCode(); 1167674Snate@binkert.org PyObject *result = PyObject_CallMethod(importerModule, PyCC("add_module"), 1177674Snate@binkert.org PyCC("sssO"), filename, abspath, modpath, code); 1187674Snate@binkert.org if (!result) { 1197674Snate@binkert.org PyErr_Print(); 1207674Snate@binkert.org return false; 1217674Snate@binkert.org } 1227674Snate@binkert.org 1237674Snate@binkert.org Py_DECREF(result); 1247674Snate@binkert.org return true; 1257674Snate@binkert.org} 1267674Snate@binkert.org 1275522Snate@binkert.org/* 1285522Snate@binkert.org * Load and initialize all of the python parts of M5, including Swig 1295522Snate@binkert.org * and the embedded module importer. 1305522Snate@binkert.org */ 1315522Snate@binkert.orgint 1327674Snate@binkert.orgEmbeddedPython::initAll() 1335522Snate@binkert.org{ 1345522Snate@binkert.org // Load the importer module 1357674Snate@binkert.org PyObject *code = importer->getCode(); 1367674Snate@binkert.org importerModule = PyImport_ExecCodeModule(PyCC("importer"), code); 1377674Snate@binkert.org if (!importerModule) { 1385522Snate@binkert.org PyErr_Print(); 1395522Snate@binkert.org return 1; 1405522Snate@binkert.org } 1415522Snate@binkert.org 1425522Snate@binkert.org // Load the rest of the embedded python files into the embedded 1435522Snate@binkert.org // python importer 1447674Snate@binkert.org list<EmbeddedPython *>::iterator i = getList().begin(); 1457674Snate@binkert.org list<EmbeddedPython *>::iterator end = getList().end(); 1467674Snate@binkert.org for (; i != end; ++i) 1477674Snate@binkert.org if (!(*i)->addModule()) 1485522Snate@binkert.org return 1; 1495522Snate@binkert.org 1505522Snate@binkert.org return 0; 1515522Snate@binkert.org} 1525522Snate@binkert.org 15311548Sandreas.hansson@arm.comEmbeddedSwig::EmbeddedSwig(void (*init_func)(), const string& _context) 15411548Sandreas.hansson@arm.com : initFunc(init_func), context(_context) 1557674Snate@binkert.org{ 1567674Snate@binkert.org getList().push_back(this); 1577674Snate@binkert.org} 1587674Snate@binkert.org 1597674Snate@binkert.orglist<EmbeddedSwig *> & 1607674Snate@binkert.orgEmbeddedSwig::getList() 1617674Snate@binkert.org{ 1627674Snate@binkert.org static list<EmbeddedSwig *> the_list; 1637674Snate@binkert.org return the_list; 1647674Snate@binkert.org} 1657674Snate@binkert.org 1667674Snate@binkert.orgvoid 1677674Snate@binkert.orgEmbeddedSwig::initAll() 1687674Snate@binkert.org{ 16911548Sandreas.hansson@arm.com char* old_context = _Py_PackageContext; 17011548Sandreas.hansson@arm.com // initialize SWIG modules. initFunc() is autogenerated and calls 1717674Snate@binkert.org // all of the individual swig initialization functions. 17211548Sandreas.hansson@arm.com for (auto i : getList()) { 17311548Sandreas.hansson@arm.com // to ensure that the loaded modules are placed in the right 17411548Sandreas.hansson@arm.com // package we have to be a bit unorthodox and directly 17511548Sandreas.hansson@arm.com // manipulate the package context since swig simply calls 17611548Sandreas.hansson@arm.com // Py_InitModule with nothing but the module name of the 17711548Sandreas.hansson@arm.com // wrapper 17811548Sandreas.hansson@arm.com char* cstr = new char[i->context.size() + 1]; 17911548Sandreas.hansson@arm.com strcpy(cstr, i->context.c_str()); 18011548Sandreas.hansson@arm.com _Py_PackageContext = cstr; 18111548Sandreas.hansson@arm.com i->initFunc(); 18211548Sandreas.hansson@arm.com delete[] cstr; 18311548Sandreas.hansson@arm.com } 18411548Sandreas.hansson@arm.com _Py_PackageContext = old_context; 1857674Snate@binkert.org} 1867674Snate@binkert.org 1877674Snate@binkert.orgint 1887674Snate@binkert.orginitM5Python() 1897674Snate@binkert.org{ 1907674Snate@binkert.org EmbeddedSwig::initAll(); 1917674Snate@binkert.org return EmbeddedPython::initAll(); 1927674Snate@binkert.org} 1937674Snate@binkert.org 1945522Snate@binkert.org/* 1958234Snate@binkert.org * Make the commands array weak so that they can be overridden (used 1968234Snate@binkert.org * by unit tests to specify a different python main function. 1978234Snate@binkert.org */ 1988234Snate@binkert.orgconst char * __attribute__((weak)) m5MainCommands[] = { 1998234Snate@binkert.org "import m5", 2008234Snate@binkert.org "m5.main()", 2018234Snate@binkert.org 0 // sentinel is required 2028234Snate@binkert.org}; 2038234Snate@binkert.org 2048234Snate@binkert.org/* 2055522Snate@binkert.org * Start up the M5 simulator. This mostly vectors into the python 2065522Snate@binkert.org * main function. 2075522Snate@binkert.org */ 2085522Snate@binkert.orgint 2095522Snate@binkert.orgm5Main(int argc, char **argv) 2105522Snate@binkert.org{ 2119397Sandreas.hansson@arm.com#if HAVE_PROTOBUF 2129397Sandreas.hansson@arm.com // Verify that the version of the protobuf library that we linked 2139397Sandreas.hansson@arm.com // against is compatible with the version of the headers we 2149397Sandreas.hansson@arm.com // compiled against. 2159397Sandreas.hansson@arm.com GOOGLE_PROTOBUF_VERIFY_VERSION; 2169397Sandreas.hansson@arm.com#endif 2179397Sandreas.hansson@arm.com 2185522Snate@binkert.org PySys_SetArgv(argc, argv); 2195522Snate@binkert.org 2205522Snate@binkert.org // We have to set things up in the special __main__ module 2215522Snate@binkert.org PyObject *module = PyImport_AddModule(PyCC("__main__")); 2225522Snate@binkert.org if (module == NULL) 2235522Snate@binkert.org panic("Could not import __main__"); 2245522Snate@binkert.org PyObject *dict = PyModule_GetDict(module); 2255522Snate@binkert.org 2265522Snate@binkert.org // import the main m5 module 2275522Snate@binkert.org PyObject *result; 2288234Snate@binkert.org const char **command = m5MainCommands; 2298234Snate@binkert.org 2308234Snate@binkert.org // evaluate each command in the m5MainCommands array (basically a 2318234Snate@binkert.org // bunch of python statements. 2328234Snate@binkert.org while (*command) { 2338234Snate@binkert.org result = PyRun_String(*command, Py_file_input, dict, dict); 2348234Snate@binkert.org if (!result) { 2358234Snate@binkert.org PyErr_Print(); 2368234Snate@binkert.org return 1; 2378234Snate@binkert.org } 2388234Snate@binkert.org Py_DECREF(result); 2398234Snate@binkert.org 2408234Snate@binkert.org command++; 2415522Snate@binkert.org } 2425522Snate@binkert.org 2439397Sandreas.hansson@arm.com#if HAVE_PROTOBUF 2449397Sandreas.hansson@arm.com google::protobuf::ShutdownProtobufLibrary(); 2459397Sandreas.hansson@arm.com#endif 2469397Sandreas.hansson@arm.com 2475522Snate@binkert.org return 0; 2485522Snate@binkert.org} 2495601Snate@binkert.org 2505601Snate@binkert.orgPyMODINIT_FUNC 2515601Snate@binkert.orginitm5(void) 2525601Snate@binkert.org{ 2535601Snate@binkert.org initM5Python(); 2545601Snate@binkert.org PyImport_ImportModule(PyCC("m5")); 2555601Snate@binkert.org} 256