From 579b98c5963c2b86d191d481a2147a663a8196dd Mon Sep 17 00:00:00 2001 From: gatecat Date: Tue, 1 Jun 2021 16:51:18 +0100 Subject: Use hashlib for core netlist structures Signed-off-by: gatecat --- common/basectx.h | 26 ++++---- common/chain_utils.h | 4 +- common/context.cc | 4 +- common/hashlib.h | 4 ++ common/nextpnr_types.h | 23 +++---- common/place_common.cc | 14 ++--- common/placer1.cc | 30 ++++----- common/placer_heap.cc | 38 +++++------ common/pybindings.cc | 14 ++--- common/router2.cc | 8 +-- common/sdf.cc | 8 +-- common/timing.cc | 14 ++--- common/timing_opt.cc | 6 +- common/util.h | 5 +- ecp5/arch_place.cc | 12 ++-- ecp5/arch_pybindings.cc | 8 +-- ecp5/bitstream.cc | 3 +- ecp5/globals.cc | 12 ++-- ecp5/main.cc | 4 +- ecp5/pack.cc | 122 ++++++++++++++++++------------------ fpga_interchange/arch.cc | 4 +- fpga_interchange/arch_pybindings.cc | 8 +-- fpga_interchange/archdefs.h | 2 + fpga_interchange/globals.cc | 8 +-- fpga_interchange/macros.cc | 4 +- generic/arch.cc | 4 +- generic/arch_pybindings.cc | 6 +- generic/pack.cc | 25 ++++---- gowin/arch.cc | 4 +- gowin/arch_pybindings.cc | 6 +- gowin/pack.cc | 25 ++++---- ice40/arch_pybindings.cc | 8 +-- ice40/chains.cc | 4 +- ice40/pack.cc | 65 ++++++++++--------- ice40/pcf.cc | 4 +- json/jsonwrite.cc | 5 +- machxo2/arch_pybindings.cc | 8 +-- machxo2/bitstream.cc | 3 +- machxo2/pack.cc | 25 ++++---- mistral/arch.cc | 4 +- mistral/arch_pybindings.cc | 8 +-- mistral/bitstream.cc | 10 +-- mistral/pack.cc | 28 ++++----- nexus/arch.cc | 8 +-- nexus/arch_pybindings.cc | 8 +-- nexus/fasm.cc | 20 +++--- nexus/global.cc | 4 +- nexus/pack.cc | 80 +++++++++++------------ nexus/post_place.cc | 4 +- 49 files changed, 383 insertions(+), 368 deletions(-) diff --git a/common/basectx.h b/common/basectx.h index fccd12af..dd48c33c 100644 --- a/common/basectx.h +++ b/common/basectx.h @@ -59,29 +59,29 @@ struct BaseCtx mutable StrRingBuffer log_strs; // Project settings and config switches - std::unordered_map settings; + dict settings; // Placed nets and cells. - std::unordered_map> nets; - std::unordered_map> cells; + dict> nets; + dict> cells; // Hierarchical (non-leaf) cells by full path - std::unordered_map hierarchy; + dict hierarchy; // This is the root of the above structure IdString top_module; // Aliases for nets, which may have more than one name due to assignments and hierarchy - std::unordered_map net_aliases; + dict net_aliases; // Top-level ports - std::unordered_map ports; - std::unordered_map port_cells; + dict ports; + dict port_cells; // Floorplanning regions - std::unordered_map> region; + dict> region; // Context meta data - std::unordered_map attrs; + dict attrs; Context *as_ctx = nullptr; @@ -186,10 +186,10 @@ struct BaseCtx bool allUiReload = true; bool frameUiReload = false; - std::unordered_set belUiReload; - std::unordered_set wireUiReload; - std::unordered_set pipUiReload; - std::unordered_set groupUiReload; + pool belUiReload; + pool wireUiReload; + pool pipUiReload; + pool groupUiReload; void refreshUi() { allUiReload = true; } diff --git a/common/chain_utils.h b/common/chain_utils.h index 300d96a1..1bd95c9e 100644 --- a/common/chain_utils.h +++ b/common/chain_utils.h @@ -37,10 +37,10 @@ std::vector find_chains(const Context *ctx, F1 cell_type_predicate, F { std::set chained; std::vector chains; - for (auto cell : sorted(ctx->cells)) { + for (auto &cell : ctx->cells) { if (chained.find(cell.first) != chained.end()) continue; - CellInfo *ci = cell.second; + CellInfo *ci = cell.second.get(); if (cell_type_predicate(ctx, ci)) { CellInfo *start = ci; CellInfo *prev_start = ci; diff --git a/common/context.cc b/common/context.cc index 05c1e094..115b333a 100644 --- a/common/context.cc +++ b/common/context.cc @@ -389,8 +389,8 @@ struct FixupHierarchyWorker // Update hierarchy structure for nets and cells that have hiercell set void rebuild_hierarchy() { - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->hierpath == IdString()) ci->hierpath = ctx->top_module; auto &hc = ctx->hierarchy.at(ci->hierpath); diff --git a/common/hashlib.h b/common/hashlib.h index 48db024f..30fefc65 100644 --- a/common/hashlib.h +++ b/common/hashlib.h @@ -339,6 +339,10 @@ template class dict } public: + using key_type = K; + using mapped_type = T; + using value_type = std::pair; + class const_iterator : public std::iterator> { friend class dict; diff --git a/common/nextpnr_types.h b/common/nextpnr_types.h index 67e60c50..4770f8ae 100644 --- a/common/nextpnr_types.h +++ b/common/nextpnr_types.h @@ -28,6 +28,7 @@ #include #include "archdefs.h" +#include "hashlib.h" #include "nextpnr_base_types.h" #include "nextpnr_namespaces.h" #include "property.h" @@ -56,9 +57,9 @@ struct Region bool constr_wires = false; bool constr_pips = false; - std::unordered_set bels; - std::unordered_set wires; - std::unordered_set piplocs; + pool bels; + pool wires; + pool piplocs; }; struct PipMap @@ -128,10 +129,10 @@ struct NetInfo : ArchNetInfo PortRef driver; std::vector users; - std::unordered_map attrs; + dict attrs; // wire -> uphill_pip - std::unordered_map wires; + dict wires; std::vector aliases; // entries in net_aliases that point to this net @@ -159,8 +160,8 @@ struct CellInfo : ArchCellInfo IdString name, type, hierpath; int32_t udata; - std::unordered_map ports; - std::unordered_map attrs, params; + dict ports; + dict attrs, params; BelId bel; PlaceStrength belStrength = STRENGTH_NONE; @@ -232,13 +233,13 @@ struct HierarchicalCell { IdString name, type, parent, fullpath; // Name inside cell instance -> global name - std::unordered_map leaf_cells, nets; + dict leaf_cells, nets; // Global name -> name inside cell instance - std::unordered_map leaf_cells_by_gname, nets_by_gname; + dict leaf_cells_by_gname, nets_by_gname; // Cell port to net - std::unordered_map ports; + dict ports; // Name inside cell instance -> global name - std::unordered_map hier_cells; + dict hier_cells; }; NEXTPNR_NAMESPACE_END diff --git a/common/place_common.cc b/common/place_common.cc index 7cbeca65..ece47b5a 100644 --- a/common/place_common.cc +++ b/common/place_common.cc @@ -377,9 +377,9 @@ class ConstraintLegaliseWorker public: ConstraintLegaliseWorker(Context *ctx) : ctx(ctx) { - for (auto cell : sorted(ctx->cells)) { + for (auto &cell : ctx->cells) { if (cell.second->cluster != ClusterId()) - cluster2cells[cell.second->cluster].push_back(cell.second); + cluster2cells[cell.second->cluster].push_back(cell.second.get()); } }; @@ -414,11 +414,11 @@ class ConstraintLegaliseWorker int legalise_constraints() { log_info("Legalising relative constraints...\n"); - for (auto cell : sorted(ctx->cells)) { + for (auto &cell : ctx->cells) { oldLocations[cell.first] = ctx->getBelLocation(cell.second->bel); } - for (auto cell : sorted(ctx->cells)) { - bool res = legalise_cell(cell.second); + for (auto &cell : ctx->cells) { + bool res = legalise_cell(cell.second.get()); if (!res) { log_error("failed to place chain starting at cell '%s'\n", cell.first.c_str(ctx)); return -1; @@ -434,8 +434,8 @@ class ConstraintLegaliseWorker } } auto score = print_stats("replacing ripped up cells"); - for (auto cell : sorted(ctx->cells)) - if (get_constraints_distance(ctx, cell.second) != 0) + for (auto &cell : ctx->cells) + if (get_constraints_distance(ctx, cell.second.get()) != 0) log_error("constraint satisfaction check failed for cell '%s' at Bel '%s'\n", cell.first.c_str(ctx), ctx->nameOfBel(cell.second->bel)); return score; diff --git a/common/placer1.cc b/common/placer1.cc index a3e7a696..f9cef92f 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -88,7 +88,7 @@ class SAPlacer diameter = std::max(max_x, max_y) + 1; std::unordered_set cell_types_in_use; - for (auto cell : sorted(ctx->cells)) { + for (auto &cell : ctx->cells) { IdString cell_type = cell.second->type; cell_types_in_use.insert(cell_type); } @@ -108,8 +108,8 @@ class SAPlacer net.second->udata = n++; net_by_udata.push_back(net.second.get()); } - for (auto ®ion : sorted(ctx->region)) { - Region *r = region.second; + for (auto ®ion : ctx->region) { + Region *r = region.second.get(); BoundingBox bb; if (r->constr_bels) { bb.x0 = std::numeric_limits::max(); @@ -360,12 +360,12 @@ class SAPlacer // Only increase temperature if something was moved autoplaced.clear(); chain_basis.clear(); - for (auto cell : sorted(ctx->cells)) { + for (auto &cell : ctx->cells) { if (cell.second->belStrength <= STRENGTH_STRONG && cell.second->cluster != ClusterId() && - ctx->getClusterRootCell(cell.second->cluster) == cell.second) - chain_basis.push_back(cell.second); + ctx->getClusterRootCell(cell.second->cluster) == cell.second.get()) + chain_basis.push_back(cell.second.get()); else if (cell.second->belStrength < STRENGTH_STRONG) - autoplaced.push_back(cell.second); + autoplaced.push_back(cell.second.get()); } // temp = post_legalise_temp; // diameter = std::min(M, diameter * post_legalise_dia_scale); @@ -421,8 +421,8 @@ class SAPlacer } } } - for (auto cell : sorted(ctx->cells)) - if (get_constraints_distance(ctx, cell.second) != 0) + for (auto &cell : ctx->cells) + if (get_constraints_distance(ctx, cell.second.get()) != 0) log_error("constraint satisfaction check failed for cell '%s' at Bel '%s'\n", cell.first.c_str(ctx), ctx->nameOfBel(cell.second->bel)); timing_analysis(ctx); @@ -831,8 +831,8 @@ class SAPlacer // Set up the cost maps void setup_costs() { - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); if (ignore_net(ni)) continue; net_bounds[ni->udata] = get_net_bounds(ni); @@ -1118,8 +1118,8 @@ class SAPlacer // Build the cell port -> user index void build_port_index() { - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); for (size_t i = 0; i < ni->users.size(); i++) { auto &usr = ni->users.at(i); fast_port_to_user[&(usr.cell->ports.at(usr.port))] = i; @@ -1135,8 +1135,8 @@ class SAPlacer { total_net_share = 0; nets_by_tile.resize(max_x + 1, std::vector>(max_y + 1)); - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (int(ci->ports.size()) > large_cell_thresh) continue; Loc loc = ctx->getBelLocation(ci->bel); diff --git a/common/placer_heap.cc b/common/placer_heap.cc index 2f7c7ccb..c26e1556 100644 --- a/common/placer_heap.cc +++ b/common/placer_heap.cc @@ -146,9 +146,9 @@ class HeAPPlacer tmg.setup_only = true; tmg.setup(); - for (auto cell : sorted(ctx->cells)) + for (auto &cell : ctx->cells) if (cell.second->cluster != ClusterId()) - cluster2cells[cell.second->cluster].push_back(cell.second); + cluster2cells[cell.second->cluster].push_back(cell.second.get()); } bool place() @@ -283,8 +283,8 @@ class HeAPPlacer stalled = 0; // Save solution solution.clear(); - for (auto cell : sorted(ctx->cells)) { - solution.emplace_back(cell.second, cell.second->bel, cell.second->belStrength); + for (auto &cell : ctx->cells) { + solution.emplace_back(cell.second.get(), cell.second->bel, cell.second->belStrength); } } else { ++stalled; @@ -311,10 +311,10 @@ class HeAPPlacer ctx->bindBel(bel, cell, strength); } - for (auto cell : sorted(ctx->cells)) { + for (auto &cell : ctx->cells) { if (cell.second->bel == BelId()) log_error("Found unbound cell %s\n", cell.first.c_str(ctx)); - if (ctx->getBoundBelCell(cell.second->bel) != cell.second) + if (ctx->getBoundBelCell(cell.second->bel) != cell.second.get()) log_error("Found cell %s with mismatched binding\n", cell.first.c_str(ctx)); if (ctx->debug) log_info("AP soln: %s -> %s\n", cell.first.c_str(ctx), ctx->nameOfBel(cell.second->bel)); @@ -450,7 +450,7 @@ class HeAPPlacer std::unordered_set cell_types_in_use; std::unordered_set buckets_in_use; - for (auto cell : sorted(ctx->cells)) { + for (auto &cell : ctx->cells) { IdString cell_type = cell.second->type; cell_types_in_use.insert(cell_type); BelBucketId bucket = ctx->getBelBucketForCellType(cell_type); @@ -465,8 +465,8 @@ class HeAPPlacer } // Determine bounding boxes of region constraints - for (auto ®ion : sorted(ctx->region)) { - Region *r = region.second; + for (auto ®ion : ctx->region) { + Region *r = region.second.get(); BoundingBox bb; if (r->constr_bels) { bb.x0 = std::numeric_limits::max(); @@ -539,8 +539,8 @@ class HeAPPlacer ctx->shuffle(t.second.begin(), t.second.end()); } - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->bel != BelId()) { Loc loc = ctx->getBelLocation(ci->bel); cell_locs[cell.first].x = loc.x; @@ -591,7 +591,7 @@ class HeAPPlacer cell_locs[cell.first].global = ctx->getBelGlobalBuf(bel); // FIXME - if (has_connectivity(cell.second) && !cfg.ioBufTypes.count(ci->type)) { + if (has_connectivity(cell.second.get()) && !cfg.ioBufTypes.count(ci->type)) { bels_used.insert(bel); place_cells.push_back(ci); placed = true; @@ -617,7 +617,7 @@ class HeAPPlacer int row = 0; solve_cells.clear(); // First clear the udata of all cells - for (auto cell : sorted(ctx->cells)) + for (auto &cell : ctx->cells) cell.second->udata = dont_solve; // Then update cells to be placed, which excludes cell children for (auto cell : place_cells) { @@ -671,8 +671,8 @@ class HeAPPlacer es.reset(); - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); if (ni->driver.cell == nullptr) continue; if (ni->users.empty()) @@ -783,8 +783,8 @@ class HeAPPlacer wirelen_t total_hpwl() { wirelen_t hpwl = 0; - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); if (ni->driver.cell == nullptr) continue; CellLocation &drvloc = cell_locs.at(ni->driver.cell->name); @@ -809,8 +809,8 @@ class HeAPPlacer auto startt = std::chrono::high_resolution_clock::now(); // Unbind all cells placed in this solution - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->bel != BelId() && (ci->udata != dont_solve || (ci->cluster != ClusterId() && ctx->getClusterRootCell(ci->cluster)->udata != dont_solve))) diff --git a/common/pybindings.cc b/common/pybindings.cc index 504074e1..00ebe66e 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -164,10 +164,10 @@ PYBIND11_EMBEDDED_MODULE(MODULE_NAME, m) .def("maxFallDelay", &DelayQuad::maxFallDelay) .def("delayPair", &DelayQuad::delayPair); - typedef std::unordered_map AttrMap; - typedef std::unordered_map PortMap; - typedef std::unordered_map IdIdMap; - typedef std::unordered_map> RegionMap; + typedef dict AttrMap; + typedef dict PortMap; + typedef dict IdIdMap; + typedef dict> RegionMap; py::class_(m, "BaseCtx"); @@ -218,9 +218,9 @@ PYBIND11_EMBEDDED_MODULE(MODULE_NAME, m) pass_through>::def_wrap(pi_cls, "type"); typedef std::vector PortRefVector; - typedef std::unordered_map WireMap; - typedef std::unordered_set BelSet; - typedef std::unordered_set WireSet; + typedef dict WireMap; + typedef pool BelSet; + typedef pool WireSet; auto ni_cls = py::class_>(m, "NetInfo"); readwrite_wrapper, diff --git a/common/router2.cc b/common/router2.cc index 2156ce28..b0f53ce1 100644 --- a/common/router2.cc +++ b/common/router2.cc @@ -131,8 +131,8 @@ struct Router2 nets.resize(ctx->nets.size()); nets_by_udata.resize(ctx->nets.size()); size_t i = 0; - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); ni->udata = i; nets_by_udata.at(i) = ni; nets.at(i).arcs.resize(ni->users.size()); @@ -231,8 +231,8 @@ struct Router2 flat_wires.push_back(pwd); } - for (auto net_pair : sorted(ctx->nets)) { - auto *net = net_pair.second; + for (auto &net_pair : ctx->nets) { + auto *net = net_pair.second.get(); auto &nd = nets.at(net->udata); for (size_t usr = 0; usr < net->users.size(); usr++) { auto &ad = nd.arcs.at(usr); diff --git a/common/sdf.cc b/common/sdf.cc index 5c3d0a5a..814bf09a 100644 --- a/common/sdf.cc +++ b/common/sdf.cc @@ -254,9 +254,9 @@ void Context::writeSDF(std::ostream &out, bool cvc_mode) const return rf; }; - for (auto cell : sorted(cells)) { + for (const auto &cell : cells) { Cell sc; - const CellInfo *ci = cell.second; + const CellInfo *ci = cell.second.get(); sc.instance = ci->name.str(this); sc.celltype = ci->type.str(this); for (auto port : ci->ports) { @@ -313,8 +313,8 @@ void Context::writeSDF(std::ostream &out, bool cvc_mode) const wr.cells.push_back(sc); } - for (auto net : sorted(nets)) { - NetInfo *ni = net.second; + for (auto &net : nets) { + NetInfo *ni = net.second.get(); if (ni->driver.cell == nullptr) continue; for (auto &usr : ni->users) { diff --git a/common/timing.cc b/common/timing.cc index ef5977de..b68ca35c 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -52,17 +52,17 @@ void TimingAnalyser::run() void TimingAnalyser::init_ports() { // Per cell port structures - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; - for (auto port : sorted_ref(ci->ports)) { + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); + for (auto &port : ci->ports) { auto &data = ports[CellPortKey(ci->name, port.first)]; data.type = port.second.type; data.cell_port = CellPortKey(ci->name, port.first); } } // Cell port to net port mapping - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); if (ni->driver.cell != nullptr) ports[CellPortKey(ni->driver)].net_port = NetPortKey(ni->name); for (size_t i = 0; i < ni->users.size(); i++) @@ -138,8 +138,8 @@ void TimingAnalyser::get_cell_delays() void TimingAnalyser::get_route_delays() { - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); if (ni->driver.cell == nullptr || ni->driver.cell->bel == BelId()) continue; for (auto &usr : ni->users) { diff --git a/common/timing_opt.cc b/common/timing_opt.cc index 854cbc5b..2659f04e 100644 --- a/common/timing_opt.cc +++ b/common/timing_opt.cc @@ -68,8 +68,8 @@ class TimingOptimiser void setup_delay_limits() { max_net_delay.clear(); - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); if (ni->driver.cell == nullptr) continue; for (auto usr : ni->users) { @@ -239,7 +239,7 @@ class TimingOptimiser std::vector> crit_nets; std::vector netnames; std::transform(ctx->nets.begin(), ctx->nets.end(), std::back_inserter(netnames), - [](const std::pair> &kv) { return kv.first; }); + [](const std::pair> &kv) { return kv.first; }); ctx->sorted_shuffle(netnames); for (auto net : netnames) { if (crit_nets.size() >= max_count) diff --git a/common/util.h b/common/util.h index 540646c7..b3e8cbf0 100644 --- a/common/util.h +++ b/common/util.h @@ -55,7 +55,7 @@ std::string str_or_default(const Container &ct, const KeyType &key, std::string }; template -std::string str_or_default(const std::unordered_map &ct, const KeyType &key, std::string def = "") +std::string str_or_default(const dict &ct, const KeyType &key, std::string def = "") { auto found = ct.find(key); if (found == ct.end()) @@ -78,8 +78,7 @@ template int int_or_default(const Contain return std::stoi(found->second); }; -template -int int_or_default(const std::unordered_map &ct, const KeyType &key, int def = 0) +template int int_or_default(const dict &ct, const KeyType &key, int def = 0) { auto found = ct.find(key); if (found == ct.end()) diff --git a/ecp5/arch_place.cc b/ecp5/arch_place.cc index 57c3b181..0da20151 100644 --- a/ecp5/arch_place.cc +++ b/ecp5/arch_place.cc @@ -99,8 +99,8 @@ void Arch::permute_luts() tmg.setup(); std::unordered_map port_to_user; - for (auto net : sorted(nets)) { - NetInfo *ni = net.second; + for (auto &net : nets) { + NetInfo *ni = net.second.get(); for (size_t i = 0; i < ni->users.size(); i++) { auto &usr = ni->users.at(i); port_to_user[&(usr.cell->ports.at(usr.port))] = i; @@ -157,8 +157,8 @@ void Arch::permute_luts() ci->params[id("LUT" + std::to_string(lut) + "_INITVAL")] = Property(new_init, 16); }; - for (auto cell : sorted(cells)) { - CellInfo *ci = cell.second; + for (auto &cell : cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_TRELLIS_SLICE && str_or_default(ci->params, id("MODE"), "LOGIC") == "LOGIC") { proc_lut(ci, 0); proc_lut(ci, 1); @@ -169,8 +169,8 @@ void Arch::permute_luts() void Arch::setup_wire_locations() { wire_loc_overrides.clear(); - for (auto cell : sorted(cells)) { - CellInfo *ci = cell.second; + for (auto &cell : cells) { + CellInfo *ci = cell.second.get(); if (ci->bel == BelId()) continue; if (ci->type == id_MULT18X18D || ci->type == id_DCUA || ci->type == id_DDRDLL || ci->type == id_DQSBUFM || diff --git a/ecp5/arch_pybindings.cc b/ecp5/arch_pybindings.cc index 5218ce36..35660afd 100644 --- a/ecp5/arch_pybindings.cc +++ b/ecp5/arch_pybindings.cc @@ -44,10 +44,10 @@ void arch_wrap_python(py::module &m) .def("place", &Context::place) .def("route", &Context::route); - typedef std::unordered_map> CellMap; - typedef std::unordered_map> NetMap; - typedef std::unordered_map AliasMap; - typedef std::unordered_map HierarchyMap; + typedef dict> CellMap; + typedef dict> NetMap; + typedef dict AliasMap; + typedef dict HierarchyMap; auto belpin_cls = py::class_>(m, "BelPin"); readonly_wrapper>::def_wrap(belpin_cls, "bel"); diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc index f8d11d39..c8349f88 100644 --- a/ecp5/bitstream.cc +++ b/ecp5/bitstream.cc @@ -569,8 +569,7 @@ static std::vector parse_config_str(const Property &p, int length) return word; } -std::string intstr_or_default(const std::unordered_map &ct, const IdString &key, - std::string def = "0") +std::string intstr_or_default(const dict &ct, const IdString &key, std::string def = "0") { auto found = ct.find(key); if (found == ct.end()) diff --git a/ecp5/globals.cc b/ecp5/globals.cc index 36bec64c..1e86fe6b 100644 --- a/ecp5/globals.cc +++ b/ecp5/globals.cc @@ -91,8 +91,8 @@ class Ecp5GlobalRouter } // DCCAs must always drive globals std::vector clocks; - for (auto &cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_DCCA) { NetInfo *glb = ci->ports.at(id_CLKO).net; if (glb != nullptr) { @@ -536,8 +536,8 @@ class Ecp5GlobalRouter } std::vector> toroute; std::unordered_map clocks; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_DCCA) { NetInfo *clock = ci->ports.at(id_CLKO).net; NPNR_ASSERT(clock != nullptr); @@ -577,8 +577,8 @@ class Ecp5GlobalRouter void route_eclk_sources() { // Try and use dedicated paths if possible - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_ECLKSYNCB || ci->type == id_TRELLIS_ECLKBUF || ci->type == id_ECLKBRIDGECS) { std::vector pins; if (ci->type == id_ECLKSYNCB || ci->type == id_TRELLIS_ECLKBUF) { diff --git a/ecp5/main.cc b/ecp5/main.cc index 5d9fc965..f6d734e1 100644 --- a/ecp5/main.cc +++ b/ecp5/main.cc @@ -270,8 +270,8 @@ void ECP5CommandHandler::customAfterLoad(Context *ctx) log_error("failed to parse LPF file '%s'\n", filename.c_str()); } - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_obuf") || ci->type == ctx->id("$nextpnr_iobuf")) { if (!ci->attrs.count(ctx->id("LOC"))) { diff --git a/ecp5/pack.cc b/ecp5/pack.cc index bdf84bcf..db5d22a1 100644 --- a/ecp5/pack.cc +++ b/ecp5/pack.cc @@ -106,8 +106,8 @@ class Ecp5Packer void find_lutff_pairs() { log_info("Finding LUTFF pairs...\n"); - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_lut(ctx, ci) || is_pfumx(ctx, ci) || is_l6mux(ctx, ci)) { NetInfo *znet = ci->ports.at(ctx->id("Z")).net; if (znet != nullptr) { @@ -262,8 +262,8 @@ class Ecp5Packer { log_info("Finding LUT-LUT pairs...\n"); std::unordered_set procdLuts; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_lut(ctx, ci) && procdLuts.find(cell.first) == procdLuts.end()) { NetInfo *znet = ci->ports.at(ctx->id("Z")).net; std::vector inpnets; @@ -392,8 +392,8 @@ class Ecp5Packer } if (ctx->debug) { log_info("Singleton LUTs (packer QoR debug): \n"); - for (auto cell : sorted(ctx->cells)) - if (is_lut(ctx, cell.second) && !procdLuts.count(cell.first)) + for (auto &cell : ctx->cells) + if (is_lut(ctx, cell.second.get()) && !procdLuts.count(cell.first)) log_info(" %s\n", cell.first.c_str(ctx)); } } @@ -443,8 +443,8 @@ class Ecp5Packer { log_info("Packing IOs..\n"); - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_nextpnr_iob(ctx, ci)) { CellInfo *trio = nullptr; NetInfo *ionet = nullptr; @@ -536,8 +536,8 @@ class Ecp5Packer void pack_lut5xs() { log_info("Packing LUT5-7s...\n"); - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_pfumx(ctx, ci)) { std::unique_ptr packed = create_ecp5_cell(ctx, ctx->id("TRELLIS_SLICE"), ci->name.str(ctx) + "_SLICE"); @@ -593,8 +593,8 @@ class Ecp5Packer } flush_cells(); // Pack LUT6s - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_l6mux(ctx, ci)) { NetInfo *ofx0_0 = ci->ports.at(ctx->id("D0")).net; if (ofx0_0 == nullptr) @@ -651,8 +651,8 @@ class Ecp5Packer } flush_cells(); // Pack LUT7s - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_l6mux(ctx, ci)) { NetInfo *ofx1_0 = ci->ports.at(ctx->id("D0")).net; if (ofx1_0 == nullptr) @@ -975,8 +975,8 @@ class Ecp5Packer // Pack distributed RAM void pack_dram() { - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_dpram(ctx, ci)) { // Create RAMW slice @@ -1108,8 +1108,8 @@ class Ecp5Packer void pack_remaining_luts() { log_info("Packing unpaired LUTs into a SLICE...\n"); - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_lut(ctx, ci)) { std::unique_ptr slice = create_ecp5_cell(ctx, ctx->id("TRELLIS_SLICE"), ci->name.str(ctx) + "_SLICE"); @@ -1181,8 +1181,8 @@ class Ecp5Packer ++used_slices; log_info("Packing unpaired FFs into a SLICE...\n"); - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_ff(ctx, ci)) { bool pack_dense = used_slices > (dense_pack_mode_thresh * available_slices); bool requires_m = get_net_or_empty(ci, ctx->id("M")) != nullptr; @@ -1403,8 +1403,8 @@ class Ecp5Packer bool gnd_used = false, vcc_used = false; - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) { IdString drv_cell = ni->driver.cell->name; set_net_constant(ctx, ni, gnd_net.get(), false); @@ -1461,8 +1461,8 @@ class Ecp5Packer c->params[n] = c->params[o]; c->params.erase(o); }; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); // Convert 36-bit PDP RAMs to regular 18-bit DP ones that match the Bel if (ci->type == ctx->id("PDPW16KD")) { ci->params[ctx->id("DATA_WIDTH_A")] = 36; // force PDP mode @@ -1503,8 +1503,8 @@ class Ecp5Packer ci->type = id_DP16KD; } } - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_DP16KD) { // Add ports, even if disconnected, to ensure correct tie-offs for (int i = 0; i < 14; i++) { @@ -1544,8 +1544,8 @@ class Ecp5Packer // Pack DSPs void pack_dsps() { - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_MULT18X18D) { // Add ports, even if disconnected, to ensure correct tie-offs for (auto sig : {"CLK", "CE", "RST"}) @@ -1708,8 +1708,8 @@ class Ecp5Packer // "Pack" DCUs void pack_dcus() { - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_DCUA) { if (ci->attrs.count(ctx->id("LOC"))) { std::string loc = ci->attrs.at(ctx->id("LOC")).as_string(); @@ -1759,8 +1759,8 @@ class Ecp5Packer } } } - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_EXTREFB) { const NetInfo *refo = net_or_nullptr(ci, id_REFCLKO); CellInfo *dcu = nullptr; @@ -1800,8 +1800,8 @@ class Ecp5Packer // Miscellaneous packer tasks void pack_misc() { - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_USRMCLK) { rename_port(ctx, ci, ctx->id("USRMCLKI"), id_PADDO); rename_port(ctx, ci, ctx->id("USRMCLKTS"), id_PADDT); @@ -1829,14 +1829,14 @@ class Ecp5Packer if (ctx->getBelType(bel) == id_EHXPLLL && ctx->checkBelAvail(bel)) available_plls.insert(bel); } - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_EHXPLLL && ci->attrs.count(ctx->id("BEL"))) available_plls.erase(ctx->getBelByNameStr(ci->attrs.at(ctx->id("BEL")).as_string())); } // Place PLL connected to fixed drivers such as IO close to their source - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_EHXPLLL && !ci->attrs.count(ctx->id("BEL"))) { const NetInfo *drivernet = net_or_nullptr(ci, id_CLKI); if (drivernet == nullptr || drivernet->driver.cell == nullptr) @@ -1863,8 +1863,8 @@ class Ecp5Packer } } // Place PLLs driven by logic, etc, randomly - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_EHXPLLL && !ci->attrs.count(ctx->id("BEL"))) { if (available_plls.empty()) log_error("failed to place PLL '%s'\n", ci->name.c_str(ctx)); @@ -2030,8 +2030,8 @@ class Ecp5Packer // Pack DQSBUFs void pack_dqsbuf() { - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_DQSBUFM) { CellInfo *pio = net_driven_by(ctx, ci->ports.at(ctx->id("DQSI")).net, is_trellis_io, id_O); if (pio == nullptr || ci->ports.at(ctx->id("DQSI")).net->users.size() > 1) @@ -2265,8 +2265,8 @@ class Ecp5Packer } }; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == ctx->id("DELAYF") || ci->type == ctx->id("DELAYG")) { CellInfo *i_pio = net_driven_by(ctx, ci->ports.at(ctx->id("A")).net, is_trellis_io, id_O); CellInfo *o_pio = net_only_drives(ctx, ci->ports.at(ctx->id("Z")).net, is_trellis_io, id_I, true); @@ -2349,8 +2349,8 @@ class Ecp5Packer } } - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == ctx->id("IDDRX1F")) { CellInfo *pio = net_driven_by(ctx, ci->ports.at(ctx->id("D")).net, is_trellis_io, id_O); if (pio == nullptr || ci->ports.at(ctx->id("D")).net->users.size() > 1) @@ -2692,8 +2692,8 @@ class Ecp5Packer } flush_cells(); // Constrain ECLK-related cells - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_ECLKBRIDGECS) { Loc loc; NetInfo *i0 = get_net_or_empty(ci, id_CLK0), *i1 = get_net_or_empty(ci, id_CLK1), @@ -2760,8 +2760,8 @@ class Ecp5Packer } } // Promote/route edge clocks - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_IOLOGIC || ci->type == id_DQSBUFM) { if (!ci->ports.count(id_ECLK) || ci->ports.at(id_ECLK).net == nullptr) continue; @@ -2780,8 +2780,8 @@ class Ecp5Packer } flush_cells(); std::unordered_set used_eclksyncb; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_CLKDIVF) { const NetInfo *clki = net_or_nullptr(ci, id_CLKI); for (auto &eclk : eclks) { @@ -2896,8 +2896,8 @@ class Ecp5Packer } } - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_ECLKSYNCB) { // **All** ECLKSYNCBs must be constrained // Most will be dealt with above, but there might be some rogue cases @@ -2921,8 +2921,8 @@ class Ecp5Packer } } - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_CLKDIVF) { if (ci->attrs.count(ctx->id("BEL"))) continue; @@ -3114,8 +3114,8 @@ class Ecp5Packer { // Check for legacy-style JSON (use CEMUX as a clue) and error out, avoiding a confusing assertion failure // later - for (auto cell : sorted(ctx->cells)) { - if (is_ff(ctx, cell.second) && cell.second->params.count(ctx->id("CEMUX")) && + for (auto &cell : ctx->cells) { + if (is_ff(ctx, cell.second.get()) && cell.second->params.count(ctx->id("CEMUX")) && !cell.second->params[ctx->id("CEMUX")].is_string) log_error("Found netlist using legacy-style JSON parameter values, please update your Yosys.\n"); } @@ -3188,8 +3188,8 @@ bool Arch::pack() void Arch::assignArchInfo() { - for (auto cell : sorted(cells)) { - CellInfo *ci = cell.second; + for (auto &cell : cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_TRELLIS_SLICE) { ci->sliceInfo.using_dff = false; @@ -3301,7 +3301,7 @@ void Arch::assignArchInfo() ci->multInfo.is_clocked = ci->multInfo.timing_id != id_MULT18X18D_REGS_NONE; } } - for (auto net : sorted(nets)) { + for (auto &net : nets) { net.second->is_global = bool_or_default(net.second->attrs, id("ECP5_IS_GLOBAL")); } } diff --git a/fpga_interchange/arch.cc b/fpga_interchange/arch.cc index 71c68e66..663587fd 100644 --- a/fpga_interchange/arch.cc +++ b/fpga_interchange/arch.cc @@ -2047,8 +2047,8 @@ void Arch::pack_default_conns() std::vector dead_nets; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); const DefaultCellConnsPOD *conns = get_default_conns(ci->type); if (conns == nullptr) continue; diff --git a/fpga_interchange/arch_pybindings.cc b/fpga_interchange/arch_pybindings.cc index 68619866..03b20841 100644 --- a/fpga_interchange/arch_pybindings.cc +++ b/fpga_interchange/arch_pybindings.cc @@ -49,10 +49,10 @@ void arch_wrap_python(py::module &m) fn_wrapper_1a_v>::def_wrap(ctx_cls, "explain_bel_status"); - typedef std::unordered_map> CellMap; - typedef std::unordered_map> NetMap; - typedef std::unordered_map AliasMap; - typedef std::unordered_map HierarchyMap; + typedef dict> CellMap; + typedef dict> NetMap; + typedef dict AliasMap; + typedef dict HierarchyMap; auto belpin_cls = py::class_>(m, "BelPin"); readonly_wrapper>::def_wrap(belpin_cls, "bel"); diff --git a/fpga_interchange/archdefs.h b/fpga_interchange/archdefs.h index aa3f1e6e..ba4fe054 100644 --- a/fpga_interchange/archdefs.h +++ b/fpga_interchange/archdefs.h @@ -85,12 +85,14 @@ struct GroupId { bool operator==(const GroupId &other) const { return true; } bool operator!=(const GroupId &other) const { return false; } + unsigned int hash() const { return 0; } }; struct DecalId { bool operator==(const DecalId &other) const { return true; } bool operator!=(const DecalId &other) const { return false; } + unsigned int hash() const { return 0; } }; struct BelBucketId diff --git a/fpga_interchange/globals.cc b/fpga_interchange/globals.cc index 66d04f75..918b916e 100644 --- a/fpga_interchange/globals.cc +++ b/fpga_interchange/globals.cc @@ -160,8 +160,8 @@ void Arch::place_globals() // TODO: for more complex PLL type setups, we might want a toposort or iterative loop as the PLL must be placed // before the GBs it drives - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); const GlobalCellPOD *glb_cell = global_cell_info(ci->type); if (glb_cell == nullptr) continue; @@ -239,8 +239,8 @@ void Arch::route_globals() IdString gnd_net_name(chip_info->constants->gnd_net_name); IdString vcc_net_name(chip_info->constants->vcc_net_name); - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); const GlobalCellPOD *glb_cell = global_cell_info(ci->type); if (glb_cell == nullptr) continue; diff --git a/fpga_interchange/macros.cc b/fpga_interchange/macros.cc index eee35d9f..8339829f 100644 --- a/fpga_interchange/macros.cc +++ b/fpga_interchange/macros.cc @@ -53,8 +53,8 @@ void Arch::expand_macros() // Make up a list of cells, so we don't have modify-while-iterating issues Context *ctx = getCtx(); std::vector cells; - for (auto cell : sorted(ctx->cells)) - cells.push_back(cell.second); + for (auto &cell : ctx->cells) + cells.push_back(cell.second.get()); std::vector next_cells; diff --git a/generic/arch.cc b/generic/arch.cc index a683e34e..eb43aa6f 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -553,8 +553,8 @@ bool Arch::place() std::string placer = str_or_default(settings, id("placer"), defaultPlacer); if (placer == "heap") { bool have_iobuf_or_constr = false; - for (auto cell : sorted(cells)) { - CellInfo *ci = cell.second; + for (auto &cell : cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id("GENERIC_IOB") || ci->bel != BelId() || ci->attrs.count(id("BEL"))) { have_iobuf_or_constr = true; break; diff --git a/generic/arch_pybindings.cc b/generic/arch_pybindings.cc index 50544dc1..735c7e41 100644 --- a/generic/arch_pybindings.cc +++ b/generic/arch_pybindings.cc @@ -138,9 +138,9 @@ void arch_wrap_python(py::module &m) fn_wrapper_3a, conv_from_str, pass_through, pass_through>::def_wrap(ctx_cls, "DecalXY"); - typedef std::unordered_map> CellMap; - typedef std::unordered_map> NetMap; - typedef std::unordered_map HierarchyMap; + typedef dict> CellMap; + typedef dict> NetMap; + typedef dict HierarchyMap; readonly_wrapper>::def_wrap(ctx_cls, "cells"); diff --git a/generic/pack.cc b/generic/pack.cc index 6b984fef..a1c325f8 100644 --- a/generic/pack.cc +++ b/generic/pack.cc @@ -34,14 +34,15 @@ static void pack_lut_lutffs(Context *ctx) std::unordered_set packed_cells; std::vector> new_cells; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ctx->verbose) log_info("cell '%s' is of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx)); if (is_lut(ctx, ci)) { std::unique_ptr packed = create_generic_cell(ctx, ctx->id("GENERIC_SLICE"), ci->name.str(ctx) + "_LC"); - std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin())); + for (auto &attr : ci->attrs) + packed->attrs[attr.first] = attr.second; packed_cells.insert(ci->name); if (ctx->verbose) log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx)); @@ -91,12 +92,13 @@ static void pack_nonlut_ffs(Context *ctx) std::unordered_set packed_cells; std::vector> new_cells; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_ff(ctx, ci)) { std::unique_ptr packed = create_generic_cell(ctx, ctx->id("GENERIC_SLICE"), ci->name.str(ctx) + "_DFFLC"); - std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin())); + for (auto &attr : ci->attrs) + packed->attrs[attr.first] = attr.second; if (ctx->verbose) log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx)); packed_cells.insert(ci->name); @@ -158,8 +160,8 @@ static void pack_constants(Context *ctx) bool gnd_used = false, vcc_used = false; - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) { IdString drv_cell = ni->driver.cell->name; set_net_constant(ctx, ni, gnd_net.get(), false); @@ -207,8 +209,8 @@ static void pack_io(Context *ctx) std::vector> new_cells; log_info("Packing IOs..\n"); - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_nextpnr_iob(ctx, ci)) { CellInfo *iob = nullptr; if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_iobuf")) { @@ -254,7 +256,8 @@ static void pack_io(Context *ctx) } packed_cells.insert(ci->name); if (iob != nullptr) - std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(iob->attrs, iob->attrs.begin())); + for (auto &attr : ci->attrs) + iob->attrs[attr.first] = attr.second; } } for (auto pcell : packed_cells) { diff --git a/gowin/arch.cc b/gowin/arch.cc index 5e1811ea..85ff4829 100644 --- a/gowin/arch.cc +++ b/gowin/arch.cc @@ -1009,8 +1009,8 @@ bool Arch::place() std::string placer = str_or_default(settings, id("placer"), defaultPlacer); if (placer == "heap") { bool have_iobuf_or_constr = false; - for (auto cell : sorted(cells)) { - CellInfo *ci = cell.second; + for (auto &cell : cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id("IOB") || ci->bel != BelId() || ci->attrs.count(id("BEL"))) { have_iobuf_or_constr = true; break; diff --git a/gowin/arch_pybindings.cc b/gowin/arch_pybindings.cc index 24a55ac7..58dcbae7 100644 --- a/gowin/arch_pybindings.cc +++ b/gowin/arch_pybindings.cc @@ -137,9 +137,9 @@ void arch_wrap_python(py::module &m) fn_wrapper_3a, conv_from_str, pass_through, pass_through>::def_wrap(ctx_cls, "DecalXY"); - typedef std::unordered_map> CellMap; - typedef std::unordered_map> NetMap; - typedef std::unordered_map HierarchyMap; + typedef dict> CellMap; + typedef dict> NetMap; + typedef dict HierarchyMap; readonly_wrapper>::def_wrap(ctx_cls, "cells"); diff --git a/gowin/pack.cc b/gowin/pack.cc index 204f1c22..a2998c63 100644 --- a/gowin/pack.cc +++ b/gowin/pack.cc @@ -36,13 +36,14 @@ static void pack_lut_lutffs(Context *ctx) std::unordered_set packed_cells; std::vector> new_cells; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ctx->verbose) log_info("cell '%s' is of type '%s'\n", ctx->nameOf(ci), ci->type.c_str(ctx)); if (is_lut(ctx, ci)) { std::unique_ptr packed = create_generic_cell(ctx, ctx->id("SLICE"), ci->name.str(ctx) + "_LC"); - std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin())); + for (auto &attr : ci->attrs) + packed->attrs[attr.first] = attr.second; packed_cells.insert(ci->name); if (ctx->verbose) log_info("packed cell %s into %s\n", ctx->nameOf(ci), ctx->nameOf(packed.get())); @@ -92,11 +93,12 @@ static void pack_nonlut_ffs(Context *ctx) std::unordered_set packed_cells; std::vector> new_cells; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_ff(ctx, ci)) { std::unique_ptr packed = create_generic_cell(ctx, ctx->id("SLICE"), ci->name.str(ctx) + "_DFFLC"); - std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin())); + for (auto &attr : ci->attrs) + packed->attrs[attr.first] = attr.second; if (ctx->verbose) log_info("packed cell %s into %s\n", ctx->nameOf(ci), ctx->nameOf(packed.get())); packed_cells.insert(ci->name); @@ -158,8 +160,8 @@ static void pack_constants(Context *ctx) bool gnd_used = false; - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) { IdString drv_cell = ni->driver.cell->name; set_net_constant(ctx, ni, gnd_net.get(), false); @@ -216,8 +218,8 @@ static void pack_io(Context *ctx) std::vector> new_cells; log_info("Packing IOs..\n"); - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_gowin_iob(ctx, ci)) { CellInfo *iob = nullptr; switch (ci->type.index) { @@ -251,7 +253,8 @@ static void pack_io(Context *ctx) packed_cells.insert(ci->name); if (iob != nullptr) - std::copy(iob->attrs.begin(), iob->attrs.end(), std::inserter(gwiob->attrs, gwiob->attrs.begin())); + for (auto &attr : iob->attrs) + gwiob->attrs[attr.first] = attr.second; } } for (auto pcell : packed_cells) { diff --git a/ice40/arch_pybindings.cc b/ice40/arch_pybindings.cc index 6922887d..41c97b1b 100644 --- a/ice40/arch_pybindings.cc +++ b/ice40/arch_pybindings.cc @@ -60,10 +60,10 @@ void arch_wrap_python(py::module &m) .def("place", &Context::place) .def("route", &Context::route); - typedef std::unordered_map> CellMap; - typedef std::unordered_map> NetMap; - typedef std::unordered_map AliasMap; - typedef std::unordered_map HierarchyMap; + typedef dict> CellMap; + typedef dict> NetMap; + typedef dict AliasMap; + typedef dict HierarchyMap; auto belpin_cls = py::class_>(m, "BelPin"); readonly_wrapper>::def_wrap(belpin_cls, "bel"); diff --git a/ice40/chains.cc b/ice40/chains.cc index 2607959a..f75d329f 100644 --- a/ice40/chains.cc +++ b/ice40/chains.cc @@ -260,8 +260,8 @@ class ChainConstrainer } // Any cells not in chains, but with carry enabled, must also be put in a single-carry chain // for correct processing - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (chained.find(cell.first) == chained.end() && is_lc(ctx, ci) && bool_or_default(ci->params, ctx->id("CARRY_ENABLE"))) { CellChain sChain; diff --git a/ice40/pack.cc b/ice40/pack.cc index 51138a22..1d05a8c2 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -37,13 +37,14 @@ static void pack_lut_lutffs(Context *ctx) int lut_only = 0, lut_and_ff = 0; std::unordered_set packed_cells; std::vector> new_cells; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ctx->verbose) log_info("cell '%s' is of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx)); if (is_lut(ctx, ci)) { std::unique_ptr packed = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), ci->name.str(ctx) + "_LC"); - std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin())); + for (auto &attr : ci->attrs) + packed->attrs[attr.first] = attr.second; packed_cells.insert(ci->name); if (ctx->verbose) log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx)); @@ -103,12 +104,13 @@ static void pack_nonlut_ffs(Context *ctx) std::vector> new_cells; int ff_only = 0; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_ff(ctx, ci)) { std::unique_ptr packed = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), ci->name.str(ctx) + "_DFFLC"); - std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin())); + for (auto &attr : ci->attrs) + packed->attrs[attr.first] = attr.second; if (ctx->verbose) log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx)); packed_cells.insert(ci->name); @@ -147,8 +149,8 @@ static void pack_carries(Context *ctx) std::vector> new_cells; int carry_only = 0; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_carry(ctx, ci)) { packed_cells.insert(cell.first); @@ -275,8 +277,8 @@ static void pack_ram(Context *ctx) std::unordered_set packed_cells; std::vector> new_cells; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_ram(ctx, ci)) { std::unique_ptr packed = create_ice_cell(ctx, ctx->id("ICESTORM_RAM"), ci->name.str(ctx) + "_RAM"); @@ -379,8 +381,8 @@ static void pack_constants(Context *ctx) bool gnd_used = false; - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) { IdString drv_cell = ni->driver.cell->name; set_net_constant(ctx, ni, gnd_net_info, false); @@ -469,8 +471,8 @@ static void pack_io(Context *ctx) std::vector> new_cells; log_info("Packing IOs..\n"); - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_nextpnr_iob(ctx, ci)) { CellInfo *sb = nullptr, *rgb = nullptr; if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_iobuf")) { @@ -531,7 +533,8 @@ static void pack_io(Context *ctx) for (auto port : ci->ports) disconnect_port(ctx, ci, port.first); packed_cells.insert(ci->name); - std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(sb->attrs, sb->attrs.begin())); + for (auto &attr : ci->attrs) + sb->attrs[attr.first] = attr.second; } else if (is_sb_io(ctx, ci) || is_sb_gb_io(ctx, ci)) { NetInfo *net = ci->ports.at(ctx->id("PACKAGE_PIN")).net; if ((net != nullptr) && ((net->users.size() > 2) || @@ -541,8 +544,8 @@ static void pack_io(Context *ctx) ci->name.c_str(ctx)); } } - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_sb_gb_io(ctx, ci)) { // If something is connecto the GLOBAL OUTPUT, create the fake 'matching' SB_GB std::unique_ptr gb = @@ -637,8 +640,8 @@ static void promote_globals(Context *ctx) const int enable_fanout_thresh = 15; const int reset_fanout_thresh = 15; std::map clock_count, reset_count, cen_count, logic_count; - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); if (ni->driver.cell != nullptr && !ctx->is_global_net(ni)) { clock_count[net.first] = 0; reset_count[net.first] = 0; @@ -778,8 +781,8 @@ static void place_plls(Context *ctx) } // Find all the PLLs cells we need to place and do pre-checks - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (!is_sb_pll40(ctx, ci)) continue; @@ -861,8 +864,8 @@ static void place_plls(Context *ctx) } // Scan all SB_IOs to check for conflict with PLL BELs - for (auto io_cell : sorted(ctx->cells)) { - CellInfo *io_ci = io_cell.second; + for (auto &io_cell : ctx->cells) { + CellInfo *io_ci = io_cell.second.get(); if (!is_sb_io(ctx, io_ci)) continue; @@ -899,8 +902,8 @@ static void place_plls(Context *ctx) } // Scan all SB_GBs to check for conflicts with PLL BELs - for (auto gb_cell : sorted(ctx->cells)) { - CellInfo *gb_ci = gb_cell.second; + for (auto &gb_cell : ctx->cells) { + CellInfo *gb_ci = gb_cell.second.get(); if (!is_gbuf(ctx, gb_ci)) continue; @@ -1120,8 +1123,8 @@ static void pack_special(Context *ctx) std::vector> new_cells; // Handle LED_DRV_CUR first to set the ledCurConnected flag before RGB_DRV is handled below. - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_sb_led_drv_cur(ctx, ci)) { /* Force placement (no choices anyway) */ cell_place_unique(ctx, ci); @@ -1139,8 +1142,8 @@ static void pack_special(Context *ctx) ctx->nets.erase(ledpu_net->name); } } - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_sb_lfosc(ctx, ci)) { std::unique_ptr packed = create_ice_cell(ctx, ctx->id("ICESTORM_LFOSC"), ci->name.str(ctx) + "_OSC"); @@ -1298,8 +1301,8 @@ void pack_plls(Context *ctx) std::unordered_set packed_cells; std::vector> new_cells; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_sb_pll40(ctx, ci)) { bool is_pad = is_sb_pll40_pad(ctx, ci); bool is_core = !is_pad; diff --git a/ice40/pcf.cc b/ice40/pcf.cc index 56a4a336..c6289892 100644 --- a/ice40/pcf.cc +++ b/ice40/pcf.cc @@ -108,8 +108,8 @@ bool apply_pcf(Context *ctx, std::string filename, std::istream &in) log_error("unsupported PCF command '%s' (on line %d)\n", cmd.c_str(), lineno); } } - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_obuf") || ci->type == ctx->id("$nextpnr_iobuf")) { if (!ci->attrs.count(ctx->id("BEL"))) { diff --git a/json/jsonwrite.cc b/json/jsonwrite.cc index f92b7038..dbf43351 100644 --- a/json/jsonwrite.cc +++ b/json/jsonwrite.cc @@ -45,7 +45,7 @@ std::string get_string(std::string str) std::string get_name(IdString name, Context *ctx) { return get_string(name.c_str(ctx)); } -void write_parameters(std::ostream &f, Context *ctx, const std::unordered_map ¶meters, +void write_parameters(std::ostream &f, Context *ctx, const dict ¶meters, bool for_module = false) { bool first = true; @@ -64,8 +64,7 @@ struct PortGroup PortType dir; }; -std::vector group_ports(Context *ctx, const std::unordered_map &ports, - bool is_cell = false) +std::vector group_ports(Context *ctx, const dict &ports, bool is_cell = false) { std::vector groups; std::unordered_map base_to_group; diff --git a/machxo2/arch_pybindings.cc b/machxo2/arch_pybindings.cc index 07e25437..aaca813a 100644 --- a/machxo2/arch_pybindings.cc +++ b/machxo2/arch_pybindings.cc @@ -45,10 +45,10 @@ void arch_wrap_python(py::module &m) .def("place", &Context::place) .def("route", &Context::route); - typedef std::unordered_map> CellMap; - typedef std::unordered_map> NetMap; - typedef std::unordered_map AliasMap; - typedef std::unordered_map HierarchyMap; + typedef dict> CellMap; + typedef dict> NetMap; + typedef dict AliasMap; + typedef dict HierarchyMap; auto belpin_cls = py::class_>(m, "BelPin"); readonly_wrapper>::def_wrap(belpin_cls, "bel"); diff --git a/machxo2/bitstream.cc b/machxo2/bitstream.cc index d695b094..8c538bae 100644 --- a/machxo2/bitstream.cc +++ b/machxo2/bitstream.cc @@ -114,8 +114,7 @@ static std::vector int_to_bitvector(int val, int size) return bv; } -std::string intstr_or_default(const std::unordered_map &ct, const IdString &key, - std::string def = "0") +std::string intstr_or_default(const dict &ct, const IdString &key, std::string def = "0") { auto found = ct.find(key); if (found == ct.end()) diff --git a/machxo2/pack.cc b/machxo2/pack.cc index 5a6cd97b..26bda946 100644 --- a/machxo2/pack.cc +++ b/machxo2/pack.cc @@ -35,13 +35,14 @@ static void pack_lut_lutffs(Context *ctx) std::unordered_set packed_cells; std::vector> new_cells; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ctx->verbose) log_info("cell '%s' is of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx)); if (is_lut(ctx, ci)) { std::unique_ptr packed = create_machxo2_cell(ctx, id_FACADE_SLICE, ci->name.str(ctx) + "_LC"); - std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin())); + for (auto &attr : ci->attrs) + packed->attrs[attr.first] = attr.second; packed_cells.insert(ci->name); if (ctx->verbose) @@ -93,15 +94,16 @@ static void pack_remaining_ffs(Context *ctx) std::unordered_set packed_cells; std::vector> new_cells; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_ff(ctx, ci)) { if (ctx->verbose) log_info("cell '%s' of type '%s remains unpacked'\n", ci->name.c_str(ctx), ci->type.c_str(ctx)); std::unique_ptr packed = create_machxo2_cell(ctx, id_FACADE_SLICE, ci->name.str(ctx) + "_LC"); - std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin())); + for (auto &attr : ci->attrs) + packed->attrs[attr.first] = attr.second; auto dff_bel = ci->attrs.find(ctx->id("BEL")); dff_to_lc(ctx, ci, packed.get(), false); @@ -142,7 +144,8 @@ static void set_net_constant(Context *ctx, NetInfo *orig, NetInfo *constnet, boo log_info("FACADE_FF %s is driven by a constant\n", uc->name.c_str(ctx)); std::unique_ptr lc = create_machxo2_cell(ctx, id_FACADE_SLICE, uc->name.str(ctx) + "_CONST"); - std::copy(uc->attrs.begin(), uc->attrs.end(), std::inserter(lc->attrs, lc->attrs.begin())); + for (auto &attr : uc->attrs) + lc->attrs[attr.first] = attr.second; dff_to_lc(ctx, uc, lc.get(), true); packed_cells.insert(uc->name); @@ -193,8 +196,8 @@ static void pack_constants(Context *ctx) std::vector dead_nets; - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) { IdString drv_cell = ni->driver.cell->name; set_net_constant(ctx, ni, gnd_net.get(), false); @@ -234,8 +237,8 @@ static void pack_io(Context *ctx) log_info("Packing IOs..\n"); - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (is_nextpnr_iob(ctx, ci)) { for (auto &p : ci->ports) disconnect_port(ctx, ci, p.first); diff --git a/mistral/arch.cc b/mistral/arch.cc index cfa3e8b3..70e8f806 100644 --- a/mistral/arch.cc +++ b/mistral/arch.cc @@ -375,8 +375,8 @@ void Arch::assign_default_pinmap(CellInfo *cell) void Arch::assignArchInfo() { - for (auto cell : sorted(cells)) { - CellInfo *ci = cell.second; + for (auto &cell : cells) { + CellInfo *ci = cell.second.get(); if (is_comb_cell(ci->type)) assign_comb_info(ci); else if (ci->type == id_MISTRAL_FF) diff --git a/mistral/arch_pybindings.cc b/mistral/arch_pybindings.cc index 23716c93..c44a1fab 100644 --- a/mistral/arch_pybindings.cc +++ b/mistral/arch_pybindings.cc @@ -50,10 +50,10 @@ void arch_wrap_python(py::module &m) fn_wrapper_2a, pass_through, pass_through>::def_wrap(ctx_cls, "compute_lut_mask"); - typedef std::unordered_map> CellMap; - typedef std::unordered_map> NetMap; - typedef std::unordered_map AliasMap; - typedef std::unordered_map HierarchyMap; + typedef dict> CellMap; + typedef dict> NetMap; + typedef dict AliasMap; + typedef dict HierarchyMap; auto belpin_cls = py::class_>(m, "BelPin"); readonly_wrapper>::def_wrap(belpin_cls, "bel"); diff --git a/mistral/bitstream.cc b/mistral/bitstream.cc index 340ba6b9..0e8b9c85 100644 --- a/mistral/bitstream.cc +++ b/mistral/bitstream.cc @@ -156,9 +156,9 @@ struct MistralBitgen void write_routing() { - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; - for (auto wire : sorted_ref(ni->wires)) { + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); + for (auto &wire : ni->wires) { PipId pip = wire.second.pip; if (pip == PipId()) continue; @@ -200,8 +200,8 @@ struct MistralBitgen void write_cells() { - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); Loc loc = ctx->getBelLocation(ci->bel); int bi = ctx->bel_data(ci->bel).block_index; if (ctx->is_io_cell(ci->type)) diff --git a/mistral/pack.cc b/mistral/pack.cc index 90fbfd78..98ab22bf 100644 --- a/mistral/pack.cc +++ b/mistral/pack.cc @@ -133,8 +133,8 @@ struct MistralPacker // Remove unused inverters and high/low drivers std::vector trim_cells; std::vector trim_nets; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type != id_MISTRAL_NOT && ci->type != id_GND && ci->type != id_VCC) continue; IdString port = (ci->type == id_MISTRAL_NOT) ? id_Q : id_Y; @@ -161,15 +161,15 @@ struct MistralPacker void pack_constants() { // Iterate through cells - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); // Skip certain cells at this point if (ci->type != id_MISTRAL_NOT && ci->type != id_GND && ci->type != id_VCC) - process_inv_constants(cell.second); + process_inv_constants(ci); } // Special case - SDATA can only be trimmed if SLOAD is low - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type != id_MISTRAL_FF) continue; if (ci->get_pin_state(id_SLOAD) != PIN_0) @@ -185,7 +185,7 @@ struct MistralPacker // Find the actual IO buffer corresponding to a port; and copy attributes across to it // Note that this relies on Yosys to do IO buffer inference, to avoid tristate issues once we get to synthesised // JSON. In all cases the nextpnr-inserted IO buffers are removed as redundant. - for (auto &port : sorted_ref(ctx->ports)) { + for (auto &port : ctx->ports) { if (!ctx->cells.count(port.first)) log_error("Port '%s' doesn't seem to have a corresponding top level IO\n", ctx->nameOf(port.first)); CellInfo *ci = ctx->cells.at(port.first).get(); @@ -256,8 +256,8 @@ struct MistralPacker // Step 0: deal with top level inserted IO buffers prepare_io(); // Stage 1: apply constraints - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); // Iterate through all IO buffer primitives if (!ctx->is_io_cell(ci->type)) continue; @@ -286,8 +286,8 @@ struct MistralPacker void constrain_carries() { - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type != id_MISTRAL_ALUT_ARITH) continue; const NetInfo *cin = get_net_or_empty(ci, id_CI); @@ -332,8 +332,8 @@ struct MistralPacker } } // Check we reached all the cells in the above pass - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type != id_MISTRAL_ALUT_ARITH) continue; if (ci->cluster == ClusterId()) diff --git a/nexus/arch.cc b/nexus/arch.cc index d5bb9deb..d90236a8 100644 --- a/nexus/arch.cc +++ b/nexus/arch.cc @@ -667,19 +667,19 @@ bool Arch::place() void Arch::pre_routing() { - for (auto cell : sorted(cells)) { - CellInfo *ci = cell.second; + for (auto &cell : cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_MULT9_CORE || ci->type == id_PREADD9_CORE || ci->type == id_MULT18_CORE || ci->type == id_MULT18X36_CORE || ci->type == id_MULT36_CORE || ci->type == id_REG18_CORE || ci->type == id_ACC54_CORE) { - for (auto port : sorted_ref(ci->ports)) { + for (auto &port : ci->ports) { WireId wire = getBelPinWire(ci->bel, port.first); if (wire != WireId()) dsp_wires.insert(wire); } } if (ci->type == id_LRAM_CORE) { - for (auto port : sorted_ref(ci->ports)) { + for (auto &port : ci->ports) { WireId wire = getBelPinWire(ci->bel, port.first); if (wire != WireId()) lram_wires.insert(wire); diff --git a/nexus/arch_pybindings.cc b/nexus/arch_pybindings.cc index a8b04ba7..d6bc7329 100644 --- a/nexus/arch_pybindings.cc +++ b/nexus/arch_pybindings.cc @@ -46,10 +46,10 @@ void arch_wrap_python(py::module &m) .def("place", &Context::place) .def("route", &Context::route); - typedef std::unordered_map> CellMap; - typedef std::unordered_map> NetMap; - typedef std::unordered_map HierarchyMap; - typedef std::unordered_map AliasMap; + typedef dict> CellMap; + typedef dict> NetMap; + typedef dict HierarchyMap; + typedef dict AliasMap; typedef UpDownhillPipRange UphillPipRange; typedef UpDownhillPipRange DownhillPipRange; diff --git a/nexus/fasm.cc b/nexus/fasm.cc index 0afefa4b..13fe00c1 100644 --- a/nexus/fasm.cc +++ b/nexus/fasm.cc @@ -248,7 +248,7 @@ struct NexusFasmWriter // Write out the mux config for a cell void write_cell_muxes(const CellInfo *cell) { - for (auto port : sorted_cref(cell->ports)) { + for (auto &port : cell->ports) { // Only relevant to inputs if (port.second.type != PORT_IN) continue; @@ -539,7 +539,7 @@ struct NexusFasmWriter push_bel(bel); if (cell->type != id_MULT18_CORE && cell->type != id_MULT18X36_CORE && cell->type != id_MULT36_CORE) write_bit(stringf("MODE.%s", ctx->nameOf(cell->type))); - for (auto param : sorted_cref(cell->params)) { + for (auto ¶m : cell->params) { const std::string ¶m_name = param.first.str(ctx); if (is_mux_param(param_name)) continue; @@ -601,7 +601,7 @@ struct NexusFasmWriter write_cell_muxes(cell); pop(); push(stringf("IP_%s", ctx->nameOf(IdString(ctx->bel_data(bel).name)))); - for (auto param : sorted_cref(cell->params)) { + for (auto ¶m : cell->params) { const std::string &name = param.first.str(ctx); if (is_mux_param(name) || name == "CLKMUX_FB" || name == "SEL_FBK") continue; @@ -622,7 +622,7 @@ struct NexusFasmWriter { BelId bel = cell->bel; push(stringf("IP_%s", ctx->nameOf(IdString(ctx->bel_data(bel).name)))); - for (auto param : sorted_cref(cell->params)) { + for (auto ¶m : cell->params) { const std::string &name = param.first.str(ctx); if (is_mux_param(name) || name == "GSR") continue; @@ -753,8 +753,8 @@ struct NexusFasmWriter // Write out placeholder bankref config void write_bankcfg() { - for (auto c : sorted(ctx->cells)) { - const CellInfo *ci = c.second; + for (auto &c : ctx->cells) { + const CellInfo *ci = c.second.get(); if (ci->type != id_SEIO33_CORE) continue; if (!ci->attrs.count(id_IO_TYPE)) @@ -809,12 +809,12 @@ struct NexusFasmWriter write_attribute("oxide.device_variant", ctx->variant); blank(); // Write routing - for (auto n : sorted(ctx->nets)) { - write_net(n.second); + for (auto &n : ctx->nets) { + write_net(n.second.get()); } // Write cell config - for (auto c : sorted(ctx->cells)) { - const CellInfo *ci = c.second; + for (auto &c : ctx->cells) { + const CellInfo *ci = c.second.get(); write_comment(stringf("# Cell %s", ctx->nameOf(ci))); if (ci->type == id_OXIDE_COMB) write_comb(ci); diff --git a/nexus/global.cc b/nexus/global.cc index 53306e21..fa6212e8 100644 --- a/nexus/global.cc +++ b/nexus/global.cc @@ -155,8 +155,8 @@ struct NexusGlobalRouter void operator()() { log_info("Routing globals...\n"); - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); CellInfo *drv = ni->driver.cell; if (drv == nullptr) continue; diff --git a/nexus/pack.cc b/nexus/pack.cc index 66ab4b09..812731cf 100644 --- a/nexus/pack.cc +++ b/nexus/pack.cc @@ -182,8 +182,8 @@ struct NexusPacker { std::map cell_count; std::map new_types; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (rules.count(ci->type)) { cell_count[ci->type.str(ctx)]++; xform_cell(rules, ci); @@ -303,8 +303,8 @@ struct NexusPacker { // Gets a constant net, given the driver type (VHI or VLO) // If one doesn't exist already; then create it - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type != type) continue; NetInfo *z = get_net_or_empty(ci, id_Z); @@ -369,8 +369,8 @@ struct NexusPacker // Remove unused inverters and high/low drivers std::vector trim_cells; std::vector trim_nets; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type != id_INV && ci->type != id_VLO && ci->type != id_VHI && ci->type != id_VCC_DRV) continue; NetInfo *z = get_net_or_empty(ci, id_Z); @@ -474,7 +474,7 @@ struct NexusPacker // Find the actual IO buffer corresponding to a port; and copy attributes across to it // Note that this relies on Yosys to do IO buffer inference, to match vendor tooling behaviour // In all cases the nextpnr-inserted IO buffers are removed as redundant. - for (auto &port : sorted_ref(ctx->ports)) { + for (auto &port : ctx->ports) { if (!ctx->cells.count(port.first)) log_error("Port '%s' doesn't seem to have a corresponding top level IO\n", ctx->nameOf(port.first)); CellInfo *ci = ctx->cells.at(port.first).get(); @@ -579,8 +579,8 @@ struct NexusPacker prepare_io(); // Stage 1: setup constraints - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); // Iterate through all IO buffer primitives if (!iob_types.count(ci->type)) continue; @@ -625,8 +625,8 @@ struct NexusPacker // Stage 2: apply rules for primitives that need them generic_xform(io_rules, false); // Stage 3: all other IO primitives become their bel type - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); // Iterate through all IO buffer primitives if (!iob_types.count(ci->type)) continue; @@ -660,12 +660,12 @@ struct NexusPacker gnd_net = get_const_net(id_VLO); dedi_vcc_net = get_const_net(id_VCC_DRV); // Iterate through cells - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); // Skip certain cells at this point if (ci->type != id_LUT4 && ci->type != id_INV && ci->type != id_VHI && ci->type != id_VLO && ci->type != id_VCC_DRV) - process_inv_constants(cell.second); + process_inv_constants(ci); } // Remove superfluous inverters and constant drivers trim_design(); @@ -854,8 +854,8 @@ struct NexusPacker { std::vector> clk_fanout; int available_globals = 16; - for (auto net : sorted(ctx->nets)) { - NetInfo *ni = net.second; + for (auto &net : ctx->nets) { + NetInfo *ni = net.second.get(); // Skip undriven nets; and nets that are already global if (ni->driver.cell == nullptr) continue; @@ -894,8 +894,8 @@ struct NexusPacker bool did_something = true; while (did_something) { did_something = false; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_OSC_CORE) did_something |= preplace_singleton(ci); else if (ci->type == id_DCC) @@ -916,8 +916,8 @@ struct NexusPacker { // Do this so we don't have an iterate-and-modfiy situation std::vector lutrams; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type != id_DPR16X4) continue; lutrams.push_back(ci); @@ -1031,8 +1031,8 @@ struct NexusPacker {id_PLL, id_PLL_CORE}, {id_DPHY, id_DPHY_CORE}, }; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (!prim_map.count(ci->type)) continue; prim_to_core(ci, prim_map.at(ci->type)); @@ -1084,8 +1084,8 @@ struct NexusPacker generic_xform(bram_rules, true); int wid = 2; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type != id_OXIDE_EBR) continue; if (ci->params.count(id_WID)) @@ -1129,8 +1129,8 @@ struct NexusPacker log_info("Packing LRAM...\n"); generic_xform(lram_rules, true); - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type != id_LRAM_CORE) continue; if (str_or_default(ci->params, ctx->id("ECC_BYTE_SEL"), "BYTE_EN") == "BYTE_EN") @@ -1151,8 +1151,8 @@ struct NexusPacker void pack_widefn() { std::vector widefns; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type != id_WIDEFN9) continue; widefns.push_back(ci); @@ -1200,8 +1200,8 @@ struct NexusPacker // Find root carry cells log_info("Packing carries...\n"); std::vector roots; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type != id_CCU2) continue; if (get_net_or_empty(ci, id_CIN) != nullptr) @@ -1306,7 +1306,7 @@ struct NexusPacker continue; cell->addOutput(bp); } - for (auto port : sorted_ref(cell->ports)) { + for (auto &port : cell->ports) { // Skip if not an output, or being used already for something else if (port.second.type != PORT_OUT || port.second.net != nullptr) continue; @@ -1609,8 +1609,8 @@ struct NexusPacker log_info("Packing DSPs...\n"); std::vector to_remove; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (!dsp_types.count(ci->type)) continue; auto &mt = dsp_types.at(ci->type); @@ -1792,7 +1792,7 @@ struct NexusPacker } for (auto cell : to_remove) { - for (auto port : sorted_ref(cell->ports)) + for (auto &port : cell->ports) disconnect_port(ctx, cell, port.first); ctx->cells.erase(cell->name); } @@ -1949,8 +1949,8 @@ struct NexusPacker {id_FLOCK_CTRL, "2X"}, {id_FLOCK_EN, "ENABLED"}, {id_FLOCK_SRC_SEL, "REFCLK"}, {id_DIV_DEL, "0b0000001"}, {id_FBK_PI_RC, "0b1100"}, {id_FBK_PR_IC, "0b1000"}, }; - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_PLL_CORE) { // Extra log to phys rules rename_port(ctx, ci, id_PLLPOWERDOWN_N, id_PLLPDN); @@ -1975,8 +1975,8 @@ struct NexusPacker void pack_ip() { - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); if (ci->type == id_DPHY_CORE) { auto loc_attr = ci->attrs.find(id_LOC); if (loc_attr == ci->attrs.end()) @@ -2026,8 +2026,8 @@ bool Arch::pack() void Arch::assignArchInfo() { - for (auto cell : sorted(cells)) { - assignCellInfo(cell.second); + for (auto &cell : cells) { + assignCellInfo(cell.second.get()); } } diff --git a/nexus/post_place.cc b/nexus/post_place.cc index b6817b57..068c013e 100644 --- a/nexus/post_place.cc +++ b/nexus/post_place.cc @@ -88,9 +88,9 @@ struct NexusPostPlaceOpt void opt_lutffs() { int moves_made = 0; - for (auto cell : sorted(ctx->cells)) { + for (auto &cell : ctx->cells) { // Search for FF cells - CellInfo *ff = cell.second; + CellInfo *ff = cell.second.get(); if (ff->type != id_OXIDE_FF) continue; // Check M ('fabric') input net -- cgit v1.2.3