Skip to content

Parity report: himbaechel-xilinx-porting vs nextpnr-xilinx 0.9.3 on artix7/spartan7 (regression suite + LiteX DDR) #165

Description

@cavearr

@hansfbaier, this is the first run of the parity gate we discussed: your himbaechel tree and nextpnr-xilinx 0.9.3, same netlists, same XDC, same prjxray-db, same yosys, same fasm2frames/xc7frames2bit, on our build server. Numbers first, reading after. @jrrk2 in copy because half of it answers questions from your handover doc.

Setup (one factor: the P&R binary)

  • himbaechel: openXC7/nextpnr branch himbaechel-xilinx-porting at 2212c004 (current tip), submodule meta a4af910c. Built with your demos.yml recipe (-DARCH=himbaechel -DHIMBAECHEL_UARCH=xilinx -DHIMBAECHEL_XILINX_DEVICES='xc7a50t;xc7s50'): 89 s, 1.8 GB peak RSS, zero errors, zero local patches. archcheck (--test) green on both dies.
  • nextpnr-xilinx: the released 0.9.3 package (68aeeb39, apio release 2026-08-20), binary taken from inside the tarball.
  • prjxray-db ab1fc60 (the package's copy; both arms read the same directory — verified by inode), yosys 0.63+173, --router router2 in both arms (himbaechel's default is default, so it is passed explicitly).
  • Our regression suite (22 designs: fabric property tests, congestion pair, BRAM/DSP/LUTRAM/SRL/PLL/tristate, four board demos) runs on himbaechel without changing a line: a 40-line shim translates --chipdb F--chipdb F --device <part>-1, --xdc/--fasm-o xdc=/-o fasm=, and --post-route--report (upstream's report carries the same fmax/utilisation fields). Happy to send the shim; it is almost identical to your .github/scripts/nextpnr-xilinx-shim.sh plus that last translation.

Chipdb

0.9.3 (per package footprint) himbaechel (per die)
the 6 footprints on the xc7a50t die (a35t ×4, a50t ×2) 6 bins, 558.0 MB 1 bin, 29.6 MB (18.9×)
xc7s50csga324 92.4 MB 28.9 MB
generation (xilinx_gen.py + bbasm) 32 s, 1.8 GB RSS, byte-reproducible

Suite, xc7a35tcsg324, tier ≤2 (22 designs)

  • 19 of 20 comparable designs reach a bitstream on himbaechel (fasm2frames accepted every emitted feature, 0 warnings; xc7frames2bit produced 19 .bit). The other two: demo-basys3 fails in both arms (our runner forces --part, its XDC is for cpg236 — artefact), demo-genesys2 is expected-fail in both (kintex7 not packaged).
  • LUT/FF utilisation identical to 0.9.3 in 19 of 20; the one delta is carry-const-di (20 → 22 LUTs). BRAM and DSP identical everywhere.
  • The only himbaechel-specific failure is bram, and it is policy, not coverage (next section).
  • Fmax: median −6.7 %, 14 of 17 within ±15 %, but see "fmax is not comparable" below.
  • Runtime: himbaechel 3-4× faster on the small designs (1.1-1.8 s vs 3.7-4.6 s), slower on the two congestion designs (29.7 vs 22.3 s; 56.5 vs 31.9 s).

Spartan-7 (xc7s50csga324, carry/SRL tests): 5/5 complete in both arms, same utilisation.

LiteX DDR (litex-ddr-arty-s7, xc7s50, main and deep-hierarchy variants)

Both complete on himbaechel with the full DDR3 PHY — 45 OSERDESE2, 16 ISERDESE2, 16 IDELAYE2, IDELAYCTRL, PLLE2_ADV, 38 RAMB18E1 + 3 RAMB36E1, 4 DSP48E1, 260 CARRY4, 138 SELMUX2_1 in the deep variant — with the same utilisation as 0.9.3 (FF 3590/3590, LUT 7373 vs 7349), and fasm2frames + xc7frames2bit produce a bitstream. Jonathan's layer-1 blockers did not fire on these parts (no GT, no HP-bank pins in these designs), and the SELMUX2_1 placement that exploded on an empty vx485t places without incident here.

himbaechel also derives the clock constraints through the PLL natively (Derived VCO frequency 1600.0 MHz, 100/200/400 MHz outputs) — the thing our #156 just added to nextpnr-xilinx — so #156 does not need porting.

Control leg, one factor (no create_clock in either arm, --freq 100 in both, no derived constraints in either): critical clock main_crg_clkout_buf0 66.9 MHz (0.9.3) vs 97.3 MHz (himbaechel); deep variant sys_clk 73.0 vs 93.5 MHz. Read with the caveat below.

The one blocker: hold violations are fatal

himbaechel runs hold analysis with the chipdb's single DEFAULT speed grade and combinational-only cell timing, and treats every violation as an error: bram and both LiteX builds exit 1 (ERROR: Hold/min time violation …) after writing the FASM. With --timing-allow-fail the FASM is byte-identical and the bitstream is produced. 0.9.3 does not analyse hold at all. This is a product decision more than a port bug: as long as the hold model is the fiction Jonathan describes for parts without their own timing, a fatal hold check rejects designs that are fine. Question for you: should the xilinx uarch default to warning here until the model deserves to be trusted?

Where the two trees actually differ (FASM dialect, litex-main as the richest design)

No FASM is identical between arms (0 of 25) — expected, placements differ. But separating site-configuration features from routing pips and folding tile types to their family, the configuration vocabulary agrees at ~95 % (287 common names, 16 only-0.9.3, 15 only-himbaechel in litex-main). The delta is four nameable things:

  1. BRAM configuration bits himbaechel does not emit: RAMB18.READ_WIDTH_{A,B}_1, WRITE_WIDTH_{A,B}_1, RSTREG_PRIORITY_{A,B}_RSTREG — 179 features in litex-main (e.g. RSTREG_PRIORITY_* 88 → 0, WRITE_WIDTH_B_1 44 → 5, READ_WIDTH_B_1 40 → 7). This is your WP2.3 ("SDP BRAM opposite-port width + 36-wide marker + ZINV_REGCLK*"), which 05-porting-plan.md lists as not done — the plan is accurate. It is the most concrete bitstream-parity item and the one I would fix first.
  2. Constant carry-in: 0.9.3 emits PRECYINIT.C0/C1 (88 in litex-main), himbaechel feeds the constant through PRECYINIT.AX (131). Both legal; different packing choice. (Related: the only utilisation delta, carry-const-di 20 → 22 LUTs, is this class — see Carry-O relocation leaves chain-root bit unrelocatable when CIN is a constant #163 / xc7: relocate CARRY4 O fabric fanout at chain root with constant CIN #164 for what the fork does at the chain root.)
  3. 5FF packing: himbaechel uses the 5FF slot and O5 heavily (*5FFMUX.IN_A 0 → 731, OUTMUX.O5 ~1200) where 0.9.3 uses the main flop and OUTMUX.CY/F7. Placement choice, not a dialect gap; it explains most of the "only-himbaechel" lines.
  4. ILOGIC defaults: 0.9.3 emits IOI3.ILOGIC.IDELMUXE3.P1 (3, litex) and ISERDES.MODE.MASTER / NUM_CE.N1 (suite); himbaechel leaves them unwritten. With 16 IDELAYE2 in use in LiteX this is the delta most worth checking at bit level.

fmax is not comparable between the trees (yet)

constant — one LUT, one FF, identical utilisation, same netlist and router — reports 2865 MHz on 0.9.3 and 1044 MHz on himbaechel. That is not placement; it is two delay models measuring the same circuit. So across trees only rc, utilisation, feature counts and FASM are comparable; fmax is meaningful only against each tree's own baseline. Any QoR claim between the two needs a board or a common analyser. We will record per-tree baselines for the gate.

What we have NOT verified

  • Nobody has programmed a board with a himbaechel bitstream yet. Whether the missing BRAM/ILOGIC bits are harmless silicon defaults or break the design is unknown; next on our side is a bit2fasm round trip on a himbaechel bitstream, and a board test (Jonathan offered an Artix-50 board; we will send a .bit + design once we know the exact part/board).
  • Jonathan's Virtex-7 numbers (78/754 MB, 14.65 GB, the four layer-1 blockers) are quoted, not reproduced; they are a different family.

Offer

The gate is running: your binary, our suite, one overlay, ~8 minutes per arm for the whole table, plus LiteX. I can wire it as a nightly on our server and post the table here (or wherever you prefer) on every push to the branch, and record per-tree baselines so metric drift on either side is visible. Three questions to point it right: the hold default above; whether WP2.3 is where you want us to look next (we can bring the missing BRAM features with the litex-main measurements as the test); and whether #161 (LUT route-through) should target this tree — it already has the is_pseudo arcs data in the db, the question is what the uarch does with them.

Everything here is reproducible from ~/data/openxc7/himba/README-0013.md on our server; scripts and the raw reports are available on request.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions