Gowin. BUGFIX Use a separate net for segment gates (#1470)

* Gowin. BUGFIX Use a separate net for segment gates

We use a temporary separate small network (typically 2 - 3 sinks) for
routing from the segment network source to the segment gate. This fixes
the rare but unpleasant case of self-intersection when a route to a gate
is routed using PIPs after the gate, this is no longer allowed when
using a separate small network.

Signed-off-by: YRabbit <rabbit@yrabbit.cyou>

* Gowin. Fix style.

Signed-off-by: YRabbit <rabbit@yrabbit.cyou>

---------

Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
This commit is contained in:
YRabbit 2025-03-31 19:36:48 +10:00 committed by GitHub
parent 0c01cb9e41
commit a5cff55520
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 26 additions and 7 deletions

View File

@ -795,23 +795,44 @@ struct GowinGlobalRouter
if (ctx->debug) { if (ctx->debug) {
log_info(" step 3: %s -> \n", ctx->nameOfWire(src_wire)); log_info(" step 3: %s -> \n", ctx->nameOfWire(src_wire));
} }
// Create a temporary small network where segment gates will be the sinks
IdString gate_net_name = ctx->idf("%s$gate_net$", ni->name.c_str(ctx));
NetInfo *gate_ni = ctx->createNet(gate_net_name);
std::vector<PipId> gate_bound_pips;
pool<WireId> gate_bound_wires;
for (WireId gatewire : gate_wires) { for (WireId gatewire : gate_wires) {
if (ctx->debug) { if (ctx->debug) {
log_info(" %s\n", ctx->nameOfWire(gatewire)); log_info(" %s\n", ctx->nameOfWire(gatewire));
} }
routed = backwards_bfs_route( routed = backwards_bfs_route(
ni, src_wire, gatewire, 1000000, false, gate_ni, src_wire, gatewire, 1000000, false,
[&](PipId pip, WireId src) { return dcs_input_filter(pip); }, &bound_pips); [&](PipId pip, WireId src) { return dcs_input_filter(pip); }, &gate_bound_pips);
if (routed) { if (routed) {
// bind src // bind src
if (ctx->checkWireAvail(src_wire)) { if (ctx->checkWireAvail(src_wire)) {
ctx->bindWire(src_wire, ni, STRENGTH_LOCKED); ctx->bindWire(src_wire, gate_ni, STRENGTH_LOCKED);
bound_wires.insert(src_wire); gate_bound_wires.insert(src_wire);
} }
} else { } else {
break; break;
} }
} }
// merge with original net
if (routed) {
for (PipId pip : gate_bound_pips) {
ctx->unbindPip(pip);
ctx->bindPip(pip, ni, STRENGTH_LOCKED);
bound_pips.push_back(pip);
}
for (WireId wire : gate_bound_wires) {
ctx->unbindWire(wire);
ctx->bindWire(wire, ni, STRENGTH_LOCKED);
bound_wires.insert(wire);
}
}
return routed ? SEG_ROUTED : SEG_NOT_ROUTED; return routed ? SEG_ROUTED : SEG_NOT_ROUTED;
} }
@ -1172,9 +1193,7 @@ struct GowinGlobalRouter
if (!wires_to_isolate.empty()) { if (!wires_to_isolate.empty()) {
ni->attrs[id_SEG_WIRES_TO_ISOLATE] = wires_to_isolate; ni->attrs[id_SEG_WIRES_TO_ISOLATE] = wires_to_isolate;
} }
if (ctx->verbose) { log_info(" '%s' is routed using segments.\n", ctx->nameOf(ni));
log_info("Net %s is routed using segments.\n", ctx->nameOf(ni));
}
if (ctx->debug) { if (ctx->debug) {
log_info(" routed\n"); log_info(" routed\n");
for (PipId pip : bound_pips) { for (PipId pip : bound_pips) {