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;