Gowin. BUGFIX. Fix routing of the FF inputs. (#1498)

A segment router replaces the source-to-sink connection by
general-purpose PIPs with bus-branch segment network connections.

The problem arises when the source is connected to the sinks directly
without switching as in the case of LUT->DFF, such wires should be left
as is, which is what this PR does.

Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
This commit is contained in:
YRabbit 2025-06-10 15:54:20 +10:00 committed by GitHub
parent fd3b4d36e7
commit 000faab213
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 27 additions and 4 deletions

View File

@ -20,7 +20,7 @@ struct GowinCstReader
Context *ctx;
std::istream &in;
GowinCstReader(Context *ctx, std::istream &in) : ctx(ctx), in(in){};
GowinCstReader(Context *ctx, std::istream &in) : ctx(ctx), in(in) {};
const PadInfoPOD *pinLookup(const PadInfoPOD *list, const size_t len, const IdString idx)
{

View File

@ -716,11 +716,25 @@ struct GowinGlobalRouter
std::vector<PipId> &bound_pips)
{
bool routed = false;
WireId lbo_wire = ctx->getWireByName(
IdStringList::concat(ctx->idf("X%dY%d", s_x, dst_loc.y), ctx->idf("LBO%d", s_idx / 4)));
if (ctx->debug) {
log_info(" step 0: %s -> %s\n", ctx->nameOfWire(lbo_wire), ctx->nameOfWire(dst_wire));
}
// The DFF can currently only connect to a neighbouring LUT. Skip such networks.
if (ctx->getWireName(dst_wire)[1].in(id_XD0, id_XD1, id_XD2, id_XD3, id_XD4, id_XD5)) {
auto pips = ctx->getPipsUphill(dst_wire);
auto pip_it = pips.begin();
++pip_it;
NPNR_ASSERT_MSG(!(pip_it != pips.end()), "DFFs have been given the ability to connect independently of the "
"neighbouring LUT. Segment routing must be corrected.\n");
// Connect LUT OUT to DFF IN
PipId pip = *pips.begin();
ctx->bindPip(pip, ni, STRENGTH_LOCKED);
bound_pips.push_back(pip);
return SEG_ROUTED_TO_ANOTHER_SEGMENT;
}
routed = backwards_bfs_route(
ni, lbo_wire, dst_wire, 1000000, false, [&](PipId pip, WireId src) { return true; }, &bound_pips);
return routed ? SEG_ROUTED : SEG_ROUTED_TO_ANOTHER_SEGMENT;
@ -1159,6 +1173,9 @@ struct GowinGlobalRouter
if (routed == SEG_NOT_ROUTED) {
break;
}
if (routed == SEG_ROUTED_TO_ANOTHER_SEGMENT) {
continue;
}
// Step 1: segment wire -> LBOx
routed = route_segmented_step1(ni, dst_loc, s_idx, s_x, bound_pips);
if (routed == SEG_NOT_ROUTED) {

View File

@ -858,7 +858,7 @@ void GowinImpl::create_passthrough_luts(void)
if (d_net->name == ctx->id("$PACKER_GND") || d_net->name == ctx->id("$PACKER_VCC")) {
if (ctx->debug) {
log("make a constant %s.\n", d_net->name == ctx->id("$PACKER_VCC") ? "VCC" : "GND");
log_info("make a constant %s.\n", d_net->name == ctx->id("$PACKER_VCC") ? "VCC" : "GND");
}
ci->disconnectPort(id_D);
if (d_net->name == ctx->id("$PACKER_GND")) {
@ -868,7 +868,7 @@ void GowinImpl::create_passthrough_luts(void)
}
} else {
if (ctx->debug) {
log("make a pass-through.\n");
log_info("make a pass-through.\n");
}
IdString lut_input = id_I3;
int lut_init = 0xff00;
@ -980,7 +980,12 @@ bool GowinImpl::slice_valid(int x, int y, int z) const
if (ramw) {
// FFs in slices 4 and 5 are not allowed
if (ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, 4 * 2 + 1))) ||
// also temporarily disallow FF to be placed near RAM
if (ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, 0 * 2 + 1))) ||
ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, 1 * 2 + 1))) ||
ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, 2 * 2 + 1))) ||
ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, 3 * 2 + 1))) ||
ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, 4 * 2 + 1))) ||
ctx->getBoundBelCell(ctx->getBelByLocation(Loc(x, y, 5 * 2 + 1)))) {
return false;
}
@ -1014,6 +1019,7 @@ bool GowinImpl::slice_valid(int x, int y, int z) const
const auto &ff_data = fast_cell_info.at(ff->flat_index);
const NetInfo *src;
// check implcit LUT(ALU) -> FF connection
NPNR_ASSERT(!ramw); // XXX shouldn't happen for now
if (lut || alu) {
if (lut) {
src = fast_cell_info.at(lut->flat_index).lut_f;