From e48c9e73e7bd30ef49fe3386330337b8a8c02054 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 22 Nov 2018 12:35:07 +0000 Subject: [PATCH] python: Add wrapper for vectors to allow Python access to net.users Signed-off-by: David Shah --- common/command.cc | 2 +- common/pybindings.cc | 19 ++++++++++++-- common/pycontainers.h | 59 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 76 insertions(+), 4 deletions(-) diff --git a/common/command.cc b/common/command.cc index 5070bf9c..d20bb2a2 100644 --- a/common/command.cc +++ b/common/command.cc @@ -144,7 +144,7 @@ void CommandHandler::setupContext(Context *ctx) int r; do { r = rand(); - } while(r == 0); + } while (r == 0); ctx->rngseed(r); } diff --git a/common/pybindings.cc b/common/pybindings.cc index 061dfc47..02928e36 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -68,6 +68,19 @@ void translate_assertfail(const assertion_failure &e) PyErr_SetString(PyExc_AssertionError, e.what()); } +namespace PythonConversion { +template <> struct string_converter +{ + inline PortRef from_str(Context *ctx, std::string name) { NPNR_ASSERT_FALSE("PortRef from_str not implemented"); } + + inline std::string to_str(Context *ctx, const PortRef &pr) + { + return pr.cell->name.str(ctx) + "." + pr.port.str(ctx); + } +}; + +} // namespace PythonConversion + BOOST_PYTHON_MODULE(MODULE_NAME) { register_exception_translator(&translate_assertfail); @@ -120,7 +133,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME) readwrite_wrapper, pass_through>::def_wrap(pi_cls, "type"); - typedef std::vector PortVector; + typedef std::vector PortRefVector; typedef std::unordered_map WireMap; auto ni_cls = class_>("NetInfo", no_init); @@ -128,7 +141,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME) conv_from_str>::def_wrap(ni_cls, "name"); readwrite_wrapper, unwrap_context>::def_wrap(ni_cls, "driver"); - readonly_wrapper>::def_wrap( + readonly_wrapper>::def_wrap( ni_cls, "users"); readonly_wrapper>::def_wrap(ni_cls, "wires"); @@ -148,6 +161,8 @@ BOOST_PYTHON_MODULE(MODULE_NAME) WRAP_MAP(PortMap, wrap_context, "PortMap"); WRAP_MAP(PinMap, conv_to_str, "PinMap"); + WRAP_VECTOR(PortRefVector, wrap_context); + arch_wrap_python(); } diff --git a/common/pycontainers.h b/common/pycontainers.h index 094706f7..70f69c51 100644 --- a/common/pycontainers.h +++ b/common/pycontainers.h @@ -118,10 +118,67 @@ struct range_wrapper #define WRAP_RANGE(t, conv) \ range_wrapper, conv>().wrap(#t "Range", #t "Iterator") +/* +A wrapper for a vector or similar structure. With support for conversion +*/ + +template , + typename value_conv = PythonConversion::pass_through> +struct vector_wrapper +{ + typedef decltype(std::declval().begin()) iterator_t; + typedef decltype(*(std::declval())) value_t; + typedef typename PythonConversion::ContextualWrapper wrapped_vector; + typedef typename PythonConversion::ContextualWrapper> wrapped_pair; + using return_t = typename value_conv::ret_type; + static wrapped_pair iter(wrapped_vector &range) + { + return wrapped_pair(range.ctx, std::make_pair(range.base.begin(), range.base.end())); + } + + static std::string repr(wrapped_vector &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 int len(wrapped_vector &range) { return range.base.size(); } + + static return_t getitem(wrapped_vector &range, int i) + { + return value_conv()(range.ctx, boost::ref(range.base.at(i))); + } + + static void wrap(const char *range_name, const char *iter_name) + { + class_(range_name, no_init) + .def("__iter__", iter) + .def("__repr__", repr) + .def("__len__", len) + .def("__getitem__", getitem); + + iterator_wrapper().wrap(iter_name); + } + + typedef iterator_wrapper iter_wrap; +}; + +#define WRAP_VECTOR(t, conv) vector_wrapper, conv>().wrap(#t, #t "Iterator") + /* Wrapper for a pair, allows accessing either using C++-style members (.first and .second) or as a Python iterable and indexable object - */ +*/ template struct pair_wrapper { typedef std::pair T;