init.cc revision 12334
12623SN/A/* 22623SN/A * Copyright (c) 2012, 2017 ARM Limited 32623SN/A * All rights reserved 42623SN/A * 52623SN/A * The license below extends only to copyright in the software and shall 62623SN/A * not be construed as granting a license to any other intellectual 72623SN/A * property including but not limited to intellectual property relating 82623SN/A * to a hardware implementation of the functionality of the software 92623SN/A * licensed hereunder. You may use the software subject to the license 102623SN/A * terms below provided that you ensure that this notice is replicated 112623SN/A * unmodified and in its entirety in all distributions of the software, 122623SN/A * modified or unmodified, in source code or in binary form. 132623SN/A * 142623SN/A * Copyright (c) 2000-2005 The Regents of The University of Michigan 152623SN/A * Copyright (c) 2008 The Hewlett-Packard Development Company 162623SN/A * All rights reserved. 172623SN/A * 182623SN/A * Redistribution and use in source and binary forms, with or without 192623SN/A * modification, are permitted provided that the following conditions are 202623SN/A * met: redistributions of source code must retain the above copyright 212623SN/A * notice, this list of conditions and the following disclaimer; 222623SN/A * redistributions in binary form must reproduce the above copyright 232623SN/A * notice, this list of conditions and the following disclaimer in the 242623SN/A * documentation and/or other materials provided with the distribution; 252623SN/A * neither the name of the copyright holders nor the names of its 262623SN/A * contributors may be used to endorse or promote products derived from 272665Ssaidi@eecs.umich.edu * this software without specific prior written permission. 282665Ssaidi@eecs.umich.edu * 292623SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 302623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 312623SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 322623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 332623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 342623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 352623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 362623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 372623SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 382623SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 392623SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 402623SN/A * 412623SN/A * Authors: Nathan Binkert 422623SN/A */ 432623SN/A 442623SN/A#include <Python.h> 452623SN/A 462623SN/A#include "sim/init.hh" 472623SN/A 482623SN/A#include <marshal.h> 492623SN/A#include <zlib.h> 502623SN/A 512623SN/A#include <iostream> 522623SN/A#include <list> 532623SN/A#include <string> 542623SN/A 552623SN/A#include "base/cprintf.hh" 562623SN/A#include "base/logging.hh" 572623SN/A#include "base/types.hh" 582623SN/A#include "config/have_protobuf.hh" 592623SN/A#include "python/pybind11/pybind.hh" 602623SN/A#include "sim/async.hh" 612623SN/A#include "sim/core.hh" 622623SN/A 632623SN/A#if HAVE_PROTOBUF 642623SN/A#include <google/protobuf/stubs/common.h> 652623SN/A 662623SN/A#endif 672623SN/A 682623SN/Ausing namespace std; 692623SN/Anamespace py = pybind11; 702623SN/A 712623SN/A// The python library is totally messed up with respect to constness, 722623SN/A// so make a simple macro to make life a little easier 732623SN/A#define PyCC(x) (const_cast<char *>(x)) 742623SN/A 752623SN/AEmbeddedPython *EmbeddedPython::importer = NULL; 762623SN/APyObject *EmbeddedPython::importerModule = NULL; 772623SN/AEmbeddedPython::EmbeddedPython(const char *filename, const char *abspath, 782623SN/A const char *modpath, const unsigned char *code, int zlen, int len) 792623SN/A : filename(filename), abspath(abspath), modpath(modpath), code(code), 802623SN/A zlen(zlen), len(len) 812623SN/A{ 822623SN/A // if we've added the importer keep track of it because we need it 832630SN/A // to bootstrap. 842623SN/A if (string(modpath) == string("importer")) 852623SN/A importer = this; 862623SN/A else 872623SN/A getList().push_back(this); 882623SN/A} 892623SN/A 902630SN/Alist<EmbeddedPython *> & 912623SN/AEmbeddedPython::getList() 922623SN/A{ 932623SN/A static list<EmbeddedPython *> the_list; 942623SN/A return the_list; 952623SN/A} 962623SN/A 972630SN/A/* 982623SN/A * Uncompress and unmarshal the code object stored in the 992623SN/A * EmbeddedPython 1002623SN/A */ 1012623SN/APyObject * 1022623SN/AEmbeddedPython::getCode() const 1032623SN/A{ 1042623SN/A Bytef marshalled[len]; 1052626SN/A uLongf unzlen = len; 1062626SN/A int ret = uncompress(marshalled, &unzlen, (const Bytef *)code, zlen); 1072626SN/A if (ret != Z_OK) 1082623SN/A panic("Could not uncompress code: %s\n", zError(ret)); 1092623SN/A assert(unzlen == (uLongf)len); 1102623SN/A 1112657Ssaidi@eecs.umich.edu return PyMarshal_ReadObjectFromString((char *)marshalled, len); 1122623SN/A} 1132623SN/A 1142623SN/Abool 1152623SN/AEmbeddedPython::addModule() const 1162623SN/A{ 1172623SN/A PyObject *code = getCode(); 1182623SN/A PyObject *result = PyObject_CallMethod(importerModule, PyCC("add_module"), 1192623SN/A PyCC("sssO"), filename, abspath, modpath, code); 1202623SN/A if (!result) { 1212640Sstever@eecs.umich.edu PyErr_Print(); 1222623SN/A return false; 1232623SN/A } 1242623SN/A 1252663Sstever@eecs.umich.edu Py_DECREF(result); 1262663Sstever@eecs.umich.edu return true; 1272641Sstever@eecs.umich.edu} 1282623SN/A 1292623SN/A/* 1302663Sstever@eecs.umich.edu * Load and initialize all of the python parts of M5. 1312641Sstever@eecs.umich.edu */ 1322641Sstever@eecs.umich.eduint 1332623SN/AEmbeddedPython::initAll() 1342623SN/A{ 1352663Sstever@eecs.umich.edu // Load the importer module 1362641Sstever@eecs.umich.edu PyObject *code = importer->getCode(); 1372641Sstever@eecs.umich.edu importerModule = PyImport_ExecCodeModule(PyCC("importer"), code); 1382623SN/A if (!importerModule) { 1392623SN/A PyErr_Print(); 1402623SN/A return 1; 1412623SN/A } 1422623SN/A 1432623SN/A // Load the rest of the embedded python files into the embedded 1442623SN/A // python importer 1452623SN/A list<EmbeddedPython *>::iterator i = getList().begin(); 1462623SN/A list<EmbeddedPython *>::iterator end = getList().end(); 1472623SN/A for (; i != end; ++i) 1482623SN/A if (!(*i)->addModule()) 1492623SN/A return 1; 1502623SN/A 1512623SN/A return 0; 1522623SN/A} 1532623SN/A 1542623SN/AEmbeddedPyBind::EmbeddedPyBind(const char *_name, 1552623SN/A void (*init_func)(py::module &), 1562623SN/A const char *_base) 1572623SN/A : initFunc(init_func), registered(false), name(_name), base(_base) 1582623SN/A{ 1592623SN/A getMap()[_name] = this; 1602623SN/A} 1612623SN/A 1622623SN/AEmbeddedPyBind::EmbeddedPyBind(const char *_name, 1632623SN/A void (*init_func)(py::module &)) 1642623SN/A : initFunc(init_func), registered(false), name(_name), base("") 1652623SN/A{ 1662623SN/A getMap()[_name] = this; 1672623SN/A} 1682623SN/A 1692623SN/Avoid 1702623SN/AEmbeddedPyBind::init(py::module &m) 1712623SN/A{ 1722623SN/A if (!registered) { 1732623SN/A initFunc(m); 1742623SN/A registered = true; 1752623SN/A } else { 1762623SN/A cprintf("Warning: %s already registered.\n", name); 1772623SN/A } 1782623SN/A} 1792623SN/A 1802623SN/Abool 1812623SN/AEmbeddedPyBind::depsReady() const 1822623SN/A{ 1832623SN/A return base.empty() || getMap()[base]->registered; 1842623SN/A} 1852623SN/A 1862623SN/Astd::map<std::string, EmbeddedPyBind *> & 1872623SN/AEmbeddedPyBind::getMap() 1882623SN/A{ 1892623SN/A static std::map<std::string, EmbeddedPyBind *> objs; 1902623SN/A return objs; 1912623SN/A} 1922623SN/A 1932623SN/Avoid 1942623SN/AEmbeddedPyBind::initAll() 1952623SN/A{ 1962623SN/A std::list<EmbeddedPyBind *> pending; 1972623SN/A 1982623SN/A py::module m_m5 = py::module("_m5"); 1992623SN/A m_m5.attr("__package__") = py::cast("_m5"); 2002623SN/A 2012623SN/A pybind_init_core(m_m5); 2022623SN/A pybind_init_debug(m_m5); 2032623SN/A 2042623SN/A pybind_init_event(m_m5); 2052623SN/A pybind_init_pyobject(m_m5); 2062623SN/A pybind_init_stats(m_m5); 2072623SN/A 2082623SN/A for (auto &kv : getMap()) { 2092623SN/A auto &obj = kv.second; 2102623SN/A if (obj->base.empty()) { 2112623SN/A obj->init(m_m5); 2122623SN/A } else { 2132623SN/A pending.push_back(obj); 2142623SN/A } 2152623SN/A } 2162623SN/A 2172626SN/A while (!pending.empty()) { 2182626SN/A for (auto it = pending.begin(); it != pending.end(); ) { 2192626SN/A EmbeddedPyBind &obj = **it; 2202626SN/A if (obj.depsReady()) { 2212626SN/A obj.init(m_m5); 2222623SN/A it = pending.erase(it); 2232623SN/A } else { 2242623SN/A ++it; 2252623SN/A } 2262623SN/A } 2272623SN/A } 2282623SN/A} 2292623SN/A 2302623SN/Aint 2312623SN/AinitM5Python() 2322663Sstever@eecs.umich.edu{ 2332623SN/A EmbeddedPyBind::initAll(); 2342623SN/A return EmbeddedPython::initAll(); 2352623SN/A} 2362623SN/A 2372623SN/A/* 2382623SN/A * Make the commands array weak so that they can be overridden (used 2392623SN/A * by unit tests to specify a different python main function. 2402623SN/A */ 2412623SN/Aconst char * __attribute__((weak)) m5MainCommands[] = { 2422623SN/A "import m5", 2432641Sstever@eecs.umich.edu "m5.main()", 2442623SN/A 0 // sentinel is required 2452662Sstever@eecs.umich.edu}; 2462623SN/A 2472623SN/A/* 2482641Sstever@eecs.umich.edu * Start up the M5 simulator. This mostly vectors into the python 2492623SN/A * main function. 2502623SN/A */ 2512623SN/Aint 2522623SN/Am5Main(int argc, char **argv) 2532623SN/A{ 2542623SN/A#if HAVE_PROTOBUF 2552623SN/A // Verify that the version of the protobuf library that we linked 2562623SN/A // against is compatible with the version of the headers we 2572623SN/A // compiled against. 2582623SN/A GOOGLE_PROTOBUF_VERIFY_VERSION; 2592623SN/A#endif 2602623SN/A 2612623SN/A PySys_SetArgv(argc, argv); 2622623SN/A 2632623SN/A // We have to set things up in the special __main__ module 2642623SN/A PyObject *module = PyImport_AddModule(PyCC("__main__")); 2652623SN/A if (module == NULL) 2662623SN/A panic("Could not import __main__"); 2672623SN/A PyObject *dict = PyModule_GetDict(module); 2682623SN/A 2692623SN/A // import the main m5 module 2702623SN/A PyObject *result; 2712623SN/A const char **command = m5MainCommands; 2722623SN/A 2732623SN/A // evaluate each command in the m5MainCommands array (basically a 2742623SN/A // bunch of python statements. 2752623SN/A while (*command) { 2762623SN/A result = PyRun_String(*command, Py_file_input, dict, dict); 2772623SN/A if (!result) { 2782623SN/A PyErr_Print(); 2792623SN/A return 1; 2802623SN/A } 2812623SN/A Py_DECREF(result); 2822623SN/A 2832623SN/A command++; 2842623SN/A } 2852623SN/A 2862623SN/A#if HAVE_PROTOBUF 2872623SN/A google::protobuf::ShutdownProtobufLibrary(); 2882623SN/A#endif 2892623SN/A 2902623SN/A return 0; 2912623SN/A} 2922623SN/A 2932623SN/APyMODINIT_FUNC 2942623SN/Ainitm5(void) 2952623SN/A{ 2962623SN/A initM5Python(); 2972623SN/A PyImport_ImportModule(PyCC("m5")); 2982623SN/A} 2992623SN/A