aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/nextpnr.cc13
-rw-r--r--ice40/main.cc1
-rw-r--r--ice40/place_legaliser.cc8
3 files changed, 20 insertions, 2 deletions
diff --git a/common/nextpnr.cc b/common/nextpnr.cc
index a7a3268e..ee0c13ba 100644
--- a/common/nextpnr.cc
+++ b/common/nextpnr.cc
@@ -185,6 +185,19 @@ void Context::check() const
assert(c.first == c.second->name);
if (c.second->bel != BelId())
assert(getBoundBelCell(c.second->bel) == c.first);
+ for (auto &port : c.second->ports) {
+ NetInfo *net = port.second.net;
+ if (net != nullptr) {
+ assert(nets.find(net->name) != nets.end());
+ if (port.second.type == PORT_OUT) {
+ assert(net->driver.cell == c.second.get() && net->driver.port == port.first);
+ } else if (port.second.type == PORT_IN) {
+ assert(std::count_if(net->users.begin(), net->users.end(), [&](const PortRef &pr) {
+ return pr.cell == c.second.get() && pr.port == port.first;
+ }) == 1);
+ }
+ }
+ }
}
}
diff --git a/ice40/main.cc b/ice40/main.cc
index c975db24..6c2602dc 100644
--- a/ice40/main.cc
+++ b/ice40/main.cc
@@ -372,6 +372,7 @@ int main(int argc, char *argv[])
if (!place_design_sa(&ctx, timing_driven) && !ctx.force)
log_error("Placing design failed.\n");
legalise_design(&ctx);
+ ctx.check();
if (!route_design(&ctx) && !ctx.force)
log_error("Routing design failed.\n");
}
diff --git a/ice40/place_legaliser.cc b/ice40/place_legaliser.cc
index 00a57866..aeef47a1 100644
--- a/ice40/place_legaliser.cc
+++ b/ice40/place_legaliser.cc
@@ -260,10 +260,12 @@ class PlacementLegaliser
start_of_chain = true;
} else {
NetInfo *carry_net = cell->ports.at(ctx->id("COUT")).net;
- if (carry_net != nullptr && carry_net->users.size() > 1) {
+ bool at_end = (curr_cell == carryc.cells.end() - 1);
+ if (carry_net != nullptr && (carry_net->users.size() > 1 || at_end)) {
if (carry_net->users.size() > 2 ||
(net_only_drives(ctx, carry_net, is_lc, ctx->id("I3"), false) !=
- net_only_drives(ctx, carry_net, is_lc, ctx->id("CIN"), false))) {
+ net_only_drives(ctx, carry_net, is_lc, ctx->id("CIN"), false)) ||
+ (at_end && !net_only_drives(ctx, carry_net, is_lc, ctx->id("I3"), true))) {
CellInfo *passout = make_carry_pass_out(cell->ports.at(ctx->id("COUT")));
chains.back().cells.push_back(passout);
tile.push_back(passout);
@@ -324,6 +326,7 @@ class PlacementLegaliser
i1_r.cell = lc.get();
ctx->nets.at(ctx->id("$PACKER_VCC_NET"))->users.push_back(i1_r);
IdString co_i3_name = co_i3_net->name;
+ assert(ctx->nets.find(co_i3_name) == ctx->nets.end());
ctx->nets[co_i3_name] = std::move(co_i3_net);
IdString name = lc->name;
ctx->cells[lc->name] = std::move(lc);
@@ -366,6 +369,7 @@ class PlacementLegaliser
cin_cell->ports.at(cin_port.name).net = out_net.get();
IdString out_net_name = out_net->name;
+ assert(ctx->nets.find(out_net_name) == ctx->nets.end());
ctx->nets[out_net_name] = std::move(out_net);
IdString name = lc->name;