Merge remote-tracking branch 'origin/master' into common_main

# Conflicts:
#	ecp5/main.cc
#	ice40/main.cc
This commit is contained in:
Miodrag Milanovic 2018-08-08 10:48:05 +02:00
commit 5df90bc5a5
22 changed files with 371 additions and 322 deletions

View File

@ -192,6 +192,7 @@ int CommandHandler::executeMain(std::unique_ptr<Context> ctx)
if (vm.count("json") || vm.count("load")) { if (vm.count("json") || vm.count("load")) {
if (!ctx->pack() && !ctx->force) if (!ctx->pack() && !ctx->force)
log_error("Packing design failed.\n"); log_error("Packing design failed.\n");
assign_budget(ctx.get());
ctx->check(); ctx->check();
print_utilisation(ctx.get()); print_utilisation(ctx.get());
if (!vm.count("pack-only")) { if (!vm.count("pack-only")) {

View File

@ -232,25 +232,26 @@ void Context::check() const
auto ni = n.second.get(); auto ni = n.second.get();
NPNR_ASSERT(n.first == ni->name); NPNR_ASSERT(n.first == ni->name);
for (auto &w : ni->wires) { for (auto &w : ni->wires) {
NPNR_ASSERT(n.first == getBoundWireNet(w.first)); NPNR_ASSERT(ni == getBoundWireNet(w.first));
if (w.second.pip != PipId()) { if (w.second.pip != PipId()) {
NPNR_ASSERT(w.first == getPipDstWire(w.second.pip)); 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()) { for (auto w : getWires()) {
IdString net = getBoundWireNet(w); auto ni = getBoundWireNet(w);
if (net != IdString()) { if (ni != nullptr) {
NPNR_ASSERT(nets.at(net)->wires.count(w)); NPNR_ASSERT(ni->wires.count(w));
} }
} }
for (auto &c : cells) { for (auto &c : cells) {
NPNR_ASSERT(c.first == c.second->name); auto ci = c.second.get();
if (c.second->bel != BelId()) NPNR_ASSERT(c.first == ci->name);
NPNR_ASSERT(getBoundBelCell(c.second->bel) == c.first); if (ci->bel != BelId())
NPNR_ASSERT(getBoundBelCell(c.second->bel) == ci);
for (auto &port : c.second->ports) { for (auto &port : c.second->ports) {
NetInfo *net = port.second.net; NetInfo *net = port.second.net;
if (net != nullptr) { if (net != nullptr) {

View File

@ -437,6 +437,13 @@ struct BaseCtx
const Context *getCtx() const { return reinterpret_cast<const Context *>(this); } const Context *getCtx() const { return reinterpret_cast<const Context *>(this); }
template<typename T> const char *nameOf(const T *obj)
{
if (obj == nullptr)
return "";
return obj->name.c_str(getCtx());
}
// -------------------------------------------------------------- // --------------------------------------------------------------
bool allUiReload = true; bool allUiReload = true;

View File

@ -131,7 +131,7 @@ bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality)
if (iters >= 4) if (iters >= 4)
wirelen += ctx->rng(25); wirelen += ctx->rng(25);
if (wirelen <= best_ripup_wirelen) { 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) { if (curr_cell->belStrength < STRENGTH_STRONG) {
best_ripup_wirelen = wirelen; best_ripup_wirelen = wirelen;
ripup_bel = bel; ripup_bel = bel;
@ -158,7 +158,7 @@ bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality)
if (ctx->verbose) if (ctx->verbose)
log_info(" placed single cell '%s' at '%s'\n", cell->name.c_str(ctx), log_info(" placed single cell '%s' at '%s'\n", cell->name.c_str(ctx),
ctx->getBelName(best_bel).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; cell = ripup_target;
} }
@ -232,8 +232,8 @@ class ConstraintLegaliseWorker
return false; return false;
} }
if (!ctx->checkBelAvail(locBel)) { if (!ctx->checkBelAvail(locBel)) {
IdString confCell = ctx->getConflictingBelCell(locBel); CellInfo *confCell = ctx->getConflictingBelCell(locBel);
if (ctx->cells[confCell]->belStrength >= STRENGTH_STRONG) { if (confCell->belStrength >= STRENGTH_STRONG) {
return false; return false;
} }
} }
@ -362,20 +362,31 @@ class ConstraintLegaliseWorker
cp.second.y, cp.second.z); cp.second.y, cp.second.z);
BelId target = ctx->getBelByLocation(cp.second); BelId target = ctx->getBelByLocation(cp.second);
if (!ctx->checkBelAvail(target)) { if (!ctx->checkBelAvail(target)) {
IdString conflicting = ctx->getConflictingBelCell(target); CellInfo *confl_cell = ctx->getConflictingBelCell(target);
if (conflicting != IdString()) { if (confl_cell != nullptr) {
CellInfo *confl_cell = ctx->cells.at(conflicting).get();
if (ctx->verbose) 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)); ctx->getBelName(confl_cell->bel).c_str(ctx));
NPNR_ASSERT(confl_cell->belStrength < STRENGTH_STRONG); NPNR_ASSERT(confl_cell->belStrength < STRENGTH_STRONG);
ctx->unbindBel(target); 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); 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)); NPNR_ASSERT(constraints_satisfied(cell));
return true; return true;
} }

View File

@ -105,7 +105,7 @@ class SAPlacer
cell->type.c_str(ctx)); cell->type.c_str(ctx));
} }
ctx->bindBel(bel, cell->name, STRENGTH_USER); ctx->bindBel(bel, cell, STRENGTH_USER);
locked_bels.insert(bel); locked_bels.insert(bel);
placed_cells++; placed_cells++;
} }
@ -138,7 +138,8 @@ class SAPlacer
if ((placed_cells - constr_placed_cells) % 500 != 0) if ((placed_cells - constr_placed_cells) % 500 != 0)
log_info(" initial placement placed %d/%d cells\n", int(placed_cells - constr_placed_cells), log_info(" initial placement placed %d/%d cells\n", int(placed_cells - constr_placed_cells),
int(autoplaced.size())); int(autoplaced.size()));
assign_budget(ctx); if (ctx->slack_redist_iter > 0)
assign_budget(ctx);
ctx->yield(); ctx->yield();
log_info("Running simulated annealing placer.\n"); log_info("Running simulated annealing placer.\n");
@ -256,11 +257,11 @@ class SAPlacer
// Final post-pacement validitiy check // Final post-pacement validitiy check
ctx->yield(); ctx->yield();
for (auto bel : ctx->getBels()) { for (auto bel : ctx->getBels()) {
IdString cell = ctx->getBoundBelCell(bel); CellInfo *cell = ctx->getBoundBelCell(bel);
if (!ctx->isBelLocationValid(bel)) { if (!ctx->isBelLocationValid(bel)) {
std::string cell_text = "no cell"; std::string cell_text = "no cell";
if (cell != IdString()) if (cell != nullptr)
cell_text = std::string("cell '") + cell.str(ctx) + "'"; cell_text = std::string("cell '") + ctx->nameOf(cell) + "'";
if (ctx->force) { if (ctx->force) {
log_warning("post-placement validity check failed for Bel '%s' " log_warning("post-placement validity check failed for Bel '%s' "
"(%s)\n", "(%s)\n",
@ -309,7 +310,7 @@ class SAPlacer
uint64_t score = ctx->rng64(); uint64_t score = ctx->rng64();
if (score <= best_ripup_score) { if (score <= best_ripup_score) {
best_ripup_score = score; best_ripup_score = score;
ripup_target = ctx->cells.at(ctx->getBoundBelCell(bel)).get(); ripup_target = ctx->getBoundBelCell(bel);
ripup_bel = bel; ripup_bel = bel;
} }
} }
@ -324,7 +325,7 @@ class SAPlacer
} else { } else {
all_placed = true; all_placed = true;
} }
ctx->bindBel(best_bel, cell->name, STRENGTH_WEAK); ctx->bindBel(best_bel, cell, STRENGTH_WEAK);
// Back annotate location // Back annotate location
cell->attrs[ctx->id("BEL")] = ctx->getBelName(cell->bel).str(ctx); cell->attrs[ctx->id("BEL")] = ctx->getBelName(cell->bel).str(ctx);
@ -340,20 +341,17 @@ class SAPlacer
new_lengths.clear(); new_lengths.clear();
update.clear(); update.clear();
BelId oldBel = cell->bel; BelId oldBel = cell->bel;
IdString other = ctx->getBoundBelCell(newBel); CellInfo *other_cell = ctx->getBoundBelCell(newBel);
CellInfo *other_cell = nullptr; if (other_cell != nullptr && other_cell->belStrength > STRENGTH_WEAK) {
if (other != IdString()) { return false;
other_cell = ctx->cells[other].get();
if (other_cell->belStrength > STRENGTH_WEAK)
return false;
} }
int old_dist = get_constraints_distance(ctx, cell); int old_dist = get_constraints_distance(ctx, cell);
int new_dist; int new_dist;
if (other != IdString()) if (other_cell != nullptr)
old_dist += get_constraints_distance(ctx, other_cell); old_dist += get_constraints_distance(ctx, other_cell);
wirelen_t new_metric = 0, delta; wirelen_t new_metric = 0, delta;
ctx->unbindBel(oldBel); ctx->unbindBel(oldBel);
if (other != IdString()) { if (other_cell != nullptr) {
ctx->unbindBel(newBel); ctx->unbindBel(newBel);
} }
@ -361,20 +359,20 @@ class SAPlacer
if (port.second.net != nullptr) if (port.second.net != nullptr)
update.insert(port.second.net); update.insert(port.second.net);
if (other != IdString()) { if (other_cell != nullptr) {
for (const auto &port : other_cell->ports) for (const auto &port : other_cell->ports)
if (port.second.net != nullptr) if (port.second.net != nullptr)
update.insert(port.second.net); update.insert(port.second.net);
} }
ctx->bindBel(newBel, cell->name, STRENGTH_WEAK); ctx->bindBel(newBel, cell, STRENGTH_WEAK);
if (other != IdString()) { if (other_cell != nullptr) {
ctx->bindBel(oldBel, other_cell->name, STRENGTH_WEAK); 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); ctx->unbindBel(newBel);
if (other != IdString()) if (other_cell != nullptr)
ctx->unbindBel(oldBel); ctx->unbindBel(oldBel);
goto swap_fail; goto swap_fail;
} }
@ -391,7 +389,7 @@ class SAPlacer
} }
new_dist = get_constraints_distance(ctx, cell); new_dist = get_constraints_distance(ctx, cell);
if (other != IdString()) if (other_cell != nullptr)
new_dist += get_constraints_distance(ctx, other_cell); new_dist += get_constraints_distance(ctx, other_cell);
delta = new_metric - curr_metric; delta = new_metric - curr_metric;
delta += (cfg.constraintWeight / temp) * (new_dist - old_dist); 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))) { if (delta < 0 || (temp > 1e-6 && (ctx->rng() / float(0x3fffffff)) <= std::exp(-delta / temp))) {
n_accept++; n_accept++;
} else { } else {
if (other != IdString()) if (other_cell != nullptr)
ctx->unbindBel(oldBel); ctx->unbindBel(oldBel);
ctx->unbindBel(newBel); ctx->unbindBel(newBel);
goto swap_fail; goto swap_fail;
@ -411,9 +409,9 @@ class SAPlacer
return true; return true;
swap_fail: swap_fail:
ctx->bindBel(oldBel, cell->name, STRENGTH_WEAK); ctx->bindBel(oldBel, cell, STRENGTH_WEAK);
if (other != IdString()) { if (other_cell != nullptr) {
ctx->bindBel(newBel, other, STRENGTH_WEAK); ctx->bindBel(newBel, other_cell, STRENGTH_WEAK);
} }
return false; return false;
} }

View File

@ -140,6 +140,14 @@ template <typename T> struct deref_and_wrap
using ret_type = ContextualWrapper<T &>; using ret_type = ContextualWrapper<T &>;
}; };
template <typename T> struct addr_and_unwrap
{
inline T *operator()(Context *ctx, ContextualWrapper<T &> x) { return &(x.base); }
using arg_type = ContextualWrapper<T &>;
using ret_type = T *;
};
// Function wrapper // Function wrapper
// Zero parameters, one return // Zero parameters, one return
template <typename Class, typename FuncT, FuncT fn, typename rv_conv> struct fn_wrapper_0a template <typename Class, typename FuncT, FuncT fn, typename rv_conv> struct fn_wrapper_0a

View File

@ -159,15 +159,15 @@ struct Router
if (!ctx->checkWireAvail(next_wire)) { if (!ctx->checkWireAvail(next_wire)) {
if (!ripup) if (!ripup)
continue; continue;
IdString ripupWireNet = ctx->getConflictingWireNet(next_wire); NetInfo *ripupWireNet = ctx->getConflictingWireNet(next_wire);
if (ripupWireNet == net_name || ripupWireNet == IdString()) if (ripupWireNet == nullptr || ripupWireNet->name == net_name)
continue; continue;
auto it1 = scores.wireScores.find(next_wire); auto it1 = scores.wireScores.find(next_wire);
if (it1 != scores.wireScores.end()) if (it1 != scores.wireScores.end())
next_delay += (it1->second * ripup_penalty) / 8; 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()) if (it2 != scores.netWireScores.end())
next_delay += it2->second * ripup_penalty; next_delay += it2->second * ripup_penalty;
@ -177,15 +177,15 @@ struct Router
if (!ctx->checkPipAvail(pip)) { if (!ctx->checkPipAvail(pip)) {
if (!ripup) if (!ripup)
continue; continue;
IdString ripupPipNet = ctx->getConflictingPipNet(pip); NetInfo *ripupPipNet = ctx->getConflictingPipNet(pip);
if (ripupPipNet == net_name || ripupPipNet == IdString()) if (ripupPipNet == nullptr || ripupPipNet->name == net_name)
continue; continue;
auto it1 = scores.pipScores.find(pip); auto it1 = scores.pipScores.find(pip);
if (it1 != scores.pipScores.end()) if (it1 != scores.pipScores.end())
next_delay += (it1->second * ripup_penalty) / 8; 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()) if (it2 != scores.netPipScores.end())
next_delay += it2->second * ripup_penalty; next_delay += it2->second * ripup_penalty;
@ -294,12 +294,12 @@ struct Router
if (reroute) { if (reroute) {
// complete ripup // complete ripup
ripup_net(ctx, net_name); 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(); src_wires[src_wire] = ctx->getWireDelay(src_wire).maxDelay();
} else { } else {
// re-use existing routes as much as possible // re-use existing routes as much as possible
if (net_info->wires.count(src_wire) == 0) 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(); src_wires[src_wire] = ctx->getWireDelay(src_wire).maxDelay();
for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) { 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)) if (src_wires.count(cursor))
break; 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(ripup);
NPNR_ASSERT(conflicting_wire_net != net_name); NPNR_ASSERT(conflicting_wire_net->name != net_name);
ctx->unbindWire(cursor); ctx->unbindWire(cursor);
if (!ctx->checkWireAvail(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.wireScores[cursor]++;
scores.netWireScores[std::make_pair(net_name, 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; 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(ripup);
NPNR_ASSERT(conflicting_pip_net != net_name); NPNR_ASSERT(conflicting_pip_net->name != net_name);
if (ctx->getBoundPipNet(pip) == conflicting_pip_net) if (ctx->getBoundPipNet(pip) == conflicting_pip_net)
ctx->unbindPip(pip); ctx->unbindPip(pip);
if (!ctx->checkPipAvail(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.pipScores[visited[cursor].pip]++;
scores.netPipScores[std::make_pair(net_name, 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; src_wires[cursor] = visited[cursor].delay;
cursor = ctx->getPipSrcWire(visited[cursor].pip); cursor = ctx->getPipSrcWire(visited[cursor].pip);
} }

View File

@ -2,6 +2,7 @@
* nextpnr -- Next Generation Place and Route * nextpnr -- Next Generation Place and Route
* *
* Copyright (C) 2018 David Shah <david@symbioticeda.com> * Copyright (C) 2018 David Shah <david@symbioticeda.com>
* Copyright (C) 2018 Eddie Hung <eddieh@ece.ubc.ca>
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -32,36 +33,42 @@ typedef std::map<int, unsigned> DelayFrequency;
struct Timing struct Timing
{ {
Context *ctx; Context *ctx;
bool net_delays;
bool update; bool update;
delay_t min_slack; delay_t min_slack;
PortRefVector current_path; PortRefVector current_path;
PortRefVector *crit_path; PortRefVector *crit_path;
DelayFrequency *slack_histogram; DelayFrequency *slack_histogram;
Timing(Context *ctx, bool update, PortRefVector *crit_path = nullptr, DelayFrequency *slack_histogram = nullptr) Timing(Context *ctx, bool net_delays, bool update, PortRefVector *crit_path = nullptr,
: ctx(ctx), update(update), min_slack(1.0e12 / ctx->target_freq), crit_path(crit_path), DelayFrequency *slack_histogram = nullptr)
slack_histogram(slack_histogram) : 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 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) { for (auto &usr : net->users) {
auto delay = net_delays ? ctx->getNetinfoRouteDelay(net, usr) : delay_t();
if (crit_path) if (crit_path)
current_path.push_back(&usr); current_path.push_back(&usr);
// If budget override is less than existing budget, then do not increment // If budget override exists, use that value and do not increment path_length
// path length auto budget = default_budget;
int pl = path_length + 1; if (ctx->getBudgetOverride(net, usr, budget)) {
auto budget = ctx->getBudgetOverride(net, usr, net_budget); if (update)
if (budget < net_budget) { usr.budget = std::min(usr.budget, budget);
net_budget = budget; budget = follow_user_port(usr, path_length, slack - budget);
pl = std::max(1, path_length); 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) if (crit_path)
current_path.pop_back(); current_path.pop_back();
} }
@ -149,10 +156,10 @@ void assign_budget(Context *ctx, bool quiet)
{ {
if (!quiet) { if (!quiet) {
log_break(); 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(); timing.assign_budget();
if (!quiet || ctx->verbose) { if (!quiet || ctx->verbose) {
@ -194,7 +201,7 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_path)
PortRefVector crit_path; PortRefVector crit_path;
DelayFrequency slack_histogram; 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); print_histogram ? &slack_histogram : nullptr);
auto min_slack = timing.walk_paths(); 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); delay_t default_slack = delay_t(1.0e12 / ctx->target_freq);
log_info("estimated Fmax = %.2f MHz\n", 1e6 / (default_slack - min_slack)); 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; constexpr unsigned num_bins = 20;
unsigned bar_width = 60; unsigned bar_width = 60;
auto min_slack = slack_histogram.begin()->first; 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_break();
log_info("Slack histogram:\n"); log_info("Slack histogram:\n");
log_info(" legend: * represents %d endpoint(s)\n", max_freq / bar_width); 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) 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), 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()); std::string(bins[i] * bar_width / max_freq, '*').c_str(),
(bins[i] * bar_width) % max_freq > 0 ? '+' : ' ');
} }
} }

View File

@ -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. 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. 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) ### 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. 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\<BelId\> getBels() const ### const\_range\<BelId\> 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. 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()` 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. 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) ### 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. 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. 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. 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 or if there is no single net that can be unbound to make this
wire available. 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. 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. 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) ### 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. 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. 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 Return the net that needs to be unbound in order to make this
pip available. 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. 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 Flow Methods
------------ ------------

View File

@ -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)); 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.type = DecalId::TYPE_BEL;
decalxy.decal.location = bel.location; decalxy.decal.location = bel.location;
decalxy.decal.z = bel.index; 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; return decalxy;
} }

View File

@ -404,10 +404,9 @@ struct Arch : BaseCtx
mutable std::unordered_map<IdString, WireId> wire_by_name; mutable std::unordered_map<IdString, WireId> wire_by_name;
mutable std::unordered_map<IdString, PipId> pip_by_name; mutable std::unordered_map<IdString, PipId> pip_by_name;
std::unordered_map<BelId, IdString> bel_to_cell; std::unordered_map<BelId, CellInfo *> bel_to_cell;
std::unordered_map<WireId, IdString> wire_to_net; std::unordered_map<WireId, NetInfo *> wire_to_net;
std::unordered_map<PipId, IdString> pip_to_net; std::unordered_map<PipId, NetInfo *> pip_to_net;
std::unordered_map<PipId, IdString> switches_locked;
ArchArgs args; ArchArgs args;
Arch(ArchArgs args); Arch(ArchArgs args);
@ -448,23 +447,23 @@ struct Arch : BaseCtx
uint32_t getBelChecksum(BelId bel) const { return bel.index; } 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 != BelId());
NPNR_ASSERT(bel_to_cell[bel] == IdString()); NPNR_ASSERT(bel_to_cell[bel] == nullptr);
bel_to_cell[bel] = cell; bel_to_cell[bel] = cell;
cells[cell]->bel = bel; cell->bel = bel;
cells[cell]->belStrength = strength; cell->belStrength = strength;
refreshUiBel(bel); refreshUiBel(bel);
} }
void unbindBel(BelId bel) void unbindBel(BelId bel)
{ {
NPNR_ASSERT(bel != BelId()); NPNR_ASSERT(bel != BelId());
NPNR_ASSERT(bel_to_cell[bel] != IdString()); NPNR_ASSERT(bel_to_cell[bel] != nullptr);
cells[bel_to_cell[bel]]->bel = BelId(); bel_to_cell[bel]->bel = BelId();
cells[bel_to_cell[bel]]->belStrength = STRENGTH_NONE; bel_to_cell[bel]->belStrength = STRENGTH_NONE;
bel_to_cell[bel] = IdString(); bel_to_cell[bel] = nullptr;
refreshUiBel(bel); refreshUiBel(bel);
} }
@ -485,23 +484,23 @@ struct Arch : BaseCtx
bool checkBelAvail(BelId bel) const bool checkBelAvail(BelId bel) const
{ {
NPNR_ASSERT(bel != BelId()); 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()); NPNR_ASSERT(bel != BelId());
if (bel_to_cell.find(bel) == bel_to_cell.end()) if (bel_to_cell.find(bel) == bel_to_cell.end())
return IdString(); return nullptr;
else else
return bel_to_cell.at(bel); return bel_to_cell.at(bel);
} }
IdString getConflictingBelCell(BelId bel) const CellInfo *getConflictingBelCell(BelId bel) const
{ {
NPNR_ASSERT(bel != BelId()); NPNR_ASSERT(bel != BelId());
if (bel_to_cell.find(bel) == bel_to_cell.end()) if (bel_to_cell.find(bel) == bel_to_cell.end())
return IdString(); return nullptr;
else else
return bel_to_cell.at(bel); return bel_to_cell.at(bel);
} }
@ -558,53 +557,53 @@ struct Arch : BaseCtx
uint32_t getWireChecksum(WireId wire) const { return wire.index; } 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 != WireId());
NPNR_ASSERT(wire_to_net[wire] == IdString()); NPNR_ASSERT(wire_to_net[wire] == nullptr);
wire_to_net[wire] = net; wire_to_net[wire] = net;
nets[net]->wires[wire].pip = PipId(); net->wires[wire].pip = PipId();
nets[net]->wires[wire].strength = strength; net->wires[wire].strength = strength;
} }
void unbindWire(WireId wire) void unbindWire(WireId wire)
{ {
NPNR_ASSERT(wire != WireId()); 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); auto it = net_wires.find(wire);
NPNR_ASSERT(it != net_wires.end()); NPNR_ASSERT(it != net_wires.end());
auto pip = it->second.pip; auto pip = it->second.pip;
if (pip != PipId()) { if (pip != PipId()) {
pip_to_net[pip] = IdString(); pip_to_net[pip] = nullptr;
} }
net_wires.erase(it); net_wires.erase(it);
wire_to_net[wire] = IdString(); wire_to_net[wire] = nullptr;
} }
bool checkWireAvail(WireId wire) const bool checkWireAvail(WireId wire) const
{ {
NPNR_ASSERT(wire != WireId()); 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()); NPNR_ASSERT(wire != WireId());
if (wire_to_net.find(wire) == wire_to_net.end()) if (wire_to_net.find(wire) == wire_to_net.end())
return IdString(); return nullptr;
else else
return wire_to_net.at(wire); return wire_to_net.at(wire);
} }
IdString getConflictingWireNet(WireId wire) const NetInfo *getConflictingWireNet(WireId wire) const
{ {
NPNR_ASSERT(wire != WireId()); NPNR_ASSERT(wire != WireId());
if (wire_to_net.find(wire) == wire_to_net.end()) if (wire_to_net.find(wire) == wire_to_net.end())
return IdString(); return nullptr;
else else
return wire_to_net.at(wire); return wire_to_net.at(wire);
} }
@ -638,57 +637,57 @@ struct Arch : BaseCtx
uint32_t getPipChecksum(PipId pip) const { return pip.index; } 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 != PipId());
NPNR_ASSERT(pip_to_net[pip] == IdString()); NPNR_ASSERT(pip_to_net[pip] == nullptr);
pip_to_net[pip] = net; pip_to_net[pip] = net;
WireId dst; WireId dst;
dst.index = locInfo(pip)->pip_data[pip.index].dst_idx; dst.index = locInfo(pip)->pip_data[pip.index].dst_idx;
dst.location = pip.location + locInfo(pip)->pip_data[pip.index].rel_dst_loc; 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; wire_to_net[dst] = net;
nets[net]->wires[dst].pip = pip; net->wires[dst].pip = pip;
nets[net]->wires[dst].strength = strength; net->wires[dst].strength = strength;
} }
void unbindPip(PipId pip) void unbindPip(PipId pip)
{ {
NPNR_ASSERT(pip != PipId()); NPNR_ASSERT(pip != PipId());
NPNR_ASSERT(pip_to_net[pip] != IdString()); NPNR_ASSERT(pip_to_net[pip] != nullptr);
WireId dst; WireId dst;
dst.index = locInfo(pip)->pip_data[pip.index].dst_idx; dst.index = locInfo(pip)->pip_data[pip.index].dst_idx;
dst.location = pip.location + locInfo(pip)->pip_data[pip.index].rel_dst_loc; 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] = IdString(); wire_to_net[dst] = nullptr;
nets[pip_to_net[pip]]->wires.erase(dst); pip_to_net[pip]->wires.erase(dst);
pip_to_net[pip] = IdString(); pip_to_net[pip] = nullptr;
} }
bool checkPipAvail(PipId pip) const bool checkPipAvail(PipId pip) const
{ {
NPNR_ASSERT(pip != PipId()); 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()); NPNR_ASSERT(pip != PipId());
if (pip_to_net.find(pip) == pip_to_net.end()) if (pip_to_net.find(pip) == pip_to_net.end())
return IdString(); return nullptr;
else else
return pip_to_net.at(pip); return pip_to_net.at(pip);
} }
IdString getConflictingPipNet(PipId pip) const NetInfo *getConflictingPipNet(PipId pip) const
{ {
NPNR_ASSERT(pip != PipId()); NPNR_ASSERT(pip != PipId());
if (pip_to_net.find(pip) == pip_to_net.end()) if (pip_to_net.find(pip) == pip_to_net.end())
return IdString(); return nullptr;
else else
return pip_to_net.at(pip); return pip_to_net.at(pip);
} }
@ -807,7 +806,7 @@ struct Arch : BaseCtx
delay_t getRipupDelayPenalty() const { return 200; } delay_t getRipupDelayPenalty() const { return 200; }
float getDelayNS(delay_t v) const { return v * 0.001; } float getDelayNS(delay_t v) const { return v * 0.001; }
uint32_t getDelayChecksum(delay_t v) const { return v; } 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;
// ------------------------------------------------- // -------------------------------------------------

View File

@ -68,19 +68,18 @@ bool Arch::isBelLocationValid(BelId bel) const
std::vector<const CellInfo *> bel_cells; std::vector<const CellInfo *> bel_cells;
Loc bel_loc = getBelLocation(bel); Loc bel_loc = getBelLocation(bel);
for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {
IdString cell_other = getBoundBelCell(bel_other); CellInfo *cell_other = getBoundBelCell(bel_other);
if (cell_other != IdString()) { if (cell_other != nullptr) {
const CellInfo *ci_other = cells.at(cell_other).get(); bel_cells.push_back(cell_other);
bel_cells.push_back(ci_other);
} }
} }
return slicesCompatible(bel_cells); return slicesCompatible(bel_cells);
} else { } else {
IdString cellId = getBoundBelCell(bel); CellInfo *cell = getBoundBelCell(bel);
if (cellId == IdString()) if (cell == nullptr)
return true; return true;
else 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<const CellInfo *> bel_cells; std::vector<const CellInfo *> bel_cells;
Loc bel_loc = getBelLocation(bel); Loc bel_loc = getBelLocation(bel);
for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {
IdString cell_other = getBoundBelCell(bel_other); CellInfo *cell_other = getBoundBelCell(bel_other);
if (cell_other != IdString() && bel_other != bel) { if (cell_other != nullptr && bel_other != bel) {
const CellInfo *ci_other = cells.at(cell_other).get(); bel_cells.push_back(cell_other);
bel_cells.push_back(ci_other);
} }
} }

View File

@ -60,13 +60,13 @@ void arch_wrap_python()
fn_wrapper_1a<Context, decltype(&Context::getBelChecksum), &Context::getBelChecksum, pass_through<uint32_t>, fn_wrapper_1a<Context, decltype(&Context::getBelChecksum), &Context::getBelChecksum, pass_through<uint32_t>,
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelChecksum"); conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelChecksum");
fn_wrapper_3a_v<Context, decltype(&Context::bindBel), &Context::bindBel, conv_from_str<BelId>, fn_wrapper_3a_v<Context, decltype(&Context::bindBel), &Context::bindBel, conv_from_str<BelId>,
conv_from_str<IdString>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindBel"); addr_and_unwrap<CellInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindBel");
fn_wrapper_1a_v<Context, decltype(&Context::unbindBel), &Context::unbindBel, conv_from_str<BelId>>::def_wrap( fn_wrapper_1a_v<Context, decltype(&Context::unbindBel), &Context::unbindBel, conv_from_str<BelId>>::def_wrap(
ctx_cls, "unbindBel"); ctx_cls, "unbindBel");
fn_wrapper_1a<Context, decltype(&Context::getBoundBelCell), &Context::getBoundBelCell, conv_to_str<IdString>, fn_wrapper_1a<Context, decltype(&Context::getBoundBelCell), &Context::getBoundBelCell, deref_and_wrap<CellInfo>,
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBoundBelCell"); conv_from_str<BelId>>::def_wrap(ctx_cls, "getBoundBelCell");
fn_wrapper_1a<Context, decltype(&Context::getConflictingBelCell), &Context::getConflictingBelCell, fn_wrapper_1a<Context, decltype(&Context::getConflictingBelCell), &Context::getConflictingBelCell,
conv_to_str<IdString>, conv_from_str<BelId>>::def_wrap(ctx_cls, "getConflictingBelCell"); deref_and_wrap<CellInfo>, conv_from_str<BelId>>::def_wrap(ctx_cls, "getConflictingBelCell");
fn_wrapper_0a<Context, decltype(&Context::getBels), &Context::getBels, wrap_context<BelRange>>::def_wrap(ctx_cls, fn_wrapper_0a<Context, decltype(&Context::getBels), &Context::getBels, wrap_context<BelRange>>::def_wrap(ctx_cls,
"getBels"); "getBels");
@ -78,15 +78,15 @@ void arch_wrap_python()
fn_wrapper_1a<Context, decltype(&Context::getWireChecksum), &Context::getWireChecksum, pass_through<uint32_t>, fn_wrapper_1a<Context, decltype(&Context::getWireChecksum), &Context::getWireChecksum, pass_through<uint32_t>,
conv_from_str<WireId>>::def_wrap(ctx_cls, "getWireChecksum"); conv_from_str<WireId>>::def_wrap(ctx_cls, "getWireChecksum");
fn_wrapper_3a_v<Context, decltype(&Context::bindWire), &Context::bindWire, conv_from_str<WireId>, fn_wrapper_3a_v<Context, decltype(&Context::bindWire), &Context::bindWire, conv_from_str<WireId>,
conv_from_str<IdString>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindWire"); addr_and_unwrap<NetInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindWire");
fn_wrapper_1a_v<Context, decltype(&Context::unbindWire), &Context::unbindWire, conv_from_str<WireId>>::def_wrap( fn_wrapper_1a_v<Context, decltype(&Context::unbindWire), &Context::unbindWire, conv_from_str<WireId>>::def_wrap(
ctx_cls, "unbindWire"); ctx_cls, "unbindWire");
fn_wrapper_1a<Context, decltype(&Context::checkWireAvail), &Context::checkWireAvail, pass_through<bool>, fn_wrapper_1a<Context, decltype(&Context::checkWireAvail), &Context::checkWireAvail, pass_through<bool>,
conv_from_str<WireId>>::def_wrap(ctx_cls, "checkWireAvail"); conv_from_str<WireId>>::def_wrap(ctx_cls, "checkWireAvail");
fn_wrapper_1a<Context, decltype(&Context::getBoundWireNet), &Context::getBoundWireNet, conv_to_str<IdString>, fn_wrapper_1a<Context, decltype(&Context::getBoundWireNet), &Context::getBoundWireNet, deref_and_wrap<NetInfo>,
conv_from_str<WireId>>::def_wrap(ctx_cls, "getBoundWireNet"); conv_from_str<WireId>>::def_wrap(ctx_cls, "getBoundWireNet");
fn_wrapper_1a<Context, decltype(&Context::getConflictingWireNet), &Context::getConflictingWireNet, fn_wrapper_1a<Context, decltype(&Context::getConflictingWireNet), &Context::getConflictingWireNet,
conv_to_str<IdString>, conv_from_str<WireId>>::def_wrap(ctx_cls, "getConflictingWireNet"); deref_and_wrap<NetInfo>, conv_from_str<WireId>>::def_wrap(ctx_cls, "getConflictingWireNet");
fn_wrapper_0a<Context, decltype(&Context::getWires), &Context::getWires, wrap_context<WireRange>>::def_wrap( fn_wrapper_0a<Context, decltype(&Context::getWires), &Context::getWires, wrap_context<WireRange>>::def_wrap(
ctx_cls, "getWires"); ctx_cls, "getWires");
@ -96,15 +96,15 @@ void arch_wrap_python()
fn_wrapper_1a<Context, decltype(&Context::getPipChecksum), &Context::getPipChecksum, pass_through<uint32_t>, fn_wrapper_1a<Context, decltype(&Context::getPipChecksum), &Context::getPipChecksum, pass_through<uint32_t>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipChecksum"); conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipChecksum");
fn_wrapper_3a_v<Context, decltype(&Context::bindPip), &Context::bindPip, conv_from_str<PipId>, fn_wrapper_3a_v<Context, decltype(&Context::bindPip), &Context::bindPip, conv_from_str<PipId>,
conv_from_str<IdString>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindPip"); addr_and_unwrap<NetInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindPip");
fn_wrapper_1a_v<Context, decltype(&Context::unbindPip), &Context::unbindPip, conv_from_str<PipId>>::def_wrap( fn_wrapper_1a_v<Context, decltype(&Context::unbindPip), &Context::unbindPip, conv_from_str<PipId>>::def_wrap(
ctx_cls, "unbindPip"); ctx_cls, "unbindPip");
fn_wrapper_1a<Context, decltype(&Context::checkPipAvail), &Context::checkPipAvail, pass_through<bool>, fn_wrapper_1a<Context, decltype(&Context::checkPipAvail), &Context::checkPipAvail, pass_through<bool>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "checkPipAvail"); conv_from_str<PipId>>::def_wrap(ctx_cls, "checkPipAvail");
fn_wrapper_1a<Context, decltype(&Context::getBoundPipNet), &Context::getBoundPipNet, conv_to_str<IdString>, fn_wrapper_1a<Context, decltype(&Context::getBoundPipNet), &Context::getBoundPipNet, deref_and_wrap<NetInfo>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "getBoundPipNet"); conv_from_str<PipId>>::def_wrap(ctx_cls, "getBoundPipNet");
fn_wrapper_1a<Context, decltype(&Context::getConflictingPipNet), &Context::getConflictingPipNet, fn_wrapper_1a<Context, decltype(&Context::getConflictingPipNet), &Context::getConflictingPipNet,
conv_to_str<IdString>, conv_from_str<PipId>>::def_wrap(ctx_cls, "getConflictingPipNet"); deref_and_wrap<NetInfo>, conv_from_str<PipId>>::def_wrap(ctx_cls, "getConflictingPipNet");
fn_wrapper_1a<Context, decltype(&Context::getPipsDownhill), &Context::getPipsDownhill, wrap_context<PipRange>, fn_wrapper_1a<Context, decltype(&Context::getPipsDownhill), &Context::getPipsDownhill, wrap_context<PipRange>,
conv_from_str<WireId>>::def_wrap(ctx_cls, "getPipsDownhill"); conv_from_str<WireId>>::def_wrap(ctx_cls, "getPipsDownhill");

View File

@ -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 // Add all set, configurable pips to the config
for (auto pip : ctx->getPips()) { for (auto pip : ctx->getPips()) {
if (ctx->getBoundPipNet(pip) != IdString()) { if (ctx->getBoundPipNet(pip) != nullptr) {
if (ctx->getPipClass(pip) == 0) { // ignore fixed pips if (ctx->getPipClass(pip) == 0) { // ignore fixed pips
std::string tile = ctx->getPipTilename(pip); std::string tile = ctx->getPipTilename(pip);
std::string source = get_trellis_wirename(ctx, pip.location, ctx->getPipSrcWire(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", cc.tiles[tname].add_enum(slice + ".REG1.REGSET",
str_or_default(ci->params, ctx->id("REG1_REGSET"), "RESET")); 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")); 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) 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( if (ctx->getBoundWireNet(ctx->getWireByName(
ctx->id(fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/LSR0")))) == lsrnet) { 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")); cc.tiles[tname].add_enum("LSR0.SRMODE", str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE"));

View File

@ -214,27 +214,27 @@ uint32_t Arch::getBelChecksum(BelId bel) const
return 0; 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; bels.at(bel).bound_cell = cell;
cells.at(cell)->bel = bel; cell->bel = bel;
cells.at(cell)->belStrength = strength; cell->belStrength = strength;
refreshUiBel(bel); refreshUiBel(bel);
} }
void Arch::unbindBel(BelId bel) void Arch::unbindBel(BelId bel)
{ {
cells.at(bels.at(bel).bound_cell)->bel = BelId(); bels.at(bel).bound_cell->bel = BelId();
cells.at(bels.at(bel).bound_cell)->belStrength = STRENGTH_NONE; bels.at(bel).bound_cell->belStrength = STRENGTH_NONE;
bels.at(bel).bound_cell = IdString(); bels.at(bel).bound_cell = nullptr;
refreshUiBel(bel); 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<BelId> &Arch::getBels() const { return bel_ids; } const std::vector<BelId> &Arch::getBels() const { return bel_ids; }
@ -271,34 +271,34 @@ uint32_t Arch::getWireChecksum(WireId wire) const
return 0; 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; wires.at(wire).bound_net = net;
nets.at(net)->wires[wire].pip = PipId(); net->wires[wire].pip = PipId();
nets.at(net)->wires[wire].strength = strength; net->wires[wire].strength = strength;
refreshUiWire(wire); refreshUiWire(wire);
} }
void Arch::unbindWire(WireId 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; auto pip = net_wires.at(wire).pip;
if (pip != PipId()) { if (pip != PipId()) {
pips.at(pip).bound_net = IdString(); pips.at(pip).bound_net = nullptr;
refreshUiPip(pip); refreshUiPip(pip);
} }
net_wires.erase(wire); net_wires.erase(wire);
wires.at(wire).bound_net = IdString(); wires.at(wire).bound_net = nullptr;
refreshUiWire(wire); 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<BelPin> &Arch::getWireBelPins(WireId wire) const { return wires.at(wire).bel_pins; } const std::vector<BelPin> &Arch::getWireBelPins(WireId wire) const { return wires.at(wire).bel_pins; }
@ -323,13 +323,13 @@ uint32_t Arch::getPipChecksum(PipId wire) const
return 0; 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; WireId wire = pips.at(pip).dstWire;
pips.at(pip).bound_net = net; pips.at(pip).bound_net = net;
wires.at(wire).bound_net = net; wires.at(wire).bound_net = net;
nets.at(net)->wires[wire].pip = pip; net->wires[wire].pip = pip;
nets.at(net)->wires[wire].strength = strength; net->wires[wire].strength = strength;
refreshUiPip(pip); refreshUiPip(pip);
refreshUiWire(wire); refreshUiWire(wire);
} }
@ -337,18 +337,18 @@ void Arch::bindPip(PipId pip, IdString net, PlaceStrength strength)
void Arch::unbindPip(PipId pip) void Arch::unbindPip(PipId pip)
{ {
WireId wire = pips.at(pip).dstWire; WireId wire = pips.at(pip).dstWire;
nets.at(wires.at(wire).bound_net)->wires.erase(wire); wires.at(wire).bound_net->wires.erase(wire);
pips.at(pip).bound_net = IdString(); pips.at(pip).bound_net = nullptr;
wires.at(wire).bound_net = IdString(); wires.at(wire).bound_net = nullptr;
refreshUiPip(pip); refreshUiPip(pip);
refreshUiWire(wire); 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<PipId> &Arch::getPips() const { return pip_ids; } const std::vector<PipId> &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; 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; }
// --------------------------------------------------------------- // ---------------------------------------------------------------

View File

@ -31,7 +31,8 @@ struct WireInfo;
struct PipInfo struct PipInfo
{ {
IdString name, type, bound_net; IdString name, type;
NetInfo *bound_net;
WireId srcWire, dstWire; WireId srcWire, dstWire;
DelayInfo delay; DelayInfo delay;
DecalXY decalxy; DecalXY decalxy;
@ -39,7 +40,8 @@ struct PipInfo
struct WireInfo struct WireInfo
{ {
IdString name, type, bound_net; IdString name, type;
NetInfo *bound_net;
std::vector<PipId> downhill, uphill, aliases; std::vector<PipId> downhill, uphill, aliases;
BelPin uphill_bel_pin; BelPin uphill_bel_pin;
std::vector<BelPin> downhill_bel_pins; std::vector<BelPin> downhill_bel_pins;
@ -57,7 +59,8 @@ struct PinInfo
struct BelInfo struct BelInfo
{ {
IdString name, type, bound_cell; IdString name, type;
CellInfo *bound_cell;
std::unordered_map<IdString, PinInfo> pins; std::unordered_map<IdString, PinInfo> pins;
DecalXY decalxy; DecalXY decalxy;
int x, y, z; int x, y, z;
@ -144,11 +147,11 @@ struct Arch : BaseCtx
const std::vector<BelId> &getBelsByTile(int x, int y) const; const std::vector<BelId> &getBelsByTile(int x, int y) const;
bool getBelGlobalBuf(BelId bel) const; bool getBelGlobalBuf(BelId bel) const;
uint32_t getBelChecksum(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); void unbindBel(BelId bel);
bool checkBelAvail(BelId bel) const; bool checkBelAvail(BelId bel) const;
IdString getBoundBelCell(BelId bel) const; CellInfo *getBoundBelCell(BelId bel) const;
IdString getConflictingBelCell(BelId bel) const; CellInfo *getConflictingBelCell(BelId bel) const;
const std::vector<BelId> &getBels() const; const std::vector<BelId> &getBels() const;
BelType getBelType(BelId bel) const; BelType getBelType(BelId bel) const;
WireId getBelPinWire(BelId bel, PortPin pin) const; WireId getBelPinWire(BelId bel, PortPin pin) const;
@ -159,11 +162,11 @@ struct Arch : BaseCtx
IdString getWireName(WireId wire) const; IdString getWireName(WireId wire) const;
IdString getWireType(WireId wire) const; IdString getWireType(WireId wire) const;
uint32_t getWireChecksum(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); void unbindWire(WireId wire);
bool checkWireAvail(WireId wire) const; bool checkWireAvail(WireId wire) const;
IdString getBoundWireNet(WireId wire) const; NetInfo *getBoundWireNet(WireId wire) const;
IdString getConflictingWireNet(WireId wire) const; NetInfo *getConflictingWireNet(WireId wire) const;
DelayInfo getWireDelay(WireId wire) const { return DelayInfo(); } DelayInfo getWireDelay(WireId wire) const { return DelayInfo(); }
const std::vector<WireId> &getWires() const; const std::vector<WireId> &getWires() const;
const std::vector<BelPin> &getWireBelPins(WireId wire) const; const std::vector<BelPin> &getWireBelPins(WireId wire) const;
@ -172,11 +175,11 @@ struct Arch : BaseCtx
IdString getPipName(PipId pip) const; IdString getPipName(PipId pip) const;
IdString getPipType(PipId pip) const; IdString getPipType(PipId pip) const;
uint32_t getPipChecksum(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); void unbindPip(PipId pip);
bool checkPipAvail(PipId pip) const; bool checkPipAvail(PipId pip) const;
IdString getBoundPipNet(PipId pip) const; NetInfo *getBoundPipNet(PipId pip) const;
IdString getConflictingPipNet(PipId pip) const; NetInfo *getConflictingPipNet(PipId pip) const;
const std::vector<PipId> &getPips() const; const std::vector<PipId> &getPips() const;
WireId getPipSrcWire(PipId pip) const; WireId getPipSrcWire(PipId pip) const;
WireId getPipDstWire(PipId pip) const; WireId getPipDstWire(PipId pip) const;
@ -199,7 +202,7 @@ struct Arch : BaseCtx
delay_t getRipupDelayPenalty() const { return 1.0; } delay_t getRipupDelayPenalty() const { return 1.0; }
float getDelayNS(delay_t v) const { return v; } float getDelayNS(delay_t v) const { return v; }
uint32_t getDelayChecksum(delay_t v) const { return 0; } 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 pack() { return true; }
bool place(); bool place();

View File

@ -407,8 +407,8 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx)); 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::String, "Type", ctx->belTypeToId(ctx->getBelType(bel)).c_str(ctx));
addProperty(topItem, QVariant::Bool, "Available", ctx->checkBelAvail(bel)); 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, "Bound Cell", ctx->nameOf(ctx->getBoundBelCell(bel)), ElementType::CELL);
addProperty(topItem, QVariant::String, "Conflicting Cell", ctx->getConflictingBelCell(bel).c_str(ctx), addProperty(topItem, QVariant::String, "Conflicting Cell", ctx->nameOf(ctx->getConflictingBelCell(bel)),
ElementType::CELL); ElementType::CELL);
QtProperty *belpinsItem = addSubGroup(topItem, "Ports"); 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, "Name", c.c_str(ctx));
addProperty(topItem, QVariant::String, "Type", ctx->getWireType(wire).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::Bool, "Available", ctx->checkWireAvail(wire));
addProperty(topItem, QVariant::String, "Bound Net", ctx->getBoundWireNet(wire).c_str(ctx), ElementType::NET); addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundWireNet(wire)), ElementType::NET);
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->getConflictingWireNet(wire).c_str(ctx), addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingWireNet(wire)),
ElementType::NET); ElementType::NET);
DelayInfo delay = ctx->getWireDelay(wire); 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, "Name", c.c_str(ctx));
addProperty(topItem, QVariant::String, "Type", ctx->getPipType(pip).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::Bool, "Available", ctx->checkPipAvail(pip));
addProperty(topItem, QVariant::String, "Bound Net", ctx->getBoundPipNet(pip).c_str(ctx), ElementType::NET); addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundPipNet(pip)), ElementType::NET);
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->getConflictingPipNet(pip).c_str(ctx), addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingPipNet(pip)),
ElementType::NET); ElementType::NET);
addProperty(topItem, QVariant::String, "Src Wire", ctx->getWireName(ctx->getPipSrcWire(pip)).c_str(ctx), addProperty(topItem, QVariant::String, "Src Wire", ctx->getWireName(ctx->getPipSrcWire(pip)).c_str(ctx),
ElementType::WIRE); ElementType::WIRE);

View File

@ -637,17 +637,34 @@ std::vector<GroupId> 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; 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 driver_loc = getBelLocation(driver.cell->bel);
auto sink_loc = getBelLocation(sink.cell->bel); auto sink_loc = getBelLocation(sink.cell->bel);
if (driver_loc.y == sink_loc.y) if (driver_loc.y == sink_loc.y)
return 0; budget = 0;
return 250; 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 decalxy;
decalxy.decal.type = DecalId::TYPE_BEL; decalxy.decal.type = DecalId::TYPE_BEL;
decalxy.decal.index = bel.index; 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; return decalxy;
} }
@ -681,7 +698,7 @@ DecalXY Arch::getWireDecal(WireId wire) const
DecalXY decalxy; DecalXY decalxy;
decalxy.decal.type = DecalId::TYPE_WIRE; decalxy.decal.type = DecalId::TYPE_WIRE;
decalxy.decal.index = wire.index; 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; return decalxy;
} }
@ -690,7 +707,7 @@ DecalXY Arch::getPipDecal(PipId pip) const
DecalXY decalxy; DecalXY decalxy;
decalxy.decal.type = DecalId::TYPE_PIP; decalxy.decal.type = DecalId::TYPE_PIP;
decalxy.decal.index = pip.index; 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; return decalxy;
}; };

View File

@ -400,10 +400,10 @@ struct Arch : BaseCtx
mutable std::unordered_map<Loc, int> bel_by_loc; mutable std::unordered_map<Loc, int> bel_by_loc;
std::vector<bool> bel_carry; std::vector<bool> bel_carry;
std::vector<IdString> bel_to_cell; std::vector<CellInfo*> bel_to_cell;
std::vector<IdString> wire_to_net; std::vector<NetInfo*> wire_to_net;
std::vector<IdString> pip_to_net; std::vector<NetInfo*> pip_to_net;
std::vector<IdString> switches_locked; std::vector<NetInfo*> switches_locked;
ArchArgs args; ArchArgs args;
Arch(ArchArgs args); Arch(ArchArgs args);
@ -438,26 +438,25 @@ struct Arch : BaseCtx
uint32_t getBelChecksum(BelId bel) const { return bel.index; } 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 != BelId());
NPNR_ASSERT(bel_to_cell[bel.index] == IdString()); NPNR_ASSERT(bel_to_cell[bel.index] == nullptr);
auto &c = cells[cell];
bel_to_cell[bel.index] = cell; bel_to_cell[bel.index] = cell;
bel_carry[bel.index] = (c->type == id_icestorm_lc && c->lcInfo.carryEnable); bel_carry[bel.index] = (cell->type == id_icestorm_lc && cell->lcInfo.carryEnable);
c->bel = bel; cell->bel = bel;
c->belStrength = strength; cell->belStrength = strength;
refreshUiBel(bel); refreshUiBel(bel);
} }
void unbindBel(BelId bel) void unbindBel(BelId bel)
{ {
NPNR_ASSERT(bel != BelId()); NPNR_ASSERT(bel != BelId());
NPNR_ASSERT(bel_to_cell[bel.index] != IdString()); NPNR_ASSERT(bel_to_cell[bel.index] != nullptr);
cells[bel_to_cell[bel.index]]->bel = BelId(); bel_to_cell[bel.index]->bel = BelId();
cells[bel_to_cell[bel.index]]->belStrength = STRENGTH_NONE; bel_to_cell[bel.index]->belStrength = STRENGTH_NONE;
bel_to_cell[bel.index] = IdString(); bel_to_cell[bel.index] = nullptr;
bel_carry[bel.index] = false; bel_carry[bel.index] = false;
refreshUiBel(bel); refreshUiBel(bel);
} }
@ -465,16 +464,16 @@ struct Arch : BaseCtx
bool checkBelAvail(BelId bel) const bool checkBelAvail(BelId bel) const
{ {
NPNR_ASSERT(bel != BelId()); 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()); NPNR_ASSERT(bel != BelId());
return bel_to_cell[bel.index]; return bel_to_cell[bel.index];
} }
IdString getConflictingBelCell(BelId bel) const CellInfo *getConflictingBelCell(BelId bel) const
{ {
NPNR_ASSERT(bel != BelId()); NPNR_ASSERT(bel != BelId());
return bel_to_cell[bel.index]; return bel_to_cell[bel.index];
@ -526,49 +525,49 @@ struct Arch : BaseCtx
uint32_t getWireChecksum(WireId wire) const { return wire.index; } 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 != WireId());
NPNR_ASSERT(wire_to_net[wire.index] == IdString()); NPNR_ASSERT(wire_to_net[wire.index] == nullptr);
wire_to_net[wire.index] = net; wire_to_net[wire.index] = net;
nets[net]->wires[wire].pip = PipId(); net->wires[wire].pip = PipId();
nets[net]->wires[wire].strength = strength; net->wires[wire].strength = strength;
refreshUiWire(wire); refreshUiWire(wire);
} }
void unbindWire(WireId wire) void unbindWire(WireId wire)
{ {
NPNR_ASSERT(wire != WireId()); 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); auto it = net_wires.find(wire);
NPNR_ASSERT(it != net_wires.end()); NPNR_ASSERT(it != net_wires.end());
auto pip = it->second.pip; auto pip = it->second.pip;
if (pip != PipId()) { if (pip != PipId()) {
pip_to_net[pip.index] = IdString(); pip_to_net[pip.index] = nullptr;
switches_locked[chip_info->pip_data[pip.index].switch_index] = IdString(); switches_locked[chip_info->pip_data[pip.index].switch_index] = nullptr;
} }
net_wires.erase(it); net_wires.erase(it);
wire_to_net[wire.index] = IdString(); wire_to_net[wire.index] = nullptr;
refreshUiWire(wire); refreshUiWire(wire);
} }
bool checkWireAvail(WireId wire) const bool checkWireAvail(WireId wire) const
{ {
NPNR_ASSERT(wire != WireId()); 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()); NPNR_ASSERT(wire != WireId());
return wire_to_net[wire.index]; return wire_to_net[wire.index];
} }
IdString getConflictingWireNet(WireId wire) const NetInfo *getConflictingWireNet(WireId wire) const
{ {
NPNR_ASSERT(wire != WireId()); NPNR_ASSERT(wire != WireId());
return wire_to_net[wire.index]; return wire_to_net[wire.index];
@ -606,21 +605,21 @@ struct Arch : BaseCtx
PipId getPipByName(IdString name) const; 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 != PipId());
NPNR_ASSERT(pip_to_net[pip.index] == IdString()); NPNR_ASSERT(pip_to_net[pip.index] == nullptr);
NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] == IdString()); NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] == nullptr);
pip_to_net[pip.index] = net; pip_to_net[pip.index] = net;
switches_locked[chip_info->pip_data[pip.index].switch_index] = net; switches_locked[chip_info->pip_data[pip.index].switch_index] = net;
WireId dst; WireId dst;
dst.index = chip_info->pip_data[pip.index].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; wire_to_net[dst.index] = net;
nets[net]->wires[dst].pip = pip; net->wires[dst].pip = pip;
nets[net]->wires[dst].strength = strength; net->wires[dst].strength = strength;
refreshUiPip(pip); refreshUiPip(pip);
refreshUiWire(dst); refreshUiWire(dst);
} }
@ -628,17 +627,17 @@ struct Arch : BaseCtx
void unbindPip(PipId pip) void unbindPip(PipId pip)
{ {
NPNR_ASSERT(pip != PipId()); NPNR_ASSERT(pip != PipId());
NPNR_ASSERT(pip_to_net[pip.index] != IdString()); NPNR_ASSERT(pip_to_net[pip.index] != nullptr);
NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] != IdString()); NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] != nullptr);
WireId dst; WireId dst;
dst.index = chip_info->pip_data[pip.index].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] = IdString(); wire_to_net[dst.index] = nullptr;
nets[pip_to_net[pip.index]]->wires.erase(dst); pip_to_net[pip.index]->wires.erase(dst);
pip_to_net[pip.index] = IdString(); pip_to_net[pip.index] = nullptr;
switches_locked[chip_info->pip_data[pip.index].switch_index] = IdString(); switches_locked[chip_info->pip_data[pip.index].switch_index] = nullptr;
refreshUiPip(pip); refreshUiPip(pip);
refreshUiWire(dst); refreshUiWire(dst);
} }
@ -649,12 +648,12 @@ struct Arch : BaseCtx
auto &pi = chip_info->pip_data[pip.index]; auto &pi = chip_info->pip_data[pip.index];
auto &si = chip_info->bits_info->switches[pi.switch_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; return false;
if (pi.flags & PipInfoPOD::FLAG_ROUTETHRU) { if (pi.flags & PipInfoPOD::FLAG_ROUTETHRU) {
NPNR_ASSERT(si.bel >= 0); NPNR_ASSERT(si.bel >= 0);
if (bel_to_cell[si.bel] != IdString()) if (bel_to_cell[si.bel] != nullptr)
return false; return false;
} }
@ -667,13 +666,13 @@ struct Arch : BaseCtx
return true; return true;
} }
IdString getBoundPipNet(PipId pip) const NetInfo *getBoundPipNet(PipId pip) const
{ {
NPNR_ASSERT(pip != PipId()); NPNR_ASSERT(pip != PipId());
return pip_to_net[pip.index]; return pip_to_net[pip.index];
} }
IdString getConflictingPipNet(PipId pip) const NetInfo *getConflictingPipNet(PipId pip) const
{ {
NPNR_ASSERT(pip != PipId()); NPNR_ASSERT(pip != PipId());
return switches_locked[chip_info->pip_data[pip.index].switch_index]; return switches_locked[chip_info->pip_data[pip.index].switch_index];
@ -768,7 +767,7 @@ struct Arch : BaseCtx
delay_t getRipupDelayPenalty() const { return 200; } delay_t getRipupDelayPenalty() const { return 200; }
float getDelayNS(delay_t v) const { return v * 0.001; } float getDelayNS(delay_t v) const { return v * 0.001; }
uint32_t getDelayChecksum(delay_t v) const { return v; } 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;
// ------------------------------------------------- // -------------------------------------------------

View File

@ -74,19 +74,18 @@ bool Arch::isBelLocationValid(BelId bel) const
std::vector<const CellInfo *> bel_cells; std::vector<const CellInfo *> bel_cells;
Loc bel_loc = getBelLocation(bel); Loc bel_loc = getBelLocation(bel);
for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {
IdString cell_other = getBoundBelCell(bel_other); CellInfo *ci_other = getBoundBelCell(bel_other);
if (cell_other != IdString()) { if (ci_other != nullptr) {
const CellInfo *ci_other = cells.at(cell_other).get();
bel_cells.push_back(ci_other); bel_cells.push_back(ci_other);
} }
} }
return logicCellsCompatible(bel_cells); return logicCellsCompatible(bel_cells);
} else { } else {
IdString cellId = getBoundBelCell(bel); CellInfo *ci = getBoundBelCell(bel);
if (cellId == IdString()) if (ci == nullptr)
return true; return true;
else 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<const CellInfo *> bel_cells; std::vector<const CellInfo *> bel_cells;
Loc bel_loc = getBelLocation(bel); Loc bel_loc = getBelLocation(bel);
for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {
IdString cell_other = getBoundBelCell(bel_other); CellInfo *ci_other = getBoundBelCell(bel_other);
if (cell_other != IdString() && bel_other != bel) { if (ci_other != nullptr && bel_other != bel) {
const CellInfo *ci_other = cells.at(cell_other).get();
bel_cells.push_back(ci_other); bel_cells.push_back(ci_other);
} }
} }
@ -126,12 +124,12 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
if (pll_bel.index != -1) { if (pll_bel.index != -1) {
auto pll_cell = getBoundBelCell(pll_bel); auto pll_cell = getBoundBelCell(pll_bel);
// Is a PLL placed in this 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? // 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) { if (pi.net != nullptr) {
// Are we perhaps a PAD INPUT Bel that can be placed here? // 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 true;
} }
return false; return false;

View File

@ -70,13 +70,13 @@ void arch_wrap_python()
fn_wrapper_1a<Context, decltype(&Context::getBelChecksum), &Context::getBelChecksum, pass_through<uint32_t>, fn_wrapper_1a<Context, decltype(&Context::getBelChecksum), &Context::getBelChecksum, pass_through<uint32_t>,
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelChecksum"); conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelChecksum");
fn_wrapper_3a_v<Context, decltype(&Context::bindBel), &Context::bindBel, conv_from_str<BelId>, fn_wrapper_3a_v<Context, decltype(&Context::bindBel), &Context::bindBel, conv_from_str<BelId>,
conv_from_str<IdString>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindBel"); addr_and_unwrap<CellInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindBel");
fn_wrapper_1a_v<Context, decltype(&Context::unbindBel), &Context::unbindBel, conv_from_str<BelId>>::def_wrap( fn_wrapper_1a_v<Context, decltype(&Context::unbindBel), &Context::unbindBel, conv_from_str<BelId>>::def_wrap(
ctx_cls, "unbindBel"); ctx_cls, "unbindBel");
fn_wrapper_1a<Context, decltype(&Context::getBoundBelCell), &Context::getBoundBelCell, conv_to_str<IdString>, fn_wrapper_1a<Context, decltype(&Context::getBoundBelCell), &Context::getBoundBelCell, deref_and_wrap<CellInfo>,
conv_from_str<BelId>>::def_wrap(ctx_cls, "getBoundBelCell"); conv_from_str<BelId>>::def_wrap(ctx_cls, "getBoundBelCell");
fn_wrapper_1a<Context, decltype(&Context::getConflictingBelCell), &Context::getConflictingBelCell, fn_wrapper_1a<Context, decltype(&Context::getConflictingBelCell), &Context::getConflictingBelCell,
conv_to_str<IdString>, conv_from_str<BelId>>::def_wrap(ctx_cls, "getConflictingBelCell"); deref_and_wrap<CellInfo>, conv_from_str<BelId>>::def_wrap(ctx_cls, "getConflictingBelCell");
fn_wrapper_0a<Context, decltype(&Context::getBels), &Context::getBels, wrap_context<BelRange>>::def_wrap(ctx_cls, fn_wrapper_0a<Context, decltype(&Context::getBels), &Context::getBels, wrap_context<BelRange>>::def_wrap(ctx_cls,
"getBels"); "getBels");
@ -88,15 +88,15 @@ void arch_wrap_python()
fn_wrapper_1a<Context, decltype(&Context::getWireChecksum), &Context::getWireChecksum, pass_through<uint32_t>, fn_wrapper_1a<Context, decltype(&Context::getWireChecksum), &Context::getWireChecksum, pass_through<uint32_t>,
conv_from_str<WireId>>::def_wrap(ctx_cls, "getWireChecksum"); conv_from_str<WireId>>::def_wrap(ctx_cls, "getWireChecksum");
fn_wrapper_3a_v<Context, decltype(&Context::bindWire), &Context::bindWire, conv_from_str<WireId>, fn_wrapper_3a_v<Context, decltype(&Context::bindWire), &Context::bindWire, conv_from_str<WireId>,
conv_from_str<IdString>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindWire"); addr_and_unwrap<NetInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindWire");
fn_wrapper_1a_v<Context, decltype(&Context::unbindWire), &Context::unbindWire, conv_from_str<WireId>>::def_wrap( fn_wrapper_1a_v<Context, decltype(&Context::unbindWire), &Context::unbindWire, conv_from_str<WireId>>::def_wrap(
ctx_cls, "unbindWire"); ctx_cls, "unbindWire");
fn_wrapper_1a<Context, decltype(&Context::checkWireAvail), &Context::checkWireAvail, pass_through<bool>, fn_wrapper_1a<Context, decltype(&Context::checkWireAvail), &Context::checkWireAvail, pass_through<bool>,
conv_from_str<WireId>>::def_wrap(ctx_cls, "checkWireAvail"); conv_from_str<WireId>>::def_wrap(ctx_cls, "checkWireAvail");
fn_wrapper_1a<Context, decltype(&Context::getBoundWireNet), &Context::getBoundWireNet, conv_to_str<IdString>, fn_wrapper_1a<Context, decltype(&Context::getBoundWireNet), &Context::getBoundWireNet, deref_and_wrap<NetInfo>,
conv_from_str<WireId>>::def_wrap(ctx_cls, "getBoundWireNet"); conv_from_str<WireId>>::def_wrap(ctx_cls, "getBoundWireNet");
fn_wrapper_1a<Context, decltype(&Context::getConflictingWireNet), &Context::getConflictingWireNet, fn_wrapper_1a<Context, decltype(&Context::getConflictingWireNet), &Context::getConflictingWireNet,
conv_to_str<IdString>, conv_from_str<WireId>>::def_wrap(ctx_cls, "getConflictingWireNet"); deref_and_wrap<NetInfo>, conv_from_str<WireId>>::def_wrap(ctx_cls, "getConflictingWireNet");
fn_wrapper_0a<Context, decltype(&Context::getWires), &Context::getWires, wrap_context<WireRange>>::def_wrap( fn_wrapper_0a<Context, decltype(&Context::getWires), &Context::getWires, wrap_context<WireRange>>::def_wrap(
ctx_cls, "getWires"); ctx_cls, "getWires");
@ -106,15 +106,15 @@ void arch_wrap_python()
fn_wrapper_1a<Context, decltype(&Context::getPipChecksum), &Context::getPipChecksum, pass_through<uint32_t>, fn_wrapper_1a<Context, decltype(&Context::getPipChecksum), &Context::getPipChecksum, pass_through<uint32_t>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipChecksum"); conv_from_str<PipId>>::def_wrap(ctx_cls, "getPipChecksum");
fn_wrapper_3a_v<Context, decltype(&Context::bindPip), &Context::bindPip, conv_from_str<PipId>, fn_wrapper_3a_v<Context, decltype(&Context::bindPip), &Context::bindPip, conv_from_str<PipId>,
conv_from_str<IdString>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindPip"); addr_and_unwrap<NetInfo>, pass_through<PlaceStrength>>::def_wrap(ctx_cls, "bindPip");
fn_wrapper_1a_v<Context, decltype(&Context::unbindPip), &Context::unbindPip, conv_from_str<PipId>>::def_wrap( fn_wrapper_1a_v<Context, decltype(&Context::unbindPip), &Context::unbindPip, conv_from_str<PipId>>::def_wrap(
ctx_cls, "unbindPip"); ctx_cls, "unbindPip");
fn_wrapper_1a<Context, decltype(&Context::checkPipAvail), &Context::checkPipAvail, pass_through<bool>, fn_wrapper_1a<Context, decltype(&Context::checkPipAvail), &Context::checkPipAvail, pass_through<bool>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "checkPipAvail"); conv_from_str<PipId>>::def_wrap(ctx_cls, "checkPipAvail");
fn_wrapper_1a<Context, decltype(&Context::getBoundPipNet), &Context::getBoundPipNet, conv_to_str<IdString>, fn_wrapper_1a<Context, decltype(&Context::getBoundPipNet), &Context::getBoundPipNet, deref_and_wrap<NetInfo>,
conv_from_str<PipId>>::def_wrap(ctx_cls, "getBoundPipNet"); conv_from_str<PipId>>::def_wrap(ctx_cls, "getBoundPipNet");
fn_wrapper_1a<Context, decltype(&Context::getConflictingPipNet), &Context::getConflictingPipNet, fn_wrapper_1a<Context, decltype(&Context::getConflictingPipNet), &Context::getConflictingPipNet,
conv_to_str<IdString>, conv_from_str<PipId>>::def_wrap(ctx_cls, "getConflictingPipNet"); deref_and_wrap<NetInfo>, conv_from_str<PipId>>::def_wrap(ctx_cls, "getConflictingPipNet");
fn_wrapper_1a<Context, decltype(&Context::getPipsDownhill), &Context::getPipsDownhill, wrap_context<PipRange>, fn_wrapper_1a<Context, decltype(&Context::getPipsDownhill), &Context::getPipsDownhill, wrap_context<PipRange>,
conv_from_str<WireId>>::def_wrap(ctx_cls, "getPipsDownhill"); conv_from_str<WireId>>::def_wrap(ctx_cls, "getPipsDownhill");

View File

@ -291,7 +291,7 @@ void write_asc(const Context *ctx, std::ostream &out)
} }
// Set pips // Set pips
for (auto pip : ctx->getPips()) { 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 PipInfoPOD &pi = ci.pip_data[pip.index];
const SwitchInfoPOD &swi = bi.switches[pi.switch_index]; const SwitchInfoPOD &swi = bi.switches[pi.switch_index];
int sw_bel_idx = swi.bel; int sw_bel_idx = swi.bel;
@ -310,7 +310,7 @@ void write_asc(const Context *ctx, std::ostream &out)
WireId permWire; WireId permWire;
for (auto permPip : ctx->getPipsUphill(ctx->getPipSrcWire(pip))) { for (auto permPip : ctx->getPipsUphill(ctx->getPipSrcWire(pip))) {
if (ctx->getBoundPipNet(permPip) != IdString()) { if (ctx->getBoundPipNet(permPip) != nullptr) {
permWire = ctx->getPipSrcWire(permPip); permWire = ctx->getPipSrcWire(permPip);
} }
} }
@ -384,7 +384,7 @@ void write_asc(const Context *ctx, std::ostream &out)
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
WireId lut_wire = ctx->getBelPinWire(bel, PortPin(PIN_I0 + i)); WireId lut_wire = ctx->getBelPinWire(bel, PortPin(PIN_I0 + i));
for (auto pip : ctx->getPipsUphill(lut_wire)) { 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(); std::string name = ci.wire_data[ctx->getPipSrcWire(pip).index].name.get();
switch (name.back()) { switch (name.back()) {
case '0': case '0':
@ -458,8 +458,8 @@ void write_asc(const Context *ctx, std::ostream &out)
NPNR_ASSERT(iez != -1); NPNR_ASSERT(iez != -1);
bool input_en = false; bool input_en = false;
if ((ctx->wire_to_net[ctx->getBelPinWire(bel, PIN_D_IN_0).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] != IdString())) { (ctx->wire_to_net[ctx->getBelPinWire(bel, PIN_D_IN_1).index] != nullptr)) {
input_en = true; input_en = true;
} }
@ -618,7 +618,7 @@ void write_asc(const Context *ctx, std::ostream &out)
} }
// Set config bits in unused IO and RAM // Set config bits in unused IO and RAM
for (auto bel : ctx->getBels()) { 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 TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO];
const BelInfoPOD &beli = ci.bel_data[bel.index]; const BelInfoPOD &beli = ci.bel_data[bel.index];
int x = beli.x, y = beli.y, z = beli.z; 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.IE_" + std::to_string(iez), true);
set_ie_bit_logical(ctx, ti, config.at(iey).at(iex), "IoCtrl.REN_" + std::to_string(iez), false); 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]; const BelInfoPOD &beli = ci.bel_data[bel.index];
int x = beli.x, y = beli.y; int x = beli.x, y = beli.y;
const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_RAMB]; const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_RAMB];
@ -751,9 +751,9 @@ void write_asc(const Context *ctx, std::ostream &out)
// Write symbols // Write symbols
// const bool write_symbols = 1; // const bool write_symbols = 1;
for (auto wire : ctx->getWires()) { for (auto wire : ctx->getWires()) {
IdString net = ctx->getBoundWireNet(wire); NetInfo *net = ctx->getBoundWireNet(wire);
if (net != IdString()) if (net != nullptr)
out << ".sym " << wire.index << " " << net.str(ctx) << std::endl; 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; WireId wire;
wire.index = wireIndex; 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) { } else if (line_nr >= 0 && strlen(buffer) > 0) {
if (line_nr > int(config.at(tile_y).at(tile_x).size() - 1)) 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); isUsed &= !(bool(cbit) ^ val);
} }
if (isUsed) { if (isUsed) {
IdString net = ctx->wire_to_net[pi.dst]; NetInfo *net = ctx->wire_to_net[pi.dst];
WireId wire; WireId wire;
wire.index = pi.dst; wire.index = pi.dst;
ctx->unbindWire(wire); ctx->unbindWire(wire);
@ -896,7 +896,7 @@ bool read_asc(Context *ctx, std::istream &in)
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LC")); std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LC"));
IdString name = created->name; IdString name = created->name;
ctx->cells[name] = std::move(created); 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 // 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<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_IO")); std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_IO"));
IdString name = created->name; IdString name = created->name;
ctx->cells[name] = std::move(created); 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 // 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<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LC")); std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LC"));
IdString name = created->name; IdString name = created->name;
ctx->cells[name] = std::move(created); 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 // TODO: Add port mapping to nets
} }
if (ctx->getBelType(belpin.bel) == TYPE_SB_IO) { if (ctx->getBelType(belpin.bel) == TYPE_SB_IO) {
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_IO")); std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_IO"));
IdString name = created->name; IdString name = created->name;
ctx->cells[name] = std::move(created); 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 // TODO: Add port mapping to nets
} }
if (ctx->getBelType(belpin.bel) == TYPE_SB_GB) { if (ctx->getBelType(belpin.bel) == TYPE_SB_GB) {
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_GB")); std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_GB"));
IdString name = created->name; IdString name = created->name;
ctx->cells[name] = std::move(created); 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 // TODO: Add port mapping to nets
} }
if (ctx->getBelType(belpin.bel) == TYPE_SB_WARMBOOT) { if (ctx->getBelType(belpin.bel) == TYPE_SB_WARMBOOT) {
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_WARMBOOT")); std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_WARMBOOT"));
IdString name = created->name; IdString name = created->name;
ctx->cells[name] = std::move(created); 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 // TODO: Add port mapping to nets
} }
if (ctx->getBelType(belpin.bel) == TYPE_ICESTORM_LFOSC) { if (ctx->getBelType(belpin.bel) == TYPE_ICESTORM_LFOSC) {
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LFOSC")); std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LFOSC"));
IdString name = created->name; IdString name = created->name;
ctx->cells[name] = std::move(created); 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 // TODO: Add port mapping to nets
} }
} }
@ -975,17 +975,17 @@ bool read_asc(Context *ctx, std::istream &in)
PortPin pin = ctx->portPinFromId(port.first); PortPin pin = ctx->portPinFromId(port.first);
WireId wire = ctx->getBelPinWire(cell.second->bel, pin); WireId wire = ctx->getBelPinWire(cell.second->bel, pin);
if (wire != WireId()) { if (wire != WireId()) {
IdString name = ctx->getBoundWireNet(wire); NetInfo *net = ctx->getBoundWireNet(wire);
if (name != IdString()) { if (net != nullptr) {
port.second.net = ctx->nets[name].get(); port.second.net = net;
PortRef ref; PortRef ref;
ref.cell = cell.second.get(); ref.cell = cell.second.get();
ref.port = port.second.name; ref.port = port.second.name;
if (port.second.type == PORT_OUT) if (port.second.type == PORT_OUT)
ctx->nets[name]->driver = ref; net->driver = ref;
else else
ctx->nets[name]->users.push_back(ref); net->users.push_back(ref);
} }
} }
} }