From 103dde79de25e2f9250b27134aa3d547d42408e2 Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 26 Jun 2018 14:13:52 +0200 Subject: Fixing Python bindings after adding unique_ptr Signed-off-by: David Shah --- common/design_utils.cc | 2 +- common/nextpnr.h | 2 +- common/place_sa.cc | 8 ++-- common/pybindings.cc | 26 ++++++------- common/pycontainers.h | 103 ++++++++++++++++++++++++++++++++++++++++++++++++- common/rulecheck.cc | 4 +- common/timing.cc | 6 +-- common/util.h | 8 ++-- 8 files changed, 130 insertions(+), 29 deletions(-) (limited to 'common') diff --git a/common/design_utils.cc b/common/design_utils.cc index 74310ab4..58257bb7 100644 --- a/common/design_utils.cc +++ b/common/design_utils.cc @@ -56,7 +56,7 @@ void print_utilisation(const Context *ctx) { // Sort by Bel type std::map used_types; - for (auto& cell : ctx->cells) { + for (auto &cell : ctx->cells) { used_types[ctx->belTypeFromId(cell.second.get()->type)]++; } std::map available_types; diff --git a/common/nextpnr.h b/common/nextpnr.h index af1ed733..c6c0f2ab 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -19,12 +19,12 @@ #include #include +#include #include #include #include #include #include -#include #ifndef NEXTPNR_H #define NEXTPNR_H diff --git a/common/place_sa.cc b/common/place_sa.cc index 56d92633..3e900c84 100644 --- a/common/place_sa.cc +++ b/common/place_sa.cc @@ -79,7 +79,7 @@ class SAPlacer size_t placed_cells = 0; // Initial constraints placer - for (auto& cell_entry : ctx->cells) { + for (auto &cell_entry : ctx->cells) { CellInfo *cell = cell_entry.second.get(); auto loc = cell->attrs.find(ctx->id("BEL")); if (loc != cell->attrs.end()) { @@ -109,7 +109,7 @@ class SAPlacer // Sort to-place cells for deterministic initial placement std::vector autoplaced; - for (auto& cell : ctx->cells) { + for (auto &cell : ctx->cells) { CellInfo *ci = cell.second.get(); if (ci->bel == BelId()) { autoplaced.push_back(cell.second.get()); @@ -137,7 +137,7 @@ class SAPlacer // Calculate wirelength after initial placement curr_wirelength = 0; curr_tns = 0; - for (auto& net : ctx->nets) { + for (auto &net : ctx->nets) { wirelen_t wl = get_wirelength(net.second.get(), curr_tns); wirelengths[net.first] = wl; curr_wirelength += wl; @@ -211,7 +211,7 @@ class SAPlacer // accumulating over time curr_wirelength = 0; curr_tns = 0; - for (auto& net : ctx->nets) { + for (auto &net : ctx->nets) { wirelen_t wl = get_wirelength(net.second.get(), curr_tns); wirelengths[net.first] = wl; curr_wirelength += wl; diff --git a/common/pybindings.cc b/common/pybindings.cc index 3a43478c..83043da1 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -26,8 +26,8 @@ #include "nextpnr.h" #include +#include #include - NEXTPNR_NAMESPACE_BEGIN // Required to determine concatenated module name (which differs for different @@ -55,10 +55,10 @@ void parse_json_shim(std::string filename, Context &d) } // Create a new Chip and load design from json file -Context load_design_shim(std::string filename, ArchArgs args) +Context *load_design_shim(std::string filename, ArchArgs args) { - Context d(args); - parse_json_shim(filename, d); + Context *d = new Context(args); + parse_json_shim(filename, *d); return d; } @@ -74,7 +74,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME) class_("PortRef").def_readwrite("cell", &PortRef::cell).def_readwrite("port", &PortRef::port); - class_("NetInfo") + class_("NetInfo") .def_readwrite("name", &NetInfo::name) .def_readwrite("driver", &NetInfo::driver) .def_readwrite("users", &NetInfo::users) @@ -96,7 +96,7 @@ 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) @@ -108,15 +108,15 @@ BOOST_PYTHON_MODULE(MODULE_NAME) WRAP_MAP(decltype(CellInfo::ports), "IdPortMap"); // WRAP_MAP(decltype(CellInfo::pins), "IdIdMap"); - class_("BaseCtx", no_init) - .def_readwrite("nets", &Context::nets) - .def_readwrite("cells", &Context::cells); + class_("BaseCtx", no_init) + .add_property("nets", make_getter(&Context::nets, return_internal_reference<>())) + .add_property("cells", make_getter(&Context::nets, return_internal_reference<>())); - WRAP_MAP(decltype(Context::nets), "IdNetMap"); - WRAP_MAP(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); + def("load_design", load_design_shim, return_value_policy()); class_("IdString") .def("__str__", &IdString::global_str, return_value_policy()) @@ -124,7 +124,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME) .def(self == self); arch_wrap_python(); - class_>("Context", no_init).def("checksum", &Context::checksum); + class_, boost::noncopyable>("Context", no_init).def("checksum", &Context::checksum); } void arch_appendinittab() { PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME); } diff --git a/common/pycontainers.h b/common/pycontainers.h index 85a19fba..01145ea7 100644 --- a/common/pycontainers.h +++ b/common/pycontainers.h @@ -228,7 +228,7 @@ template struct map_wrapper std::terminate(); } - static void set(T &x, K const &i, V const &v) { x[i] = v; } + static void set(T &x, K const &i, V &v) { x[i] = v; } static void del(T const &x, K const &i) { @@ -252,7 +252,108 @@ template struct map_wrapper } }; +/* +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 typename T::second_type::element_type V; + struct pair_iterator_wrapper + { + static object next(std::pair &iter) + { + if (iter.second == 0) { + iter.second++; + return object(iter.first.first); + } else if (iter.second == 1) { + iter.second++; + return object(iter.first.second.get()); + } 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); + } + }; + + static object get(T &x, int i) + { + if ((i >= 2) || (i < 0)) + KeyError(); + return (i == 1) ? object(x.second.get()) : object(x.first); + } + + static int len(T &x) { return 2; } + + static std::pair iter(T &x) { return std::make_pair(boost::ref(x), 0); }; + + static V &second_getter(T &t) { return *t.second.get(); } + + static void wrap(const char *pair_name, const char *iter_name) + { + pair_iterator_wrapper::wrap(iter_name); + 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<>())); + } +}; + +/* +Wrapper for a map, either an unordered_map, regular map or dict + */ + +template struct map_wrapper_uptr +{ + typedef typename std::remove_cv::type>::type K; + typedef typename T::mapped_type::pointer 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).get(); + KeyError(); + std::terminate(); + } + + static void set(T &x, K const &i, V const &v) { x[i] = typename T::mapped_type(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 *kv_iter_name, const char *iter_name) + { + map_pair_wrapper_uptr::wrap(kv_name, kv_iter_name); + 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 "KeyValueIter", #name "Iterator") +#define WRAP_MAP_UPTR(t, name) \ + map_wrapper_uptr().wrap(#name, #name "KeyValue", #name "KeyValueIter", #name "Iterator") NEXTPNR_NAMESPACE_END diff --git a/common/rulecheck.cc b/common/rulecheck.cc index d406178a..2570dd65 100644 --- a/common/rulecheck.cc +++ b/common/rulecheck.cc @@ -11,7 +11,7 @@ bool check_all_nets_driven(Context *ctx) log_info("Rule checker, Verifying pre-placed design\n"); - for (auto& cell_entry : ctx->cells) { + for (auto &cell_entry : ctx->cells) { CellInfo *cell = cell_entry.second.get(); if (debug) @@ -39,7 +39,7 @@ bool check_all_nets_driven(Context *ctx) } } - for (auto& net_entry : ctx->nets) { + for (auto &net_entry : ctx->nets) { NetInfo *net = net_entry.second.get(); assert(net->name == net_entry.first); diff --git a/common/timing.cc b/common/timing.cc index 5b929c4c..9b10068e 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -76,13 +76,13 @@ void assign_budget(Context *ctx, float default_clock) log_info("Annotating ports with timing budgets\n"); // Clear delays to a very high value first delay_t default_slack = delay_t(1.0e12 / default_clock); - for (auto& net : ctx->nets) { + for (auto &net : ctx->nets) { for (auto &usr : net.second->users) { usr.budget = default_slack; } } // Go through all clocked drivers and set up paths - for (auto& cell : ctx->cells) { + for (auto &cell : ctx->cells) { for (auto port : cell.second->ports) { if (port.second.type == PORT_OUT) { IdString clock_domain = ctx->getPortClock(cell.second.get(), port.first); @@ -96,7 +96,7 @@ void assign_budget(Context *ctx, float default_clock) } // Post-allocation check - for (auto& net : ctx->nets) { + for (auto &net : ctx->nets) { for (auto user : net.second->users) { if (user.budget < 0) log_warning("port %s.%s, connected to net '%s', has negative " diff --git a/common/util.h b/common/util.h index b1cab650..c888c8b8 100644 --- a/common/util.h +++ b/common/util.h @@ -57,11 +57,11 @@ bool bool_or_default(const Container &ct, const KeyType &key, bool def = false) }; // Wrap an unordered_map, and allow it to be iterated over sorted by key -template std::map sorted(const std::unordered_map> &orig) +template std::map sorted(const std::unordered_map> &orig) { - std::map retVal; - for(auto& item : orig) - retVal.emplace(std::make_pair(item.first,item.second.get())); + std::map retVal; + for (auto &item : orig) + retVal.emplace(std::make_pair(item.first, item.second.get())); return retVal; }; -- cgit v1.2.3