ETISS 0.8.0
Extendable Translating Instruction Set Simulator (version 0.8.0)
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 
55 template <typename T>
56 PyObject *convert(const T &t)
57 {
58  PyErr_SetString(PyExc_NotImplementedError, "failed to convert C++ object to PyObject");
59  return nullptr;
60 }
61 template <>
62 PyObject *convert<std::string>(const std::string &s);
63 template <>
64 PyObject *convert<etiss::int32>(const etiss::int32 &s);
65 
66 template <typename T>
67 T convert(PyObject *, bool &ok)
68 {
69  ok = false;
70  return T();
71 }
72 
73 template <typename T1, typename T2, typename T3>
74 PyObject *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 
104 template <typename T>
105 PyObject *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 }
129 template <typename T>
130 PyObject *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 }
154 template <typename K, typename V>
155 PyObject *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 
200 template <>
201 PyObject *convert<std::string>(const std::string &s)
202 {
203  return PyString_FromString(s.c_str());
204 }
205 template <>
206 PyObject *convert<etiss::int32>(const etiss::int32 &s)
207 {
208  return PyInt_FromSsize_t(s);
209 }
210 
211 template <>
212 std::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
231 template <std::set<std::string> (*list)()>
232 static PyObject *pyetiss_listX(PyObject *self, PyObject *args)
233 {
234  return convert(list());
235 }
236 template <std::list<std::string> (*list)()>
237 static PyObject *pyetiss_listX(PyObject *self, PyObject *args)
238 {
239  return convert(list());
240 }
241 
242 static 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 
265 static 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 }
274 static 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 }
283 static PyObject *pyetiss_cfg_all(PyObject *self, PyObject *args)
284 {
285  return convert(etiss::cfg().config());
286 }
287 static PyObject *pyetiss_cfg_help(PyObject *self, PyObject *args)
288 {
289  return convert(etiss::cfg().getAnnounced());
290 }
291 
292 static 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
307 static 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 
328 extern "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 
346 PyThreadState *etiss_main_pyThreadState = 0;
347 
348 namespace etiss
349 {
350 namespace py
351 {
352 
353 bool supported()
354 {
355  return true;
356 }
357 
358 void run(std::function<void(void)> func)
359 {
360  PyGILState_STATE gstate = PyGILState_Ensure();
361  func();
362  PyGILState_Release(gstate);
363 }
364 
365 void runEXT(std::function<void(void)> func)
366 {
367  Py_BEGIN_ALLOW_THREADS func();
368  Py_END_ALLOW_THREADS
369 }
370 
371 void runString(const char *s)
372 {
373  run([&s]() { PyRun_SimpleString(s); });
374 }
375 
376 void 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 
383 void 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
403  if (etiss::verbosity() >= etiss::INFO)
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 
410 void 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 
419 std::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 
456 namespace etiss
457 {
458 namespace py
459 {
460 
461 void init() {}
462 
463 void shutdown() {}
464 
465 void console() {}
466 
467 bool supported()
468 {
469  return false;
470 }
471 
472 void runString(std::string s) {}
473 
474 void run(std::function<void(void)> func) {}
475 
476 std::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
etiss_int32 int32
Definition: 386-GCC.h:81
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:48
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 init()
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(const std::string &cfgName)
Get reference of the global ETISS configuration object.
Definition: Misc.cpp:560
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