aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorZipCPU <dgisselq@ieee.org>2018-06-06 07:55:18 -0400
committerZipCPU <dgisselq@ieee.org>2018-06-06 07:55:18 -0400
commitd0ee08aeb12a8fb7237b31083666d9b165f13f69 (patch)
treee09d84b0389462f2c1959ce59438d88a7b5f9ed2 /common
parent2e6d0b752ab2d269f822bfd3ea029b100ecf4233 (diff)
parentd3f19cc27ea4634a64821688e9adec6046f4d7de (diff)
downloadnextpnr-d0ee08aeb12a8fb7237b31083666d9b165f13f69.tar.gz
nextpnr-d0ee08aeb12a8fb7237b31083666d9b165f13f69.tar.bz2
nextpnr-d0ee08aeb12a8fb7237b31083666d9b165f13f69.zip
Merge branch 'master' into gqtech
Diffstat (limited to 'common')
-rw-r--r--common/handle_error.cc56
-rw-r--r--common/pybindings.cc42
-rw-r--r--common/pybindings.h3
-rw-r--r--common/version.h.in6
4 files changed, 107 insertions, 0 deletions
diff --git a/common/handle_error.cc b/common/handle_error.cc
new file mode 100644
index 00000000..a06b5348
--- /dev/null
+++ b/common/handle_error.cc
@@ -0,0 +1,56 @@
+#include <boost/python.hpp>
+#include <Python.h>
+
+namespace py = boost::python;
+
+// Parses the value of the active python exception
+// NOTE SHOULD NOT BE CALLED IF NO EXCEPTION
+std::string parse_python_exception(){
+ PyObject *type_ptr = NULL, *value_ptr = NULL, *traceback_ptr = NULL;
+ // Fetch the exception info from the Python C API
+ PyErr_Fetch(&type_ptr, &value_ptr, &traceback_ptr);
+
+ // Fallback error
+ std::string ret("Unfetchable Python error");
+ // If the fetch got a type pointer, parse the type into the exception string
+ if(type_ptr != NULL){
+ py::handle<> h_type(type_ptr);
+ py::str type_pstr(h_type);
+ // Extract the string from the boost::python object
+ py::extract<std::string> e_type_pstr(type_pstr);
+ // If a valid string extraction is available, use it
+ // otherwise use fallback
+ if(e_type_pstr.check())
+ ret = e_type_pstr();
+ else
+ ret = "Unknown exception type";
+ }
+ // Do the same for the exception value (the stringification of the exception)
+ if(value_ptr != NULL){
+ py::handle<> h_val(value_ptr);
+ py::str a(h_val);
+ py::extract<std::string> returned(a);
+ if(returned.check())
+ ret += ": " + returned();
+ else
+ ret += std::string(": Unparseable Python error: ");
+ }
+ // Parse lines from the traceback using the Python traceback module
+ if(traceback_ptr != NULL){
+ py::handle<> h_tb(traceback_ptr);
+ // Load the traceback module and the format_tb function
+ py::object tb(py::import("traceback"));
+ py::object fmt_tb(tb.attr("format_tb"));
+ // Call format_tb to get a list of traceback strings
+ py::object tb_list(fmt_tb(h_tb));
+ // Join the traceback strings into a single string
+ py::object tb_str(py::str("\n").join(tb_list));
+ // Extract the string, check the extraction, and fallback in necessary
+ py::extract<std::string> returned(tb_str);
+ if(returned.check())
+ ret += ": " + returned();
+ else
+ ret += std::string(": Unparseable Python traceback");
+ }
+ return ret;
+}
diff --git a/common/pybindings.cc b/common/pybindings.cc
index 8bae4e51..4986c549 100644
--- a/common/pybindings.cc
+++ b/common/pybindings.cc
@@ -18,6 +18,7 @@
*
*/
+
#include "design.h"
#include "chip.h"
#include "pybindings.h"
@@ -26,6 +27,9 @@
#define PASTER(x, y) x ## _ ## y
#define EVALUATOR(x, y) PASTER(x,y)
#define MODULE_NAME EVALUATOR(nextpnrpy, ARCHNAME)
+#define PYINIT_MODULE_NAME EVALUATOR(&PyInit_nextpnrpy, ARCHNAME)
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY(x)
// Architecture-specific bindings should be created in the below function, which must be implemented in all
// architectures
@@ -39,3 +43,41 @@ BOOST_PYTHON_MODULE (MODULE_NAME) {
arch_wrap_python();
}
+
+void arch_appendinittab()
+{
+ PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME);
+}
+
+void execute_python_file(const char *executable, const char* python_file)
+{
+ wchar_t *program = Py_DecodeLocale(executable, NULL);
+ if (program == NULL) {
+ fprintf(stderr, "Fatal error: cannot decode executable filename\n");
+ exit(1);
+ }
+ try
+ {
+ PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME);
+ Py_SetProgramName(program);
+ Py_Initialize();
+
+ FILE* fp = fopen(python_file, "r");
+ if (fp == NULL) {
+ fprintf(stderr, "Fatal error: file not found %s\n",python_file);
+ exit(1);
+ }
+ PyRun_SimpleFile(fp , python_file);
+ fclose(fp);
+
+ Py_Finalize();
+ PyMem_RawFree(program);
+ }
+ catch(boost::python::error_already_set const &)
+ {
+ // Parse and output the exception
+ std::string perror_str = parse_python_exception();
+ std::cout << "Error in Python: " << perror_str << std::endl;
+ }
+}
+
diff --git a/common/pybindings.h b/common/pybindings.h
index eab2039d..f594784c 100644
--- a/common/pybindings.h
+++ b/common/pybindings.h
@@ -79,5 +79,8 @@ struct range_wrapper {
#define WRAP_RANGE(t) range_wrapper<t##Range>().wrap(#t "Range", #t "Iterator")
+void execute_python_file(const char *executable, const char* python_file);
+std::string parse_python_exception();
+void arch_appendinittab();
#endif /* end of include guard: COMMON_PYBINDINGS_HH */
diff --git a/common/version.h.in b/common/version.h.in
new file mode 100644
index 00000000..8072116b
--- /dev/null
+++ b/common/version.h.in
@@ -0,0 +1,6 @@
+#ifndef VERSION_H
+#define VERSION_H
+
+#define GIT_COMMIT_HASH_STR "@GIT_COMMIT_HASH@"
+
+#endif \ No newline at end of file