From ce38752f4cddb2c3a8c5a755a21b3c531b029dba Mon Sep 17 00:00:00 2001 From: Test User Date: Thu, 9 Apr 2026 17:36:49 +0800 Subject: [PATCH] Fix incorrect IO tile corner detection in nextpnr-aegis The previous corner detection used `x != y` / `x == y` which only excluded the (0,0) and (W-1,H-1) diagonal corners. The corners (W-1,0) and (0,H-1) were incorrectly treated as valid IO tiles, causing IO BELs, wires, and pips to be created at positions that don't correspond to actual IO pads in the FPGA hardware. This mismatch between the nextpnr model and the simulator/hardware could cause the placer to assign IO cells to non-existent pad positions, producing a bitstream that doesn't work on the device. Fix by adding an is_corner() helper that correctly identifies all four grid corners, and use it in init_wires, init_bels, and init_pips. Co-Authored-By: Claude Opus 4.6 --- nextpnr-aegis/aegis.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/nextpnr-aegis/aegis.cc b/nextpnr-aegis/aegis.cc index 023a6a5..0fff094 100644 --- a/nextpnr-aegis/aegis.cc +++ b/nextpnr-aegis/aegis.cc @@ -180,6 +180,10 @@ struct AegisImpl : ViaductAPI { return (x == 0) || (x == (W - 1)) || (y == 0) || (y == (H - 1)); } + bool is_corner(int x, int y) const { + return (x == 0 || x == W - 1) && (y == 0 || y == H - 1); + } + PipId add_pip(Loc loc, WireId src, WireId dst, delay_t delay = 0.05) { IdStringList name = IdStringList::concat(ctx->getWireName(dst), ctx->getWireName(src)); @@ -238,7 +242,7 @@ struct AegisImpl : ViaductAPI { tw.track_w.push_back(ctx->addWire(h.xy_id(x, y, ctx->idf("W%d", t)), ctx->id("ROUTING"), x, y)); } - } else if (x != y) { + } else if (!is_corner(x, y)) { // IO tile wires for (int z = 0; z < 2; z++) { tw.pad.push_back(ctx->addWire(h.xy_id(x, y, ctx->idf("PAD%d", z)), @@ -269,7 +273,7 @@ struct AegisImpl : ViaductAPI { for (int y = 0; y < H; y++) { for (int x = 0; x < W; x++) { if (is_io(x, y)) { - if (x == y) + if (is_corner(x, y)) continue; add_io_bels(x, y); } else { @@ -320,7 +324,7 @@ struct AegisImpl : ViaductAPI { for (int y = 0; y < H; y++) { for (int x = 0; x < W; x++) { if (is_io(x, y)) { - if (x != y) + if (!is_corner(x, y)) add_io_pips(x, y); } else { add_logic_pips(x, y);