init.cc revision 11990
17860SN/A/* 27860SN/A * Copyright (c) 2012, 2017 ARM Limited 37860SN/A * All rights reserved 49988Snilay@cs.wisc.edu * 58825Snilay@cs.wisc.edu * The license below extends only to copyright in the software and shall 69988Snilay@cs.wisc.edu * not be construed as granting a license to any other intellectual 77935SN/A * property including but not limited to intellectual property relating 87935SN/A * to a hardware implementation of the functionality of the software 97935SN/A * licensed hereunder. You may use the software subject to the license 107860SN/A * terms below provided that you ensure that this notice is replicated 117860SN/A * unmodified and in its entirety in all distributions of the software, 127860SN/A * modified or unmodified, in source code or in binary form. 1310315Snilay@cs.wisc.edu * 148825Snilay@cs.wisc.edu * Copyright (c) 2000-2005 The Regents of The University of Michigan 159885Sstever@gmail.com * Copyright (c) 2008 The Hewlett-Packard Development Company 169885Sstever@gmail.com * All rights reserved. 179988Snilay@cs.wisc.edu * 188825Snilay@cs.wisc.edu * Redistribution and use in source and binary forms, with or without 198825Snilay@cs.wisc.edu * modification, are permitted provided that the following conditions are 2010315Snilay@cs.wisc.edu * met: redistributions of source code must retain the above copyright 218825Snilay@cs.wisc.edu * notice, this list of conditions and the following disclaimer; 2210038SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 239449SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 249449SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 258464SN/A * neither the name of the copyright holders nor the names of its 2610798Ssteve.reinhardt@amd.com * contributors may be used to endorse or promote products derived from 278721SN/A * this software without specific prior written permission. 288825Snilay@cs.wisc.edu * 298825Snilay@cs.wisc.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 307935SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 317935SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 327935SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 337935SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 347935SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 357935SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 367935SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 378893Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 387860SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 399885Sstever@gmail.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 409885Sstever@gmail.com * 419885Sstever@gmail.com * Authors: Nathan Binkert 4210315Snilay@cs.wisc.edu */ 439988Snilay@cs.wisc.edu 4410315Snilay@cs.wisc.edu#include <Python.h> 459885Sstever@gmail.com 469885Sstever@gmail.com#include "sim/init.hh" 477860SN/A 487860SN/A#include <marshal.h> 4910038SAli.Saidi@ARM.com#include <zlib.h> 507860SN/A 5110451Snilay@cs.wisc.edu#include <iostream> 528210SN/A#include <list> 5310451Snilay@cs.wisc.edu#include <string> 5410451Snilay@cs.wisc.edu 557860SN/A#include "base/cprintf.hh" 567860SN/A#include "base/misc.hh" 577860SN/A#include "base/types.hh" 589481Snilay@cs.wisc.edu#include "config/have_protobuf.hh" 597860SN/A#include "python/pybind11/pybind.hh" 607860SN/A#include "sim/async.hh" 619885Sstever@gmail.com#include "sim/core.hh" 627860SN/A 637860SN/A#if HAVE_PROTOBUF 647860SN/A#include <google/protobuf/stubs/common.h> 657860SN/A 667860SN/A#endif 677860SN/A 687860SN/Ausing namespace std; 6910451Snilay@cs.wisc.edunamespace py = pybind11; 7010451Snilay@cs.wisc.edu 7110451Snilay@cs.wisc.edu// The python library is totally messed up with respect to constness, 727860SN/A// so make a simple macro to make life a little easier 738825Snilay@cs.wisc.edu#define PyCC(x) (const_cast<char *>(x)) 747860SN/A 7510038SAli.Saidi@ARM.comEmbeddedPython *EmbeddedPython::importer = NULL; 767860SN/APyObject *EmbeddedPython::importerModule = NULL; 779988Snilay@cs.wisc.eduEmbeddedPython::EmbeddedPython(const char *filename, const char *abspath, 7810451Snilay@cs.wisc.edu const char *modpath, const unsigned char *code, int zlen, int len) 7910451Snilay@cs.wisc.edu : filename(filename), abspath(abspath), modpath(modpath), code(code), 8010451Snilay@cs.wisc.edu zlen(zlen), len(len) 817860SN/A{ 8210451Snilay@cs.wisc.edu // if we've added the importer keep track of it because we need it 837860SN/A // to bootstrap. 847860SN/A if (string(modpath) == string("importer")) 857860SN/A importer = this; 867860SN/A else 877860SN/A getList().push_back(this); 887860SN/A} 897860SN/A 907860SN/Alist<EmbeddedPython *> & 918825Snilay@cs.wisc.eduEmbeddedPython::getList() 929449SAli.Saidi@ARM.com{ 937860SN/A static list<EmbeddedPython *> the_list; 947860SN/A return the_list; 9510038SAli.Saidi@ARM.com} 967860SN/A 977860SN/A/* 987860SN/A * Uncompress and unmarshal the code object stored in the 997860SN/A * EmbeddedPython 1007860SN/A */ 1018825Snilay@cs.wisc.eduPyObject * 10210451Snilay@cs.wisc.eduEmbeddedPython::getCode() const 10310451Snilay@cs.wisc.edu{ 10410451Snilay@cs.wisc.edu Bytef marshalled[len]; 10510451Snilay@cs.wisc.edu uLongf unzlen = len; 10610451Snilay@cs.wisc.edu int ret = uncompress(marshalled, &unzlen, (const Bytef *)code, zlen); 1077860SN/A if (ret != Z_OK) 1087860SN/A panic("Could not uncompress code: %s\n", zError(ret)); 1098825Snilay@cs.wisc.edu assert(unzlen == (uLongf)len); 1107860SN/A 1117860SN/A return PyMarshal_ReadObjectFromString((char *)marshalled, len); 1127860SN/A} 11310451Snilay@cs.wisc.edu 1147860SN/Abool 11510451Snilay@cs.wisc.eduEmbeddedPython::addModule() const 1169885Sstever@gmail.com{ 1177860SN/A PyObject *code = getCode(); 1187860SN/A PyObject *result = PyObject_CallMethod(importerModule, PyCC("add_module"), 1197860SN/A PyCC("sssO"), filename, abspath, modpath, code); 1207860SN/A if (!result) { 1217860SN/A PyErr_Print(); 1227860SN/A return false; 1237860SN/A } 1247860SN/A 1257860SN/A Py_DECREF(result); 12610242Ssteve.reinhardt@amd.com return true; 1277860SN/A} 1288521SN/A 1299449SAli.Saidi@ARM.com/* 1307860SN/A * Load and initialize all of the python parts of M5. 1317860SN/A */ 1327860SN/Aint 1337860SN/AEmbeddedPython::initAll() 1347860SN/A{ 1357860SN/A // Load the importer module 1367860SN/A PyObject *code = importer->getCode(); 1377860SN/A importerModule = PyImport_ExecCodeModule(PyCC("importer"), code); 1389481Snilay@cs.wisc.edu if (!importerModule) { 13910798Ssteve.reinhardt@amd.com PyErr_Print(); 14010451Snilay@cs.wisc.edu return 1; 14110451Snilay@cs.wisc.edu } 1429481Snilay@cs.wisc.edu 1439481Snilay@cs.wisc.edu // Load the rest of the embedded python files into the embedded 1449481Snilay@cs.wisc.edu // python importer 1459988Snilay@cs.wisc.edu list<EmbeddedPython *>::iterator i = getList().begin(); 1469481Snilay@cs.wisc.edu list<EmbeddedPython *>::iterator end = getList().end(); 1479481Snilay@cs.wisc.edu for (; i != end; ++i) 1489481Snilay@cs.wisc.edu if (!(*i)->addModule()) 1499481Snilay@cs.wisc.edu return 1; 1509481Snilay@cs.wisc.edu 1517860SN/A return 0; 1527860SN/A} 1539885Sstever@gmail.com 1548893Ssaidi@eecs.umich.eduEmbeddedPyBind::EmbeddedPyBind(const char *_name, 1557860SN/A void (*init_func)(py::module &), 1569885Sstever@gmail.com const char *_base) 15710636Snilay@cs.wisc.edu : initFunc(init_func), registered(false), name(_name), base(_base) 1589988Snilay@cs.wisc.edu{ 1597860SN/A getMap()[_name] = this; 1609348SAli.Saidi@ARM.com} 1618150SN/A 1627860SN/AEmbeddedPyBind::EmbeddedPyBind(const char *_name, 16310451Snilay@cs.wisc.edu void (*init_func)(py::module &)) 1647860SN/A : initFunc(init_func), registered(false), name(_name), base("") 1658835SAli.Saidi@ARM.com{ 1669348SAli.Saidi@ARM.com getMap()[_name] = this; 16710036SAli.Saidi@ARM.com} 16810451Snilay@cs.wisc.edu 1698835SAli.Saidi@ARM.comvoid 1709885Sstever@gmail.comEmbeddedPyBind::init(py::module &m) 17110451Snilay@cs.wisc.edu{ 1727860SN/A if (!registered) { 17310451Snilay@cs.wisc.edu initFunc(m); 1747860SN/A registered = true; 1758893Ssaidi@eecs.umich.edu } else { 1767860SN/A cprintf("Warning: %s already registered.\n", name); 1779885Sstever@gmail.com } 1789885Sstever@gmail.com} 1799885Sstever@gmail.com 1809885Sstever@gmail.combool 1819885Sstever@gmail.comEmbeddedPyBind::depsReady() const 1829988Snilay@cs.wisc.edu{ 1839885Sstever@gmail.com return base.empty() || getMap()[base]->registered; 18410036SAli.Saidi@ARM.com} 18510451Snilay@cs.wisc.edu 1869885Sstever@gmail.comstd::map<std::string, EmbeddedPyBind *> & 18710038SAli.Saidi@ARM.comEmbeddedPyBind::getMap() 18810038SAli.Saidi@ARM.com{ 18910038SAli.Saidi@ARM.com static std::map<std::string, EmbeddedPyBind *> objs; 19010038SAli.Saidi@ARM.com return objs; 19110038SAli.Saidi@ARM.com} 19210798Ssteve.reinhardt@amd.com 19310038SAli.Saidi@ARM.comvoid 19410038SAli.Saidi@ARM.comEmbeddedPyBind::initAll() 19510038SAli.Saidi@ARM.com{ 19610038SAli.Saidi@ARM.com std::list<EmbeddedPyBind *> pending; 19710038SAli.Saidi@ARM.com 19810038SAli.Saidi@ARM.com py::module m_m5 = py::module("_m5"); 19910038SAli.Saidi@ARM.com m_m5.attr("__package__") = py::cast("_m5"); 20010038SAli.Saidi@ARM.com 20110038SAli.Saidi@ARM.com pybind_init_core(m_m5); 20210038SAli.Saidi@ARM.com pybind_init_debug(m_m5); 20310038SAli.Saidi@ARM.com 20410038SAli.Saidi@ARM.com pybind_init_event(m_m5); 20510038SAli.Saidi@ARM.com pybind_init_pyobject(m_m5); 20610038SAli.Saidi@ARM.com pybind_init_stats(m_m5); 20710038SAli.Saidi@ARM.com 20810038SAli.Saidi@ARM.com for (auto &kv : getMap()) { 20910038SAli.Saidi@ARM.com auto &obj = kv.second; 21010038SAli.Saidi@ARM.com if (obj->base.empty()) { 2117860SN/A obj->init(m_m5); 2127860SN/A } else { 2138825Snilay@cs.wisc.edu pending.push_back(obj); 2149988Snilay@cs.wisc.edu } 21510038SAli.Saidi@ARM.com } 2167860SN/A 2178825Snilay@cs.wisc.edu while (!pending.empty()) { 2188825Snilay@cs.wisc.edu for (auto it = pending.begin(); it != pending.end(); ) { 2198825Snilay@cs.wisc.edu EmbeddedPyBind &obj = **it; 2208825Snilay@cs.wisc.edu if (obj.depsReady()) { 2219885Sstever@gmail.com obj.init(m_m5); 2229988Snilay@cs.wisc.edu it = pending.erase(it); 22310038SAli.Saidi@ARM.com } else { 2249265SAli.Saidi@ARM.com ++it; 2258825Snilay@cs.wisc.edu } 2268893Ssaidi@eecs.umich.edu } 2277860SN/A } 2287860SN/A} 2297860SN/A 23010451Snilay@cs.wisc.eduint 23110451Snilay@cs.wisc.eduinitM5Python() 2329988Snilay@cs.wisc.edu{ 2337860SN/A EmbeddedPyBind::initAll(); 2347860SN/A return EmbeddedPython::initAll(); 2357860SN/A} 2367860SN/A 23710451Snilay@cs.wisc.edu/* 2389988Snilay@cs.wisc.edu * Make the commands array weak so that they can be overridden (used 2397860SN/A * by unit tests to specify a different python main function. 2407860SN/A */ 2417860SN/Aconst char * __attribute__((weak)) m5MainCommands[] = { 2427860SN/A "import m5", 2439988Snilay@cs.wisc.edu "m5.main()", 2447860SN/A 0 // sentinel is required 2457860SN/A}; 2467860SN/A 2477860SN/A/* 2487860SN/A * Start up the M5 simulator. This mostly vectors into the python 2497860SN/A * main function. 25010451Snilay@cs.wisc.edu */ 25110451Snilay@cs.wisc.eduint 2529988Snilay@cs.wisc.edum5Main(int argc, char **argv) 25310451Snilay@cs.wisc.edu{ 2547860SN/A#if HAVE_PROTOBUF 2557860SN/A // Verify that the version of the protobuf library that we linked 2567860SN/A // against is compatible with the version of the headers we 2579988Snilay@cs.wisc.edu // compiled against. 2587860SN/A GOOGLE_PROTOBUF_VERIFY_VERSION; 2597860SN/A#endif 2607860SN/A 2617860SN/A PySys_SetArgv(argc, argv); 2627860SN/A 2637860SN/A // We have to set things up in the special __main__ module 2649988Snilay@cs.wisc.edu PyObject *module = PyImport_AddModule(PyCC("__main__")); 26510451Snilay@cs.wisc.edu if (module == NULL) 2667860SN/A panic("Could not import __main__"); 26710451Snilay@cs.wisc.edu PyObject *dict = PyModule_GetDict(module); 26810451Snilay@cs.wisc.edu 26910451Snilay@cs.wisc.edu // import the main m5 module 27010451Snilay@cs.wisc.edu PyObject *result; 27110451Snilay@cs.wisc.edu const char **command = m5MainCommands; 27210451Snilay@cs.wisc.edu 27310451Snilay@cs.wisc.edu // evaluate each command in the m5MainCommands array (basically a 27410451Snilay@cs.wisc.edu // bunch of python statements. 2757860SN/A while (*command) { 2767860SN/A result = PyRun_String(*command, Py_file_input, dict, dict); 2777860SN/A if (!result) { 27810451Snilay@cs.wisc.edu PyErr_Print(); 27910451Snilay@cs.wisc.edu return 1; 2809988Snilay@cs.wisc.edu } 28110451Snilay@cs.wisc.edu Py_DECREF(result); 2827860SN/A 28310451Snilay@cs.wisc.edu command++; 2847860SN/A } 2859988Snilay@cs.wisc.edu 2867860SN/A#if HAVE_PROTOBUF 28710451Snilay@cs.wisc.edu google::protobuf::ShutdownProtobufLibrary(); 2887860SN/A#endif 2897860SN/A 2907860SN/A return 0; 2917860SN/A} 29210451Snilay@cs.wisc.edu 29310451Snilay@cs.wisc.eduPyMODINIT_FUNC 2949988Snilay@cs.wisc.eduinitm5(void) 29510451Snilay@cs.wisc.edu{ 2967860SN/A initM5Python(); 29710451Snilay@cs.wisc.edu PyImport_ImportModule(PyCC("m5")); 2987860SN/A} 2999988Snilay@cs.wisc.edu