prjxray-db/virtex7/FIXES.md

165 lines
9.6 KiB
Markdown
Raw Permalink Normal View History

# Segbit fixes carried in this database
Substantive corrections this virtex7 DB carries over a stock prjxray fuzz.
These are what make the fully-open VC707 flow produce correct bitstreams.
(Commit hashes refer to the prjxray fuzzer-code repo that produced them.)
## CLB OUTMUX.O5 duplicate → incomplete encoding (`6fd1d26`)
The "telegraph bug." Duplicate `OUTMUX.O5` segbit definitions; last-wins
picked the incomplete one (missing the shared xMUX-enable bit) → output muxes
encoded as `0x55`. Fix: dedupe keeping the **complete** definition. This was
the root cause of long-chased open-flow output corruption.
## IOB18 OLOGIC SING-row segbits (`afb49cc`, fuzzer `036-iob18-ologic-sing`)
SING-row IOB18 sites had no OLOGIC segbits. Added via a dedicated sub-fuzzer.
## LIOI / RIOI OLOGIC inversion segbits (local fuzz, superset)
`segbits_lioi*.db` / `segbits_rioi_sing.db` gained the `OLOGIC_Y*.IS_*_INVERTED`
features (`IS_CLKDIV_INVERTED`, `IS_D1..D4_INVERTED`, etc.) — +88 lines per
file over the last release (216 vs 128). Plus `mask_lioi*.db` and
`tileconn.json`. This is why the build-area copy is a strict superset of the
released DB.
## LIOB18 / RIOB18 IOB_Y1 IN_ONLY (`09588f3`)
Dropped spurious bits `!38_32 !38_34` from the Y1 (slave-site) input-only
encoding, fixing left-HP single-ended LVCMOS inputs.
## Tilegrid SING propagation for HP-only LIOB18 / LIOI columns (`1c63972`, `1574e9c`)
Propagated SING-row bits and added the `iob18_sing` sub-fuzzer so HP-only
columns get correct SING-row geometry.
## Top-SING tile alias start_offset (OLOGIC/IOB "invalid word address")
`tilegrid.json`: the **top** SING-row tiles (`LIOI_SING`/`RIOI_SING`/`LIOB18_SING`/
`RIOB18_SING` at `bits.CLB_IO_CLK.offset == 99`) had alias `start_offset: 0`,
but it must be **2** (matching the bottom SING tiles at `offset 0`). With
`start_offset 0` the aliased regular OLOGIC_Y0 / IOB features (regular words
23) mapped to absolute frame words 101102, which don't exist — fasm2frames
emitted `invalid word address` and silently dropped them (e.g. VC707 counter
LED on `LIOI_SING_X82Y51.OLOGIC_Y0.OMUX.D1`). With `start_offset 2` the
effective offset becomes `99-2=97`, so regular word 3 → abs 100, word 2 → abs
99 — landing in the tile's real 2-word window.
Confirmed empirically: fuzzer `036-iob18-ologic-sing` (re-run at N=50) places
`OLOGIC_Y0.OMUX.D1` at abs word 100, exactly what `start_offset 2` produces.
28 tiles fixed (7 each of LIOI/RIOI/LIOB18/RIOB18_SING). (The dedicated
`segbits_*_sing.db` are NOT consulted for aliased tiles, so this is a tilegrid
fix, not a segbits one.) Follow-up: fix the generator (`fuzzers/005-tilegrid`)
so a regenerated tilegrid doesn't reintroduce `start_offset 0`.
## Known remaining gap (worked around downstream, not yet fixed in DB)
LVCMOS18 single-ended **input** on certain HP-bank sites (e.g. AU33) is missing
segbit `bit_0042101c_063_18` and sets a spurious `IBUF_HP_BANK_GLUE` — the
rx-distortion bug. Currently patched at the frame level in the demo
(`uartram/patch_rx_iob.py`); a proper fix belongs here as a segbit correction.
## 2026-06-10: SING-tile OLOGIC route-thru features are bit-free (ppips)
`ppips_{l,r}ioi_sing.db`: added `*IOI_SING.OLOGIC_Y{0,1}.{OQUSED, OMUX.D1,
OSERDES.DATA_RATE_TQ.BUF} always`. The SING tilegrid entries alias into the
regular LIOI/RIOI segbits with start_offset 2, so these route-thru features
resolved to WRONG physical bits and poisoned the pad output path (HW symptom:
led[4]/AR35 = IO_0_VRN_13 on LIOI_SING_X82Y51 stuck high in every open-flow
VC707 build, confirmed in both picosoc and johnson). Raw-frame diff against
a HW-working Vivado golden shows Vivado sets NO OLOGIC config bits in the
SING window — the D1->OQ pass-through is bit-free there — while on regular
LIOI tiles it sets the same OQUSED/OMUX.D1 bits we do. Declaring the
features as pseudo-pips makes fasm2frames emit no bits for them
(TileSegbitsAlias.feature_to_bits short-circuits on the tile's own ppips).
RIOI_SING entries added by symmetry (same alias structure), not HW-verified.
Suspected same misalias issue for SING ILOGIC input features (not yet seen).
## 2026-06-11: targeted solve of 3 HCLK_CMT_L CK_IN <- MUX_CLK segbits
Added to `segbits_hclk_cmt_l.db` (3 bits each):
CK_IN1 <- MUX_CLK_8: 28_183 29_152 29_155
CK_IN0 <- MUX_CLK_7: 26_152 26_154 29_182
CK_IN10 <- MUX_CLK_5: 29_181 29_203 29_206
Method: one Vivado specimen per pip (pipsolve/ in v7-johnson-demo) with
FIXED_ROUTE forced through the pip; residual = raw window bits minus the
bit2fasm->fasm2frames re-encoding. KEY: these "MUX_CLK_<n>" wires are the
GT MGT clock spine (node of HCLK_CMT_L_X305Y26/MUX_CLK_8 is
GTX_COMMON_X394Y23/GTXE2_COMMON_MGT_CLK4; MUX_CLK_7=MGT_CLK3<-TXOUTCLK_1,
MUX_CLK_5=MGT_CLK1<-RXOUTCLK_1) - which is why the 045 fuzzer (no GT in
specimens) could never solve them. Each entry's 3rd bit (~_181..183) looks
like a per-lane spine-tap enable shared with other consumers of the same
MUX_CLK lane; included in the pip entry since lanes are single-consumer in
practice. Remaining family members (other CK_IN x MUX_CLK combos) still
unsolved - a proper fuzz needs GT-driven specimens.
## 2026-06-11: BRAM_L_X114Y0 tilegrid entry was empty
`xc7vx485t/tilegrid.json`: BRAM_L_X114Y0 had `bits: {}` (tilegrid fuzzer
gap at the column bottom), silently dropping every feature for any BRAM
placed there. Filled from the column pattern (same baseaddrs as
BRAM_L_X114Y5/Y10, offset 0): BLOCK_RAM 0x00C20500/128f/10w,
CLB_IO_CLK 0x00423900/28f/10w. Found by the dcp2fasm bit-equivalence
campaign (ethsoc Vivado DCP -> fasm -> frames vs golden bit).
## 2026-06-11: SING IOB tiles - prefer own segbits db over broken alias
`prjxray/grid.py get_tile_segbits_at_tilename()`: tiles whose tilegrid
bits carry an `alias` (LIOB18_SING etc.) were ALWAYS resolved through
TileSegbitsAlias, but the virtex7 SING alias metadata is wrong (sites
map names IOB33_* on an IOB18 part; start_offset arithmetic places the
LIOB18-db Y1 bits 2 words below the SING window) -- features for e.g.
led[4]'s LIOB18_SING_X81Y51 silently CORRUPTED the neighbouring
LIOB18_X81Y49 frames (6 stray bits, found by the bit-equivalence
ledger). Fix: when the tile type has its own segbits db
(segbits_liob18_sing.db exists), use it directly; alias only as
fallback. Applied to deps/prjxray and $HOME/prjxray.
## 2026-06-17: kintex7 transplant removal — IOI ILOGIC + ISERDES re-fuzzed
The LIOI/RIOI segbits carried features whose origin_info recorded fuzzers
that CANNOT run on this HP-only part (IOB33/HR-targeted), i.e. kintex7
transplants. Audited via the per-bit `origin:` provenance; retired so far:
- `035-iob-ilogic` (114 bits): replaced by new fuzzer fuzzers/035-iob18-ilogic
(IOB18 sites, L+R, tag-grouped enums). Real ILOGIC/IFF config measured on
both sides. IMPORTANT: `ILOGIC_Y{0,1}.ZINV_D` has NO virtex7 frame bit
(exhaustive frame search = zero correlation; kintex7/artix7 don't carry it
as a bit either) — the transplant was wrong, not just incomplete. Now
declared bit-free via `<tile>.ILOGIC_Y{0,1}.ZINV_D always` in the IOI ppips.
- `035b-iob-iserdes` (156 bits): replaced by fuzzers/035b-iob18-iserdes
(IOB18 ISERDESE2, L+R). Real ISERDES taxonomy
(MEMORY/NETWORKING/OVERSAMPLE x rate x width, MODE, DYN_*, IN_USE).
Method: utils/strip_transplant.py drops bits by origin from both the .db and
.origin_info.db, then the new fuzzer's `make pushdb` merges real L+R data
(segmaker's IOI. prefix -> mergedb rewrites per side). Validated by rebuilding
the open-flow picosoc: ILOGIC/ISERDES warnings gone, bit configures on VC707.
Still transplanted (to do): `f4pga` (768 bits, lioi left-side IOI pips — needs
037-iob18-pips driven to cover the left column) and `hand-copied-from-LIOB18`
(5 bits, LIOB18_SING IOB_Y1 DRIVE/SLEW/PULLTYPE/STEPDOWN + OBUF_HP_BANK_GLUE).
## 2026-06-18: SING IOB18 — hand-copied transplant replaced by validated mirror
LIOB18_SING / RIOB18_SING IOB18 carried 5 hand-copied (origin
hand-copied-from-LIOB18), partly mis-addressed entries. Built
fuzzers/030-iob18-sing (OBUF/IBUF/unused mix on the ~28 SING IOB18 sites) and
confirmed by real measurement that the SING IOB18 DRIVE/SLEW/PULLTYPE/IN bits
are BIT-IDENTICAL to the regular LIOB18 (e.g. Y1 DRIVE 38_32/38_34/39_23/39_55).
Finding: nextpnr emits the regular LIOB18 feature *names* for SING tiles, and
the ~28 rare SING sites cannot make segmatch resolve the multi-bit DRIVE enum
(OUT stays <N candidates> at any N). So the SING IOB db must mirror LIOB18's
names exactly; it cannot be independently fuzzed into a nextpnr-consumable form.
Resolution: replaced the hand-copy with a COMPLETE, correct mirror of every
LIOB18/RIOB18 IOB_Y0/Y1 feature (origin liob18-arch-mirror), excluding STEPDOWN
whose !00_127 (frame 0) bit overflows the SING tilegrid word window (word 102)
and corrupts neighbours -- left as a tolerated "not found" rather than the
corrupting "invalid word address". picosoc now builds with only that one
benign STEPDOWN warning. This is a same-part architectural mirror, NOT a
kintex7 transplant.
## SLICEM DOUTMUX.MC31 spurious A5FFMUX bit (2026-07-02)
`CLBLM_{L,R}.SLICEM_X0.DOUTMUX.MC31` carried a spurious `30_10` — that bit is
`A5FFMUX.IN_B` (fuzzer-specimen contamination). A real Vivado SRL cascade
(SRLC32E chain crossing a slice: A-LUT MC31 -> DMUX -> fabric -> next slice's
DI pin) sets only `{30_52, 30_57}` in the DOUTMUX group, so bit2fasm decoded NO
DOUTMUX feature and the cascade link was silently dropped. Fix: remove `30_10`;
the remaining `!30_51 30_52 !30_56 30_57` is distinct from every other DOUTMUX
leg. Found via the bit2verilog srl differential test (160-deep SRL, d3 diverged
at cycle 129 = the first value needing the cross-slice hop).