diff options
author | David Shah <davey1576@gmail.com> | 2018-07-02 15:59:18 +0200 |
---|---|---|
committer | David Shah <davey1576@gmail.com> | 2018-07-04 14:55:24 +0200 |
commit | 1e96d65ded029f68bb294cfb25c56f138dd51180 (patch) | |
tree | 7b4d9b9804fa400d7e8bf5f0b4afcaf00fbc9dd2 /common | |
parent | 4bc12f2eadc2c369f38dfa54f086b8aa2c94fd05 (diff) | |
download | nextpnr-1e96d65ded029f68bb294cfb25c56f138dd51180.tar.gz nextpnr-1e96d65ded029f68bb294cfb25c56f138dd51180.tar.bz2 nextpnr-1e96d65ded029f68bb294cfb25c56f138dd51180.zip |
python: Add context wrapper support for ranges
Signed-off-by: David Shah <davey1576@gmail.com>
Diffstat (limited to 'common')
-rw-r--r-- | common/pybindings.cc | 9 | ||||
-rw-r--r-- | common/pybindings.h | 56 | ||||
-rw-r--r-- | common/pycontainers.h | 39 | ||||
-rw-r--r-- | common/pywrappers.h | 44 |
4 files changed, 74 insertions, 74 deletions
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_<std::vector<PortRef>>("PortRefVector").def(vector_indexing_suite<std::vector<PortRef>>()); @@ -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, BaseCtx *, boost::noncopyable>("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<manage_new_object>()); @@ -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 <typename T> struct string_wrapper -{ - template <typename F> struct from_pystring_converter - { - from_pystring_converter() - { - converter::registry::push_back(&convertible, &construct, boost::python::type_id<T>()); - }; - - 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<T> *)data)->storage.bytes; - new (storage) T(fn(std::string(value_ws.begin(), value_ws.end()))); - data->convertible = storage; - } - - static F fn; - }; - - template <typename F> struct to_str_wrapper - { - static F fn; - - std::string str(T &x) { return fn(x); } - }; - - template <typename F1, typename F2> static void wrap(const char *type_name, F1 to_str_fn, F2 from_str_fn) - { - from_pystring_converter<F2>::fn = from_str_fn; - from_pystring_converter<F2>(); - to_str_wrapper<F1>::fn = to_str_fn; - class_<T>(type_name, no_init).def("__str__", to_str_wrapper<F1>::str); - }; -}; - std::string parse_python_exception(); template <typename Tn> 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<IdString> +{ + 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 <type_traits> #include <utility> #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<Iterator, Iterator> containing (current, end) +pair<Iterator, Iterator> containing (current, end), wrapped in a ContextualWrapper + */ -template <typename T, typename P> struct iterator_wrapper +template <typename T, typename P, typename value_conv = PythonConversion::pass_through<T>> struct iterator_wrapper { typedef decltype(*(std::declval<T>())) value_t; - static value_t next(std::pair<T, T> &iter) + typedef PythonConversion::ContextualWrapper<std::pair<T, T>> 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 <typename T, typename P> struct iterator_wrapper static void wrap(const char *python_name) { - class_<std::pair<T, T>>(python_name, no_init).def("__next__", next, P()); + class_<wrapped_iter_t>(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 <typename T, typename P = return_value_policy<return_by_value>> struct range_wrapper +template <typename T, typename P = return_value_policy<return_by_value>, + typename value_conv = PythonConversion::pass_through<T>> +struct range_wrapper { typedef decltype(std::declval<T>().begin()) iterator_t; - - static std::pair<iterator_t, iterator_t> iter(T &range) { return std::make_pair(range.begin(), range.end()); } + typedef typename PythonConversion::ContextualWrapper<T> wrapped_range; + typedef typename PythonConversion::ContextualWrapper<std::pair<iterator_t, iterator_t>> 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_<T>(range_name, no_init).def("__iter__", iter); - iterator_wrapper<iterator_t, P>().wrap(iter_name); + class_<wrapped_range>(range_name, no_init).def("__iter__", iter); + iterator_wrapper<iterator_t, P, value_conv>().wrap(iter_name); } typedef iterator_wrapper<iterator_t, P> iter_wrap; }; -#define WRAP_RANGE(t) range_wrapper<t##Range>().wrap(#t "Range", #t "Iterator") +#define WRAP_RANGE(t, conv) \ + range_wrapper<t##Range, return_value_policy<return_by_value>, conv>().wrap(#t "Range", #t "Iterator") /* Wrapper for a pair, allows accessing either using C++-style members (.first and @@ -259,6 +271,7 @@ template <typename T1, typename T2> struct map_pair_wrapper_uptr { typedef std::pair<T1, T2> T; typedef typename T::second_type::element_type V; + struct pair_iterator_wrapper { static object next(std::pair<T &, int> &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 <typename T> 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 <typename T> struct WrapIfNotContext { - typedef ContextualWrapper<T> maybe_wrapped_t; +template <typename T> struct WrapIfNotContext +{ + typedef ContextualWrapper<T> maybe_wrapped_t; }; -template <> struct WrapIfNotContext<Context> { +template <> struct WrapIfNotContext<Context> +{ typedef Context maybe_wrapped_t; }; - -template <typename T> inline Context *get_ctx(typename WrapIfNotContext<T>::maybe_wrapped_t &wrp_ctx) { +template <typename T> inline Context *get_ctx(typename WrapIfNotContext<T>::maybe_wrapped_t &wrp_ctx) +{ return wrp_ctx.ctx; } -template <> inline Context *get_ctx<Context>(WrapIfNotContext<Context>::maybe_wrapped_t &unwrp_ctx) { +template <> inline Context *get_ctx<Context>(WrapIfNotContext<Context>::maybe_wrapped_t &unwrp_ctx) +{ return &unwrp_ctx; } -template <typename T> inline T&get_base(typename WrapIfNotContext<T>::maybe_wrapped_t &wrp_ctx) { +template <typename T> inline T &get_base(typename WrapIfNotContext<T>::maybe_wrapped_t &wrp_ctx) +{ return wrp_ctx.base; } -template <> inline Context &get_base<Context>(WrapIfNotContext<Context>::maybe_wrapped_t &unwrp_ctx) { +template <> inline Context &get_base<Context>(WrapIfNotContext<Context>::maybe_wrapped_t &unwrp_ctx) +{ return unwrp_ctx; } @@ -76,7 +81,7 @@ template <typename T> ContextualWrapper<T> wrap_ctx(Context *ctx, T x) { return template <typename T> struct string_converter; // Action options -template <typename T> struct do_nothing +template <typename T> struct pass_through { inline T operator()(Context *ctx, T x) { return x; } @@ -113,8 +118,23 @@ template <typename T> struct conv_to_str }; // Function wrapper -// Example: one parameter, one return -template <typename Class, typename FuncT, FuncT fn, typename rv_conv, typename arg1_conv> struct fn_wrapper +// Zero parameters, one return +template <typename Class, typename FuncT, FuncT fn, typename rv_conv> struct fn_wrapper_0a +{ + using class_type = typename WrapIfNotContext<Class>::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<Class>(cls); + Class &base = get_base<Class>(cls); + return rv_conv()(ctx, (base.*fn)()); + } + + template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } +}; +// One parameter, one return +template <typename Class, typename FuncT, FuncT fn, typename rv_conv, typename arg1_conv> struct fn_wrapper_1a { using class_type = typename WrapIfNotContext<Class>::maybe_wrapped_t; using conv_result_type = typename rv_conv::ret_type; |