diff --git a/common/command.cc b/common/command.cc index 9eace237..5b30df58 100644 --- a/common/command.cc +++ b/common/command.cc @@ -192,6 +192,7 @@ int CommandHandler::executeMain(std::unique_ptr ctx) if (vm.count("json") || vm.count("load")) { if (!ctx->pack() && !ctx->force) log_error("Packing design failed.\n"); + assign_budget(ctx.get()); ctx->check(); print_utilisation(ctx.get()); if (!vm.count("pack-only")) { diff --git a/common/nextpnr.cc b/common/nextpnr.cc index dbea26d8..3bdca166 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -232,25 +232,26 @@ void Context::check() const auto ni = n.second.get(); NPNR_ASSERT(n.first == ni->name); for (auto &w : ni->wires) { - NPNR_ASSERT(n.first == getBoundWireNet(w.first)); + NPNR_ASSERT(ni == getBoundWireNet(w.first)); if (w.second.pip != PipId()) { NPNR_ASSERT(w.first == getPipDstWire(w.second.pip)); - NPNR_ASSERT(n.first == getBoundPipNet(w.second.pip)); + NPNR_ASSERT(ni == getBoundPipNet(w.second.pip)); } } } for (auto w : getWires()) { - IdString net = getBoundWireNet(w); - if (net != IdString()) { - NPNR_ASSERT(nets.at(net)->wires.count(w)); + auto ni = getBoundWireNet(w); + if (ni != nullptr) { + NPNR_ASSERT(ni->wires.count(w)); } } for (auto &c : cells) { - NPNR_ASSERT(c.first == c.second->name); - if (c.second->bel != BelId()) - NPNR_ASSERT(getBoundBelCell(c.second->bel) == c.first); + auto ci = c.second.get(); + NPNR_ASSERT(c.first == ci->name); + if (ci->bel != BelId()) + NPNR_ASSERT(getBoundBelCell(c.second->bel) == ci); for (auto &port : c.second->ports) { NetInfo *net = port.second.net; if (net != nullptr) { diff --git a/common/nextpnr.h b/common/nextpnr.h index bb55d4ff..3d9a66ca 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -437,6 +437,13 @@ struct BaseCtx const Context *getCtx() const { return reinterpret_cast(this); } + template const char *nameOf(const T *obj) + { + if (obj == nullptr) + return ""; + return obj->name.c_str(getCtx()); + } + // -------------------------------------------------------------- bool allUiReload = true; diff --git a/common/place_common.cc b/common/place_common.cc index 1baab8a1..fe9cf03d 100644 --- a/common/place_common.cc +++ b/common/place_common.cc @@ -131,7 +131,7 @@ bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality) if (iters >= 4) wirelen += ctx->rng(25); if (wirelen <= best_ripup_wirelen) { - CellInfo *curr_cell = ctx->cells.at(ctx->getBoundBelCell(bel)).get(); + CellInfo *curr_cell = ctx->getBoundBelCell(bel); if (curr_cell->belStrength < STRENGTH_STRONG) { best_ripup_wirelen = wirelen; ripup_bel = bel; @@ -158,7 +158,7 @@ bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality) if (ctx->verbose) log_info(" placed single cell '%s' at '%s'\n", cell->name.c_str(ctx), ctx->getBelName(best_bel).c_str(ctx)); - ctx->bindBel(best_bel, cell->name, STRENGTH_WEAK); + ctx->bindBel(best_bel, cell, STRENGTH_WEAK); cell = ripup_target; } @@ -232,8 +232,8 @@ class ConstraintLegaliseWorker return false; } if (!ctx->checkBelAvail(locBel)) { - IdString confCell = ctx->getConflictingBelCell(locBel); - if (ctx->cells[confCell]->belStrength >= STRENGTH_STRONG) { + CellInfo *confCell = ctx->getConflictingBelCell(locBel); + if (confCell->belStrength >= STRENGTH_STRONG) { return false; } } @@ -362,20 +362,31 @@ class ConstraintLegaliseWorker cp.second.y, cp.second.z); BelId target = ctx->getBelByLocation(cp.second); if (!ctx->checkBelAvail(target)) { - IdString conflicting = ctx->getConflictingBelCell(target); - if (conflicting != IdString()) { - CellInfo *confl_cell = ctx->cells.at(conflicting).get(); + CellInfo *confl_cell = ctx->getConflictingBelCell(target); + if (confl_cell != nullptr) { if (ctx->verbose) - log_info(" '%s' already placed at '%s'\n", conflicting.c_str(ctx), + log_info(" '%s' already placed at '%s'\n", ctx->nameOf(confl_cell), ctx->getBelName(confl_cell->bel).c_str(ctx)); NPNR_ASSERT(confl_cell->belStrength < STRENGTH_STRONG); ctx->unbindBel(target); - rippedCells.insert(conflicting); + rippedCells.insert(confl_cell->name); } } - ctx->bindBel(target, cp.first, STRENGTH_LOCKED); + ctx->bindBel(target, ctx->cells.at(cp.first).get(), STRENGTH_LOCKED); rippedCells.erase(cp.first); } + for (auto cp : solution) { + for (auto bel : ctx->getBelsByTile(cp.second.x, cp.second.y)) { + CellInfo *belCell = ctx->getBoundBelCell(bel); + if (belCell != nullptr && !solution.count(belCell->name)) { + if (!ctx->isValidBelForCell(belCell, bel)) { + NPNR_ASSERT(belCell->belStrength < STRENGTH_STRONG); + ctx->unbindBel(bel); + rippedCells.insert(belCell->name); + } + } + } + } NPNR_ASSERT(constraints_satisfied(cell)); return true; } diff --git a/common/placer1.cc b/common/placer1.cc index c4543e2a..1d00e77a 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -105,7 +105,7 @@ class SAPlacer cell->type.c_str(ctx)); } - ctx->bindBel(bel, cell->name, STRENGTH_USER); + ctx->bindBel(bel, cell, STRENGTH_USER); locked_bels.insert(bel); placed_cells++; } @@ -138,7 +138,8 @@ class SAPlacer if ((placed_cells - constr_placed_cells) % 500 != 0) log_info(" initial placement placed %d/%d cells\n", int(placed_cells - constr_placed_cells), int(autoplaced.size())); - assign_budget(ctx); + if (ctx->slack_redist_iter > 0) + assign_budget(ctx); ctx->yield(); log_info("Running simulated annealing placer.\n"); @@ -256,11 +257,11 @@ class SAPlacer // Final post-pacement validitiy check ctx->yield(); for (auto bel : ctx->getBels()) { - IdString cell = ctx->getBoundBelCell(bel); + CellInfo *cell = ctx->getBoundBelCell(bel); if (!ctx->isBelLocationValid(bel)) { std::string cell_text = "no cell"; - if (cell != IdString()) - cell_text = std::string("cell '") + cell.str(ctx) + "'"; + if (cell != nullptr) + cell_text = std::string("cell '") + ctx->nameOf(cell) + "'"; if (ctx->force) { log_warning("post-placement validity check failed for Bel '%s' " "(%s)\n", @@ -309,7 +310,7 @@ class SAPlacer uint64_t score = ctx->rng64(); if (score <= best_ripup_score) { best_ripup_score = score; - ripup_target = ctx->cells.at(ctx->getBoundBelCell(bel)).get(); + ripup_target = ctx->getBoundBelCell(bel); ripup_bel = bel; } } @@ -324,7 +325,7 @@ class SAPlacer } else { all_placed = true; } - ctx->bindBel(best_bel, cell->name, STRENGTH_WEAK); + ctx->bindBel(best_bel, cell, STRENGTH_WEAK); // Back annotate location cell->attrs[ctx->id("BEL")] = ctx->getBelName(cell->bel).str(ctx); @@ -340,20 +341,17 @@ class SAPlacer new_lengths.clear(); update.clear(); BelId oldBel = cell->bel; - IdString other = ctx->getBoundBelCell(newBel); - CellInfo *other_cell = nullptr; - if (other != IdString()) { - other_cell = ctx->cells[other].get(); - if (other_cell->belStrength > STRENGTH_WEAK) - return false; + CellInfo *other_cell = ctx->getBoundBelCell(newBel); + if (other_cell != nullptr && other_cell->belStrength > STRENGTH_WEAK) { + return false; } int old_dist = get_constraints_distance(ctx, cell); int new_dist; - if (other != IdString()) + if (other_cell != nullptr) old_dist += get_constraints_distance(ctx, other_cell); wirelen_t new_metric = 0, delta; ctx->unbindBel(oldBel); - if (other != IdString()) { + if (other_cell != nullptr) { ctx->unbindBel(newBel); } @@ -361,20 +359,20 @@ class SAPlacer if (port.second.net != nullptr) update.insert(port.second.net); - if (other != IdString()) { + if (other_cell != nullptr) { for (const auto &port : other_cell->ports) if (port.second.net != nullptr) update.insert(port.second.net); } - ctx->bindBel(newBel, cell->name, STRENGTH_WEAK); + ctx->bindBel(newBel, cell, STRENGTH_WEAK); - if (other != IdString()) { - ctx->bindBel(oldBel, other_cell->name, STRENGTH_WEAK); + if (other_cell != nullptr) { + ctx->bindBel(oldBel, other_cell, STRENGTH_WEAK); } - if (!ctx->isBelLocationValid(newBel) || ((other != IdString() && !ctx->isBelLocationValid(oldBel)))) { + if (!ctx->isBelLocationValid(newBel) || ((other_cell != nullptr && !ctx->isBelLocationValid(oldBel)))) { ctx->unbindBel(newBel); - if (other != IdString()) + if (other_cell != nullptr) ctx->unbindBel(oldBel); goto swap_fail; } @@ -391,7 +389,7 @@ class SAPlacer } new_dist = get_constraints_distance(ctx, cell); - if (other != IdString()) + if (other_cell != nullptr) new_dist += get_constraints_distance(ctx, other_cell); delta = new_metric - curr_metric; delta += (cfg.constraintWeight / temp) * (new_dist - old_dist); @@ -400,7 +398,7 @@ class SAPlacer if (delta < 0 || (temp > 1e-6 && (ctx->rng() / float(0x3fffffff)) <= std::exp(-delta / temp))) { n_accept++; } else { - if (other != IdString()) + if (other_cell != nullptr) ctx->unbindBel(oldBel); ctx->unbindBel(newBel); goto swap_fail; @@ -411,9 +409,9 @@ class SAPlacer return true; swap_fail: - ctx->bindBel(oldBel, cell->name, STRENGTH_WEAK); - if (other != IdString()) { - ctx->bindBel(newBel, other, STRENGTH_WEAK); + ctx->bindBel(oldBel, cell, STRENGTH_WEAK); + if (other_cell != nullptr) { + ctx->bindBel(newBel, other_cell, STRENGTH_WEAK); } return false; } diff --git a/common/pywrappers.h b/common/pywrappers.h index 725caca8..4e463afd 100644 --- a/common/pywrappers.h +++ b/common/pywrappers.h @@ -140,6 +140,14 @@ template struct deref_and_wrap using ret_type = ContextualWrapper; }; +template struct addr_and_unwrap +{ + inline T *operator()(Context *ctx, ContextualWrapper x) { return &(x.base); } + + using arg_type = ContextualWrapper; + using ret_type = T *; +}; + // Function wrapper // Zero parameters, one return template struct fn_wrapper_0a diff --git a/common/router1.cc b/common/router1.cc index 77e84696..0733a61e 100644 --- a/common/router1.cc +++ b/common/router1.cc @@ -159,15 +159,15 @@ struct Router if (!ctx->checkWireAvail(next_wire)) { if (!ripup) continue; - IdString ripupWireNet = ctx->getConflictingWireNet(next_wire); - if (ripupWireNet == net_name || ripupWireNet == IdString()) + NetInfo *ripupWireNet = ctx->getConflictingWireNet(next_wire); + if (ripupWireNet == nullptr || ripupWireNet->name == net_name) continue; auto it1 = scores.wireScores.find(next_wire); if (it1 != scores.wireScores.end()) next_delay += (it1->second * ripup_penalty) / 8; - auto it2 = scores.netWireScores.find(std::make_pair(ripupWireNet, next_wire)); + auto it2 = scores.netWireScores.find(std::make_pair(ripupWireNet->name, next_wire)); if (it2 != scores.netWireScores.end()) next_delay += it2->second * ripup_penalty; @@ -177,15 +177,15 @@ struct Router if (!ctx->checkPipAvail(pip)) { if (!ripup) continue; - IdString ripupPipNet = ctx->getConflictingPipNet(pip); - if (ripupPipNet == net_name || ripupPipNet == IdString()) + NetInfo *ripupPipNet = ctx->getConflictingPipNet(pip); + if (ripupPipNet == nullptr || ripupPipNet->name == net_name) continue; auto it1 = scores.pipScores.find(pip); if (it1 != scores.pipScores.end()) next_delay += (it1->second * ripup_penalty) / 8; - auto it2 = scores.netPipScores.find(std::make_pair(ripupPipNet, pip)); + auto it2 = scores.netPipScores.find(std::make_pair(ripupPipNet->name, pip)); if (it2 != scores.netPipScores.end()) next_delay += it2->second * ripup_penalty; @@ -294,12 +294,12 @@ struct Router if (reroute) { // complete ripup ripup_net(ctx, net_name); - ctx->bindWire(src_wire, net_name, STRENGTH_WEAK); + ctx->bindWire(src_wire, ctx->nets.at(net_name).get(), STRENGTH_WEAK); src_wires[src_wire] = ctx->getWireDelay(src_wire).maxDelay(); } else { // re-use existing routes as much as possible if (net_info->wires.count(src_wire) == 0) - ctx->bindWire(src_wire, net_name, STRENGTH_WEAK); + ctx->bindWire(src_wire, ctx->nets.at(net_name).get(), STRENGTH_WEAK); src_wires[src_wire] = ctx->getWireDelay(src_wire).maxDelay(); for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) { @@ -399,42 +399,42 @@ struct Router if (src_wires.count(cursor)) break; - IdString conflicting_wire_net = ctx->getConflictingWireNet(cursor); + NetInfo *conflicting_wire_net = ctx->getConflictingWireNet(cursor); - if (conflicting_wire_net != IdString()) { + if (conflicting_wire_net != nullptr) { NPNR_ASSERT(ripup); - NPNR_ASSERT(conflicting_wire_net != net_name); + NPNR_ASSERT(conflicting_wire_net->name != net_name); ctx->unbindWire(cursor); if (!ctx->checkWireAvail(cursor)) - ripup_net(ctx, conflicting_wire_net); + ripup_net(ctx, conflicting_wire_net->name); - rippedNets.insert(conflicting_wire_net); + rippedNets.insert(conflicting_wire_net->name); scores.wireScores[cursor]++; scores.netWireScores[std::make_pair(net_name, cursor)]++; - scores.netWireScores[std::make_pair(conflicting_wire_net, cursor)]++; + scores.netWireScores[std::make_pair(conflicting_wire_net->name, cursor)]++; } PipId pip = visited[cursor].pip; - IdString conflicting_pip_net = ctx->getConflictingPipNet(pip); + NetInfo *conflicting_pip_net = ctx->getConflictingPipNet(pip); - if (conflicting_pip_net != IdString()) { + if (conflicting_pip_net != nullptr) { NPNR_ASSERT(ripup); - NPNR_ASSERT(conflicting_pip_net != net_name); + NPNR_ASSERT(conflicting_pip_net->name != net_name); if (ctx->getBoundPipNet(pip) == conflicting_pip_net) ctx->unbindPip(pip); if (!ctx->checkPipAvail(pip)) - ripup_net(ctx, conflicting_pip_net); + ripup_net(ctx, conflicting_pip_net->name); - rippedNets.insert(conflicting_pip_net); + rippedNets.insert(conflicting_pip_net->name); scores.pipScores[visited[cursor].pip]++; scores.netPipScores[std::make_pair(net_name, visited[cursor].pip)]++; - scores.netPipScores[std::make_pair(conflicting_pip_net, visited[cursor].pip)]++; + scores.netPipScores[std::make_pair(conflicting_pip_net->name, visited[cursor].pip)]++; } - ctx->bindPip(visited[cursor].pip, net_name, STRENGTH_WEAK); + ctx->bindPip(visited[cursor].pip, ctx->nets.at(net_name).get(), STRENGTH_WEAK); src_wires[cursor] = visited[cursor].delay; cursor = ctx->getPipSrcWire(visited[cursor].pip); } diff --git a/common/timing.cc b/common/timing.cc index f6c5f001..c00e1ba5 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -2,6 +2,7 @@ * nextpnr -- Next Generation Place and Route * * Copyright (C) 2018 David Shah + * Copyright (C) 2018 Eddie Hung * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -32,36 +33,42 @@ typedef std::map DelayFrequency; struct Timing { Context *ctx; + bool net_delays; bool update; delay_t min_slack; PortRefVector current_path; PortRefVector *crit_path; DelayFrequency *slack_histogram; - Timing(Context *ctx, bool update, PortRefVector *crit_path = nullptr, DelayFrequency *slack_histogram = nullptr) - : ctx(ctx), update(update), min_slack(1.0e12 / ctx->target_freq), crit_path(crit_path), - slack_histogram(slack_histogram) + Timing(Context *ctx, bool net_delays, bool update, PortRefVector *crit_path = nullptr, + DelayFrequency *slack_histogram = nullptr) + : ctx(ctx), net_delays(net_delays), update(update), min_slack(1.0e12 / ctx->target_freq), + crit_path(crit_path), slack_histogram(slack_histogram) { } delay_t follow_net(NetInfo *net, int path_length, delay_t slack) { - delay_t net_budget = slack / (path_length + 1); + const delay_t default_budget = slack / (path_length + 1); + delay_t net_budget = default_budget; for (auto &usr : net->users) { + auto delay = net_delays ? ctx->getNetinfoRouteDelay(net, usr) : delay_t(); if (crit_path) current_path.push_back(&usr); - // If budget override is less than existing budget, then do not increment - // path length - int pl = path_length + 1; - auto budget = ctx->getBudgetOverride(net, usr, net_budget); - if (budget < net_budget) { - net_budget = budget; - pl = std::max(1, path_length); + // If budget override exists, use that value and do not increment path_length + auto budget = default_budget; + if (ctx->getBudgetOverride(net, usr, budget)) { + if (update) + usr.budget = std::min(usr.budget, budget); + budget = follow_user_port(usr, path_length, slack - budget); + net_budget = std::min(net_budget, budget); + } + else { + budget = follow_user_port(usr, path_length + 1, slack - delay); + net_budget = std::min(net_budget, budget); + if (update) + usr.budget = std::min(usr.budget, delay + budget); } - auto delay = ctx->getNetinfoRouteDelay(net, usr); - net_budget = std::min(net_budget, follow_user_port(usr, pl, slack - delay)); - if (update) - usr.budget = std::min(usr.budget, delay + net_budget); if (crit_path) current_path.pop_back(); } @@ -149,10 +156,10 @@ void assign_budget(Context *ctx, bool quiet) { if (!quiet) { log_break(); - log_info("Annotating ports with timing budgets for target frequency %.2f MHz\n", ctx->target_freq/1e6); + log_info("Annotating ports with timing budgets for target frequency %.2f MHz\n", ctx->target_freq / 1e6); } - Timing timing(ctx, true /* update */); + Timing timing(ctx, ctx->slack_redist_iter > 0 /* net_delays */, true /* update */); timing.assign_budget(); if (!quiet || ctx->verbose) { @@ -194,7 +201,7 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_path) PortRefVector crit_path; DelayFrequency slack_histogram; - Timing timing(ctx, false /* update */, print_path ? &crit_path : nullptr, + Timing timing(ctx, true /* net_delays */, false /* update */, print_path ? &crit_path : nullptr, print_histogram ? &slack_histogram : nullptr); auto min_slack = timing.walk_paths(); @@ -238,7 +245,7 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_path) delay_t default_slack = delay_t(1.0e12 / ctx->target_freq); log_info("estimated Fmax = %.2f MHz\n", 1e6 / (default_slack - min_slack)); - if (print_histogram) { + if (print_histogram && slack_histogram.size() > 0) { constexpr unsigned num_bins = 20; unsigned bar_width = 60; auto min_slack = slack_histogram.begin()->first; @@ -256,9 +263,11 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_path) log_break(); log_info("Slack histogram:\n"); log_info(" legend: * represents %d endpoint(s)\n", max_freq / bar_width); + log_info(" + represents [1,%d) endpoint(s)\n", max_freq / bar_width); for (unsigned i = 0; i < bins.size(); ++i) - log_info("%6d < ps < %6d |%s\n", min_slack + bin_size * i, min_slack + bin_size * (i + 1), - std::string(bins[i] * bar_width / max_freq, '*').c_str()); + log_info("[%6d, %6d) |%s%c\n", min_slack + bin_size * i, min_slack + bin_size * (i + 1), + std::string(bins[i] * bar_width / max_freq, '*').c_str(), + (bins[i] * bar_width) % max_freq > 0 ? '+' : ' '); } } diff --git a/docs/archapi.md b/docs/archapi.md index 0d910f9e..222b9f78 100644 --- a/docs/archapi.md +++ b/docs/archapi.md @@ -139,11 +139,11 @@ Returns true if the given bel is a global buffer. A global buffer does not "pull Return a (preferably unique) number that represents this bel. This is used in design state checksum calculations. -### void bindBel(BelId bel, IdString cell, PlaceStrength strength) +### void bindBel(BelId bel, CellInfo \*cell, PlaceStrength strength) Bind a given bel to a given cell with the given strength. -This method must also update `CellInfo::bel` and `CellInfo::belStrength`. +This method must also update `cell->bel` and `cell->belStrength`. ### void unbindBel(BelId bel) @@ -155,13 +155,13 @@ This method must also update `CellInfo::bel` and `CellInfo::belStrength`. Returns true if the bel is available. A bel can be unavailable because it is bound, or because it is exclusive to some other resource that is bound. -### IdString getBoundBelCell(BelId bel) const +### CellInfo \*getBoundBelCell(BelId bel) const -Return the cell the given bel is bound to, or `IdString()` if the bel is not bound. +Return the cell the given bel is bound to, or nullptr if the bel is not bound. -### IdString getConflictingBelCell(BelId bel) const +### CellInfo \*getConflictingBelCell(BelId bel) const -If the bel is unavailable, and unbinding a single cell would make it available, then this method must return the name of that cell. +If the bel is unavailable, and unbinding a single cell would make it available, then this method must return that cell. ### const\_range\ getBels() const @@ -204,12 +204,12 @@ simply return `IdString()`. Return a (preferably unique) number that represents this wire. This is used in design state checksum calculations. -### void bindWire(WireId wire, IdString net, PlaceStrength strength) +### void bindWire(WireId wire, NetInfo \*net, PlaceStrength strength) Bind a wire to a net. This method must be used when binding a wire that is driven by a bel pin. Use `binPip()` when binding a wire that is driven by a pip. -This method must also update `NetInfo::wires`. +This method must also update `net->wires`. ### void unbindWire(WireId wire) @@ -221,16 +221,16 @@ This method must also update `NetInfo::wires`. Return true if the wire is available, i.e. can be bound to a net. -### IdString getBoundWireNet(WireId wire) const +### NetInfo \*getBoundWireNet(WireId wire) const Return the net a wire is bound to. -### IdString getConflictingWireNet(WireId wire) const +### NetInfo \*getConflictingWireNet(WireId wire) const -If this returns a non-empty IdString, then unbinding that net +If this returns a non-nullptr, then unbinding that net will make the given wire available. -This returns an empty IdString if the wire is already available, +This returns nullptr if the wire is already available, or if there is no single net that can be unbound to make this wire available. @@ -266,11 +266,11 @@ implementations may simply return `IdString()`. Return a (preferably unique) number that represents this pip. This is used in design state checksum calculations. -### void bindPip(PipId pip, IdString net, PlaceStrength strength) +### void bindPip(PipId pip, NetInfo \*net, PlaceStrength strength) Bid a pip to a net. This also bind the destination wire of that pip. -This method must also update `NetInfo::wires`. +This method must also update `net->wires`. ### void unbindPip(PipId pip) @@ -282,11 +282,11 @@ This method must also update `NetInfo::wires`. Returns true if the given pip is available to be bound to a net. -### IdString getBoundPipNet(PipId pip) const +### NetInfo \*getBoundPipNet(PipId pip) const Return the net this pip is bound to. -### IdString getConflictingPipNet(PipId pip) const +### NetInfo \*getConflictingPipNet(PipId pip) const Return the net that needs to be unbound in order to make this pip available. @@ -402,9 +402,9 @@ Convert an `delay_t` to an actual real-world delay in nanoseconds. Convert a `delay_t` to an integer for checksum calculations. -### delay\_t getBudgetOverride(const NetInfo \*net\_info, const PortRef &sink, delay\_t budget) const +### bool getBudgetOverride(const NetInfo \*net\_info, const PortRef &sink, delay\_t &budget) const -Overwrite or modify the timing budget for a given arc. Returns the new budget. +Overwrite or modify (in-place) the timing budget for a given arc. Returns a bool to indicate whether this was done. Flow Methods ------------ diff --git a/ecp5/arch.cc b/ecp5/arch.cc index 377b8665..d2d62241 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -422,7 +422,7 @@ delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const return 200 * (abs(driver_loc.x - sink_loc.x) + abs(driver_loc.y - sink_loc.y)); } -delay_t Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t budget) const { return budget; } +bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const { return false; } // ----------------------------------------------------------------------- @@ -479,7 +479,7 @@ DecalXY Arch::getBelDecal(BelId bel) const decalxy.decal.type = DecalId::TYPE_BEL; decalxy.decal.location = bel.location; decalxy.decal.z = bel.index; - decalxy.decal.active = bel_to_cell.count(bel) && (bel_to_cell.at(bel) != IdString()); + decalxy.decal.active = bel_to_cell.count(bel) && (bel_to_cell.at(bel) != nullptr); return decalxy; } diff --git a/ecp5/arch.h b/ecp5/arch.h index 223f1ec5..55c1caa1 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -404,10 +404,9 @@ struct Arch : BaseCtx mutable std::unordered_map wire_by_name; mutable std::unordered_map pip_by_name; - std::unordered_map bel_to_cell; - std::unordered_map wire_to_net; - std::unordered_map pip_to_net; - std::unordered_map switches_locked; + std::unordered_map bel_to_cell; + std::unordered_map wire_to_net; + std::unordered_map pip_to_net; ArchArgs args; Arch(ArchArgs args); @@ -448,23 +447,23 @@ struct Arch : BaseCtx uint32_t getBelChecksum(BelId bel) const { return bel.index; } - void bindBel(BelId bel, IdString cell, PlaceStrength strength) + void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength) { NPNR_ASSERT(bel != BelId()); - NPNR_ASSERT(bel_to_cell[bel] == IdString()); + NPNR_ASSERT(bel_to_cell[bel] == nullptr); bel_to_cell[bel] = cell; - cells[cell]->bel = bel; - cells[cell]->belStrength = strength; + cell->bel = bel; + cell->belStrength = strength; refreshUiBel(bel); } void unbindBel(BelId bel) { NPNR_ASSERT(bel != BelId()); - NPNR_ASSERT(bel_to_cell[bel] != IdString()); - cells[bel_to_cell[bel]]->bel = BelId(); - cells[bel_to_cell[bel]]->belStrength = STRENGTH_NONE; - bel_to_cell[bel] = IdString(); + NPNR_ASSERT(bel_to_cell[bel] != nullptr); + bel_to_cell[bel]->bel = BelId(); + bel_to_cell[bel]->belStrength = STRENGTH_NONE; + bel_to_cell[bel] = nullptr; refreshUiBel(bel); } @@ -485,23 +484,23 @@ struct Arch : BaseCtx bool checkBelAvail(BelId bel) const { NPNR_ASSERT(bel != BelId()); - return bel_to_cell.find(bel) == bel_to_cell.end() || bel_to_cell.at(bel) == IdString(); + return bel_to_cell.find(bel) == bel_to_cell.end() || bel_to_cell.at(bel) == nullptr; } - IdString getBoundBelCell(BelId bel) const + CellInfo *getBoundBelCell(BelId bel) const { NPNR_ASSERT(bel != BelId()); if (bel_to_cell.find(bel) == bel_to_cell.end()) - return IdString(); + return nullptr; else return bel_to_cell.at(bel); } - IdString getConflictingBelCell(BelId bel) const + CellInfo *getConflictingBelCell(BelId bel) const { NPNR_ASSERT(bel != BelId()); if (bel_to_cell.find(bel) == bel_to_cell.end()) - return IdString(); + return nullptr; else return bel_to_cell.at(bel); } @@ -558,53 +557,53 @@ struct Arch : BaseCtx uint32_t getWireChecksum(WireId wire) const { return wire.index; } - void bindWire(WireId wire, IdString net, PlaceStrength strength) + void bindWire(WireId wire, NetInfo *net, PlaceStrength strength) { NPNR_ASSERT(wire != WireId()); - NPNR_ASSERT(wire_to_net[wire] == IdString()); + NPNR_ASSERT(wire_to_net[wire] == nullptr); wire_to_net[wire] = net; - nets[net]->wires[wire].pip = PipId(); - nets[net]->wires[wire].strength = strength; + net->wires[wire].pip = PipId(); + net->wires[wire].strength = strength; } void unbindWire(WireId wire) { NPNR_ASSERT(wire != WireId()); - NPNR_ASSERT(wire_to_net[wire] != IdString()); + NPNR_ASSERT(wire_to_net[wire] != nullptr); - auto &net_wires = nets[wire_to_net[wire]]->wires; + auto &net_wires = wire_to_net[wire]->wires; auto it = net_wires.find(wire); NPNR_ASSERT(it != net_wires.end()); auto pip = it->second.pip; if (pip != PipId()) { - pip_to_net[pip] = IdString(); + pip_to_net[pip] = nullptr; } net_wires.erase(it); - wire_to_net[wire] = IdString(); + wire_to_net[wire] = nullptr; } bool checkWireAvail(WireId wire) const { NPNR_ASSERT(wire != WireId()); - return wire_to_net.find(wire) == wire_to_net.end() || wire_to_net.at(wire) == IdString(); + return wire_to_net.find(wire) == wire_to_net.end() || wire_to_net.at(wire) == nullptr; } - IdString getBoundWireNet(WireId wire) const + NetInfo *getBoundWireNet(WireId wire) const { NPNR_ASSERT(wire != WireId()); if (wire_to_net.find(wire) == wire_to_net.end()) - return IdString(); + return nullptr; else return wire_to_net.at(wire); } - IdString getConflictingWireNet(WireId wire) const + NetInfo *getConflictingWireNet(WireId wire) const { NPNR_ASSERT(wire != WireId()); if (wire_to_net.find(wire) == wire_to_net.end()) - return IdString(); + return nullptr; else return wire_to_net.at(wire); } @@ -638,57 +637,57 @@ struct Arch : BaseCtx uint32_t getPipChecksum(PipId pip) const { return pip.index; } - void bindPip(PipId pip, IdString net, PlaceStrength strength) + void bindPip(PipId pip, NetInfo *net, PlaceStrength strength) { NPNR_ASSERT(pip != PipId()); - NPNR_ASSERT(pip_to_net[pip] == IdString()); + NPNR_ASSERT(pip_to_net[pip] == nullptr); pip_to_net[pip] = net; WireId dst; dst.index = locInfo(pip)->pip_data[pip.index].dst_idx; dst.location = pip.location + locInfo(pip)->pip_data[pip.index].rel_dst_loc; - NPNR_ASSERT(wire_to_net[dst] == IdString()); + NPNR_ASSERT(wire_to_net[dst] == nullptr); wire_to_net[dst] = net; - nets[net]->wires[dst].pip = pip; - nets[net]->wires[dst].strength = strength; + net->wires[dst].pip = pip; + net->wires[dst].strength = strength; } void unbindPip(PipId pip) { NPNR_ASSERT(pip != PipId()); - NPNR_ASSERT(pip_to_net[pip] != IdString()); + NPNR_ASSERT(pip_to_net[pip] != nullptr); WireId dst; dst.index = locInfo(pip)->pip_data[pip.index].dst_idx; dst.location = pip.location + locInfo(pip)->pip_data[pip.index].rel_dst_loc; - NPNR_ASSERT(wire_to_net[dst] != IdString()); - wire_to_net[dst] = IdString(); - nets[pip_to_net[pip]]->wires.erase(dst); + NPNR_ASSERT(wire_to_net[dst] != nullptr); + wire_to_net[dst] = nullptr; + pip_to_net[pip]->wires.erase(dst); - pip_to_net[pip] = IdString(); + pip_to_net[pip] = nullptr; } bool checkPipAvail(PipId pip) const { NPNR_ASSERT(pip != PipId()); - return pip_to_net.find(pip) == pip_to_net.end() || pip_to_net.at(pip) == IdString(); + return pip_to_net.find(pip) == pip_to_net.end() || pip_to_net.at(pip) == nullptr; } - IdString getBoundPipNet(PipId pip) const + NetInfo *getBoundPipNet(PipId pip) const { NPNR_ASSERT(pip != PipId()); if (pip_to_net.find(pip) == pip_to_net.end()) - return IdString(); + return nullptr; else return pip_to_net.at(pip); } - IdString getConflictingPipNet(PipId pip) const + NetInfo *getConflictingPipNet(PipId pip) const { NPNR_ASSERT(pip != PipId()); if (pip_to_net.find(pip) == pip_to_net.end()) - return IdString(); + return nullptr; else return pip_to_net.at(pip); } @@ -807,7 +806,7 @@ struct Arch : BaseCtx delay_t getRipupDelayPenalty() const { return 200; } float getDelayNS(delay_t v) const { return v * 0.001; } uint32_t getDelayChecksum(delay_t v) const { return v; } - delay_t getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t budget) const; + bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const; // ------------------------------------------------- diff --git a/ecp5/arch_place.cc b/ecp5/arch_place.cc index 84432043..dee4f620 100644 --- a/ecp5/arch_place.cc +++ b/ecp5/arch_place.cc @@ -68,19 +68,18 @@ bool Arch::isBelLocationValid(BelId bel) const std::vector bel_cells; Loc bel_loc = getBelLocation(bel); for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { - IdString cell_other = getBoundBelCell(bel_other); - if (cell_other != IdString()) { - const CellInfo *ci_other = cells.at(cell_other).get(); - bel_cells.push_back(ci_other); + CellInfo *cell_other = getBoundBelCell(bel_other); + if (cell_other != nullptr) { + bel_cells.push_back(cell_other); } } return slicesCompatible(bel_cells); } else { - IdString cellId = getBoundBelCell(bel); - if (cellId == IdString()) + CellInfo *cell = getBoundBelCell(bel); + if (cell == nullptr) return true; else - return isValidBelForCell(cells.at(cellId).get(), bel); + return isValidBelForCell(cell, bel); } } @@ -92,10 +91,9 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const std::vector bel_cells; Loc bel_loc = getBelLocation(bel); for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { - IdString cell_other = getBoundBelCell(bel_other); - if (cell_other != IdString() && bel_other != bel) { - const CellInfo *ci_other = cells.at(cell_other).get(); - bel_cells.push_back(ci_other); + CellInfo *cell_other = getBoundBelCell(bel_other); + if (cell_other != nullptr && bel_other != bel) { + bel_cells.push_back(cell_other); } } diff --git a/ecp5/arch_pybindings.cc b/ecp5/arch_pybindings.cc index c261c3ec..1dc9945b 100644 --- a/ecp5/arch_pybindings.cc +++ b/ecp5/arch_pybindings.cc @@ -60,13 +60,13 @@ void arch_wrap_python() fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getBelChecksum"); fn_wrapper_3a_v, - conv_from_str, pass_through>::def_wrap(ctx_cls, "bindBel"); + addr_and_unwrap, pass_through>::def_wrap(ctx_cls, "bindBel"); fn_wrapper_1a_v>::def_wrap( ctx_cls, "unbindBel"); - fn_wrapper_1a, + fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getBoundBelCell"); fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getConflictingBelCell"); + deref_and_wrap, conv_from_str>::def_wrap(ctx_cls, "getConflictingBelCell"); fn_wrapper_0a>::def_wrap(ctx_cls, "getBels"); @@ -78,15 +78,15 @@ void arch_wrap_python() fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getWireChecksum"); fn_wrapper_3a_v, - conv_from_str, pass_through>::def_wrap(ctx_cls, "bindWire"); + addr_and_unwrap, pass_through>::def_wrap(ctx_cls, "bindWire"); fn_wrapper_1a_v>::def_wrap( ctx_cls, "unbindWire"); fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "checkWireAvail"); - fn_wrapper_1a, + fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getBoundWireNet"); fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getConflictingWireNet"); + deref_and_wrap, conv_from_str>::def_wrap(ctx_cls, "getConflictingWireNet"); fn_wrapper_0a>::def_wrap( ctx_cls, "getWires"); @@ -96,15 +96,15 @@ void arch_wrap_python() fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getPipChecksum"); fn_wrapper_3a_v, - conv_from_str, pass_through>::def_wrap(ctx_cls, "bindPip"); + addr_and_unwrap, pass_through>::def_wrap(ctx_cls, "bindPip"); fn_wrapper_1a_v>::def_wrap( ctx_cls, "unbindPip"); fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "checkPipAvail"); - fn_wrapper_1a, + fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getBoundPipNet"); fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getConflictingPipNet"); + deref_and_wrap, conv_from_str>::def_wrap(ctx_cls, "getConflictingPipNet"); fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getPipsDownhill"); diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc index f12e09b2..a1edf9e5 100644 --- a/ecp5/bitstream.cc +++ b/ecp5/bitstream.cc @@ -163,7 +163,7 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex // Add all set, configurable pips to the config for (auto pip : ctx->getPips()) { - if (ctx->getBoundPipNet(pip) != IdString()) { + if (ctx->getBoundPipNet(pip) != nullptr) { if (ctx->getPipClass(pip) == 0) { // ignore fixed pips std::string tile = ctx->getPipTilename(pip); std::string source = get_trellis_wirename(ctx, pip.location, ctx->getPipSrcWire(pip)); @@ -244,9 +244,9 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex cc.tiles[tname].add_enum(slice + ".REG1.REGSET", str_or_default(ci->params, ctx->id("REG1_REGSET"), "RESET")); cc.tiles[tname].add_enum(slice + ".CEMUX", str_or_default(ci->params, ctx->id("CEMUX"), "1")); - IdString lsrnet; + NetInfo *lsrnet = nullptr; if (ci->ports.find(ctx->id("LSR")) != ci->ports.end() && ci->ports.at(ctx->id("LSR")).net != nullptr) - lsrnet = ci->ports.at(ctx->id("LSR")).net->name; + lsrnet = ci->ports.at(ctx->id("LSR")).net; if (ctx->getBoundWireNet(ctx->getWireByName( ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/LSR0")))) == lsrnet) { cc.tiles[tname].add_enum("LSR0.SRMODE", str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE")); diff --git a/generic/arch.cc b/generic/arch.cc index 3389ac0d..e867d310 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -214,27 +214,27 @@ uint32_t Arch::getBelChecksum(BelId bel) const return 0; } -void Arch::bindBel(BelId bel, IdString cell, PlaceStrength strength) +void Arch::bindBel(BelId bel, CellInfo *cell, PlaceStrength strength) { bels.at(bel).bound_cell = cell; - cells.at(cell)->bel = bel; - cells.at(cell)->belStrength = strength; + cell->bel = bel; + cell->belStrength = strength; refreshUiBel(bel); } void Arch::unbindBel(BelId bel) { - cells.at(bels.at(bel).bound_cell)->bel = BelId(); - cells.at(bels.at(bel).bound_cell)->belStrength = STRENGTH_NONE; - bels.at(bel).bound_cell = IdString(); + bels.at(bel).bound_cell->bel = BelId(); + bels.at(bel).bound_cell->belStrength = STRENGTH_NONE; + bels.at(bel).bound_cell = nullptr; refreshUiBel(bel); } -bool Arch::checkBelAvail(BelId bel) const { return bels.at(bel).bound_cell == IdString(); } +bool Arch::checkBelAvail(BelId bel) const { return bels.at(bel).bound_cell == nullptr; } -IdString Arch::getBoundBelCell(BelId bel) const { return bels.at(bel).bound_cell; } +CellInfo *Arch::getBoundBelCell(BelId bel) const { return bels.at(bel).bound_cell; } -IdString Arch::getConflictingBelCell(BelId bel) const { return bels.at(bel).bound_cell; } +CellInfo *Arch::getConflictingBelCell(BelId bel) const { return bels.at(bel).bound_cell; } const std::vector &Arch::getBels() const { return bel_ids; } @@ -271,34 +271,34 @@ uint32_t Arch::getWireChecksum(WireId wire) const return 0; } -void Arch::bindWire(WireId wire, IdString net, PlaceStrength strength) +void Arch::bindWire(WireId wire, NetInfo *net, PlaceStrength strength) { wires.at(wire).bound_net = net; - nets.at(net)->wires[wire].pip = PipId(); - nets.at(net)->wires[wire].strength = strength; + net->wires[wire].pip = PipId(); + net->wires[wire].strength = strength; refreshUiWire(wire); } void Arch::unbindWire(WireId wire) { - auto &net_wires = nets[wires.at(wire).bound_net]->wires; + auto &net_wires = wires.at(wire).bound_net->wires; auto pip = net_wires.at(wire).pip; if (pip != PipId()) { - pips.at(pip).bound_net = IdString(); + pips.at(pip).bound_net = nullptr; refreshUiPip(pip); } net_wires.erase(wire); - wires.at(wire).bound_net = IdString(); + wires.at(wire).bound_net = nullptr; refreshUiWire(wire); } -bool Arch::checkWireAvail(WireId wire) const { return wires.at(wire).bound_net == IdString(); } +bool Arch::checkWireAvail(WireId wire) const { return wires.at(wire).bound_net == nullptr; } -IdString Arch::getBoundWireNet(WireId wire) const { return wires.at(wire).bound_net; } +NetInfo *Arch::getBoundWireNet(WireId wire) const { return wires.at(wire).bound_net; } -IdString Arch::getConflictingWireNet(WireId wire) const { return wires.at(wire).bound_net; } +NetInfo *Arch::getConflictingWireNet(WireId wire) const { return wires.at(wire).bound_net; } const std::vector &Arch::getWireBelPins(WireId wire) const { return wires.at(wire).bel_pins; } @@ -323,13 +323,13 @@ uint32_t Arch::getPipChecksum(PipId wire) const return 0; } -void Arch::bindPip(PipId pip, IdString net, PlaceStrength strength) +void Arch::bindPip(PipId pip, NetInfo *net, PlaceStrength strength) { WireId wire = pips.at(pip).dstWire; pips.at(pip).bound_net = net; wires.at(wire).bound_net = net; - nets.at(net)->wires[wire].pip = pip; - nets.at(net)->wires[wire].strength = strength; + net->wires[wire].pip = pip; + net->wires[wire].strength = strength; refreshUiPip(pip); refreshUiWire(wire); } @@ -337,18 +337,18 @@ void Arch::bindPip(PipId pip, IdString net, PlaceStrength strength) void Arch::unbindPip(PipId pip) { WireId wire = pips.at(pip).dstWire; - nets.at(wires.at(wire).bound_net)->wires.erase(wire); - pips.at(pip).bound_net = IdString(); - wires.at(wire).bound_net = IdString(); + wires.at(wire).bound_net->wires.erase(wire); + pips.at(pip).bound_net = nullptr; + wires.at(wire).bound_net = nullptr; refreshUiPip(pip); refreshUiWire(wire); } -bool Arch::checkPipAvail(PipId pip) const { return pips.at(pip).bound_net == IdString(); } +bool Arch::checkPipAvail(PipId pip) const { return pips.at(pip).bound_net == nullptr; } -IdString Arch::getBoundPipNet(PipId pip) const { return pips.at(pip).bound_net; } +NetInfo *Arch::getBoundPipNet(PipId pip) const { return pips.at(pip).bound_net; } -IdString Arch::getConflictingPipNet(PipId pip) const { return pips.at(pip).bound_net; } +NetInfo *Arch::getConflictingPipNet(PipId pip) const { return pips.at(pip).bound_net; } const std::vector &Arch::getPips() const { return pip_ids; } @@ -408,7 +408,7 @@ delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const return (dx + dy) * grid_distance_to_delay; } -delay_t Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t budget) const { return budget; } +bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const { return false; } // --------------------------------------------------------------- diff --git a/generic/arch.h b/generic/arch.h index 10cd1d5a..0e0aec27 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -31,7 +31,8 @@ struct WireInfo; struct PipInfo { - IdString name, type, bound_net; + IdString name, type; + NetInfo *bound_net; WireId srcWire, dstWire; DelayInfo delay; DecalXY decalxy; @@ -39,7 +40,8 @@ struct PipInfo struct WireInfo { - IdString name, type, bound_net; + IdString name, type; + NetInfo *bound_net; std::vector downhill, uphill, aliases; BelPin uphill_bel_pin; std::vector downhill_bel_pins; @@ -57,7 +59,8 @@ struct PinInfo struct BelInfo { - IdString name, type, bound_cell; + IdString name, type; + CellInfo *bound_cell; std::unordered_map pins; DecalXY decalxy; int x, y, z; @@ -144,11 +147,11 @@ struct Arch : BaseCtx const std::vector &getBelsByTile(int x, int y) const; bool getBelGlobalBuf(BelId bel) const; uint32_t getBelChecksum(BelId bel) const; - void bindBel(BelId bel, IdString cell, PlaceStrength strength); + void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength); void unbindBel(BelId bel); bool checkBelAvail(BelId bel) const; - IdString getBoundBelCell(BelId bel) const; - IdString getConflictingBelCell(BelId bel) const; + CellInfo *getBoundBelCell(BelId bel) const; + CellInfo *getConflictingBelCell(BelId bel) const; const std::vector &getBels() const; BelType getBelType(BelId bel) const; WireId getBelPinWire(BelId bel, PortPin pin) const; @@ -159,11 +162,11 @@ struct Arch : BaseCtx IdString getWireName(WireId wire) const; IdString getWireType(WireId wire) const; uint32_t getWireChecksum(WireId wire) const; - void bindWire(WireId wire, IdString net, PlaceStrength strength); + void bindWire(WireId wire, NetInfo *net, PlaceStrength strength); void unbindWire(WireId wire); bool checkWireAvail(WireId wire) const; - IdString getBoundWireNet(WireId wire) const; - IdString getConflictingWireNet(WireId wire) const; + NetInfo *getBoundWireNet(WireId wire) const; + NetInfo *getConflictingWireNet(WireId wire) const; DelayInfo getWireDelay(WireId wire) const { return DelayInfo(); } const std::vector &getWires() const; const std::vector &getWireBelPins(WireId wire) const; @@ -172,11 +175,11 @@ struct Arch : BaseCtx IdString getPipName(PipId pip) const; IdString getPipType(PipId pip) const; uint32_t getPipChecksum(PipId pip) const; - void bindPip(PipId pip, IdString net, PlaceStrength strength); + void bindPip(PipId pip, NetInfo *net, PlaceStrength strength); void unbindPip(PipId pip); bool checkPipAvail(PipId pip) const; - IdString getBoundPipNet(PipId pip) const; - IdString getConflictingPipNet(PipId pip) const; + NetInfo *getBoundPipNet(PipId pip) const; + NetInfo *getConflictingPipNet(PipId pip) const; const std::vector &getPips() const; WireId getPipSrcWire(PipId pip) const; WireId getPipDstWire(PipId pip) const; @@ -199,7 +202,7 @@ struct Arch : BaseCtx delay_t getRipupDelayPenalty() const { return 1.0; } float getDelayNS(delay_t v) const { return v; } uint32_t getDelayChecksum(delay_t v) const { return 0; } - delay_t getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t budget) const; + bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const; bool pack() { return true; } bool place(); diff --git a/gui/designwidget.cc b/gui/designwidget.cc index 5a448235..ce205a81 100644 --- a/gui/designwidget.cc +++ b/gui/designwidget.cc @@ -407,8 +407,8 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti addProperty(topItem, QVariant::String, "Name", c.c_str(ctx)); addProperty(topItem, QVariant::String, "Type", ctx->belTypeToId(ctx->getBelType(bel)).c_str(ctx)); addProperty(topItem, QVariant::Bool, "Available", ctx->checkBelAvail(bel)); - addProperty(topItem, QVariant::String, "Bound Cell", ctx->getBoundBelCell(bel).c_str(ctx), ElementType::CELL); - addProperty(topItem, QVariant::String, "Conflicting Cell", ctx->getConflictingBelCell(bel).c_str(ctx), + addProperty(topItem, QVariant::String, "Bound Cell", ctx->nameOf(ctx->getBoundBelCell(bel)), ElementType::CELL); + addProperty(topItem, QVariant::String, "Conflicting Cell", ctx->nameOf(ctx->getConflictingBelCell(bel)), ElementType::CELL); QtProperty *belpinsItem = addSubGroup(topItem, "Ports"); @@ -429,8 +429,8 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti addProperty(topItem, QVariant::String, "Name", c.c_str(ctx)); addProperty(topItem, QVariant::String, "Type", ctx->getWireType(wire).c_str(ctx)); addProperty(topItem, QVariant::Bool, "Available", ctx->checkWireAvail(wire)); - addProperty(topItem, QVariant::String, "Bound Net", ctx->getBoundWireNet(wire).c_str(ctx), ElementType::NET); - addProperty(topItem, QVariant::String, "Conflicting Net", ctx->getConflictingWireNet(wire).c_str(ctx), + addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundWireNet(wire)), ElementType::NET); + addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingWireNet(wire)), ElementType::NET); DelayInfo delay = ctx->getWireDelay(wire); @@ -484,8 +484,8 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti addProperty(topItem, QVariant::String, "Name", c.c_str(ctx)); addProperty(topItem, QVariant::String, "Type", ctx->getPipType(pip).c_str(ctx)); addProperty(topItem, QVariant::Bool, "Available", ctx->checkPipAvail(pip)); - addProperty(topItem, QVariant::String, "Bound Net", ctx->getBoundPipNet(pip).c_str(ctx), ElementType::NET); - addProperty(topItem, QVariant::String, "Conflicting Net", ctx->getConflictingPipNet(pip).c_str(ctx), + addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundPipNet(pip)), ElementType::NET); + addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingPipNet(pip)), ElementType::NET); addProperty(topItem, QVariant::String, "Src Wire", ctx->getWireName(ctx->getPipSrcWire(pip)).c_str(ctx), ElementType::WIRE); diff --git a/ice40/arch.cc b/ice40/arch.cc index 5d79a487..fcc9d798 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -637,17 +637,34 @@ std::vector Arch::getGroupGroups(GroupId group) const // ----------------------------------------------------------------------- -delay_t Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t budget) const +bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const { const auto &driver = net_info->driver; - if (driver.port == id_cout) { + if (driver.port == id_cout && sink.port == id_cin) { auto driver_loc = getBelLocation(driver.cell->bel); auto sink_loc = getBelLocation(sink.cell->bel); if (driver_loc.y == sink_loc.y) - return 0; - return 250; + budget = 0; + else switch (args.type) { +#ifndef ICE40_HX1K_ONLY + case ArchArgs::HX8K: +#endif + case ArchArgs::HX1K: + budget = 190; break; +#ifndef ICE40_HX1K_ONLY + case ArchArgs::LP384: + case ArchArgs::LP1K: + case ArchArgs::LP8K: + budget = 290; break; + case ArchArgs::UP5K: + budget = 560; break; +#endif + default: + log_error("Unsupported iCE40 chip type.\n"); + } + return true; } - return budget; + return false; } // ----------------------------------------------------------------------- @@ -672,7 +689,7 @@ DecalXY Arch::getBelDecal(BelId bel) const DecalXY decalxy; decalxy.decal.type = DecalId::TYPE_BEL; decalxy.decal.index = bel.index; - decalxy.decal.active = bel_to_cell.at(bel.index) != IdString(); + decalxy.decal.active = bel_to_cell.at(bel.index) != nullptr; return decalxy; } @@ -681,7 +698,7 @@ DecalXY Arch::getWireDecal(WireId wire) const DecalXY decalxy; decalxy.decal.type = DecalId::TYPE_WIRE; decalxy.decal.index = wire.index; - decalxy.decal.active = wire_to_net.at(wire.index) != IdString(); + decalxy.decal.active = wire_to_net.at(wire.index) != nullptr; return decalxy; } @@ -690,7 +707,7 @@ DecalXY Arch::getPipDecal(PipId pip) const DecalXY decalxy; decalxy.decal.type = DecalId::TYPE_PIP; decalxy.decal.index = pip.index; - decalxy.decal.active = pip_to_net.at(pip.index) != IdString(); + decalxy.decal.active = pip_to_net.at(pip.index) != nullptr; return decalxy; }; diff --git a/ice40/arch.h b/ice40/arch.h index bc968b74..73f1ea0e 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -400,10 +400,10 @@ struct Arch : BaseCtx mutable std::unordered_map bel_by_loc; std::vector bel_carry; - std::vector bel_to_cell; - std::vector wire_to_net; - std::vector pip_to_net; - std::vector switches_locked; + std::vector bel_to_cell; + std::vector wire_to_net; + std::vector pip_to_net; + std::vector switches_locked; ArchArgs args; Arch(ArchArgs args); @@ -438,26 +438,25 @@ struct Arch : BaseCtx uint32_t getBelChecksum(BelId bel) const { return bel.index; } - void bindBel(BelId bel, IdString cell, PlaceStrength strength) + void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength) { NPNR_ASSERT(bel != BelId()); - NPNR_ASSERT(bel_to_cell[bel.index] == IdString()); - auto &c = cells[cell]; + NPNR_ASSERT(bel_to_cell[bel.index] == nullptr); bel_to_cell[bel.index] = cell; - bel_carry[bel.index] = (c->type == id_icestorm_lc && c->lcInfo.carryEnable); - c->bel = bel; - c->belStrength = strength; + bel_carry[bel.index] = (cell->type == id_icestorm_lc && cell->lcInfo.carryEnable); + cell->bel = bel; + cell->belStrength = strength; refreshUiBel(bel); } void unbindBel(BelId bel) { NPNR_ASSERT(bel != BelId()); - NPNR_ASSERT(bel_to_cell[bel.index] != IdString()); - cells[bel_to_cell[bel.index]]->bel = BelId(); - cells[bel_to_cell[bel.index]]->belStrength = STRENGTH_NONE; - bel_to_cell[bel.index] = IdString(); + NPNR_ASSERT(bel_to_cell[bel.index] != nullptr); + bel_to_cell[bel.index]->bel = BelId(); + bel_to_cell[bel.index]->belStrength = STRENGTH_NONE; + bel_to_cell[bel.index] = nullptr; bel_carry[bel.index] = false; refreshUiBel(bel); } @@ -465,16 +464,16 @@ struct Arch : BaseCtx bool checkBelAvail(BelId bel) const { NPNR_ASSERT(bel != BelId()); - return bel_to_cell[bel.index] == IdString(); + return bel_to_cell[bel.index] == nullptr; } - IdString getBoundBelCell(BelId bel) const + CellInfo *getBoundBelCell(BelId bel) const { NPNR_ASSERT(bel != BelId()); return bel_to_cell[bel.index]; } - IdString getConflictingBelCell(BelId bel) const + CellInfo *getConflictingBelCell(BelId bel) const { NPNR_ASSERT(bel != BelId()); return bel_to_cell[bel.index]; @@ -526,49 +525,49 @@ struct Arch : BaseCtx uint32_t getWireChecksum(WireId wire) const { return wire.index; } - void bindWire(WireId wire, IdString net, PlaceStrength strength) + void bindWire(WireId wire, NetInfo *net, PlaceStrength strength) { NPNR_ASSERT(wire != WireId()); - NPNR_ASSERT(wire_to_net[wire.index] == IdString()); + NPNR_ASSERT(wire_to_net[wire.index] == nullptr); wire_to_net[wire.index] = net; - nets[net]->wires[wire].pip = PipId(); - nets[net]->wires[wire].strength = strength; + net->wires[wire].pip = PipId(); + net->wires[wire].strength = strength; refreshUiWire(wire); } void unbindWire(WireId wire) { NPNR_ASSERT(wire != WireId()); - NPNR_ASSERT(wire_to_net[wire.index] != IdString()); + NPNR_ASSERT(wire_to_net[wire.index] != nullptr); - auto &net_wires = nets[wire_to_net[wire.index]]->wires; + auto &net_wires = wire_to_net[wire.index]->wires; auto it = net_wires.find(wire); NPNR_ASSERT(it != net_wires.end()); auto pip = it->second.pip; if (pip != PipId()) { - pip_to_net[pip.index] = IdString(); - switches_locked[chip_info->pip_data[pip.index].switch_index] = IdString(); + pip_to_net[pip.index] = nullptr; + switches_locked[chip_info->pip_data[pip.index].switch_index] = nullptr; } net_wires.erase(it); - wire_to_net[wire.index] = IdString(); + wire_to_net[wire.index] = nullptr; refreshUiWire(wire); } bool checkWireAvail(WireId wire) const { NPNR_ASSERT(wire != WireId()); - return wire_to_net[wire.index] == IdString(); + return wire_to_net[wire.index] == nullptr; } - IdString getBoundWireNet(WireId wire) const + NetInfo *getBoundWireNet(WireId wire) const { NPNR_ASSERT(wire != WireId()); return wire_to_net[wire.index]; } - IdString getConflictingWireNet(WireId wire) const + NetInfo *getConflictingWireNet(WireId wire) const { NPNR_ASSERT(wire != WireId()); return wire_to_net[wire.index]; @@ -606,21 +605,21 @@ struct Arch : BaseCtx PipId getPipByName(IdString name) const; - void bindPip(PipId pip, IdString net, PlaceStrength strength) + void bindPip(PipId pip, NetInfo *net, PlaceStrength strength) { NPNR_ASSERT(pip != PipId()); - NPNR_ASSERT(pip_to_net[pip.index] == IdString()); - NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] == IdString()); + NPNR_ASSERT(pip_to_net[pip.index] == nullptr); + NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] == nullptr); pip_to_net[pip.index] = net; switches_locked[chip_info->pip_data[pip.index].switch_index] = net; WireId dst; dst.index = chip_info->pip_data[pip.index].dst; - NPNR_ASSERT(wire_to_net[dst.index] == IdString()); + NPNR_ASSERT(wire_to_net[dst.index] == nullptr); wire_to_net[dst.index] = net; - nets[net]->wires[dst].pip = pip; - nets[net]->wires[dst].strength = strength; + net->wires[dst].pip = pip; + net->wires[dst].strength = strength; refreshUiPip(pip); refreshUiWire(dst); } @@ -628,17 +627,17 @@ struct Arch : BaseCtx void unbindPip(PipId pip) { NPNR_ASSERT(pip != PipId()); - NPNR_ASSERT(pip_to_net[pip.index] != IdString()); - NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] != IdString()); + NPNR_ASSERT(pip_to_net[pip.index] != nullptr); + NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] != nullptr); WireId dst; dst.index = chip_info->pip_data[pip.index].dst; - NPNR_ASSERT(wire_to_net[dst.index] != IdString()); - wire_to_net[dst.index] = IdString(); - nets[pip_to_net[pip.index]]->wires.erase(dst); + NPNR_ASSERT(wire_to_net[dst.index] != nullptr); + wire_to_net[dst.index] = nullptr; + pip_to_net[pip.index]->wires.erase(dst); - pip_to_net[pip.index] = IdString(); - switches_locked[chip_info->pip_data[pip.index].switch_index] = IdString(); + pip_to_net[pip.index] = nullptr; + switches_locked[chip_info->pip_data[pip.index].switch_index] = nullptr; refreshUiPip(pip); refreshUiWire(dst); } @@ -649,12 +648,12 @@ struct Arch : BaseCtx auto &pi = chip_info->pip_data[pip.index]; auto &si = chip_info->bits_info->switches[pi.switch_index]; - if (switches_locked[pi.switch_index] != IdString()) + if (switches_locked[pi.switch_index] != nullptr) return false; if (pi.flags & PipInfoPOD::FLAG_ROUTETHRU) { NPNR_ASSERT(si.bel >= 0); - if (bel_to_cell[si.bel] != IdString()) + if (bel_to_cell[si.bel] != nullptr) return false; } @@ -667,13 +666,13 @@ struct Arch : BaseCtx return true; } - IdString getBoundPipNet(PipId pip) const + NetInfo *getBoundPipNet(PipId pip) const { NPNR_ASSERT(pip != PipId()); return pip_to_net[pip.index]; } - IdString getConflictingPipNet(PipId pip) const + NetInfo *getConflictingPipNet(PipId pip) const { NPNR_ASSERT(pip != PipId()); return switches_locked[chip_info->pip_data[pip.index].switch_index]; @@ -768,7 +767,7 @@ struct Arch : BaseCtx delay_t getRipupDelayPenalty() const { return 200; } float getDelayNS(delay_t v) const { return v * 0.001; } uint32_t getDelayChecksum(delay_t v) const { return v; } - delay_t getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t budget) const; + bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const; // ------------------------------------------------- diff --git a/ice40/arch_place.cc b/ice40/arch_place.cc index b3404d6c..274dc1d3 100644 --- a/ice40/arch_place.cc +++ b/ice40/arch_place.cc @@ -74,19 +74,18 @@ bool Arch::isBelLocationValid(BelId bel) const std::vector bel_cells; Loc bel_loc = getBelLocation(bel); for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { - IdString cell_other = getBoundBelCell(bel_other); - if (cell_other != IdString()) { - const CellInfo *ci_other = cells.at(cell_other).get(); + CellInfo *ci_other = getBoundBelCell(bel_other); + if (ci_other != nullptr) { bel_cells.push_back(ci_other); } } return logicCellsCompatible(bel_cells); } else { - IdString cellId = getBoundBelCell(bel); - if (cellId == IdString()) + CellInfo *ci = getBoundBelCell(bel); + if (ci == nullptr) return true; else - return isValidBelForCell(cells.at(cellId).get(), bel); + return isValidBelForCell(ci, bel); } } @@ -98,9 +97,8 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const std::vector bel_cells; Loc bel_loc = getBelLocation(bel); for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { - IdString cell_other = getBoundBelCell(bel_other); - if (cell_other != IdString() && bel_other != bel) { - const CellInfo *ci_other = cells.at(cell_other).get(); + CellInfo *ci_other = getBoundBelCell(bel_other); + if (ci_other != nullptr && bel_other != bel) { bel_cells.push_back(ci_other); } } @@ -126,12 +124,12 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const if (pll_bel.index != -1) { auto pll_cell = getBoundBelCell(pll_bel); // Is a PLL placed in this PLL bel? - if (pll_cell != IdString()) { + if (pll_cell != nullptr) { // Is the shared port driving a net? - auto pi = cells.at(pll_cell)->ports[portPinToId(pll_bel_pin)]; + auto pi = pll_cell->ports[portPinToId(pll_bel_pin)]; if (pi.net != nullptr) { // Are we perhaps a PAD INPUT Bel that can be placed here? - if (cells.at(pll_cell)->attrs[id("BEL_PAD_INPUT")] == getBelName(bel).str(this)) { + if (pll_cell->attrs[id("BEL_PAD_INPUT")] == getBelName(bel).str(this)) { return true; } return false; diff --git a/ice40/arch_pybindings.cc b/ice40/arch_pybindings.cc index 98164e87..1d16ade0 100644 --- a/ice40/arch_pybindings.cc +++ b/ice40/arch_pybindings.cc @@ -70,13 +70,13 @@ void arch_wrap_python() fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getBelChecksum"); fn_wrapper_3a_v, - conv_from_str, pass_through>::def_wrap(ctx_cls, "bindBel"); + addr_and_unwrap, pass_through>::def_wrap(ctx_cls, "bindBel"); fn_wrapper_1a_v>::def_wrap( ctx_cls, "unbindBel"); - fn_wrapper_1a, + fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getBoundBelCell"); fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getConflictingBelCell"); + deref_and_wrap, conv_from_str>::def_wrap(ctx_cls, "getConflictingBelCell"); fn_wrapper_0a>::def_wrap(ctx_cls, "getBels"); @@ -88,15 +88,15 @@ void arch_wrap_python() fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getWireChecksum"); fn_wrapper_3a_v, - conv_from_str, pass_through>::def_wrap(ctx_cls, "bindWire"); + addr_and_unwrap, pass_through>::def_wrap(ctx_cls, "bindWire"); fn_wrapper_1a_v>::def_wrap( ctx_cls, "unbindWire"); fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "checkWireAvail"); - fn_wrapper_1a, + fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getBoundWireNet"); fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getConflictingWireNet"); + deref_and_wrap, conv_from_str>::def_wrap(ctx_cls, "getConflictingWireNet"); fn_wrapper_0a>::def_wrap( ctx_cls, "getWires"); @@ -106,15 +106,15 @@ void arch_wrap_python() fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getPipChecksum"); fn_wrapper_3a_v, - conv_from_str, pass_through>::def_wrap(ctx_cls, "bindPip"); + addr_and_unwrap, pass_through>::def_wrap(ctx_cls, "bindPip"); fn_wrapper_1a_v>::def_wrap( ctx_cls, "unbindPip"); fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "checkPipAvail"); - fn_wrapper_1a, + fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getBoundPipNet"); fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getConflictingPipNet"); + deref_and_wrap, conv_from_str>::def_wrap(ctx_cls, "getConflictingPipNet"); fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getPipsDownhill"); diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc index 543d7b35..979a274d 100644 --- a/ice40/bitstream.cc +++ b/ice40/bitstream.cc @@ -291,7 +291,7 @@ void write_asc(const Context *ctx, std::ostream &out) } // Set pips for (auto pip : ctx->getPips()) { - if (ctx->pip_to_net[pip.index] != IdString()) { + if (ctx->pip_to_net[pip.index] != nullptr) { const PipInfoPOD &pi = ci.pip_data[pip.index]; const SwitchInfoPOD &swi = bi.switches[pi.switch_index]; int sw_bel_idx = swi.bel; @@ -310,7 +310,7 @@ void write_asc(const Context *ctx, std::ostream &out) WireId permWire; for (auto permPip : ctx->getPipsUphill(ctx->getPipSrcWire(pip))) { - if (ctx->getBoundPipNet(permPip) != IdString()) { + if (ctx->getBoundPipNet(permPip) != nullptr) { permWire = ctx->getPipSrcWire(permPip); } } @@ -384,7 +384,7 @@ void write_asc(const Context *ctx, std::ostream &out) for (int i = 0; i < 4; i++) { WireId lut_wire = ctx->getBelPinWire(bel, PortPin(PIN_I0 + i)); for (auto pip : ctx->getPipsUphill(lut_wire)) { - if (ctx->getBoundPipNet(pip) != IdString()) { + if (ctx->getBoundPipNet(pip) != nullptr) { std::string name = ci.wire_data[ctx->getPipSrcWire(pip).index].name.get(); switch (name.back()) { case '0': @@ -458,8 +458,8 @@ void write_asc(const Context *ctx, std::ostream &out) NPNR_ASSERT(iez != -1); bool input_en = false; - if ((ctx->wire_to_net[ctx->getBelPinWire(bel, PIN_D_IN_0).index] != IdString()) || - (ctx->wire_to_net[ctx->getBelPinWire(bel, PIN_D_IN_1).index] != IdString())) { + if ((ctx->wire_to_net[ctx->getBelPinWire(bel, PIN_D_IN_0).index] != nullptr) || + (ctx->wire_to_net[ctx->getBelPinWire(bel, PIN_D_IN_1).index] != nullptr)) { input_en = true; } @@ -618,7 +618,7 @@ void write_asc(const Context *ctx, std::ostream &out) } // Set config bits in unused IO and RAM for (auto bel : ctx->getBels()) { - if (ctx->bel_to_cell[bel.index] == IdString() && ctx->getBelType(bel) == TYPE_SB_IO) { + if (ctx->bel_to_cell[bel.index] == nullptr && ctx->getBelType(bel) == TYPE_SB_IO) { const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO]; const BelInfoPOD &beli = ci.bel_data[bel.index]; int x = beli.x, y = beli.y, z = beli.z; @@ -633,7 +633,7 @@ void write_asc(const Context *ctx, std::ostream &out) set_ie_bit_logical(ctx, ti, config.at(iey).at(iex), "IoCtrl.IE_" + std::to_string(iez), true); set_ie_bit_logical(ctx, ti, config.at(iey).at(iex), "IoCtrl.REN_" + std::to_string(iez), false); } - } else if (ctx->bel_to_cell[bel.index] == IdString() && ctx->getBelType(bel) == TYPE_ICESTORM_RAM) { + } else if (ctx->bel_to_cell[bel.index] == nullptr && ctx->getBelType(bel) == TYPE_ICESTORM_RAM) { const BelInfoPOD &beli = ci.bel_data[bel.index]; int x = beli.x, y = beli.y; const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_RAMB]; @@ -751,9 +751,9 @@ void write_asc(const Context *ctx, std::ostream &out) // Write symbols // const bool write_symbols = 1; for (auto wire : ctx->getWires()) { - IdString net = ctx->getBoundWireNet(wire); - if (net != IdString()) - out << ".sym " << wire.index << " " << net.str(ctx) << std::endl; + NetInfo *net = ctx->getBoundWireNet(wire); + if (net != nullptr) + out << ".sym " << wire.index << " " << net->name.str(ctx) << std::endl; } } @@ -825,7 +825,7 @@ void read_config(Context *ctx, std::istream &in, chipconfig_t &config) WireId wire; wire.index = wireIndex; - ctx->bindWire(wire, netName, STRENGTH_WEAK); + ctx->bindWire(wire, ctx->nets.at(netName).get(), STRENGTH_WEAK); } } else if (line_nr >= 0 && strlen(buffer) > 0) { if (line_nr > int(config.at(tile_y).at(tile_x).size() - 1)) @@ -869,7 +869,7 @@ bool read_asc(Context *ctx, std::istream &in) isUsed &= !(bool(cbit) ^ val); } if (isUsed) { - IdString net = ctx->wire_to_net[pi.dst]; + NetInfo *net = ctx->wire_to_net[pi.dst]; WireId wire; wire.index = pi.dst; ctx->unbindWire(wire); @@ -896,7 +896,7 @@ bool read_asc(Context *ctx, std::istream &in) std::unique_ptr created = create_ice_cell(ctx, ctx->id("ICESTORM_LC")); IdString name = created->name; ctx->cells[name] = std::move(created); - ctx->bindBel(bel, name, STRENGTH_WEAK); + ctx->bindBel(bel, ctx->cells[name].get(), STRENGTH_WEAK); // TODO: Add port mapping to nets and assign values of properties } } @@ -916,7 +916,7 @@ bool read_asc(Context *ctx, std::istream &in) std::unique_ptr created = create_ice_cell(ctx, ctx->id("SB_IO")); IdString name = created->name; ctx->cells[name] = std::move(created); - ctx->bindBel(bel, name, STRENGTH_WEAK); + ctx->bindBel(bel, ctx->cells[name].get(), STRENGTH_WEAK); // TODO: Add port mapping to nets and assign values of properties } } @@ -933,35 +933,35 @@ bool read_asc(Context *ctx, std::istream &in) std::unique_ptr created = create_ice_cell(ctx, ctx->id("ICESTORM_LC")); IdString name = created->name; ctx->cells[name] = std::move(created); - ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); + ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK); // TODO: Add port mapping to nets } if (ctx->getBelType(belpin.bel) == TYPE_SB_IO) { std::unique_ptr created = create_ice_cell(ctx, ctx->id("SB_IO")); IdString name = created->name; ctx->cells[name] = std::move(created); - ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); + ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK); // TODO: Add port mapping to nets } if (ctx->getBelType(belpin.bel) == TYPE_SB_GB) { std::unique_ptr created = create_ice_cell(ctx, ctx->id("SB_GB")); IdString name = created->name; ctx->cells[name] = std::move(created); - ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); + ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK); // TODO: Add port mapping to nets } if (ctx->getBelType(belpin.bel) == TYPE_SB_WARMBOOT) { std::unique_ptr created = create_ice_cell(ctx, ctx->id("SB_WARMBOOT")); IdString name = created->name; ctx->cells[name] = std::move(created); - ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); + ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK); // TODO: Add port mapping to nets } if (ctx->getBelType(belpin.bel) == TYPE_ICESTORM_LFOSC) { std::unique_ptr created = create_ice_cell(ctx, ctx->id("ICESTORM_LFOSC")); IdString name = created->name; ctx->cells[name] = std::move(created); - ctx->bindBel(belpin.bel, name, STRENGTH_WEAK); + ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK); // TODO: Add port mapping to nets } } @@ -975,17 +975,17 @@ bool read_asc(Context *ctx, std::istream &in) PortPin pin = ctx->portPinFromId(port.first); WireId wire = ctx->getBelPinWire(cell.second->bel, pin); if (wire != WireId()) { - IdString name = ctx->getBoundWireNet(wire); - if (name != IdString()) { - port.second.net = ctx->nets[name].get(); + NetInfo *net = ctx->getBoundWireNet(wire); + if (net != nullptr) { + port.second.net = net; PortRef ref; ref.cell = cell.second.get(); ref.port = port.second.name; if (port.second.type == PORT_OUT) - ctx->nets[name]->driver = ref; + net->driver = ref; else - ctx->nets[name]->users.push_back(ref); + net->users.push_back(ref); } } }