diff options
-rw-r--r-- | common/design_utils.cc | 2 | ||||
-rw-r--r-- | common/nextpnr.h | 2 | ||||
-rw-r--r-- | common/place_sa.cc | 8 | ||||
-rw-r--r-- | common/pybindings.cc | 26 | ||||
-rw-r--r-- | common/pycontainers.h | 103 | ||||
-rw-r--r-- | common/rulecheck.cc | 4 | ||||
-rw-r--r-- | common/timing.cc | 6 | ||||
-rw-r--r-- | common/util.h | 8 | ||||
-rw-r--r-- | ice40/pybindings.cc | 2 | ||||
-rw-r--r-- | json/jsonparse.cc | 12 |
10 files changed, 137 insertions, 36 deletions
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<BelType, int> used_types; - for (auto& cell : ctx->cells) { + for (auto &cell : ctx->cells) { used_types[ctx->belTypeFromId(cell.second.get()->type)]++; } std::map<BelType, int> 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 <algorithm> #include <assert.h> +#include <memory> #include <stdint.h> #include <string> #include <unordered_map> #include <unordered_set> #include <vector> -#include <memory> #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<CellInfo *> 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 <fstream> +#include <memory> #include <signal.h> - 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>("PortRef").def_readwrite("cell", &PortRef::cell).def_readwrite("port", &PortRef::port); - class_<NetInfo, NetInfo *>("NetInfo") + class_<NetInfo, NetInfo *, boost::noncopyable>("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, CellInfo *>("CellInfo") + class_<CellInfo, CellInfo *, boost::noncopyable>("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, BaseCtx *>("BaseCtx", no_init) - .def_readwrite("nets", &Context::nets) - .def_readwrite("cells", &Context::cells); + class_<BaseCtx, BaseCtx *, boost::noncopyable>("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<manage_new_object>()); class_<IdString>("IdString") .def("__str__", &IdString::global_str, return_value_policy<copy_const_reference>()) @@ -124,7 +124,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME) .def(self == self); arch_wrap_python(); - class_<Context, Context *, bases<Arch>>("Context", no_init).def("checksum", &Context::checksum); + class_<Context, Context *, bases<Arch>, 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 <typename T> 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 <typename T> struct map_wrapper } }; +/* +Special case of above for map key/values where value is a unique_ptr + */ +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) + { + 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_<std::pair<T &, int>>(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<T &, int> 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_<T, boost::noncopyable>(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 <typename T> struct map_wrapper_uptr +{ + typedef typename std::remove_cv<typename std::remove_reference<typename T::key_type>::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<typename KV::first_type, typename KV::second_type>::wrap(kv_name, kv_iter_name); + typedef range_wrapper<T, return_value_policy<copy_non_const_reference>> rw; + typename rw::iter_wrap().wrap(iter_name); + class_<T, boost::noncopyable>(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<t>().wrap(#name, #name "KeyValue", #name "KeyValueIter", #name "Iterator") +#define WRAP_MAP_UPTR(t, name) \ + map_wrapper_uptr<t>().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 <typename K, typename V> std::map<K, V*> sorted(const std::unordered_map<K, std::unique_ptr<V>> &orig) +template <typename K, typename V> std::map<K, V *> sorted(const std::unordered_map<K, std::unique_ptr<V>> &orig) { - std::map<K, V*> retVal; - for(auto& item : orig) - retVal.emplace(std::make_pair(item.first,item.second.get())); + std::map<K, V *> retVal; + for (auto &item : orig) + retVal.emplace(std::make_pair(item.first, item.second.get())); return retVal; }; diff --git a/ice40/pybindings.cc b/ice40/pybindings.cc index bb591289..3c3e2394 100644 --- a/ice40/pybindings.cc +++ b/ice40/pybindings.cc @@ -53,7 +53,7 @@ void arch_wrap_python() ; #undef X - class_<Arch, Arch *, bases<BaseCtx>>("Arch", init<ArchArgs>()) + class_<Arch, Arch *, bases<BaseCtx>, boost::noncopyable>("Arch", init<ArchArgs>()) .def("getBelByName", &Arch::getBelByName) .def("getWireByName", &Arch::getWireByName) .def("getBelName", &Arch::getBelName) diff --git a/json/jsonparse.cc b/json/jsonparse.cc index 36c4f91b..418147e8 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -259,7 +259,7 @@ void vcc_net(Context *ctx, NetInfo *net) cell->ports[port_info.name] = port_info; - ctx->cells[cell->name] = std::move(cell); + ctx->cells[cell->name] = std::move(cell); } void floating_net(Context *ctx, NetInfo *net) @@ -429,12 +429,12 @@ void json_import_ports(Context *ctx, const string &modname, const std::vector<Id if (json_debug) log_info(" Generating a new net, \'%d\'\n", net_num); - std::unique_ptr<NetInfo> net = std::unique_ptr<NetInfo>(new NetInfo()); + std::unique_ptr<NetInfo> net = std::unique_ptr<NetInfo>(new NetInfo()); net->name = net_id; net->driver.cell = NULL; net->driver.port = IdString(); ctx->nets[net_id] = std::move(net); - + this_net = ctx->nets[net_id].get(); } else { // @@ -455,7 +455,7 @@ void json_import_ports(Context *ctx, const string &modname, const std::vector<Id // values here. // // Constants always get their own new net - std::unique_ptr<NetInfo> net = std::unique_ptr<NetInfo>(new NetInfo()); + std::unique_ptr<NetInfo> net = std::unique_ptr<NetInfo>(new NetInfo()); net->name = ctx->id("$const_" + std::to_string(const_net_idx++)); if (wire_node->data_string.compare(string("0")) == 0) { @@ -484,7 +484,7 @@ void json_import_ports(Context *ctx, const string &modname, const std::vector<Id log_error(" Unknown fixed type wire node " "value, \'%s\'\n", wire_node->data_string.c_str()); - IdString n = net->name; + IdString n = net->name; ctx->nets[net->name] = std::move(net); this_net = ctx->nets[n].get(); } @@ -652,7 +652,7 @@ static void insert_iobuf(Context *ctx, NetInfo *net, PortType type, const string iobuf->ports[ctx->id("I")] = PortInfo{ctx->id("I"), nullptr, PORT_IN}; // Split the input and output nets for bidir ports - std::unique_ptr<NetInfo> net2 = std::unique_ptr<NetInfo>(new NetInfo()); + std::unique_ptr<NetInfo> net2 = std::unique_ptr<NetInfo>(new NetInfo()); net2->name = ctx->id("$" + net->name.str(ctx) + "$iobuf_i"); net2->driver = net->driver; if (net->driver.cell != nullptr) { |