mirror of
https://github.com/YosysHQ/nextpnr.git
synced 2026-04-28 04:54:43 +00:00
Merge pull request #37 from YosysHQ/ngapi
API change: Use CellInfo* and NetInfo* as cell/net handles
This commit is contained in:
@@ -232,25 +232,26 @@ void Context::check() const
|
||||
auto ni = n.second.get();
|
||||
NPNR_ASSERT(n.first == ni->name);
|
||||
for (auto &w : ni->wires) {
|
||||
NPNR_ASSERT(n.first == getBoundWireNet(w.first));
|
||||
NPNR_ASSERT(ni == getBoundWireNet(w.first));
|
||||
if (w.second.pip != PipId()) {
|
||||
NPNR_ASSERT(w.first == getPipDstWire(w.second.pip));
|
||||
NPNR_ASSERT(n.first == getBoundPipNet(w.second.pip));
|
||||
NPNR_ASSERT(ni == getBoundPipNet(w.second.pip));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto w : getWires()) {
|
||||
IdString net = getBoundWireNet(w);
|
||||
if (net != IdString()) {
|
||||
NPNR_ASSERT(nets.at(net)->wires.count(w));
|
||||
auto ni = getBoundWireNet(w);
|
||||
if (ni != nullptr) {
|
||||
NPNR_ASSERT(ni->wires.count(w));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &c : cells) {
|
||||
NPNR_ASSERT(c.first == c.second->name);
|
||||
if (c.second->bel != BelId())
|
||||
NPNR_ASSERT(getBoundBelCell(c.second->bel) == c.first);
|
||||
auto ci = c.second.get();
|
||||
NPNR_ASSERT(c.first == ci->name);
|
||||
if (ci->bel != BelId())
|
||||
NPNR_ASSERT(getBoundBelCell(c.second->bel) == ci);
|
||||
for (auto &port : c.second->ports) {
|
||||
NetInfo *net = port.second.net;
|
||||
if (net != nullptr) {
|
||||
|
||||
@@ -437,6 +437,13 @@ struct BaseCtx
|
||||
|
||||
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;
|
||||
|
||||
@@ -131,7 +131,7 @@ bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality)
|
||||
if (iters >= 4)
|
||||
wirelen += ctx->rng(25);
|
||||
if (wirelen <= best_ripup_wirelen) {
|
||||
CellInfo *curr_cell = ctx->cells.at(ctx->getBoundBelCell(bel)).get();
|
||||
CellInfo *curr_cell = ctx->getBoundBelCell(bel);
|
||||
if (curr_cell->belStrength < STRENGTH_STRONG) {
|
||||
best_ripup_wirelen = wirelen;
|
||||
ripup_bel = bel;
|
||||
@@ -158,7 +158,7 @@ bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality)
|
||||
if (ctx->verbose)
|
||||
log_info(" placed single cell '%s' at '%s'\n", cell->name.c_str(ctx),
|
||||
ctx->getBelName(best_bel).c_str(ctx));
|
||||
ctx->bindBel(best_bel, cell->name, STRENGTH_WEAK);
|
||||
ctx->bindBel(best_bel, cell, STRENGTH_WEAK);
|
||||
|
||||
cell = ripup_target;
|
||||
}
|
||||
@@ -232,8 +232,8 @@ class ConstraintLegaliseWorker
|
||||
return false;
|
||||
}
|
||||
if (!ctx->checkBelAvail(locBel)) {
|
||||
IdString confCell = ctx->getConflictingBelCell(locBel);
|
||||
if (ctx->cells[confCell]->belStrength >= STRENGTH_STRONG) {
|
||||
CellInfo *confCell = ctx->getConflictingBelCell(locBel);
|
||||
if (confCell->belStrength >= STRENGTH_STRONG) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -362,18 +362,17 @@ class ConstraintLegaliseWorker
|
||||
cp.second.y, cp.second.z);
|
||||
BelId target = ctx->getBelByLocation(cp.second);
|
||||
if (!ctx->checkBelAvail(target)) {
|
||||
IdString conflicting = ctx->getConflictingBelCell(target);
|
||||
if (conflicting != IdString()) {
|
||||
CellInfo *confl_cell = ctx->cells.at(conflicting).get();
|
||||
CellInfo *confl_cell = ctx->getConflictingBelCell(target);
|
||||
if (confl_cell != nullptr) {
|
||||
if (ctx->verbose)
|
||||
log_info(" '%s' already placed at '%s'\n", conflicting.c_str(ctx),
|
||||
log_info(" '%s' already placed at '%s'\n", ctx->nameOf(confl_cell),
|
||||
ctx->getBelName(confl_cell->bel).c_str(ctx));
|
||||
NPNR_ASSERT(confl_cell->belStrength < STRENGTH_STRONG);
|
||||
ctx->unbindBel(target);
|
||||
rippedCells.insert(conflicting);
|
||||
rippedCells.insert(confl_cell->name);
|
||||
}
|
||||
}
|
||||
ctx->bindBel(target, cp.first, STRENGTH_LOCKED);
|
||||
ctx->bindBel(target, ctx->cells.at(cp.first).get(), STRENGTH_LOCKED);
|
||||
rippedCells.erase(cp.first);
|
||||
}
|
||||
NPNR_ASSERT(constraints_satisfied(cell));
|
||||
|
||||
@@ -105,7 +105,7 @@ class SAPlacer
|
||||
cell->type.c_str(ctx));
|
||||
}
|
||||
|
||||
ctx->bindBel(bel, cell->name, STRENGTH_USER);
|
||||
ctx->bindBel(bel, cell, STRENGTH_USER);
|
||||
locked_bels.insert(bel);
|
||||
placed_cells++;
|
||||
}
|
||||
@@ -256,11 +256,11 @@ class SAPlacer
|
||||
// Final post-pacement validitiy check
|
||||
ctx->yield();
|
||||
for (auto bel : ctx->getBels()) {
|
||||
IdString cell = ctx->getBoundBelCell(bel);
|
||||
CellInfo *cell = ctx->getBoundBelCell(bel);
|
||||
if (!ctx->isBelLocationValid(bel)) {
|
||||
std::string cell_text = "no cell";
|
||||
if (cell != IdString())
|
||||
cell_text = std::string("cell '") + cell.str(ctx) + "'";
|
||||
if (cell != nullptr)
|
||||
cell_text = std::string("cell '") + ctx->nameOf(cell) + "'";
|
||||
if (ctx->force) {
|
||||
log_warning("post-placement validity check failed for Bel '%s' "
|
||||
"(%s)\n",
|
||||
@@ -309,7 +309,7 @@ class SAPlacer
|
||||
uint64_t score = ctx->rng64();
|
||||
if (score <= best_ripup_score) {
|
||||
best_ripup_score = score;
|
||||
ripup_target = ctx->cells.at(ctx->getBoundBelCell(bel)).get();
|
||||
ripup_target = ctx->getBoundBelCell(bel);
|
||||
ripup_bel = bel;
|
||||
}
|
||||
}
|
||||
@@ -324,7 +324,7 @@ class SAPlacer
|
||||
} else {
|
||||
all_placed = true;
|
||||
}
|
||||
ctx->bindBel(best_bel, cell->name, STRENGTH_WEAK);
|
||||
ctx->bindBel(best_bel, cell, STRENGTH_WEAK);
|
||||
|
||||
// Back annotate location
|
||||
cell->attrs[ctx->id("BEL")] = ctx->getBelName(cell->bel).str(ctx);
|
||||
@@ -340,20 +340,17 @@ class SAPlacer
|
||||
new_lengths.clear();
|
||||
update.clear();
|
||||
BelId oldBel = cell->bel;
|
||||
IdString other = ctx->getBoundBelCell(newBel);
|
||||
CellInfo *other_cell = nullptr;
|
||||
if (other != IdString()) {
|
||||
other_cell = ctx->cells[other].get();
|
||||
if (other_cell->belStrength > STRENGTH_WEAK)
|
||||
return false;
|
||||
CellInfo *other_cell = ctx->getBoundBelCell(newBel);
|
||||
if (other_cell != nullptr && other_cell->belStrength > STRENGTH_WEAK) {
|
||||
return false;
|
||||
}
|
||||
int old_dist = get_constraints_distance(ctx, cell);
|
||||
int new_dist;
|
||||
if (other != IdString())
|
||||
if (other_cell != nullptr)
|
||||
old_dist += get_constraints_distance(ctx, other_cell);
|
||||
wirelen_t new_metric = 0, delta;
|
||||
ctx->unbindBel(oldBel);
|
||||
if (other != IdString()) {
|
||||
if (other_cell != nullptr) {
|
||||
ctx->unbindBel(newBel);
|
||||
}
|
||||
|
||||
@@ -361,20 +358,20 @@ class SAPlacer
|
||||
if (port.second.net != nullptr)
|
||||
update.insert(port.second.net);
|
||||
|
||||
if (other != IdString()) {
|
||||
if (other_cell != nullptr) {
|
||||
for (const auto &port : other_cell->ports)
|
||||
if (port.second.net != nullptr)
|
||||
update.insert(port.second.net);
|
||||
}
|
||||
|
||||
ctx->bindBel(newBel, cell->name, STRENGTH_WEAK);
|
||||
ctx->bindBel(newBel, cell, STRENGTH_WEAK);
|
||||
|
||||
if (other != IdString()) {
|
||||
ctx->bindBel(oldBel, other_cell->name, STRENGTH_WEAK);
|
||||
if (other_cell != nullptr) {
|
||||
ctx->bindBel(oldBel, other_cell, STRENGTH_WEAK);
|
||||
}
|
||||
if (!ctx->isBelLocationValid(newBel) || ((other != IdString() && !ctx->isBelLocationValid(oldBel)))) {
|
||||
if (!ctx->isBelLocationValid(newBel) || ((other_cell != nullptr && !ctx->isBelLocationValid(oldBel)))) {
|
||||
ctx->unbindBel(newBel);
|
||||
if (other != IdString())
|
||||
if (other_cell != nullptr)
|
||||
ctx->unbindBel(oldBel);
|
||||
goto swap_fail;
|
||||
}
|
||||
@@ -391,7 +388,7 @@ class SAPlacer
|
||||
}
|
||||
|
||||
new_dist = get_constraints_distance(ctx, cell);
|
||||
if (other != IdString())
|
||||
if (other_cell != nullptr)
|
||||
new_dist += get_constraints_distance(ctx, other_cell);
|
||||
delta = new_metric - curr_metric;
|
||||
delta += (cfg.constraintWeight / temp) * (new_dist - old_dist);
|
||||
@@ -400,7 +397,7 @@ class SAPlacer
|
||||
if (delta < 0 || (temp > 1e-6 && (ctx->rng() / float(0x3fffffff)) <= std::exp(-delta / temp))) {
|
||||
n_accept++;
|
||||
} else {
|
||||
if (other != IdString())
|
||||
if (other_cell != nullptr)
|
||||
ctx->unbindBel(oldBel);
|
||||
ctx->unbindBel(newBel);
|
||||
goto swap_fail;
|
||||
@@ -411,9 +408,9 @@ class SAPlacer
|
||||
|
||||
return true;
|
||||
swap_fail:
|
||||
ctx->bindBel(oldBel, cell->name, STRENGTH_WEAK);
|
||||
if (other != IdString()) {
|
||||
ctx->bindBel(newBel, other, STRENGTH_WEAK);
|
||||
ctx->bindBel(oldBel, cell, STRENGTH_WEAK);
|
||||
if (other_cell != nullptr) {
|
||||
ctx->bindBel(newBel, other_cell, STRENGTH_WEAK);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -140,6 +140,14 @@ template <typename T> struct deref_and_wrap
|
||||
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
|
||||
// Zero parameters, one return
|
||||
template <typename Class, typename FuncT, FuncT fn, typename rv_conv> struct fn_wrapper_0a
|
||||
|
||||
@@ -159,15 +159,15 @@ struct Router
|
||||
if (!ctx->checkWireAvail(next_wire)) {
|
||||
if (!ripup)
|
||||
continue;
|
||||
IdString ripupWireNet = ctx->getConflictingWireNet(next_wire);
|
||||
if (ripupWireNet == net_name || ripupWireNet == IdString())
|
||||
NetInfo *ripupWireNet = ctx->getConflictingWireNet(next_wire);
|
||||
if (ripupWireNet == nullptr || ripupWireNet->name == net_name)
|
||||
continue;
|
||||
|
||||
auto it1 = scores.wireScores.find(next_wire);
|
||||
if (it1 != scores.wireScores.end())
|
||||
next_delay += (it1->second * ripup_penalty) / 8;
|
||||
|
||||
auto it2 = scores.netWireScores.find(std::make_pair(ripupWireNet, next_wire));
|
||||
auto it2 = scores.netWireScores.find(std::make_pair(ripupWireNet->name, next_wire));
|
||||
if (it2 != scores.netWireScores.end())
|
||||
next_delay += it2->second * ripup_penalty;
|
||||
|
||||
@@ -177,15 +177,15 @@ struct Router
|
||||
if (!ctx->checkPipAvail(pip)) {
|
||||
if (!ripup)
|
||||
continue;
|
||||
IdString ripupPipNet = ctx->getConflictingPipNet(pip);
|
||||
if (ripupPipNet == net_name || ripupPipNet == IdString())
|
||||
NetInfo *ripupPipNet = ctx->getConflictingPipNet(pip);
|
||||
if (ripupPipNet == nullptr || ripupPipNet->name == net_name)
|
||||
continue;
|
||||
|
||||
auto it1 = scores.pipScores.find(pip);
|
||||
if (it1 != scores.pipScores.end())
|
||||
next_delay += (it1->second * ripup_penalty) / 8;
|
||||
|
||||
auto it2 = scores.netPipScores.find(std::make_pair(ripupPipNet, pip));
|
||||
auto it2 = scores.netPipScores.find(std::make_pair(ripupPipNet->name, pip));
|
||||
if (it2 != scores.netPipScores.end())
|
||||
next_delay += it2->second * ripup_penalty;
|
||||
|
||||
@@ -294,12 +294,12 @@ struct Router
|
||||
if (reroute) {
|
||||
// complete ripup
|
||||
ripup_net(ctx, net_name);
|
||||
ctx->bindWire(src_wire, net_name, STRENGTH_WEAK);
|
||||
ctx->bindWire(src_wire, ctx->nets.at(net_name).get(), STRENGTH_WEAK);
|
||||
src_wires[src_wire] = ctx->getWireDelay(src_wire).maxDelay();
|
||||
} else {
|
||||
// re-use existing routes as much as possible
|
||||
if (net_info->wires.count(src_wire) == 0)
|
||||
ctx->bindWire(src_wire, net_name, STRENGTH_WEAK);
|
||||
ctx->bindWire(src_wire, ctx->nets.at(net_name).get(), STRENGTH_WEAK);
|
||||
src_wires[src_wire] = ctx->getWireDelay(src_wire).maxDelay();
|
||||
|
||||
for (int user_idx = 0; user_idx < int(net_info->users.size()); user_idx++) {
|
||||
@@ -399,42 +399,42 @@ struct Router
|
||||
if (src_wires.count(cursor))
|
||||
break;
|
||||
|
||||
IdString conflicting_wire_net = ctx->getConflictingWireNet(cursor);
|
||||
NetInfo *conflicting_wire_net = ctx->getConflictingWireNet(cursor);
|
||||
|
||||
if (conflicting_wire_net != IdString()) {
|
||||
if (conflicting_wire_net != nullptr) {
|
||||
NPNR_ASSERT(ripup);
|
||||
NPNR_ASSERT(conflicting_wire_net != net_name);
|
||||
NPNR_ASSERT(conflicting_wire_net->name != net_name);
|
||||
|
||||
ctx->unbindWire(cursor);
|
||||
if (!ctx->checkWireAvail(cursor))
|
||||
ripup_net(ctx, conflicting_wire_net);
|
||||
ripup_net(ctx, conflicting_wire_net->name);
|
||||
|
||||
rippedNets.insert(conflicting_wire_net);
|
||||
rippedNets.insert(conflicting_wire_net->name);
|
||||
scores.wireScores[cursor]++;
|
||||
scores.netWireScores[std::make_pair(net_name, cursor)]++;
|
||||
scores.netWireScores[std::make_pair(conflicting_wire_net, cursor)]++;
|
||||
scores.netWireScores[std::make_pair(conflicting_wire_net->name, cursor)]++;
|
||||
}
|
||||
|
||||
PipId pip = visited[cursor].pip;
|
||||
IdString conflicting_pip_net = ctx->getConflictingPipNet(pip);
|
||||
NetInfo *conflicting_pip_net = ctx->getConflictingPipNet(pip);
|
||||
|
||||
if (conflicting_pip_net != IdString()) {
|
||||
if (conflicting_pip_net != nullptr) {
|
||||
NPNR_ASSERT(ripup);
|
||||
NPNR_ASSERT(conflicting_pip_net != net_name);
|
||||
NPNR_ASSERT(conflicting_pip_net->name != net_name);
|
||||
|
||||
if (ctx->getBoundPipNet(pip) == conflicting_pip_net)
|
||||
ctx->unbindPip(pip);
|
||||
|
||||
if (!ctx->checkPipAvail(pip))
|
||||
ripup_net(ctx, conflicting_pip_net);
|
||||
ripup_net(ctx, conflicting_pip_net->name);
|
||||
|
||||
rippedNets.insert(conflicting_pip_net);
|
||||
rippedNets.insert(conflicting_pip_net->name);
|
||||
scores.pipScores[visited[cursor].pip]++;
|
||||
scores.netPipScores[std::make_pair(net_name, visited[cursor].pip)]++;
|
||||
scores.netPipScores[std::make_pair(conflicting_pip_net, visited[cursor].pip)]++;
|
||||
scores.netPipScores[std::make_pair(conflicting_pip_net->name, visited[cursor].pip)]++;
|
||||
}
|
||||
|
||||
ctx->bindPip(visited[cursor].pip, net_name, STRENGTH_WEAK);
|
||||
ctx->bindPip(visited[cursor].pip, ctx->nets.at(net_name).get(), STRENGTH_WEAK);
|
||||
src_wires[cursor] = visited[cursor].delay;
|
||||
cursor = ctx->getPipSrcWire(visited[cursor].pip);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user