ETISS 0.8.0
Extendable Translating Instruction Set Simulator (version 0.8.0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ETISSPython.cpp
Go to the documentation of this file.
1/*
2
3 @copyright
4
5 <pre>
6
7 Copyright 2018 Infineon Technologies AG
8
9 This file is part of ETISS tool, see <https://github.com/tum-ei-eda/etiss>.
10
11 The initial version of this software has been created with the funding support by the German Federal
12 Ministry of Education and Research (BMBF) in the project EffektiV under grant 01IS13022.
13
14 Redistribution and use in source and binary forms, with or without modification, are permitted
15 provided that the following conditions are met:
16
17 1. Redistributions of source code must retain the above copyright notice, this list of conditions and
18 the following disclaimer.
19
20 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
21 and the following disclaimer in the documentation and/or other materials provided with the distribution.
22
23 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse
24 or promote products derived from this software without specific prior written permission.
25
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
27 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
28 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
29 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 POSSIBILITY OF SUCH DAMAGE.
34
35 </pre>
36
37 @author Chair of Electronic Design Automation, TUM
38
39 @version 0.1
40
41*/
42
43#include "etiss/config.h"
44
45#if ETISS_USE_PYTHON
46#include <Python.h> // include before anyting else
47#endif
48
49#include "etiss/ETISS.h"
50
51#if ETISS_USE_PYTHON
53// move to ETISS.h ? ETISSPython.h?
54
55template <typename T>
56PyObject *convert(const T &t)
57{
58 PyErr_SetString(PyExc_NotImplementedError, "failed to convert C++ object to PyObject");
59 return nullptr;
60}
61template <>
62PyObject *convert<std::string>(const std::string &s);
63template <>
64PyObject *convert<etiss::int32>(const etiss::int32 &s);
65
66template <typename T>
67T convert(PyObject *, bool &ok)
68{
69 ok = false;
70 return T();
71}
72
73template <typename T1, typename T2, typename T3>
74PyObject *convert(const std::tuple<T1, T2, T3> &a234)
75{
76 PyObject *list = PyList_New(0);
77 PyObject *o = convert(std::get<0>(a234));
78 if (o == 0)
79 {
80 Py_DecRef(list);
81 return 0;
82 }
83 PyList_Append(list, o);
84 Py_DecRef(o);
85 o = convert(std::get<1>(a234));
86 if (o == 0)
87 {
88 Py_DecRef(list);
89 return 0;
90 }
91 PyList_Append(list, o);
92 Py_DecRef(o);
93 o = convert(std::get<2>(a234));
94 if (o == 0)
95 {
96 Py_DecRef(list);
97 return 0;
98 }
99 PyList_Append(list, o);
100 Py_DecRef(o);
101 return list;
102}
103
104template <typename T>
105PyObject *convert(const std::set<T> &set)
106{
107 PyObject *list = PyList_New(0);
108 for (auto iter = set.begin(); iter != set.end(); iter++)
109 {
110 PyObject *e = convert(*iter);
111 if (e == 0)
112 {
113 Py_DecRef(list);
114 return 0;
115 }
116 else
117 {
118 if (PyList_Append(list, convert(*iter)) != 0)
119 {
120 Py_DecRef(e);
121 Py_DecRef(list);
122 return 0;
123 }
124 Py_DecRef(e);
125 }
126 }
127 return list;
128}
129template <typename T>
130PyObject *convert(const std::list<T> &set)
131{
132 PyObject *list = PyList_New(0);
133 for (auto iter = set.begin(); iter != set.end(); iter++)
134 {
135 PyObject *e = convert(*iter);
136 if (e == 0)
137 {
138 Py_DecRef(list);
139 return 0;
140 }
141 else
142 {
143 if (PyList_Append(list, convert(*iter)) != 0)
144 {
145 Py_DecRef(e);
146 Py_DecRef(list);
147 return 0;
148 }
149 Py_DecRef(e);
150 }
151 }
152 return list;
153}
154template <typename K, typename V>
155PyObject *convert(const std::map<K, V> &set)
156{
157 PyObject *dict = PyDict_New();
158 for (auto iter = set.begin(); iter != set.end(); iter++)
159 {
160 PyObject *k = convert(iter->first);
161 if (k == 0)
162 {
163 Py_DecRef(dict);
164 return 0;
165 }
166 else
167 {
168 PyObject *v = convert(iter->second);
169 if (v == 0)
170 {
171 Py_DecRef(k);
172 Py_DecRef(dict);
173 return 0;
174 }
175 else
176 {
177 if (PyDict_SetItem(dict, k, v) != 0)
178 {
179 Py_DecRef(k);
180 Py_DecRef(v);
181 Py_DecRef(dict);
182 return 0;
183 }
184 Py_DecRef(k);
185 Py_DecRef(v);
186 }
187 }
188 }
189 return dict;
190}
191
193
195// PYTHON
196
198// conversion
199
200template <>
201PyObject *convert<std::string>(const std::string &s)
202{
203 return PyString_FromString(s.c_str());
204}
205template <>
206PyObject *convert<etiss::int32>(const etiss::int32 &s)
207{
208 return PyInt_FromSsize_t(s);
209}
210
211template <>
212std::string convert<std::string>(PyObject *o, bool &ok)
213{
214 char *str = PyString_AsString(o);
215 if (str != nullptr)
216 {
217 return std::string(str);
218 }
219 else
220 {
221 ok = false;
222 return "";
223 }
224}
225
226// /conversion
228
230// helper functions
231template <std::set<std::string> (*list)()>
232static PyObject *pyetiss_listX(PyObject *self, PyObject *args)
233{
234 return convert(list());
235}
236template <std::list<std::string> (*list)()>
237static PyObject *pyetiss_listX(PyObject *self, PyObject *args)
238{
239 return convert(list());
240}
241
242static PyObject *pyetiss_loadLibrary(PyObject *self, PyObject *args)
243{
244 const char *name;
245 const char *path;
246
247 if (!PyArg_ParseTuple(args, "ss", &name, &path))
248 {
249 Py_IncRef(Py_False);
250 return Py_False;
251 }
252
253 if (etiss::loadLibrary(std::string(name), std::string(path)))
254 {
255 Py_IncRef(Py_True);
256 return Py_True;
257 }
258 else
259 {
260 Py_IncRef(Py_False);
261 return Py_False;
262 }
263}
264
265static PyObject *pyetiss_cfg_get(PyObject *self, PyObject *args)
266{
267 const char *name;
268 const char *def;
269
270 if (!PyArg_ParseTuple(args, "ss", &name, &def))
271 return nullptr;
272 return convert(etiss::cfg().get<std::string>(std::string(name), std::string(def)));
273}
274static PyObject *pyetiss_cfg_set(PyObject *self, PyObject *args)
275{
276 const char *name;
277 const char *def;
278
279 if (!PyArg_ParseTuple(args, "ss", &name, &def))
280 return nullptr;
281 return convert(etiss::cfg().get<std::string>(std::string(name), std::string(def)));
282}
283static PyObject *pyetiss_cfg_all(PyObject *self, PyObject *args)
284{
285 return convert(etiss::cfg().config());
286}
287static PyObject *pyetiss_cfg_help(PyObject *self, PyObject *args)
288{
289 return convert(etiss::cfg().getAnnounced());
290}
291
292static PyObject *pyetiss_returnCodes(PyObject *self, PyObject *args)
293{
294 std::map<etiss::int32, const char *> m = etiss::RETURNCODE::getErrorMessages();
295 std::map<etiss::int32, std::string> ret;
296 for (auto iter = m.begin(); iter != m.end(); iter++)
297 {
298 ret[iter->first] = std::string(etiss::RETURNCODE::getErrorNames()[iter->first]) + ": " + iter->second;
299 }
300 return convert(ret);
301}
302
303// /helper functions
305
306// function register table
307static PyMethodDef ETISSMethods[] = {
308
309 { "listCPUArchs", pyetiss_listX<etiss::listCPUArchs>, METH_VARARGS, "List available cpu architectures." },
310 { "listJITs", pyetiss_listX<etiss::listJITs>, METH_VARARGS, "List compilers." },
311 { "listPlugins", pyetiss_listX<etiss::listPlugins>, METH_VARARGS, "List plugins." },
312 { "listCPUs", pyetiss_listX<etiss::CPUCore::list>, METH_VARARGS, "List plugins." },
313 { "listLibraries", pyetiss_listX<etiss::listLibraries>, METH_VARARGS, "List loaded libraries." },
314 { "loadLibrary", pyetiss_loadLibrary, METH_VARARGS, "Try to open a shared library." },
315 { "cfgGet", pyetiss_cfg_get, METH_VARARGS, "Get the string value of an option" },
316 { "cfgSet", pyetiss_cfg_set, METH_VARARGS, "Set the string value of an option" },
317 { "cfg", pyetiss_cfg_all, METH_VARARGS, "Get all options in a list" },
318 { "cfgHelp", pyetiss_cfg_help, METH_VARARGS, "Get all announced option info in a dictionary" },
319 { "RETURNCODES", pyetiss_returnCodes, METH_VARARGS, "Get global return codes" },
320 { NULL, NULL, 0, NULL } /* Sentinel */
321};
322
323// /function register table
325
326// initialization
327
328extern "C"
329{
333 void initETISS()
334 {
335 static bool done = false;
336 if (done)
337 return;
338 done = true;
339 Py_InitModule3("etiss", ETISSMethods, "ETISS python bindings");
340 }
341}
342
343// /PYTHON
345
346PyThreadState *etiss_main_pyThreadState = 0;
347
348namespace etiss
349{
350namespace py
351{
352
353bool supported()
354{
355 return true;
356}
357
358void run(std::function<void(void)> func)
359{
360 PyGILState_STATE gstate = PyGILState_Ensure();
361 func();
362 PyGILState_Release(gstate);
363}
364
365void runEXT(std::function<void(void)> func)
366{
367 Py_BEGIN_ALLOW_THREADS func();
368 Py_END_ALLOW_THREADS
369}
370
371void runString(const char *s)
372{
373 run([&s]() { PyRun_SimpleString(s); });
374}
375
376void console()
377{
378 initETISS();
379 runString("print('ETISS functions are provided the the module \\'etiss\\'.')");
380 runString("import code;\ncode.interact(\"ETISS Python Console\")");
381}
382
383void init()
384{
385
386 if (etiss::cfg().get<bool>("pyinitialize", true))
387 {
388 Py_Initialize();
389 if (etiss::cfg().get<bool>("pyinittheads", true))
390 {
391 if (PyEval_ThreadsInitialized() == 0)
392 {
393 PyEval_InitThreads(); // init gil
394 PyEval_ReleaseLock(); // release gil
395 etiss::log(etiss::VERBOSE, "PyEval_InitThreads() called.");
396 }
397 }
398 etiss::log(etiss::VERBOSE, "Py_Initialize() called.");
399 }
400
401 run([]() {
402 PyEval_AcquireLock(); // lock gil
404 PyRun_SimpleString("print('ETISS: INFO: ETISS has been build with python support.')\n");
405 // Py_InitModule3("etiss", ETISSMethods,"ETISS python bindings");
406 PyEval_ReleaseLock(); // release gil
407 });
408}
409
410void shutdown()
411{
412 if (etiss::cfg().get<bool>("pyfinalize", true))
413 {
414 Py_Finalize();
415 etiss::log(etiss::VERBOSE, "Py_Finalize() called");
416 }
417}
418
419std::string evalForString(const char *stmt, bool *ok = nullptr)
420{
421 if (ok != 0)
422 *ok = false;
423 PyObject *result = 0;
424 run([stmt, &result]() {
425 PyObject *main = PyImport_AddModule("__main__");
426 if (main == 0)
427 {
428 return;
429 }
430 PyObject *globalDictionary = PyModule_GetDict(main);
431 if (globalDictionary == 0)
432 {
433 return;
434 }
435 PyObject *localDictionary = PyDict_New();
436 if (localDictionary == 0)
437 {
438 return;
439 }
440 result = PyRun_String(stmt, Py_file_input, globalDictionary, localDictionary);
441 });
442 if (result == 0)
443 return "";
444 bool lok = false;
445 std::string ret = convert<std::string>(result, ok ? *ok : lok);
446 Py_DecRef(result);
447 return ret;
448}
449
450} // namespace py
451} // namespace etiss
452
453#else
454// ETISS_USE_PYTHON == 0
455
456namespace etiss
457{
458namespace py
459{
460
461void init() {}
462
463void shutdown() {}
464
465void console() {}
466
468{
469 return false;
470}
471
472void runString(std::string s) {}
473
474void run(std::function<void(void)> func) {}
475
476std::string evalForString(const char *stmt, bool *ok = nullptr)
477{
478 if (ok)
479 *ok = false;
480 return "";
481}
482
483} // namespace py
484} // namespace etiss
485
486#endif
Header file of the ETISS library.
__device__ __2f16 float bool s
do v
Definition arm_acle.h:76
contains defines to configure ETISS.
bool loadLibrary(std::string path, std::string name)
Load a library.
Definition ETISS.cpp:288
int main(int argc, const char *argv[])
Definition main.cpp:47
void console()
bool supported()
std::string evalForString(const char *stmt, bool *ok=nullptr)
void runString(std::string s)
void run(std::function< void(void)> func)
void shutdown()
void runEXT(std::function< void(void)> func)
Page Table Entry (PTE) defines the composition of Page Frame Number (PFN) and relavant flags.
Definition Benchmark.h:53
@ INFO
Definition Misc.h:129
@ VERBOSE
Definition Misc.h:130
Configuration & cfg()
Definition Misc.cpp:577
Verbosity & verbosity()
Get log level reference.
Definition Misc.cpp:120
void log(Verbosity level, std::string msg)
write log message at the given level.
Definition Misc.cpp:125
#define NULL