From 65195513eb2676d974f1cef94be5e84f42a52f0f Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 2 Jul 2018 15:13:09 +0200 Subject: python: Restructuring wrapper system Signed-off-by: David Shah --- common/pywrappers.h | 57 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 16 deletions(-) (limited to 'common') diff --git a/common/pywrappers.h b/common/pywrappers.h index 2c91f26f..fe786a3b 100644 --- a/common/pywrappers.h +++ b/common/pywrappers.h @@ -41,66 +41,91 @@ template struct ContextualWrapper Context *ctx; T base; - ContextualWrapper(Context *c, T &&x) : ctx(c), base(x){}; + inline ContextualWrapper(Context *c, T &&x) : ctx(c), base(x){}; - operator T() { return base; }; + inline operator T() { return base; }; typedef T base_type; }; +template struct WrapIfNotContext { + typedef ContextualWrapper maybe_wrapped_t; +}; + +template <> struct WrapIfNotContext { + typedef Context maybe_wrapped_t; +}; + + +template inline Context *get_ctx(typename WrapIfNotContext::maybe_wrapped_t &wrp_ctx) { + return wrp_ctx.ctx; +} +template <> inline Context *get_ctx(WrapIfNotContext::maybe_wrapped_t &unwrp_ctx) { + return &unwrp_ctx; +} + +template inline T&get_base(typename WrapIfNotContext::maybe_wrapped_t &wrp_ctx) { + return wrp_ctx.base; +} +template <> inline Context &get_base(WrapIfNotContext::maybe_wrapped_t &unwrp_ctx) { + return unwrp_ctx; +} + template ContextualWrapper wrap_ctx(Context *ctx, T x) { return ContextualWrapper(ctx, x); } // Dummy class, to be implemented by users -template class string_converter; +template struct string_converter; // Action options -template class do_nothing +template struct do_nothing { - T operator()(Context *ctx, T x) { return x; } + inline T operator()(Context *ctx, T x) { return x; } using ret_type = T; using arg_type = T; }; -template class wrap_context +template struct wrap_context { - ContextualWrapper operator()(Context *ctx, T x) { return ContextualWrapper(ctx, x); } + inline ContextualWrapper operator()(Context *ctx, T x) { return ContextualWrapper(ctx, x); } using arg_type = T; using ret_type = ContextualWrapper; }; -template class unwrap_context +template struct unwrap_context { - T operator()(Context *ctx, ContextualWrapper x) { return x.base; } + inline T operator()(Context *ctx, ContextualWrapper x) { return x.base; } using ret_type = T; using arg_type = ContextualWrapper; }; -template class conv_from_string +template struct conv_from_str { - T operator()(Context *ctx, std::string x) { return string_converter().from_str(ctx, x); } + inline T operator()(Context *ctx, std::string x) { return string_converter().from_str(ctx, x); } using ret_type = T; using arg_type = std::string; }; -template class conv_to_string +template struct conv_to_str { - std::string operator()(Context *ctx, T x) { return string_converter().to_str(ctx, x); } + inline std::string operator()(Context *ctx, T x) { return string_converter().to_str(ctx, x); } using ret_type = std::string; using arg_type = T; }; // Function wrapper // Example: one parameter, one return -template struct function_wrapper +template struct fn_wrapper { - using class_type = ContextualWrapper; + using class_type = typename WrapIfNotContext::maybe_wrapped_t; using conv_result_type = typename rv_conv::ret_type; using conv_arg1_type = typename arg1_conv::arg_type; static conv_result_type wrapped_fn(class_type &cls, conv_arg1_type arg1) { - return rv_conv()(cls.ctx, cls.base.*fn(arg1_conv()(cls.ctx, arg1))); + return rv_conv()(get_base(cls).ctx, get_base(cls).*fn(arg1_conv()(get_ctx(cls), arg1))); } + + template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } }; } // namespace PythonConversion -- cgit v1.2.3 From 4bc12f2eadc2c369f38dfa54f086b8aa2c94fd05 Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 2 Jul 2018 15:29:58 +0200 Subject: Progress on new wrapper system Signed-off-by: David Shah --- common/pybindings.cc | 1 - common/pywrappers.h | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/pybindings.cc b/common/pybindings.cc index e9ceca51..329bcf1e 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -123,7 +123,6 @@ BOOST_PYTHON_MODULE(MODULE_NAME) .def(self == self); arch_wrap_python(); - class_, boost::noncopyable>("Context", no_init).def("checksum", &Context::checksum); } static wchar_t *program; diff --git a/common/pywrappers.h b/common/pywrappers.h index fe786a3b..5b0146ac 100644 --- a/common/pywrappers.h +++ b/common/pywrappers.h @@ -122,7 +122,9 @@ template (cls); + Class &base = get_base(cls); + return rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1))); } template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } -- cgit v1.2.3 From 1e96d65ded029f68bb294cfb25c56f138dd51180 Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 2 Jul 2018 15:59:18 +0200 Subject: python: Add context wrapper support for ranges Signed-off-by: David Shah --- common/pybindings.cc | 9 ++++----- common/pybindings.h | 56 +++++++++++---------------------------------------- common/pycontainers.h | 39 +++++++++++++++++++++++------------ common/pywrappers.h | 44 +++++++++++++++++++++++++++++----------- 4 files changed, 74 insertions(+), 74 deletions(-) (limited to 'common') diff --git a/common/pybindings.cc b/common/pybindings.cc index 329bcf1e..1746c517 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -80,7 +80,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME) .def_readwrite("attrs", &NetInfo::attrs) .def_readwrite("wires", &NetInfo::wires); - WRAP_MAP(decltype(NetInfo::attrs), "IdStrMap"); + // WRAP_MAP(decltype(NetInfo::attrs), "IdStrMap"); class_>("PortRefVector").def(vector_indexing_suite>()); @@ -104,15 +104,15 @@ BOOST_PYTHON_MODULE(MODULE_NAME) .def_readwrite("bel", &CellInfo::bel) .def_readwrite("pins", &CellInfo::pins); - WRAP_MAP(decltype(CellInfo::ports), "IdPortMap"); + // WRAP_MAP(decltype(CellInfo::ports), "IdPortMap"); // WRAP_MAP(decltype(CellInfo::pins), "IdIdMap"); class_("BaseCtx", no_init) .add_property("nets", make_getter(&Context::nets, return_internal_reference<>())) .add_property("cells", make_getter(&Context::cells, return_internal_reference<>())); - WRAP_MAP_UPTR(decltype(Context::nets), "IdNetMap"); - WRAP_MAP_UPTR(decltype(Context::cells), "IdCellMap"); + // WRAP_MAP_UPTR(decltype(Context::nets), "IdNetMap"); + // WRAP_MAP_UPTR(decltype(Context::cells), "IdCellMap"); def("parse_json", parse_json_shim); def("load_design", load_design_shim, return_value_policy()); @@ -122,7 +122,6 @@ BOOST_PYTHON_MODULE(MODULE_NAME) .def(self < self) .def(self == self); arch_wrap_python(); - } static wchar_t *program; diff --git a/common/pybindings.h b/common/pybindings.h index 1565a138..852fb21f 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -36,50 +36,6 @@ NEXTPNR_NAMESPACE_BEGIN 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); - }; -}; - std::string parse_python_exception(); template void python_export_global(const char *name, Tn &x) @@ -106,6 +62,18 @@ void deinit_python(); void execute_python_file(const char *python_file); +// Defauld IdString conversions +namespace PythonConversion { + +template <> struct string_converter +{ + inline IdString from_str(Context *ctx, std::string name) { return ctx->id(name); } + + inline std::string to_str(Context *ctx, IdString id) { return id.str(ctx); } +}; + +} // namespace PythonConversion + NEXTPNR_NAMESPACE_END #endif /* end of include guard: COMMON_PYBINDINGS_HH */ diff --git a/common/pycontainers.h b/common/pycontainers.h index 917f49e9..e1a73d75 100644 --- a/common/pycontainers.h +++ b/common/pycontainers.h @@ -28,6 +28,7 @@ #include #include #include "nextpnr.h" +#include "pywrappers.h" NEXTPNR_NAMESPACE_BEGIN @@ -37,18 +38,22 @@ inline void KeyError() { PyErr_SetString(PyExc_KeyError, "Key not found"); } /* A wrapper for a Pythonised nextpnr Iterator. The actual class wrapped is a -pair containing (current, end) +pair containing (current, end), wrapped in a ContextualWrapper + */ -template struct iterator_wrapper +template > struct iterator_wrapper { typedef decltype(*(std::declval())) value_t; - static value_t next(std::pair &iter) + typedef PythonConversion::ContextualWrapper> wrapped_iter_t; + using return_t = typename value_conv::ret_type; + + static return_t next(wrapped_iter_t &iter) { - if (iter.first != iter.second) { - value_t val = *iter.first; - ++iter.first; + if (iter.base.first != iter.base.second) { + return_t val = value_conv()(iter.ctx, *iter.base.first); + ++iter.base.first; return val; } else { PyErr_SetString(PyExc_StopIteration, "End of range reached"); @@ -61,7 +66,7 @@ template struct iterator_wrapper static void wrap(const char *python_name) { - class_>(python_name, no_init).def("__next__", next, P()); + class_(python_name, no_init).def("__next__", next, P()); } }; @@ -71,22 +76,29 @@ 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 +template , + typename value_conv = PythonConversion::pass_through> +struct range_wrapper { typedef decltype(std::declval().begin()) iterator_t; - - static std::pair iter(T &range) { return std::make_pair(range.begin(), range.end()); } + typedef typename PythonConversion::ContextualWrapper wrapped_range; + typedef typename PythonConversion::ContextualWrapper> wrapped_pair; + static wrapped_pair iter(wrapped_range &range) + { + return wrapped_pair(range.ctx, std::make_pair(range.base.begin(), range.base.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); + 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") +#define WRAP_RANGE(t, conv) \ + range_wrapper, conv>().wrap(#t "Range", #t "Iterator") /* Wrapper for a pair, allows accessing either using C++-style members (.first and @@ -259,6 +271,7 @@ template struct map_pair_wrapper_uptr { typedef std::pair T; typedef typename T::second_type::element_type V; + struct pair_iterator_wrapper { static object next(std::pair &iter) diff --git a/common/pywrappers.h b/common/pywrappers.h index 5b0146ac..55d70e42 100644 --- a/common/pywrappers.h +++ b/common/pywrappers.h @@ -41,32 +41,37 @@ template struct ContextualWrapper Context *ctx; T base; - inline ContextualWrapper(Context *c, T &&x) : ctx(c), base(x){}; + inline ContextualWrapper(Context *c, T x) : ctx(c), base(x){}; inline operator T() { return base; }; typedef T base_type; }; -template struct WrapIfNotContext { - typedef ContextualWrapper maybe_wrapped_t; +template struct WrapIfNotContext +{ + typedef ContextualWrapper maybe_wrapped_t; }; -template <> struct WrapIfNotContext { +template <> struct WrapIfNotContext +{ typedef Context maybe_wrapped_t; }; - -template inline Context *get_ctx(typename WrapIfNotContext::maybe_wrapped_t &wrp_ctx) { +template inline Context *get_ctx(typename WrapIfNotContext::maybe_wrapped_t &wrp_ctx) +{ return wrp_ctx.ctx; } -template <> inline Context *get_ctx(WrapIfNotContext::maybe_wrapped_t &unwrp_ctx) { +template <> inline Context *get_ctx(WrapIfNotContext::maybe_wrapped_t &unwrp_ctx) +{ return &unwrp_ctx; } -template inline T&get_base(typename WrapIfNotContext::maybe_wrapped_t &wrp_ctx) { +template inline T &get_base(typename WrapIfNotContext::maybe_wrapped_t &wrp_ctx) +{ return wrp_ctx.base; } -template <> inline Context &get_base(WrapIfNotContext::maybe_wrapped_t &unwrp_ctx) { +template <> inline Context &get_base(WrapIfNotContext::maybe_wrapped_t &unwrp_ctx) +{ return unwrp_ctx; } @@ -76,7 +81,7 @@ template ContextualWrapper wrap_ctx(Context *ctx, T x) { return template struct string_converter; // Action options -template struct do_nothing +template struct pass_through { inline T operator()(Context *ctx, T x) { return x; } @@ -113,8 +118,23 @@ template struct conv_to_str }; // Function wrapper -// Example: one parameter, one return -template struct fn_wrapper +// Zero parameters, one return +template struct fn_wrapper_0a +{ + using class_type = typename WrapIfNotContext::maybe_wrapped_t; + using conv_result_type = typename rv_conv::ret_type; + + static conv_result_type wrapped_fn(class_type &cls) + { + Context *ctx = get_ctx(cls); + Class &base = get_base(cls); + return rv_conv()(ctx, (base.*fn)()); + } + + template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } +}; +// One parameter, one return +template struct fn_wrapper_1a { using class_type = typename WrapIfNotContext::maybe_wrapped_t; using conv_result_type = typename rv_conv::ret_type; -- cgit v1.2.3 From 45ec502dedf1503fa0117c6eef4a765e4c736315 Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 2 Jul 2018 16:20:59 +0200 Subject: python: Adding more bindings Signed-off-by: David Shah --- common/pybindings.cc | 4 ---- common/pycontainers.h | 20 +++++++++++++++++++- 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'common') diff --git a/common/pybindings.cc b/common/pybindings.cc index 1746c517..f84d21f5 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -117,10 +117,6 @@ BOOST_PYTHON_MODULE(MODULE_NAME) def("parse_json", parse_json_shim); def("load_design", load_design_shim, return_value_policy()); - class_("IdString") - .def("__str__", &IdString::global_str, return_value_policy()) - .def(self < self) - .def(self == self); arch_wrap_python(); } diff --git a/common/pycontainers.h b/common/pycontainers.h index e1a73d75..6870c3a4 100644 --- a/common/pycontainers.h +++ b/common/pycontainers.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -81,6 +82,7 @@ template , struct range_wrapper { typedef decltype(std::declval().begin()) iterator_t; + typedef decltype(*(std::declval())) value_t; typedef typename PythonConversion::ContextualWrapper wrapped_range; typedef typename PythonConversion::ContextualWrapper> wrapped_pair; static wrapped_pair iter(wrapped_range &range) @@ -88,9 +90,25 @@ struct range_wrapper return wrapped_pair(range.ctx, std::make_pair(range.base.begin(), range.base.end())); } + static std::string repr(wrapped_range &range) + { + PythonConversion::string_converter conv; + bool first = true; + std::stringstream ss; + ss << "["; + for (const auto &item : range.base) { + if (!first) + ss << ", "; + ss << "'" << conv.to_str(range.ctx, item) << "'"; + first = false; + } + ss << "]"; + return ss.str(); + } + static void wrap(const char *range_name, const char *iter_name) { - class_(range_name, no_init).def("__iter__", iter); + class_(range_name, no_init).def("__iter__", iter).def("__repr__", repr); iterator_wrapper().wrap(iter_name); } -- cgit v1.2.3 From a382d906efda9b096c4e841ebcff83be85fa3e5c Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 3 Jul 2018 10:55:32 +0200 Subject: python: Developing context wrappers for maps Signed-off-by: David Shah --- common/pybindings.cc | 6 ++--- common/pybindings.h | 7 ++++++ common/pycontainers.h | 64 +++++++++++++++++++++++++++++++++------------------ common/pywrappers.h | 19 +++++++++++++++ 4 files changed, 70 insertions(+), 26 deletions(-) (limited to 'common') diff --git a/common/pybindings.cc b/common/pybindings.cc index f84d21f5..b15a6c79 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -107,9 +107,9 @@ BOOST_PYTHON_MODULE(MODULE_NAME) // WRAP_MAP(decltype(CellInfo::ports), "IdPortMap"); // WRAP_MAP(decltype(CellInfo::pins), "IdIdMap"); - class_("BaseCtx", no_init) - .add_property("nets", make_getter(&Context::nets, return_internal_reference<>())) - .add_property("cells", make_getter(&Context::cells, return_internal_reference<>())); + class_("BaseCtx", no_init); + //.add_property("nets", make_getter(&Context::nets, return_internal_reference<>())) + //.add_property("cells", make_getter(&Context::cells, return_internal_reference<>())); // WRAP_MAP_UPTR(decltype(Context::nets), "IdNetMap"); // WRAP_MAP_UPTR(decltype(Context::cells), "IdCellMap"); diff --git a/common/pybindings.h b/common/pybindings.h index 852fb21f..c4d84442 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -72,6 +72,13 @@ template <> struct string_converter inline std::string to_str(Context *ctx, IdString id) { return id.str(ctx); } }; +template <> struct string_converter +{ + inline IdString from_str(Context *ctx, std::string name) { return ctx->id(name); } + + inline std::string to_str(Context *ctx, IdString id) { return id.str(ctx); } +}; + } // namespace PythonConversion NEXTPNR_NAMESPACE_END diff --git a/common/pycontainers.h b/common/pycontainers.h index 6870c3a4..845c2847 100644 --- a/common/pycontainers.h +++ b/common/pycontainers.h @@ -112,7 +112,7 @@ struct range_wrapper iterator_wrapper().wrap(iter_name); } - typedef iterator_wrapper iter_wrap; + typedef iterator_wrapper iter_wrap; }; #define WRAP_RANGE(t, conv) \ @@ -288,18 +288,20 @@ Special case of above for map key/values where value is a unique_ptr template struct map_pair_wrapper_uptr { typedef std::pair T; + typedef PythonConversion::ContextualWrapper wrapped_pair; typedef typename T::second_type::element_type V; struct pair_iterator_wrapper { - static object next(std::pair &iter) + static object next(std::pair &iter) { if (iter.second == 0) { iter.second++; - return object(iter.first.first); + return object(PythonConversion::string_converter().to_str( + iter.first.ctx, iter.first.base.first)); } else if (iter.second == 1) { iter.second++; - return object(iter.first.second.get()); + return object(PythonConversion::ContextualWrapper(iter.first.ctx, *iter.first.base.second.get())); } else { PyErr_SetString(PyExc_StopIteration, "End of range reached"); boost::python::throw_error_already_set(); @@ -311,32 +313,41 @@ template struct map_pair_wrapper_uptr static void wrap(const char *python_name) { - class_>(python_name, no_init).def("__next__", next); + class_>(python_name, no_init).def("__next__", next); } }; - static object get(T &x, int i) + static object get(wrapped_pair &x, int i) { if ((i >= 2) || (i < 0)) KeyError(); - return (i == 1) ? object(x.second.get()) : object(x.first); + return (i == 1) ? object(PythonConversion::ContextualWrapper(x.ctx, *x.base.second.get())) + : object(x.base.first); } - static int len(T &x) { return 2; } + static int len(wrapped_pair &x) { return 2; } - static std::pair iter(T &x) { return std::make_pair(boost::ref(x), 0); }; + static std::pair iter(wrapped_pair &x) { return std::make_pair(boost::ref(x), 0); }; - static V &second_getter(T &t) { return *t.second.get(); } + static std::string first_getter(wrapped_pair &t) + { + return PythonConversion::string_converter().to_str(t.ctx, t.base.first); + } + + static PythonConversion::ContextualWrapper second_getter(wrapped_pair &t) + { + return PythonConversion::ContextualWrapper(t.ctx, *t.base.second.get()); + } static void wrap(const char *pair_name, const char *iter_name) { pair_iterator_wrapper::wrap(iter_name); - class_(pair_name, no_init) + class_(pair_name, no_init) .def("__iter__", iter) .def("__len__", len) .def("__getitem__", get) - .def_readonly("first", &T::first) - .add_property("second", make_function(second_getter, return_internal_reference<>())); + .add_property("first", first_getter) + .add_property("second", second_getter); } }; @@ -348,22 +359,29 @@ template struct map_wrapper_uptr { typedef typename std::remove_cv::type>::type K; typedef typename T::mapped_type::pointer V; + typedef typename T::mapped_type::element_type &Vr; typedef typename T::value_type KV; + typedef typename PythonConversion::ContextualWrapper wrapped_map; - static V get(T &x, K const &i) + static PythonConversion::ContextualWrapper get(wrapped_map &x, std::string const &i) { - if (x.find(i) != x.end()) - return x.at(i).get(); + K k = PythonConversion::string_converter().from_str(x.ctx, i); + if (x.base.find(k) != x.base.end()) + return PythonConversion::ContextualWrapper(x.ctx, *x.base.at(k).get()); KeyError(); std::terminate(); } - static void set(T &x, K const &i, V const &v) { x[i] = typename T::mapped_type(v); } + static void set(wrapped_map &x, std::string const &i, V const &v) + { + x.base[PythonConversion::string_converter().from_str(x.ctx, i)] = typename T::mapped_type(v); + } - static void del(T const &x, K const &i) + static void del(T const &x, std::string const &i) { - if (x.find(i) != x.end()) - x.erase(i); + K k = PythonConversion::string_converter().from_str(x.ctx, i); + if (x.base.find(k) != x.base.end()) + x.base.erase(k); else KeyError(); std::terminate(); @@ -372,12 +390,12 @@ template struct map_wrapper_uptr static void wrap(const char *map_name, const char *kv_name, const char *kv_iter_name, const char *iter_name) { map_pair_wrapper_uptr::wrap(kv_name, kv_iter_name); - typedef range_wrapper> rw; + typedef range_wrapper, PythonConversion::wrap_context> rw; typename rw::iter_wrap().wrap(iter_name); - class_(map_name, no_init) + class_(map_name, no_init) .def("__iter__", rw::iter) .def("__len__", &T::size) - .def("__getitem__", get, return_internal_reference<>()) + .def("__getitem__", get) .def("__setitem__", set, with_custodian_and_ward<1, 2>()); } }; diff --git a/common/pywrappers.h b/common/pywrappers.h index 55d70e42..125308e3 100644 --- a/common/pywrappers.h +++ b/common/pywrappers.h @@ -150,6 +150,25 @@ template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } }; +// Wrapped getter +template struct readonly_wrapper +{ + using class_type = typename WrapIfNotContext::maybe_wrapped_t; + using conv_val_type = typename v_conv::ret_type; + + static conv_val_type wrapped_getter(class_type &cls) + { + Context *ctx = get_ctx(cls); + Class &base = get_base(cls); + return v_conv()(ctx, (base.*mem)); + } + + template static void def_wrap(WrapCls cls_, const char *name) + { + cls_.add_property(name, wrapped_getter); + } +}; + } // namespace PythonConversion NEXTPNR_NAMESPACE_END -- cgit v1.2.3 From 3e8bdb5cbdc50a38ca12fa4509261da5080209a1 Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 3 Jul 2018 11:04:55 +0200 Subject: python: New wrapper system working for unique_ptr maps Signed-off-by: David Shah --- common/pybindings.cc | 10 ++++++++-- common/pycontainers.h | 6 +++--- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'common') diff --git a/common/pybindings.cc b/common/pybindings.cc index b15a6c79..e776e33a 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -63,6 +63,8 @@ Context *load_design_shim(std::string filename, ArchArgs args) BOOST_PYTHON_MODULE(MODULE_NAME) { + using namespace PythonConversion; + class_("GraphicElement") .def_readwrite("type", &GraphicElement::type) .def_readwrite("x1", &GraphicElement::x1) @@ -95,14 +97,14 @@ BOOST_PYTHON_MODULE(MODULE_NAME) .def_readwrite("net", &PortInfo::net) .def_readwrite("type", &PortInfo::type); - class_("CellInfo") + /*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); + .def_readwrite("pins", &CellInfo::pins);*/ // WRAP_MAP(decltype(CellInfo::ports), "IdPortMap"); // WRAP_MAP(decltype(CellInfo::pins), "IdIdMap"); @@ -114,6 +116,10 @@ BOOST_PYTHON_MODULE(MODULE_NAME) // WRAP_MAP_UPTR(decltype(Context::nets), "IdNetMap"); // WRAP_MAP_UPTR(decltype(Context::cells), "IdCellMap"); + auto ci_cls = class_>("CellInfo", no_init); + readonly_wrapper>::def_wrap(ci_cls, + "type"); + def("parse_json", parse_json_shim); def("load_design", load_design_shim, return_value_policy()); diff --git a/common/pycontainers.h b/common/pycontainers.h index 845c2847..0257e9e4 100644 --- a/common/pycontainers.h +++ b/common/pycontainers.h @@ -342,7 +342,7 @@ template struct map_pair_wrapper_uptr static void wrap(const char *pair_name, const char *iter_name) { pair_iterator_wrapper::wrap(iter_name); - class_(pair_name, no_init) + class_(pair_name, no_init) .def("__iter__", iter) .def("__len__", len) .def("__getitem__", get) @@ -390,9 +390,9 @@ template struct map_wrapper_uptr static void wrap(const char *map_name, const char *kv_name, const char *kv_iter_name, const char *iter_name) { map_pair_wrapper_uptr::wrap(kv_name, kv_iter_name); - typedef range_wrapper, PythonConversion::wrap_context> rw; + typedef range_wrapper, PythonConversion::wrap_context> rw; typename rw::iter_wrap().wrap(iter_name); - class_(map_name, no_init) + class_(map_name, no_init) .def("__iter__", rw::iter) .def("__len__", &T::size) .def("__getitem__", get) -- cgit v1.2.3 From f8ad2b31a9a1a43ac415e8b203851c6f091dde6f Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 4 Jul 2018 12:23:35 +0200 Subject: python: Translate NPNR_ASSERTs to Python Signed-off-by: David Shah --- common/pybindings.cc | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'common') diff --git a/common/pybindings.cc b/common/pybindings.cc index e776e33a..ea57dbbb 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -61,8 +61,15 @@ Context *load_design_shim(std::string filename, ArchArgs args) return d; } +void translate_assertfail(const assertion_failure &e) { + // Use the Python 'C' API to set up an exception object + PyErr_SetString(PyExc_AssertionError, e.what()); +} + BOOST_PYTHON_MODULE(MODULE_NAME) { + register_exception_translator(&translate_assertfail); + using namespace PythonConversion; class_("GraphicElement") -- cgit v1.2.3 From f6432aa88e8a9d6347a60f9898e74a4ebc1b2b3a Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 4 Jul 2018 13:35:15 +0200 Subject: python: Adding more wrapped bindings for ice40 Signed-off-by: David Shah --- common/pybindings.cc | 9 +++-- common/pycontainers.h | 2 +- common/pywrappers.h | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 5 deletions(-) (limited to 'common') diff --git a/common/pybindings.cc b/common/pybindings.cc index ea57dbbb..5ad8a983 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -61,7 +61,8 @@ Context *load_design_shim(std::string filename, ArchArgs args) return d; } -void translate_assertfail(const assertion_failure &e) { +void translate_assertfail(const assertion_failure &e) +{ // Use the Python 'C' API to set up an exception object PyErr_SetString(PyExc_AssertionError, e.what()); } @@ -123,9 +124,9 @@ BOOST_PYTHON_MODULE(MODULE_NAME) // WRAP_MAP_UPTR(decltype(Context::nets), "IdNetMap"); // WRAP_MAP_UPTR(decltype(Context::cells), "IdCellMap"); - auto ci_cls = class_>("CellInfo", no_init); - readonly_wrapper>::def_wrap(ci_cls, - "type"); + auto ci_cls = class_>("CellInfo", no_init); + readonly_wrapper>::def_wrap(ci_cls, + "type"); def("parse_json", parse_json_shim); def("load_design", load_design_shim, return_value_policy()); diff --git a/common/pycontainers.h b/common/pycontainers.h index 0257e9e4..cc3c2c84 100644 --- a/common/pycontainers.h +++ b/common/pycontainers.h @@ -390,7 +390,7 @@ template struct map_wrapper_uptr static void wrap(const char *map_name, const char *kv_name, const char *kv_iter_name, const char *iter_name) { map_pair_wrapper_uptr::wrap(kv_name, kv_iter_name); - typedef range_wrapper, PythonConversion::wrap_context> rw; + typedef range_wrapper, PythonConversion::wrap_context> rw; typename rw::iter_wrap().wrap(iter_name); class_(map_name, no_init) .def("__iter__", rw::iter) diff --git a/common/pywrappers.h b/common/pywrappers.h index 125308e3..560d645d 100644 --- a/common/pywrappers.h +++ b/common/pywrappers.h @@ -150,6 +150,112 @@ template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } }; +// Two parameters, one return +template +struct fn_wrapper_2a +{ + using class_type = typename WrapIfNotContext::maybe_wrapped_t; + using conv_result_type = typename rv_conv::ret_type; + using conv_arg1_type = typename arg1_conv::arg_type; + using conv_arg2_type = typename arg2_conv::arg_type; + + static conv_result_type wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2) + { + Context *ctx = get_ctx(cls); + Class &base = get_base(cls); + return rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2))); + } + + template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } +}; + +// Three parameters, one return +template +struct fn_wrapper_3a +{ + using class_type = typename WrapIfNotContext::maybe_wrapped_t; + using conv_result_type = typename rv_conv::ret_type; + using conv_arg1_type = typename arg1_conv::arg_type; + using conv_arg2_type = typename arg2_conv::arg_type; + using conv_arg3_type = typename arg3_conv::arg_type; + + static conv_result_type wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2, conv_arg3_type arg3) + { + Context *ctx = get_ctx(cls); + Class &base = get_base(cls); + return rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3))); + } + + template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } +}; + +// Zero parameters void +template struct fn_wrapper_0a_v +{ + using class_type = typename WrapIfNotContext::maybe_wrapped_t; + + static void wrapped_fn(class_type &cls) + { + Context *ctx = get_ctx(cls); + Class &base = get_base(cls); + return (base.*fn)(); + } + + template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } +}; +// One parameter, void +template struct fn_wrapper_1a_v +{ + using class_type = typename WrapIfNotContext::maybe_wrapped_t; + using conv_arg1_type = typename arg1_conv::arg_type; + + static void wrapped_fn(class_type &cls, conv_arg1_type arg1) + { + Context *ctx = get_ctx(cls); + Class &base = get_base(cls); + return (base.*fn)(arg1_conv()(ctx, arg1)); + } + + template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } +}; + +// Two parameters, one return +template struct fn_wrapper_2a_v +{ + using class_type = typename WrapIfNotContext::maybe_wrapped_t; + using conv_arg1_type = typename arg1_conv::arg_type; + using conv_arg2_type = typename arg2_conv::arg_type; + + static void wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2) + { + Context *ctx = get_ctx(cls); + Class &base = get_base(cls); + return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2)); + } + + template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } +}; + +// Three parameters, one return +template +struct fn_wrapper_3a_v +{ + using class_type = typename WrapIfNotContext::maybe_wrapped_t; + using conv_arg1_type = typename arg1_conv::arg_type; + using conv_arg2_type = typename arg2_conv::arg_type; + using conv_arg3_type = typename arg3_conv::arg_type; + + static void wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2, conv_arg3_type arg3) + { + Context *ctx = get_ctx(cls); + Class &base = get_base(cls); + return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3)); + } + + template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } +}; + // Wrapped getter template struct readonly_wrapper { -- cgit v1.2.3 From 79e91368f901343c7f0c88d5841ae231432a4c0b Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 4 Jul 2018 14:13:55 +0200 Subject: python: Update wrapper for non-unique_ptr maps Signed-off-by: David Shah --- common/pybindings.cc | 23 +++++------------ common/pycontainers.h | 68 ++++++++++++++++++++++++++++++++------------------- 2 files changed, 49 insertions(+), 42 deletions(-) (limited to 'common') diff --git a/common/pybindings.cc b/common/pybindings.cc index 5ad8a983..a85c5fe2 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -21,6 +21,7 @@ #ifndef NO_PYTHON #include "pybindings.h" +#include "arch_pybindings.h" #include "jsonparse.h" #include "nextpnr.h" @@ -105,32 +106,20 @@ BOOST_PYTHON_MODULE(MODULE_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_("BaseCtx", no_init); - //.add_property("nets", make_getter(&Context::nets, return_internal_reference<>())) - //.add_property("cells", make_getter(&Context::cells, return_internal_reference<>())); - // WRAP_MAP_UPTR(decltype(Context::nets), "IdNetMap"); - // WRAP_MAP_UPTR(decltype(Context::cells), "IdCellMap"); + typedef std::unordered_map AttrMap; auto ci_cls = class_>("CellInfo", no_init); readonly_wrapper>::def_wrap(ci_cls, "type"); - + readonly_wrapper>::def_wrap( + ci_cls, "attrs"); def("parse_json", parse_json_shim); def("load_design", load_design_shim, return_value_policy()); + WRAP_MAP(AttrMap, pass_through, "AttrMap"); + arch_wrap_python(); } diff --git a/common/pycontainers.h b/common/pycontainers.h index cc3c2c84..c8d2257b 100644 --- a/common/pycontainers.h +++ b/common/pycontainers.h @@ -188,20 +188,23 @@ template struct pair_wrapper /* Special case of above for map key/values */ -template struct map_pair_wrapper +template struct map_pair_wrapper { typedef std::pair T; + typedef PythonConversion::ContextualWrapper wrapped_pair; + typedef typename T::second_type V; struct pair_iterator_wrapper { - static object next(std::pair &iter) + static object next(std::pair &iter) { if (iter.second == 0) { iter.second++; - return object(iter.first.first); + return object(PythonConversion::string_converter().to_str( + iter.first.ctx, iter.first.base.first)); } else if (iter.second == 1) { iter.second++; - return object(iter.first.second); + return object(value_conv()(iter.first.ctx, iter.first.base.second)); } else { PyErr_SetString(PyExc_StopIteration, "End of range reached"); boost::python::throw_error_already_set(); @@ -213,30 +216,37 @@ template struct map_pair_wrapper static void wrap(const char *python_name) { - class_>(python_name, no_init).def("__next__", next); + class_>(python_name, no_init).def("__next__", next); } }; - static object get(T &x, int i) + static object get(wrapped_pair &x, int i) { if ((i >= 2) || (i < 0)) KeyError(); - return (i == 1) ? object(x.second) : object(x.first); + return (i == 1) ? object(value_conv()(x.ctx, x.base.second)) : object(x.base.first); } - static int len(T &x) { return 2; } + static int len(wrapped_pair &x) { return 2; } - static std::pair iter(T &x) { return std::make_pair(boost::ref(x), 0); }; + static std::pair iter(wrapped_pair &x) { return std::make_pair(boost::ref(x), 0); }; + + static std::string first_getter(wrapped_pair &t) + { + return PythonConversion::string_converter().to_str(t.ctx, t.base.first); + } + + static typename value_conv::ret_type second_getter(wrapped_pair &t) { return value_conv()(t.ctx, t.base.second); } static void wrap(const char *pair_name, const char *iter_name) { pair_iterator_wrapper::wrap(iter_name); - class_(pair_name, no_init) + class_(pair_name, no_init) .def("__iter__", iter) .def("__len__", len) .def("__getitem__", get) - .def_readonly("first", &T::first) - .def_readwrite("second", &T::second); + .add_property("first", first_getter) + .add_property("second", second_getter); } }; @@ -244,26 +254,33 @@ template struct map_pair_wrapper Wrapper for a map, either an unordered_map, regular map or dict */ -template struct map_wrapper +template struct map_wrapper { typedef typename std::remove_cv::type>::type K; typedef typename T::mapped_type V; + typedef typename value_conv::ret_type wrapped_V; typedef typename T::value_type KV; + typedef typename PythonConversion::ContextualWrapper wrapped_map; - static V &get(T &x, K const &i) + static wrapped_V get(wrapped_map &x, std::string const &i) { - if (x.find(i) != x.end()) - return x.at(i); + K k = PythonConversion::string_converter().from_str(x.ctx, i); + if (x.base.find(k) != x.base.end()) + return value_conv()(x.ctx, x.base.at(k)); KeyError(); std::terminate(); } - static void set(T &x, K const &i, V &v) { x[i] = v; } + static void set(wrapped_map &x, std::string const &i, V const &v) + { + x.base[PythonConversion::string_converter().from_str(x.ctx, i)] = v; + } - static void del(T const &x, K const &i) + static void del(T const &x, std::string const &i) { - if (x.find(i) != x.end()) - x.erase(i); + K k = PythonConversion::string_converter().from_str(x.ctx, i); + if (x.base.find(k) != x.base.end()) + x.base.erase(k); else KeyError(); std::terminate(); @@ -271,13 +288,13 @@ template struct map_wrapper static void wrap(const char *map_name, const char *kv_name, const char *kv_iter_name, const char *iter_name) { - map_pair_wrapper::wrap(kv_name, kv_iter_name); - typedef range_wrapper> rw; + map_pair_wrapper::wrap(kv_name, kv_iter_name); + typedef range_wrapper, PythonConversion::wrap_context> rw; typename rw::iter_wrap().wrap(iter_name); - class_(map_name, no_init) + class_(map_name, no_init) .def("__iter__", rw::iter) .def("__len__", &T::size) - .def("__getitem__", get, return_internal_reference<>()) + .def("__getitem__", get) .def("__setitem__", set, with_custodian_and_ward<1, 2>()); } }; @@ -400,7 +417,8 @@ template struct map_wrapper_uptr } }; -#define WRAP_MAP(t, name) map_wrapper().wrap(#name, #name "KeyValue", #name "KeyValueIter", #name "Iterator") +#define WRAP_MAP(t, conv, name) \ + map_wrapper().wrap(#name, #name "KeyValue", #name "KeyValueIter", #name "Iterator") #define WRAP_MAP_UPTR(t, name) \ map_wrapper_uptr().wrap(#name, #name "KeyValue", #name "KeyValueIter", #name "Iterator") -- cgit v1.2.3 From 46db5001234ff42cd5b94407c2122bbf0b2994df Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 4 Jul 2018 14:44:45 +0200 Subject: python: More design-related bindings, dump_design.py working again Signed-off-by: David Shah --- common/pybindings.cc | 70 +++++++++++++++++++++++++++++++++++---------------- common/pycontainers.h | 14 +++++++++-- common/pywrappers.h | 65 +++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 124 insertions(+), 25 deletions(-) (limited to 'common') diff --git a/common/pybindings.cc b/common/pybindings.cc index a85c5fe2..9bca307c 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -82,43 +82,71 @@ BOOST_PYTHON_MODULE(MODULE_NAME) .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); + typedef std::unordered_map AttrMap; + typedef std::unordered_map PortMap; + typedef std::unordered_map PinMap; class_("BaseCtx", no_init); - typedef std::unordered_map AttrMap; - auto ci_cls = class_>("CellInfo", no_init); - readonly_wrapper>::def_wrap(ci_cls, - "type"); + readwrite_wrapper, + conv_from_str>::def_wrap(ci_cls, "name"); + readwrite_wrapper, + conv_from_str>::def_wrap(ci_cls, "type"); readonly_wrapper>::def_wrap( ci_cls, "attrs"); + readonly_wrapper>::def_wrap( + ci_cls, "params"); + readonly_wrapper>::def_wrap( + ci_cls, "ports"); + readwrite_wrapper, + conv_from_str>::def_wrap(ci_cls, "bel"); + readwrite_wrapper, + pass_through>::def_wrap(ci_cls, "belStrength"); + readonly_wrapper>::def_wrap(ci_cls, + "pins"); + + auto pi_cls = class_>("PortInfo", no_init); + readwrite_wrapper, + conv_from_str>::def_wrap(pi_cls, "name"); + readonly_wrapper>::def_wrap(pi_cls, + "net"); + readwrite_wrapper, + pass_through>::def_wrap(pi_cls, "type"); + + typedef std::vector PortVector; + typedef std::unordered_map WireMap; + + auto ni_cls = class_>("NetInfo", no_init); + readwrite_wrapper, + conv_from_str>::def_wrap(ni_cls, "name"); + readwrite_wrapper, + unwrap_context>::def_wrap(ni_cls, "driver"); + readonly_wrapper>::def_wrap( + ni_cls, "users"); + readonly_wrapper>::def_wrap(ni_cls, + "wires"); + + auto pr_cls = class_>("PortRef", no_init); + readonly_wrapper>::def_wrap(pr_cls, + "cell"); + readwrite_wrapper, + conv_from_str>::def_wrap(pr_cls, "port"); + readwrite_wrapper, + pass_through>::def_wrap(pr_cls, "budget"); + def("parse_json", parse_json_shim); def("load_design", load_design_shim, return_value_policy()); WRAP_MAP(AttrMap, pass_through, "AttrMap"); + WRAP_MAP(PortMap, wrap_context, "PortMap"); + WRAP_MAP(PinMap, conv_to_str, "PinMap"); arch_wrap_python(); } diff --git a/common/pycontainers.h b/common/pycontainers.h index c8d2257b..260a9dd6 100644 --- a/common/pycontainers.h +++ b/common/pycontainers.h @@ -276,6 +276,11 @@ template struct map_wrapper x.base[PythonConversion::string_converter().from_str(x.ctx, i)] = v; } + static size_t len(wrapped_map &x) + { + return x.base.size(); + } + static void del(T const &x, std::string const &i) { K k = PythonConversion::string_converter().from_str(x.ctx, i); @@ -293,7 +298,7 @@ template struct map_wrapper typename rw::iter_wrap().wrap(iter_name); class_(map_name, no_init) .def("__iter__", rw::iter) - .def("__len__", &T::size) + .def("__len__", len) .def("__getitem__", get) .def("__setitem__", set, with_custodian_and_ward<1, 2>()); } @@ -394,6 +399,11 @@ template struct map_wrapper_uptr x.base[PythonConversion::string_converter().from_str(x.ctx, i)] = typename T::mapped_type(v); } + static size_t len(wrapped_map &x) + { + return x.base.size(); + } + static void del(T const &x, std::string const &i) { K k = PythonConversion::string_converter().from_str(x.ctx, i); @@ -411,7 +421,7 @@ template struct map_wrapper_uptr typename rw::iter_wrap().wrap(iter_name); class_(map_name, no_init) .def("__iter__", rw::iter) - .def("__len__", &T::size) + .def("__len__", len) .def("__getitem__", get) .def("__setitem__", set, with_custodian_and_ward<1, 2>()); } diff --git a/common/pywrappers.h b/common/pywrappers.h index 560d645d..0643eb0a 100644 --- a/common/pywrappers.h +++ b/common/pywrappers.h @@ -61,6 +61,7 @@ template inline Context *get_ctx(typename WrapIfNotContext::mayb { return wrp_ctx.ctx; } + template <> inline Context *get_ctx(WrapIfNotContext::maybe_wrapped_t &unwrp_ctx) { return &unwrp_ctx; @@ -70,6 +71,7 @@ template inline T &get_base(typename WrapIfNotContext::maybe_wra { return wrp_ctx.base; } + template <> inline Context &get_base(WrapIfNotContext::maybe_wrapped_t &unwrp_ctx) { return unwrp_ctx; @@ -80,6 +82,10 @@ template ContextualWrapper wrap_ctx(Context *ctx, T x) { return // Dummy class, to be implemented by users template struct string_converter; +class bad_wrap +{ +}; + // Action options template struct pass_through { @@ -92,6 +98,7 @@ template struct pass_through template struct wrap_context { inline ContextualWrapper operator()(Context *ctx, T x) { return ContextualWrapper(ctx, x); } + using arg_type = T; using ret_type = ContextualWrapper; }; @@ -99,6 +106,7 @@ template struct wrap_context template struct unwrap_context { inline T operator()(Context *ctx, ContextualWrapper x) { return x.base; } + using ret_type = T; using arg_type = ContextualWrapper; }; @@ -106,6 +114,7 @@ template struct unwrap_context template struct conv_from_str { inline T operator()(Context *ctx, std::string x) { return string_converter().from_str(ctx, x); } + using ret_type = T; using arg_type = std::string; }; @@ -113,10 +122,24 @@ template struct conv_from_str template struct conv_to_str { inline std::string operator()(Context *ctx, T x) { return string_converter().to_str(ctx, x); } + using ret_type = std::string; using arg_type = T; }; +template struct deref_and_wrap +{ + inline ContextualWrapper operator()(Context *ctx, T *x) + { + if (x == nullptr) + throw bad_wrap(); + return ContextualWrapper(ctx, *x); + } + + using arg_type = T *; + using ret_type = ContextualWrapper; +}; + // Function wrapper // Zero parameters, one return template struct fn_wrapper_0a @@ -133,6 +156,7 @@ template struct fn_ template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } }; + // One parameter, one return template struct fn_wrapper_1a { @@ -204,6 +228,7 @@ template struct fn_wrapper_0a_v template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } }; + // One parameter, void template struct fn_wrapper_1a_v { @@ -262,11 +287,15 @@ template struct reado using class_type = typename WrapIfNotContext::maybe_wrapped_t; using conv_val_type = typename v_conv::ret_type; - static conv_val_type wrapped_getter(class_type &cls) + static object wrapped_getter(class_type &cls) { Context *ctx = get_ctx(cls); Class &base = get_base(cls); - return v_conv()(ctx, (base.*mem)); + try { + return object(v_conv()(ctx, (base.*mem))); + } catch (bad_wrap &) { + return object(); + } } template static void def_wrap(WrapCls cls_, const char *name) @@ -275,6 +304,38 @@ template struct reado } }; +// Wrapped getter/setter +template struct readwrite_wrapper +{ + using class_type = typename WrapIfNotContext::maybe_wrapped_t; + using conv_val_type = typename get_conv::ret_type; + + static object wrapped_getter(class_type &cls) + { + Context *ctx = get_ctx(cls); + Class &base = get_base(cls); + try { + return object(get_conv()(ctx, (base.*mem))); + } catch (bad_wrap &) { + return object(); + } + } + + using conv_arg_type = typename set_conv::arg_type; + + static void wrapped_setter(class_type &cls, conv_arg_type val) + { + Context *ctx = get_ctx(cls); + Class &base = get_base(cls); + (base.*mem) = set_conv()(ctx, val); + } + + template static void def_wrap(WrapCls cls_, const char *name) + { + cls_.add_property(name, wrapped_getter, wrapped_setter); + } +}; + } // namespace PythonConversion NEXTPNR_NAMESPACE_END -- cgit v1.2.3 From f1bddc2852de2412e6ed9399edf269aaaea4b2e0 Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 4 Jul 2018 14:49:13 +0200 Subject: common: Remove deprecated global IdStrings Signed-off-by: David Shah --- common/nextpnr.cc | 2 -- common/nextpnr.h | 13 ------------- common/pycontainers.h | 10 ++-------- common/pywrappers.h | 6 +++--- 4 files changed, 5 insertions(+), 26 deletions(-) (limited to 'common') diff --git a/common/nextpnr.cc b/common/nextpnr.cc index a197eaff..3861e5fe 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -27,8 +27,6 @@ assertion_failure::assertion_failure(std::string msg, std::string expr_str, std: { } -std::unordered_set IdString::global_ctx; - void IdString::set(const BaseCtx *ctx, const std::string &s) { auto it = ctx->idstring_str_to_idx->find(s); diff --git a/common/nextpnr.h b/common/nextpnr.h index 6a45875b..ec0c2f9f 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -118,16 +118,6 @@ struct IdString bool operator!=(const IdString &other) const { return index != other.index; } bool empty() const { return index == 0; } - - // --- deprecated old API --- - - static std::unordered_set global_ctx; - - NPNR_DEPRECATED const std::string &global_str() const - { - assert(global_ctx.size() == 1); - return str(*global_ctx.begin()); - } }; NEXTPNR_NAMESPACE_END @@ -252,8 +242,6 @@ struct BaseCtx BaseCtx() { - IdString::global_ctx.insert(this); - idstring_str_to_idx = new std::unordered_map; idstring_idx_to_str = new std::vector; IdString::initialize_add(this, "", 0); @@ -262,7 +250,6 @@ struct BaseCtx ~BaseCtx() { - IdString::global_ctx.erase(this); delete idstring_str_to_idx; delete idstring_idx_to_str; } diff --git a/common/pycontainers.h b/common/pycontainers.h index 260a9dd6..f4251558 100644 --- a/common/pycontainers.h +++ b/common/pycontainers.h @@ -276,10 +276,7 @@ template struct map_wrapper x.base[PythonConversion::string_converter().from_str(x.ctx, i)] = v; } - static size_t len(wrapped_map &x) - { - return x.base.size(); - } + static size_t len(wrapped_map &x) { return x.base.size(); } static void del(T const &x, std::string const &i) { @@ -399,10 +396,7 @@ template struct map_wrapper_uptr x.base[PythonConversion::string_converter().from_str(x.ctx, i)] = typename T::mapped_type(v); } - static size_t len(wrapped_map &x) - { - return x.base.size(); - } + static size_t len(wrapped_map &x) { return x.base.size(); } static void del(T const &x, std::string const &i) { diff --git a/common/pywrappers.h b/common/pywrappers.h index 0643eb0a..be274aad 100644 --- a/common/pywrappers.h +++ b/common/pywrappers.h @@ -129,15 +129,15 @@ template struct conv_to_str template struct deref_and_wrap { - inline ContextualWrapper operator()(Context *ctx, T *x) + inline ContextualWrapper operator()(Context *ctx, T *x) { if (x == nullptr) throw bad_wrap(); - return ContextualWrapper(ctx, *x); + return ContextualWrapper(ctx, *x); } using arg_type = T *; - using ret_type = ContextualWrapper; + using ret_type = ContextualWrapper; }; // Function wrapper -- cgit v1.2.3 From 11fb625195168c0b6c4d49cfb2a9ed9a70108ccf Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 4 Jul 2018 14:55:16 +0200 Subject: python: Renaming and fixing 'generic' build Signed-off-by: David Shah --- common/pywrappers.h | 1 - 1 file changed, 1 deletion(-) (limited to 'common') diff --git a/common/pywrappers.h b/common/pywrappers.h index be274aad..725caca8 100644 --- a/common/pywrappers.h +++ b/common/pywrappers.h @@ -221,7 +221,6 @@ template struct fn_wrapper_0a_v static void wrapped_fn(class_type &cls) { - Context *ctx = get_ctx(cls); Class &base = get_base(cls); return (base.*fn)(); } -- cgit v1.2.3