From 3a6e400f4478161c72bbabb1bcbc71ece7318877 Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 6 Jun 2018 21:14:42 +0200 Subject: rulecheck.cc: Add missing return Signed-off-by: David Shah --- common/rulecheck.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'common') diff --git a/common/rulecheck.cc b/common/rulecheck.cc index b81695b9..28d4b6b7 100644 --- a/common/rulecheck.cc +++ b/common/rulecheck.cc @@ -57,5 +57,6 @@ bool check_all_nets_driven(Design *design) { } if (debug) log_info(" Verified!\n"); + return true; } -- cgit v1.2.3 From bdd93135823ae1ef293d4be3eb50d0ca6bdeee9e Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 7 Jun 2018 08:56:54 +0200 Subject: Allow loading and running Python files before GUI starts Signed-off-by: David Shah --- common/pybindings.cc | 74 +++++++++++++++++++++++++++++----------------------- common/pybindings.h | 6 +++-- 2 files changed, 46 insertions(+), 34 deletions(-) (limited to 'common') diff --git a/common/pybindings.cc b/common/pybindings.cc index 556e838e..7a542dc1 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -22,6 +22,7 @@ #include "design.h" #include "chip.h" #include "pybindings.h" +#include "emb.h" // Required to determine concatenated module name (which differs for different archs) #define PASTER(x, y) x ## _ ## y @@ -36,43 +37,52 @@ void arch_wrap_python(); BOOST_PYTHON_MODULE (MODULE_NAME) { - arch_wrap_python(); + arch_wrap_python(); } -void arch_appendinittab() -{ - PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME); +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(); +static wchar_t *program; - 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); +void init_python(const char *executable) { + 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); + emb::append_inittab(); + Py_SetProgramName(program); + Py_Initialize(); + } 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; + } +} + +void deinit_python() { + Py_Finalize(); + PyMem_RawFree(program); +} - 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; - } +void execute_python_file(const char *python_file) { + try { + 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); + } + 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 f594784c..84280908 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -26,7 +26,6 @@ #include #include #include - using namespace boost::python; /* A wrapper for a Pythonised nextpnr Iterator. The actual class wrapped is a @@ -79,7 +78,10 @@ struct range_wrapper { #define WRAP_RANGE(t) range_wrapper().wrap(#t "Range", #t "Iterator") -void execute_python_file(const char *executable, const char* python_file); +void init_python(const char *executable); +void deinit_python(); + +void execute_python_file(const char* python_file); std::string parse_python_exception(); void arch_appendinittab(); -- cgit v1.2.3 From 3769b2058019ce7c6be824085e1047e1beec07dc Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 7 Jun 2018 09:47:00 +0200 Subject: Adding Python to/from string wrappers for internal IDs --- common/pybindings.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'common') diff --git a/common/pybindings.h b/common/pybindings.h index 84280908..5b2adc6a 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -76,6 +76,54 @@ struct range_wrapper { } }; +/* +A wrapper to enable custom type/ID to/from string conversions + */ +template struct string_wrapper { + template + struct from_pystring_converter { + from_pystring_converter() { + converter::registry::push_back( + &convertible, + &construct, + boost::python::type_id()); + }; + + static void* convertible(PyObject* object) { + return PyUnicode_Check(object) ? object : 0; + } + + static void construct( + PyObject* object, + converter::rvalue_from_python_stage1_data* data) { + const wchar_t* value = PyUnicode_AsUnicode(object); + const std::wstring value_ws(value); + if (value == 0) throw_error_already_set(); + void* storage = ( + (boost::python::converter::rvalue_from_python_storage*) + data)->storage.bytes; + new (storage) T(fn(std::string(value_ws.begin(), value_ws.end()))); + data->convertible = storage; + } + + static F fn; + }; + + template struct to_str_wrapper { + static F fn; + std::string str(T& x) { + return fn(x); + } + }; + + template static void wrap(const char *type_name, F1 to_str_fn, F2 from_str_fn) { + from_pystring_converter::fn = from_str_fn; + from_pystring_converter(); + to_str_wrapper::fn = to_str_fn; + class_(type_name, no_init).def("__str__", to_str_wrapper::str); + }; +}; + #define WRAP_RANGE(t) range_wrapper().wrap(#t "Range", #t "Iterator") void init_python(const char *executable); -- cgit v1.2.3 From e576f71838290ff12b98145fb02af84563fc03c1 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 7 Jun 2018 11:41:54 +0200 Subject: Developing Python bindings for Design and related types --- common/pybindings.cc | 47 ++++++++++++++++++ common/pybindings.h | 52 ++------------------ common/pycontainers.h | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+), 49 deletions(-) create mode 100644 common/pycontainers.h (limited to 'common') diff --git a/common/pybindings.cc b/common/pybindings.cc index 7a542dc1..04b2fa27 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -36,7 +36,54 @@ // architectures void arch_wrap_python(); +bool operator==(const PortRef &a, const PortRef &b) { + return (a.cell == b.cell) && (a.port == b.port); +} + BOOST_PYTHON_MODULE (MODULE_NAME) { + class_("GraphicElement") + .def_readwrite("style", &GraphicElement::style) + .def_readwrite("type", &GraphicElement::type) + .def_readwrite("x1", &GraphicElement::x1) + .def_readwrite("y1", &GraphicElement::y1) + .def_readwrite("x2", &GraphicElement::x2) + .def_readwrite("y2", &GraphicElement::y2) + .def_readwrite("text", &GraphicElement::text); + + class_("PortRef") + .def_readwrite("cell", &PortRef::cell) + .def_readwrite("port", &PortRef::port); + + class_("NetInfo") + .def_readwrite("name", &NetInfo::name) + .def_readwrite("driver", &NetInfo::driver) + .def_readwrite("users", &NetInfo::users) + .def_readwrite("attrs", &NetInfo::attrs) + .def_readwrite("wires", &NetInfo::wires); + + WRAP_MAP(decltype(NetInfo::attrs), "IdStrMap"); + + class_>("PortRefVector") + .def(vector_indexing_suite>()); + + class_("PortInfo") + .def_readwrite("name", &PortInfo::name) + .def_readwrite("net", &PortInfo::net) + .def_readwrite("type", &PortInfo::type); + + class_("CellInfo") + .def_readwrite("name", &CellInfo::name) + .def_readwrite("type", &CellInfo::type) + .def_readwrite("ports", &CellInfo::ports) + .def_readwrite("attrs", &CellInfo::attrs) + .def_readwrite("params", &CellInfo::params) + .def_readwrite("bel", &CellInfo::bel) + .def_readwrite("pins", &CellInfo::pins); + + class_("Design", no_init) + .def_readwrite("chip", &Design::chip) + .def_readwrite("nets", &Design::nets) + .def_readwrite("cells", &Design::cells); arch_wrap_python(); } diff --git a/common/pybindings.h b/common/pybindings.h index 5b2adc6a..3dfadeee 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -20,6 +20,9 @@ #ifndef COMMON_PYBINDINGS_H #define COMMON_PYBINDINGS_H + +#include "pycontainers.h" + #include #include #include @@ -27,54 +30,6 @@ #include #include using namespace boost::python; -/* -A wrapper for a Pythonised nextpnr Iterator. The actual class wrapped is a -pair containing (current, end) -*/ - -template -struct iterator_wrapper { - typedef decltype(*(std::declval())) value_t; - - static value_t next(std::pair &iter) { - if (iter.first != iter.second) { - value_t val = *iter.first; - ++iter.first; - return val; - } else { - PyErr_SetString(PyExc_StopIteration, "End of range reached"); - boost::python::throw_error_already_set(); - // Should be unreachable, but prevent control may reach end of non-void - throw std::runtime_error("unreachable"); - } - } - - static void wrap(const char *python_name) { - class_>(python_name, no_init) - .def("__next__", next); - } -}; - -/* -A wrapper for a nextpnr Range. Ranges should have two functions, begin() -and end() which return iterator-like objects supporting ++, * and != -Full STL iterator semantics are not required, unlike the standard Boost wrappers -*/ - -template -struct range_wrapper { - typedef decltype(std::declval().begin()) iterator_t; - - static std::pair iter(T &range) { - return std::make_pair(range.begin(), range.end()); - } - - static void wrap(const char *range_name, const char *iter_name) { - class_(range_name, no_init) - .def("__iter__", iter); - iterator_wrapper().wrap(iter_name); - } -}; /* A wrapper to enable custom type/ID to/from string conversions @@ -124,7 +79,6 @@ template struct string_wrapper { }; }; -#define WRAP_RANGE(t) range_wrapper().wrap(#t "Range", #t "Iterator") void init_python(const char *executable); void deinit_python(); diff --git a/common/pycontainers.h b/common/pycontainers.h new file mode 100644 index 00000000..64fb265b --- /dev/null +++ b/common/pycontainers.h @@ -0,0 +1,129 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Clifford Wolf + * Copyright (C) 2018 David Shah + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef COMMON_PYCONTAINERS_H +#define COMMON_PYCONTAINERS_H + +#include +#include +#include +#include +#include +#include +#include + +using namespace boost::python; + +/* +A wrapper for a Pythonised nextpnr Iterator. The actual class wrapped is a +pair containing (current, end) +*/ + +template +struct iterator_wrapper { + typedef decltype(*(std::declval())) value_t; + + static value_t next(std::pair &iter) { + if (iter.first != iter.second) { + value_t val = *iter.first; + ++iter.first; + return val; + } else { + PyErr_SetString(PyExc_StopIteration, "End of range reached"); + boost::python::throw_error_already_set(); + // Should be unreachable, but prevent control may reach end of non-void + throw std::runtime_error("unreachable"); + } + } + + static void wrap(const char *python_name) { + class_ < std::pair < T, T >> (python_name, no_init) + .def("__next__", next, P()); + } +}; + +/* +A wrapper for a nextpnr Range. Ranges should have two functions, begin() +and end() which return iterator-like objects supporting ++, * and != +Full STL iterator semantics are not required, unlike the standard Boost wrappers +*/ + +template> +struct range_wrapper { + typedef decltype(std::declval().begin()) iterator_t; + + static std::pair iter(T &range) { + return std::make_pair(range.begin(), range.end()); + } + + static void wrap(const char *range_name, const char *iter_name) { + class_(range_name, no_init) + .def("__iter__", iter); + iterator_wrapper().wrap(iter_name); + } + typedef iterator_wrapper iter_wrap; +}; + +#define WRAP_RANGE(t) range_wrapper().wrap(#t "Range", #t "Iterator") + +/* +Wrapper for a map, either an unordered_map, regular map or dict + */ +inline void KeyError() { PyErr_SetString(PyExc_KeyError, "Key not found"); } + +template +struct map_wrapper { + typedef boost::remove_cv_t> K; + typedef typename T::mapped_type V; + typedef typename T::value_type KV; + + static V &get(T &x, K const &i) { + if (x.find(i) != x.end()) return x.at(i); + KeyError(); + std::terminate(); + } + + static void set(T &x, K const &i, V const &v) { + x[i] = v; + } + + static void del(T const &x, K const &i) { + if (x.find(i) != x.end()) x.erase(i); + else KeyError(); + std::terminate(); + } + + static void wrap(const char *map_name, const char *kv_name, const char *iter_name) { + class_(kv_name) + .def_readonly("first", &KV::first) + .def_readwrite("second", &KV::second); + typedef range_wrapper> rw; + typename rw::iter_wrap().wrap(iter_name); + class_(map_name, no_init) + .def("__iter__", rw::iter) + .def("__len__", &T::size) + .def("__getitem__", get, return_internal_reference<>()) + .def("__setitem__", set, with_custodian_and_ward<1,2>()); + } +}; + +#define WRAP_MAP(t, name) map_wrapper().wrap(#name, #name "KeyValue", #name "Iterator") + +#endif -- cgit v1.2.3 From a5249da02d2a55d4b838dd8c29e159513dd71418 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 7 Jun 2018 12:40:31 +0200 Subject: Working on global Python design object Signed-off-by: David Shah --- common/pybindings.cc | 10 +++++++++- common/pybindings.h | 53 +++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 49 insertions(+), 14 deletions(-) (limited to 'common') diff --git a/common/pybindings.cc b/common/pybindings.cc index 04b2fa27..4ae83cb0 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -80,10 +80,17 @@ BOOST_PYTHON_MODULE (MODULE_NAME) { .def_readwrite("bel", &CellInfo::bel) .def_readwrite("pins", &CellInfo::pins); - class_("Design", no_init) + WRAP_MAP(decltype(CellInfo::ports), "IdPortMap"); + //WRAP_MAP(decltype(CellInfo::pins), "IdIdMap"); + + class_("Design", no_init) .def_readwrite("chip", &Design::chip) .def_readwrite("nets", &Design::nets) .def_readwrite("cells", &Design::cells); + + WRAP_MAP(decltype(Design::nets), "IdNetMap"); + WRAP_MAP(decltype(Design::cells), "IdCellMap"); + arch_wrap_python(); } @@ -104,6 +111,7 @@ void init_python(const char *executable) { emb::append_inittab(); Py_SetProgramName(program); Py_Initialize(); + PyImport_ImportModule(TOSTRING(MODULE_NAME)); } catch (boost::python::error_already_set const &) { // Parse and output the exception std::string perror_str = parse_python_exception(); diff --git a/common/pybindings.h b/common/pybindings.h index 3dfadeee..44898198 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -29,12 +29,14 @@ #include #include #include +#include using namespace boost::python; /* A wrapper to enable custom type/ID to/from string conversions */ -template struct string_wrapper { +template +struct string_wrapper { template struct from_pystring_converter { from_pystring_converter() { @@ -44,34 +46,37 @@ template struct string_wrapper { boost::python::type_id()); }; - static void* convertible(PyObject* object) { + static void *convertible(PyObject *object) { return PyUnicode_Check(object) ? object : 0; } static void construct( - PyObject* object, - converter::rvalue_from_python_stage1_data* data) { - const wchar_t* value = PyUnicode_AsUnicode(object); + PyObject *object, + converter::rvalue_from_python_stage1_data *data) { + const wchar_t *value = PyUnicode_AsUnicode(object); const std::wstring value_ws(value); if (value == 0) throw_error_already_set(); - void* storage = ( - (boost::python::converter::rvalue_from_python_storage*) + void *storage = ( + (boost::python::converter::rvalue_from_python_storage *) data)->storage.bytes; - new (storage) T(fn(std::string(value_ws.begin(), value_ws.end()))); + new(storage) T(fn(std::string(value_ws.begin(), value_ws.end()))); data->convertible = storage; } - static F fn; + static F fn; }; - template struct to_str_wrapper { + template + struct to_str_wrapper { static F fn; - std::string str(T& x) { + + std::string str(T &x) { return fn(x); } }; - template static void wrap(const char *type_name, F1 to_str_fn, F2 from_str_fn) { + template + static void wrap(const char *type_name, F1 to_str_fn, F2 from_str_fn) { from_pystring_converter::fn = from_str_fn; from_pystring_converter(); to_str_wrapper::fn = to_str_fn; @@ -79,12 +84,34 @@ template struct string_wrapper { }; }; +std::string parse_python_exception(); + +template +void python_export_global(const char *name, Tn &x) { + PyObject * m, *d; + m = PyImport_AddModule("__main__"); + if (m == NULL) + return; + d = PyModule_GetDict(m); + try { + PyObject * p = object(boost::ref(x)).ptr(); + PyDict_SetItemString(d, name, p); + } 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; + std::terminate(); + } +}; void init_python(const char *executable); + void deinit_python(); -void execute_python_file(const char* python_file); +void execute_python_file(const char *python_file); + std::string parse_python_exception(); + void arch_appendinittab(); #endif /* end of include guard: COMMON_PYBINDINGS_HH */ -- cgit v1.2.3 From 2edde06c07cc3cd58ab156d9598d75e1cff1e7de Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 7 Jun 2018 12:48:53 +0200 Subject: Fix clang-format include order issues Signed-off-by: Clifford Wolf --- common/pybindings.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'common') diff --git a/common/pybindings.cc b/common/pybindings.cc index 7a542dc1..10c8fd44 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -21,9 +21,11 @@ #include "design.h" #include "chip.h" -#include "pybindings.h" #include "emb.h" +// include after design.h/chip.h +#include "pybindings.h" + // Required to determine concatenated module name (which differs for different archs) #define PASTER(x, y) x ## _ ## y #define EVALUATOR(x, y) PASTER(x,y) -- cgit v1.2.3 From 1ea8fa488127c63e119b07b05ec1c468e820db9c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 7 Jun 2018 12:56:49 +0200 Subject: clang-format for design and chip codebase Signed-off-by: Clifford Wolf --- common/design.cc | 1 - common/design.h | 119 ++++++++++++++++++++++++++++--------------------------- 2 files changed, 61 insertions(+), 59 deletions(-) (limited to 'common') diff --git a/common/design.cc b/common/design.cc index 7ba6a9b1..6ab122df 100644 --- a/common/design.cc +++ b/common/design.cc @@ -18,4 +18,3 @@ */ #include "design.h" - diff --git a/common/design.h b/common/design.h index 314c2fd7..f4c24f15 100644 --- a/common/design.h +++ b/common/design.h @@ -20,50 +20,52 @@ #ifndef DESIGN_H #define DESIGN_H -#include #include -#include +#include #include -#include #include +#include +#include // replace with proper IdString later typedef std::string IdString; // replace with haslib later -template using pool = std::unordered_set; -template using dict = std::unordered_map; +template using pool = std::unordered_set; +template using dict = std::unordered_map; using std::vector; struct GraphicElement { - // This will control colour, and there should be separate - // visibility controls in some cases also - enum { - // Wires entirely inside tiles, e.g. between switchbox and bels - G_LOCAL_WIRES, - // Standard inter-tile routing - G_GENERAL_WIRES, - // Special inter-tile wires, e.g. carry chains - G_DEDICATED_WIRES, - G_BEL_OUTLINE, - G_SWITCHBOX_OUTLINE, - G_TILE_OUTLINE, - G_BEL_PINS, - G_SWITCHBOX_PINS, - G_BEL_MISC, - G_TILE_MISC, - } style; - - enum { - G_LINE, - G_BOX, - G_CIRCLE, - G_LABEL - } type; - - float x1, y1, x2, y2, z; - std::string text; + // This will control colour, and there should be separate + // visibility controls in some cases also + enum + { + // Wires entirely inside tiles, e.g. between switchbox and bels + G_LOCAL_WIRES, + // Standard inter-tile routing + G_GENERAL_WIRES, + // Special inter-tile wires, e.g. carry chains + G_DEDICATED_WIRES, + G_BEL_OUTLINE, + G_SWITCHBOX_OUTLINE, + G_TILE_OUTLINE, + G_BEL_PINS, + G_SWITCHBOX_PINS, + G_BEL_MISC, + G_TILE_MISC, + } style; + + enum + { + G_LINE, + G_BOX, + G_CIRCLE, + G_LABEL + } type; + + float x1, y1, x2, y2, z; + std::string text; }; #include "chip.h" @@ -72,56 +74,57 @@ struct CellInfo; struct PortRef { - CellInfo *cell; - IdString port; + CellInfo *cell; + IdString port; }; struct NetInfo { - IdString name; - PortRef driver; - vector users; - dict attrs; + IdString name; + PortRef driver; + vector users; + dict attrs; - // wire -> (uphill_wire, delay) - dict> wires; + // wire -> (uphill_wire, delay) + dict> wires; }; enum PortType { - PORT_IN = 0, - PORT_OUT = 1, - PORT_INOUT = 2 + PORT_IN = 0, + PORT_OUT = 1, + PORT_INOUT = 2 }; struct PortInfo { - IdString name; - NetInfo *net; - PortType type; + IdString name; + NetInfo *net; + PortType type; }; struct CellInfo { - IdString name, type; - dict ports; - dict attrs, params; + IdString name, type; + dict ports; + dict attrs, params; - BelId bel; - // cell_port -> bel_pin - dict pins; + BelId bel; + // cell_port -> bel_pin + dict pins; }; struct Design { - struct Chip chip; + struct Chip chip; - Design(ChipArgs args) : chip(args) { - // ... - } + Design(ChipArgs args) : chip(args) + { + // ... + } - dict nets; - dict cells; + dict nets; + dict cells; }; #endif -- cgit v1.2.3 From b0e66d441cf584e7e48049d4f07afcc8e743309a Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 7 Jun 2018 12:57:52 +0200 Subject: Global design object working Signed-off-by: David Shah --- common/pybindings.cc | 6 ++++++ common/pybindings.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'common') diff --git a/common/pybindings.cc b/common/pybindings.cc index 4ae83cb0..a051eea6 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -66,6 +66,12 @@ BOOST_PYTHON_MODULE (MODULE_NAME) { class_>("PortRefVector") .def(vector_indexing_suite>()); + enum_("PortType") + .value("PORT_IN", PORT_IN) + .value("PORT_OUT", PORT_OUT) + .value("PORT_INOUT", PORT_INOUT) + .export_values(); + class_("PortInfo") .def_readwrite("name", &PortInfo::name) .def_readwrite("net", &PortInfo::net) diff --git a/common/pybindings.h b/common/pybindings.h index 44898198..a99ad51b 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -94,7 +94,7 @@ void python_export_global(const char *name, Tn &x) { return; d = PyModule_GetDict(m); try { - PyObject * p = object(boost::ref(x)).ptr(); + PyObject * p = incref(object(boost::ref(x)).ptr()); PyDict_SetItemString(d, name, p); } catch (boost::python::error_already_set const &) { // Parse and output the exception -- cgit v1.2.3 From c3e02527030c11f0177e3bf8d8c5d9a5c9925dc4 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 7 Jun 2018 13:10:53 +0200 Subject: Reformat Python bindings and ice40 main Signed-off-by: David Shah --- common/pybindings.cc | 214 ++++++++++++++++++++++++++------------------------- common/pybindings.h | 136 ++++++++++++++++---------------- 2 files changed, 177 insertions(+), 173 deletions(-) (limited to 'common') diff --git a/common/pybindings.cc b/common/pybindings.cc index c3818cad..5c86720e 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -18,134 +18,138 @@ * */ - -#include "design.h" #include "chip.h" +#include "design.h" #include "emb.h" // include after design.h/chip.h #include "pybindings.h" -// Required to determine concatenated module name (which differs for different archs) -#define PASTER(x, y) x ## _ ## y -#define EVALUATOR(x, y) PASTER(x,y) +// Required to determine concatenated module name (which differs for different +// archs) +#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 +// Architecture-specific bindings should be created in the below function, which +// must be implemented in all architectures void arch_wrap_python(); -bool operator==(const PortRef &a, const PortRef &b) { - return (a.cell == b.cell) && (a.port == b.port); +bool operator==(const PortRef &a, const PortRef &b) +{ + return (a.cell == b.cell) && (a.port == b.port); } -BOOST_PYTHON_MODULE (MODULE_NAME) { - class_("GraphicElement") - .def_readwrite("style", &GraphicElement::style) - .def_readwrite("type", &GraphicElement::type) - .def_readwrite("x1", &GraphicElement::x1) - .def_readwrite("y1", &GraphicElement::y1) - .def_readwrite("x2", &GraphicElement::x2) - .def_readwrite("y2", &GraphicElement::y2) - .def_readwrite("text", &GraphicElement::text); - - class_("PortRef") - .def_readwrite("cell", &PortRef::cell) - .def_readwrite("port", &PortRef::port); - - class_("NetInfo") - .def_readwrite("name", &NetInfo::name) - .def_readwrite("driver", &NetInfo::driver) - .def_readwrite("users", &NetInfo::users) - .def_readwrite("attrs", &NetInfo::attrs) - .def_readwrite("wires", &NetInfo::wires); - - WRAP_MAP(decltype(NetInfo::attrs), "IdStrMap"); - - class_>("PortRefVector") - .def(vector_indexing_suite>()); - - enum_("PortType") - .value("PORT_IN", PORT_IN) - .value("PORT_OUT", PORT_OUT) - .value("PORT_INOUT", PORT_INOUT) - .export_values(); - - class_("PortInfo") - .def_readwrite("name", &PortInfo::name) - .def_readwrite("net", &PortInfo::net) - .def_readwrite("type", &PortInfo::type); - - class_("CellInfo") - .def_readwrite("name", &CellInfo::name) - .def_readwrite("type", &CellInfo::type) - .def_readwrite("ports", &CellInfo::ports) - .def_readwrite("attrs", &CellInfo::attrs) - .def_readwrite("params", &CellInfo::params) - .def_readwrite("bel", &CellInfo::bel) - .def_readwrite("pins", &CellInfo::pins); - - WRAP_MAP(decltype(CellInfo::ports), "IdPortMap"); - //WRAP_MAP(decltype(CellInfo::pins), "IdIdMap"); - - class_("Design", no_init) - .def_readwrite("chip", &Design::chip) - .def_readwrite("nets", &Design::nets) - .def_readwrite("cells", &Design::cells); - - WRAP_MAP(decltype(Design::nets), "IdNetMap"); - WRAP_MAP(decltype(Design::cells), "IdCellMap"); - - arch_wrap_python(); +BOOST_PYTHON_MODULE(MODULE_NAME) +{ + class_("GraphicElement") + .def_readwrite("style", &GraphicElement::style) + .def_readwrite("type", &GraphicElement::type) + .def_readwrite("x1", &GraphicElement::x1) + .def_readwrite("y1", &GraphicElement::y1) + .def_readwrite("x2", &GraphicElement::x2) + .def_readwrite("y2", &GraphicElement::y2) + .def_readwrite("text", &GraphicElement::text); + + class_("PortRef") + .def_readwrite("cell", &PortRef::cell) + .def_readwrite("port", &PortRef::port); + + class_("NetInfo") + .def_readwrite("name", &NetInfo::name) + .def_readwrite("driver", &NetInfo::driver) + .def_readwrite("users", &NetInfo::users) + .def_readwrite("attrs", &NetInfo::attrs) + .def_readwrite("wires", &NetInfo::wires); + + WRAP_MAP(decltype(NetInfo::attrs), "IdStrMap"); + + class_>("PortRefVector") + .def(vector_indexing_suite>()); + + enum_("PortType") + .value("PORT_IN", PORT_IN) + .value("PORT_OUT", PORT_OUT) + .value("PORT_INOUT", PORT_INOUT) + .export_values(); + + class_("PortInfo") + .def_readwrite("name", &PortInfo::name) + .def_readwrite("net", &PortInfo::net) + .def_readwrite("type", &PortInfo::type); + + class_("CellInfo") + .def_readwrite("name", &CellInfo::name) + .def_readwrite("type", &CellInfo::type) + .def_readwrite("ports", &CellInfo::ports) + .def_readwrite("attrs", &CellInfo::attrs) + .def_readwrite("params", &CellInfo::params) + .def_readwrite("bel", &CellInfo::bel) + .def_readwrite("pins", &CellInfo::pins); + + WRAP_MAP(decltype(CellInfo::ports), "IdPortMap"); + // WRAP_MAP(decltype(CellInfo::pins), "IdIdMap"); + + class_("Design", no_init) + .def_readwrite("chip", &Design::chip) + .def_readwrite("nets", &Design::nets) + .def_readwrite("cells", &Design::cells); + + WRAP_MAP(decltype(Design::nets), "IdNetMap"); + WRAP_MAP(decltype(Design::cells), "IdCellMap"); + + arch_wrap_python(); } -void arch_appendinittab() { - PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME); +void arch_appendinittab() +{ + PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME); } static wchar_t *program; -void init_python(const char *executable) { - 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); - emb::append_inittab(); - Py_SetProgramName(program); - Py_Initialize(); - PyImport_ImportModule(TOSTRING(MODULE_NAME)); - } 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; - } +void init_python(const char *executable) +{ + 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); + emb::append_inittab(); + Py_SetProgramName(program); + Py_Initialize(); + PyImport_ImportModule(TOSTRING(MODULE_NAME)); + } 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; + } } -void deinit_python() { - Py_Finalize(); - PyMem_RawFree(program); +void deinit_python() +{ + Py_Finalize(); + PyMem_RawFree(program); } -void execute_python_file(const char *python_file) { - try { - 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); - } - 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; - } +void execute_python_file(const char *python_file) +{ + try { + 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); + } 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 a99ad51b..bb060718 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -23,85 +23,85 @@ #include "pycontainers.h" -#include -#include +#include #include -#include -#include #include -#include +#include +#include +#include using namespace boost::python; /* A wrapper to enable custom type/ID to/from string conversions */ -template -struct string_wrapper { - template - struct from_pystring_converter { - from_pystring_converter() { - converter::registry::push_back( - &convertible, - &construct, - boost::python::type_id()); - }; - - static void *convertible(PyObject *object) { - return PyUnicode_Check(object) ? object : 0; - } - - static void construct( - PyObject *object, - converter::rvalue_from_python_stage1_data *data) { - const wchar_t *value = PyUnicode_AsUnicode(object); - const std::wstring value_ws(value); - if (value == 0) throw_error_already_set(); - void *storage = ( - (boost::python::converter::rvalue_from_python_storage *) - data)->storage.bytes; - new(storage) T(fn(std::string(value_ws.begin(), value_ws.end()))); - data->convertible = storage; - } - - static F fn; - }; - - template - struct to_str_wrapper { - static F fn; - - std::string str(T &x) { - return fn(x); - } - }; - - template - static void wrap(const char *type_name, F1 to_str_fn, F2 from_str_fn) { - from_pystring_converter::fn = from_str_fn; - from_pystring_converter(); - to_str_wrapper::fn = to_str_fn; - class_(type_name, no_init).def("__str__", to_str_wrapper::str); - }; +template struct string_wrapper +{ + template struct from_pystring_converter + { + from_pystring_converter() + { + converter::registry::push_back(&convertible, &construct, + boost::python::type_id()); + }; + + static void *convertible(PyObject *object) + { + return PyUnicode_Check(object) ? object : 0; + } + + static void construct(PyObject *object, + converter::rvalue_from_python_stage1_data *data) + { + const wchar_t *value = PyUnicode_AsUnicode(object); + const std::wstring value_ws(value); + if (value == 0) + throw_error_already_set(); + void *storage = + ((boost::python::converter::rvalue_from_python_storage *) + data) + ->storage.bytes; + new (storage) T(fn(std::string(value_ws.begin(), value_ws.end()))); + data->convertible = storage; + } + + static F fn; + }; + + template struct to_str_wrapper + { + static F fn; + + std::string str(T &x) { return fn(x); } + }; + + template + static void wrap(const char *type_name, F1 to_str_fn, F2 from_str_fn) + { + from_pystring_converter::fn = from_str_fn; + from_pystring_converter(); + to_str_wrapper::fn = to_str_fn; + class_(type_name, no_init).def("__str__", to_str_wrapper::str); + }; }; std::string parse_python_exception(); -template -void python_export_global(const char *name, Tn &x) { - PyObject * m, *d; - m = PyImport_AddModule("__main__"); - if (m == NULL) - return; - d = PyModule_GetDict(m); - try { - PyObject * p = incref(object(boost::ref(x)).ptr()); - PyDict_SetItemString(d, name, p); - } 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; - std::terminate(); - } +template void python_export_global(const char *name, Tn &x) +{ + PyObject *m, *d; + m = PyImport_AddModule("__main__"); + if (m == NULL) + return; + d = PyModule_GetDict(m); + try { + PyObject *p = incref(object(boost::ref(x)).ptr()); + PyDict_SetItemString(d, name, p); + } 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; + std::terminate(); + } }; void init_python(const char *executable); -- cgit v1.2.3 From ed0c44891fb510c8181c2ae9332d7a030f0aaaff Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 7 Jun 2018 13:36:42 +0200 Subject: Replacing Boost type_traits with std Signed-off-by: David Shah --- common/pycontainers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common') diff --git a/common/pycontainers.h b/common/pycontainers.h index 64fb265b..6e2cdea9 100644 --- a/common/pycontainers.h +++ b/common/pycontainers.h @@ -90,7 +90,7 @@ inline void KeyError() { PyErr_SetString(PyExc_KeyError, "Key not found"); } template struct map_wrapper { - typedef boost::remove_cv_t> K; + typedef typename std::remove_cv::type>::type K; typedef typename T::mapped_type V; typedef typename T::value_type KV; -- cgit v1.2.3