2 * Copyright (c) 2012, 2017 ARM Limited
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.
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.
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.
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.
41 * Authors: Nathan Binkert
46 #include "sim/init.hh"
56 #include "base/cprintf.hh"
57 #include "base/logging.hh"
58 #include "base/types.hh"
59 #include "config/have_protobuf.hh"
60 #include "python/pybind11/pybind.hh"
61 #include "sim/async.hh"
62 #include "sim/core.hh"
65 #include <google/protobuf/stubs/common.h>
70 namespace py
= pybind11
;
72 // The python library is totally messed up with respect to constness,
73 // so make a simple macro to make life a little easier
74 #define PyCC(x) (const_cast<char *>(x))
76 EmbeddedPython
*EmbeddedPython::importer
= NULL
;
77 PyObject
*EmbeddedPython::importerModule
= NULL
;
78 EmbeddedPython::EmbeddedPython(const char *filename
, const char *abspath
,
79 const char *modpath
, const unsigned char *code
, int zlen
, int len
)
80 : filename(filename
), abspath(abspath
), modpath(modpath
), code(code
),
83 // if we've added the importer keep track of it because we need it
85 if (string(modpath
) == string("importer"))
88 getList().push_back(this);
91 list
<EmbeddedPython
*> &
92 EmbeddedPython::getList()
94 static list
<EmbeddedPython
*> the_list
;
99 * Uncompress and unmarshal the code object stored in the
103 EmbeddedPython::getCode() const
105 Bytef marshalled
[len
];
107 int ret
= uncompress(marshalled
, &unzlen
, (const Bytef
*)code
, zlen
);
109 panic("Could not uncompress code: %s\n", zError(ret
));
110 assert(unzlen
== (uLongf
)len
);
112 return PyMarshal_ReadObjectFromString((char *)marshalled
, len
);
116 EmbeddedPython::addModule() const
118 PyObject
*code
= getCode();
119 PyObject
*result
= PyObject_CallMethod(importerModule
, PyCC("add_module"),
120 PyCC("sssO"), filename
, abspath
, modpath
, code
);
131 * Load and initialize all of the python parts of M5.
134 EmbeddedPython::initAll()
136 // Load the importer module
137 PyObject
*code
= importer
->getCode();
138 importerModule
= PyImport_ExecCodeModule(PyCC("importer"), code
);
139 if (!importerModule
) {
144 // Load the rest of the embedded python files into the embedded
146 list
<EmbeddedPython
*>::iterator i
= getList().begin();
147 list
<EmbeddedPython
*>::iterator end
= getList().end();
148 for (; i
!= end
; ++i
)
149 if (!(*i
)->addModule())
155 EmbeddedPyBind::EmbeddedPyBind(const char *_name
,
156 void (*init_func
)(py::module
&),
158 : initFunc(init_func
), registered(false), name(_name
), base(_base
)
160 getMap()[_name
] = this;
163 EmbeddedPyBind::EmbeddedPyBind(const char *_name
,
164 void (*init_func
)(py::module
&))
165 : initFunc(init_func
), registered(false), name(_name
), base("")
167 getMap()[_name
] = this;
171 EmbeddedPyBind::init(py::module
&m
)
177 cprintf("Warning: %s already registered.\n", name
);
182 EmbeddedPyBind::depsReady() const
184 return base
.empty() || getMap()[base
]->registered
;
187 std::map
<std::string
, EmbeddedPyBind
*> &
188 EmbeddedPyBind::getMap()
190 static std::map
<std::string
, EmbeddedPyBind
*> objs
;
194 #if PY_MAJOR_VERSION >= 3
199 EmbeddedPyBind::initAll()
201 std::list
<EmbeddedPyBind
*> pending
;
203 py::module m_m5
= py::module("_m5");
204 m_m5
.attr("__package__") = py::cast("_m5");
206 pybind_init_core(m_m5
);
207 pybind_init_debug(m_m5
);
209 pybind_init_event(m_m5
);
210 pybind_init_pyobject(m_m5
);
211 pybind_init_stats(m_m5
);
213 for (auto &kv
: getMap()) {
214 auto &obj
= kv
.second
;
215 if (obj
->base
.empty()) {
218 pending
.push_back(obj
);
222 while (!pending
.empty()) {
223 for (auto it
= pending
.begin(); it
!= pending
.end(); ) {
224 EmbeddedPyBind
&obj
= **it
;
225 if (obj
.depsReady()) {
227 it
= pending
.erase(it
);
234 #if PY_MAJOR_VERSION >= 3
240 registerNativeModules()
242 auto result
= PyImport_AppendInittab("_m5", EmbeddedPyBind::initAll
);
244 panic("Failed to add _m5 to Python's inittab\n");
248 * Make the commands array weak so that they can be overridden (used
249 * by unit tests to specify a different python main function.
251 const char * __attribute__((weak
)) m5MainCommands
[] = {
254 0 // sentinel is required
258 * Start up the M5 simulator. This mostly vectors into the python
262 m5Main(int argc
, char **_argv
)
265 // Verify that the version of the protobuf library that we linked
266 // against is compatible with the version of the headers we
268 GOOGLE_PROTOBUF_VERIFY_VERSION
;
272 #if PY_MAJOR_VERSION >= 3
273 typedef std::unique_ptr
<wchar_t[], decltype(&PyMem_RawFree
)> WArgUPtr
;
274 std::vector
<WArgUPtr
> v_argv
;
275 std::vector
<wchar_t *> vp_argv
;
276 v_argv
.reserve(argc
);
277 vp_argv
.reserve(argc
);
278 for (int i
= 0; i
< argc
; i
++) {
279 v_argv
.emplace_back(Py_DecodeLocale(_argv
[i
], NULL
), &PyMem_RawFree
);
280 vp_argv
.emplace_back(v_argv
.back().get());
283 wchar_t **argv
= vp_argv
.data();
288 PySys_SetArgv(argc
, argv
);
290 // We have to set things up in the special __main__ module
291 PyObject
*module
= PyImport_AddModule(PyCC("__main__"));
293 panic("Could not import __main__");
294 PyObject
*dict
= PyModule_GetDict(module
);
296 // import the main m5 module
298 const char **command
= m5MainCommands
;
300 // evaluate each command in the m5MainCommands array (basically a
301 // bunch of python statements.
303 result
= PyRun_String(*command
, Py_file_input
, dict
, dict
);
314 google::protobuf::ShutdownProtobufLibrary();