aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2018-06-23 15:16:24 +0200
committerClifford Wolf <clifford@clifford.at>2018-06-23 15:16:24 +0200
commit746d63f9fa7ffd7fcc5c460c04b65eccfbb3f205 (patch)
tree0e39eddba232e0abae90dfe30ba4643ca5f0b7d5 /common
parentd72fe0c230f79248a56e47c2f31f14b15c7f13fe (diff)
downloadnextpnr-746d63f9fa7ffd7fcc5c460c04b65eccfbb3f205.tar.gz
nextpnr-746d63f9fa7ffd7fcc5c460c04b65eccfbb3f205.tar.bz2
nextpnr-746d63f9fa7ffd7fcc5c460c04b65eccfbb3f205.zip
Refactoring bind/unbind API
Signed-off-by: Clifford Wolf <clifford@clifford.at>
Diffstat (limited to 'common')
-rw-r--r--common/nextpnr.cc40
-rw-r--r--common/nextpnr.h11
-rw-r--r--common/place_sa.cc36
-rw-r--r--common/route.cc45
4 files changed, 84 insertions, 48 deletions
diff --git a/common/nextpnr.cc b/common/nextpnr.cc
index d29d3fec..188906e2 100644
--- a/common/nextpnr.cc
+++ b/common/nextpnr.cc
@@ -97,20 +97,12 @@ uint32_t Context::checksum() const
for (auto &w : ni.wires) {
uint32_t wire_x = 123456789;
wire_x = xorshift32(wire_x + xorshift32(getWireChecksum(w.first)));
- wire_x = xorshift32(wire_x + xorshift32(getPipChecksum(w.second)));
+ wire_x = xorshift32(wire_x + xorshift32(getPipChecksum(w.second.pip)));
+ wire_x = xorshift32(wire_x + xorshift32(int(w.second.strength)));
wire_x_sum += wire_x;
}
x = xorshift32(x + xorshift32(wire_x_sum));
- uint32_t pip_x_sum = 0;
- for (auto &p : ni.pips) {
- uint32_t pip_x = 123456789;
- pip_x = xorshift32(pip_x + xorshift32(getPipChecksum(p.first)));
- pip_x = xorshift32(pip_x + xorshift32(p.second));
- pip_x_sum += pip_x;
- }
- x = xorshift32(x + xorshift32(pip_x_sum));
-
cksum_nets_sum += x;
}
cksum = xorshift32(cksum + xorshift32(cksum_nets_sum));
@@ -175,4 +167,32 @@ uint32_t Context::checksum() const
return cksum;
}
+void Context::check() const
+{
+ for (auto &n : nets) {
+ auto ni = n.second;
+ assert(n.first == ni->name);
+ for (auto &w : ni->wires) {
+ assert(n.first == getBoundWireNet(w.first));
+ if (w.second.pip != PipId()) {
+ assert(w.first == getPipDstWire(w.second.pip));
+ assert(n.first == getBoundPipNet(w.second.pip));
+ }
+ }
+ }
+
+ for (auto w : getWires()) {
+ IdString net = getBoundWireNet(w);
+ if (net != IdString()) {
+ assert(nets.at(net)->wires.count(w));
+ }
+ }
+
+ for (auto &c : cells) {
+ assert(c.first == c.second->name);
+ if (c.second->bel != BelId())
+ assert(getBoundBelCell(c.second->bel) == c.first);
+ }
+}
+
NEXTPNR_NAMESPACE_END
diff --git a/common/nextpnr.h b/common/nextpnr.h
index 9c6c9d68..8cbead7d 100644
--- a/common/nextpnr.h
+++ b/common/nextpnr.h
@@ -211,6 +211,12 @@ struct PortRef
delay_t budget = 0;
};
+struct PipMap
+{
+ PipId pip = PipId();
+ PlaceStrength strength = STRENGTH_NONE;
+};
+
struct NetInfo
{
IdString name;
@@ -219,9 +225,7 @@ struct NetInfo
std::unordered_map<IdString, std::string> attrs;
// wire -> uphill_pip
- std::unordered_map<WireId, PipId> wires;
-
- std::unordered_map<PipId, PlaceStrength> pips;
+ std::unordered_map<WireId, PipMap> wires;
};
enum PortType
@@ -357,6 +361,7 @@ struct Context : Arch
}
uint32_t checksum() const;
+ void check() const;
};
NEXTPNR_NAMESPACE_END
diff --git a/common/place_sa.cc b/common/place_sa.cc
index 6743e0ce..f4fb5aff 100644
--- a/common/place_sa.cc
+++ b/common/place_sa.cc
@@ -103,9 +103,7 @@ class SAPlacer
cell->name.c_str(ctx), cell->type.c_str(ctx));
}
- cell->bel = bel;
- cell->belStrength = STRENGTH_USER;
- ctx->bindBel(bel, cell->name);
+ ctx->bindBel(bel, cell->name, STRENGTH_USER);
locked_bels.insert(bel);
placed_cells++;
}
@@ -231,7 +229,7 @@ class SAPlacer
}
// Final post-pacement validitiy check
for (auto bel : ctx->getBels()) {
- IdString cell = ctx->getBelCell(bel, false);
+ IdString cell = ctx->getBoundBelCell(bel);
if (!checker->isBelLocationValid(bel)) {
std::string cell_text = "no cell";
if (cell != IdString())
@@ -266,7 +264,6 @@ class SAPlacer
BelId ripup_bel = BelId();
if (cell->bel != BelId()) {
ctx->unbindBel(cell->bel);
- cell->bel = BelId();
}
BelType targetType = ctx->belTypeFromId(cell->type);
for (auto bel : ctx->getBels()) {
@@ -283,7 +280,7 @@ class SAPlacer
if (score <= best_ripup_score) {
best_ripup_score = score;
ripup_target =
- ctx->cells.at(ctx->getBelCell(bel, true));
+ ctx->cells.at(ctx->getBoundBelCell(bel));
ripup_bel = bel;
}
}
@@ -295,14 +292,11 @@ class SAPlacer
cell->name.c_str(ctx), cell->type.c_str(ctx));
--iters;
ctx->unbindBel(ripup_target->bel);
- ripup_target->bel = BelId();
best_bel = ripup_bel;
} else {
all_placed = true;
}
- cell->bel = best_bel;
- cell->belStrength = STRENGTH_WEAK;
- ctx->bindBel(cell->bel, cell->name);
+ ctx->bindBel(best_bel, cell->name, STRENGTH_WEAK);
// Back annotate location
cell->attrs[ctx->id("BEL")] = ctx->getBelName(cell->bel).str(ctx);
@@ -375,7 +369,7 @@ class SAPlacer
new_lengths.clear();
update.clear();
BelId oldBel = cell->bel;
- IdString other = ctx->getBelCell(newBel, true);
+ IdString other = ctx->getBoundBelCell(newBel);
CellInfo *other_cell = nullptr;
wirelen_t new_wirelength = 0, delta;
ctx->unbindBel(oldBel);
@@ -394,10 +388,10 @@ class SAPlacer
update.insert(port.second.net);
}
- ctx->bindBel(newBel, cell->name);
+ ctx->bindBel(newBel, cell->name, STRENGTH_WEAK);
if (other != IdString()) {
- ctx->bindBel(oldBel, other_cell->name);
+ ctx->bindBel(oldBel, other_cell->name, STRENGTH_WEAK);
}
if (!checker->isBelLocationValid(newBel) ||
@@ -408,10 +402,6 @@ class SAPlacer
goto swap_fail;
}
- cell->bel = newBel;
- if (other != IdString())
- other_cell->bel = oldBel;
-
new_wirelength = curr_wirelength;
// Recalculate wirelengths for all nets touched by the peturbation
@@ -442,11 +432,9 @@ class SAPlacer
return true;
swap_fail:
- ctx->bindBel(oldBel, cell->name);
- cell->bel = oldBel;
+ ctx->bindBel(oldBel, cell->name, STRENGTH_WEAK);
if (other != IdString()) {
- ctx->bindBel(newBel, other);
- other_cell->bel = newBel;
+ ctx->bindBel(newBel, other, STRENGTH_WEAK);
}
return false;
}
@@ -498,8 +486,14 @@ bool place_design_sa(Context *ctx, bool timing_driven)
SAPlacer placer(ctx, timing_driven);
placer.place();
log_info("Checksum: 0x%08x\n", ctx->checksum());
+#ifndef NDEBUG
+ ctx->check();
+#endif
return true;
} catch (log_execution_error_exception) {
+#ifndef NDEBUG
+ ctx->check();
+#endif
return false;
}
}
diff --git a/common/route.cc b/common/route.cc
index a60f1c41..fe2c05e4 100644
--- a/common/route.cc
+++ b/common/route.cc
@@ -79,14 +79,26 @@ struct RipupScoreboard
void ripup_net(Context *ctx, IdString net_name)
{
auto net_info = ctx->nets.at(net_name);
+ std::vector<PipId> pips;
+ std::vector<WireId> wires;
+
+ pips.reserve(net_info->wires.size());
+ wires.reserve(net_info->wires.size());
for (auto &it : net_info->wires) {
- if (it.second != PipId())
- ctx->unbindPip(it.second);
- ctx->unbindWire(it.first);
+ if (it.second.pip != PipId())
+ pips.push_back(it.second.pip);
+ else
+ wires.push_back(it.first);
}
- net_info->wires.clear();
+ for (auto pip : pips)
+ ctx->unbindPip(pip);
+
+ for (auto wire : wires)
+ ctx->unbindWire(wire);
+
+ assert(net_info->wires.empty());
}
struct Router
@@ -147,7 +159,7 @@ struct Router
if (!ctx->checkWireAvail(next_wire)) {
if (!ripup)
continue;
- IdString ripupWireNet = ctx->getWireNet(next_wire, true);
+ IdString ripupWireNet = ctx->getConflictingWireNet(next_wire);
if (ripupWireNet == net_name || ripupWireNet == IdString())
continue;
auto it = scores.wireScores.find(
@@ -160,7 +172,7 @@ struct Router
if (!ctx->checkPipAvail(pip)) {
if (!ripup)
continue;
- IdString ripupPipNet = ctx->getPipNet(pip, true);
+ IdString ripupPipNet = ctx->getConflictingPipNet(pip);
if (ripupPipNet == net_name || ripupPipNet == IdString())
continue;
auto it = scores.pipScores.find(
@@ -280,8 +292,7 @@ struct Router
std::unordered_map<WireId, delay_t> src_wires;
src_wires[src_wire] = 0;
- net_info->wires[src_wire] = PipId();
- ctx->bindWire(src_wire, net_name);
+ ctx->bindWire(src_wire, net_name, STRENGTH_WEAK);
std::vector<PortRef> users_array = net_info->users;
ctx->shuffle(users_array);
@@ -361,9 +372,9 @@ struct Router
if (src_wires.count(cursor))
break;
- IdString conflicting_wire_net = ctx->getWireNet(cursor, true);
+ IdString conflicting_wire_net = ctx->getConflictingWireNet(cursor);
IdString conflicting_pip_net =
- ctx->getPipNet(visited[cursor].pip, true);
+ ctx->getConflictingPipNet(visited[cursor].pip);
if (conflicting_wire_net != IdString()) {
assert(ripup);
@@ -388,10 +399,7 @@ struct Router
visited[cursor].pip)]++;
}
- net_info->wires[cursor] = visited[cursor].pip;
- ctx->bindWire(cursor, net_name);
- ctx->bindPip(visited[cursor].pip, net_name);
-
+ ctx->bindPip(visited[cursor].pip, net_name, STRENGTH_WEAK);
src_wires[cursor] = visited[cursor].delay;
cursor = ctx->getPipSrcWire(visited[cursor].pip);
}
@@ -495,6 +503,9 @@ bool route_design(Context *ctx)
if (iterCnt == 200) {
log_warning("giving up after %d iterations.\n", iterCnt);
log_info("Checksum: 0x%08x\n", ctx->checksum());
+#ifndef NDEBUG
+ ctx->check();
+#endif
return false;
}
@@ -655,8 +666,14 @@ bool route_design(Context *ctx)
(100.0 * totalOvertimeRevisitCnt) / totalVisitCnt);
log_info("Checksum: 0x%08x\n", ctx->checksum());
+#ifndef NDEBUG
+ ctx->check();
+#endif
return true;
} catch (log_execution_error_exception) {
+#ifndef NDEBUG
+ ctx->check();
+#endif
return false;
}
}