ci: green the smoke/heavy matrix on the nextpnr engine - #18
Conversation
openXC7.mk now runs fpga-as instead of fasm2frames + xc7frames2bit: one process, no .frames intermediate, and unlike prjxray 0.9.2's fasm2frames it can assemble what the engine emits for an Artix-7 GTP (litex-sata's IBUFDS_GTE2 swing setting, now emitted under the segment name the database uses). The seven blinky goldens are regenerated with the fpga-as revision pinned in the toolchain (hansfbaier/fpga-assembler@cf0e3f0, lromor/fpga-assembler#47). That revision reproduces xc7frames2bit's header and bit choices, so the bitstreams match the reference build apart from the date/time stamp that .github/scripts/normbit.py blanks; the previous fpga-as revision wrote "fasm" in place of the part name and left seven bits set that the reference clears. Assisted-by: deepseek/deepseek-flash
…behaviour The port enforces what the fork only reported: hold analysis is new and fatal, and the derived MMCM clock constraints are actually checked. Every LiteX DDR SoC here failed its derived clock under 0.9.7 as well -- the run #80 logs show the same designs reporting "Info: Max frequency ... FAIL", non-fatal -- and the engine's own parity report (nextpnr-xilinx#165) records that the FASM is byte-identical with and without --timing-allow-fail, so these demos now declare it explicitly, like litex-sata, litex-ddr-hdmi-* and litex-minimal already do. ddr3-test-arty-s7 loses its --pre-place/--pre-route hook: the port is packaged with BUILD_PYTHON=OFF, so the fork's python hooks no longer exist, and they are not needed any more -- the current prjxray-db has the _SING-tile PIPs and the design routes without either pinning (it now places an ISERDES on LIOI3_SING_X0Y149, which the constraints.py workaround existed to avoid). The two enclustra XDCs set SLEW both FAST and SLOW on ddram0_reset_n; the new xdc.cc counts a repeated property as an error and stops, and every other board XDC in the tree has FAST only. Drop the stray SLOW. Assisted-by: deepseek/deepseek-flash
Brings the GTP common segment fix (litex-sata), the OFB-fed ISERDESE2 pack fix (ddr3-test-arty-s7), the fpga-as reference-parity revision the goldens were regenerated with, and the chipdb part-name symlinks. The rev is the pre-merge commit from openXC7/toolchain-nix#20 and the engine rev inside it from openXC7/nextpnr#45; re-pin to the merge commits once those land. Assisted-by: deepseek/deepseek-flash
Reviewer's GuideThe PR restores the smoke and heavy matrices on the pinned openXC7/nextpnr toolchain by switching all projects to fpga-as assembly, pinning the toolchain containing nextpnr fixes, and updating affected DDR demos and constraints for stricter timing, routing, and XDC validation. Sequence diagram for project bitstream assemblysequenceDiagram
participant Make as Makefile
participant Synth as Yosys
participant PNR as nextpnr-xilinx
participant Assembler as fpga-as
participant CI as CI matrix
Make->>Synth: synthesize project
Synth-->>Make: project.json
Make->>PNR: nextpnr-xilinx --json --xdc --fasm
PNR-->>Make: project.fasm
Make->>Assembler: fpga-as --prjxray_db_path --part
Assembler-->>Make: project.bit
Make-->>CI: build result
CI->>CI: compare golden bitstream
Flow diagram for the restored CI smoke and heavy matrixflowchart TD
Pin["Resolve pinned toolchain"] --> ChipDB["Build or download chipdb"]
ChipDB --> Build["Build project"]
Build --> Timing{"Timing failure allowed?"}
Timing -->|yes| Bit["Assemble .bit with fpga-as"]
Timing -->|no| Bit
Bit --> Golden{"Golden comparison required?"}
Golden -->|yes| Compare["Compare regenerated bitstream"]
Golden -->|no| Pass["Matrix job passes"]
Compare --> Pass
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="openXC7.mk" line_range="72" />
<code_context>
+# fpga-as assembles the FASM into the bitstream in one process, where
+# fasm2frames and xc7frames2bit needed two plus the .frames file between them.
+# It assembles the same configuration as that pair on every design in this
+# repo (23 designs, five families, compared frame by frame) and is 8x to 112x
+# faster doing it.
+${PROJECT}.bit: ${PROJECT}.fasm
</code_context>
<issue_to_address>
**nitpick:** The new validation comment claims that the repository covers five FPGA families, but the Makefiles and CI matrices cover only Artix-7, Kintex-7, Spartan-7, and Zynq-7. This overstates the scope of the frame-by-frame equivalence check and can mislead future changes about which device families are protected by the assembler parity claim.
**Suggested fix:** Correct the comment to state the actual number of families, or name the families explicitly.
```suggestion
# repo (23 designs, four families, compared frame by frame) and is 8x to 112x
```
</issue_to_address>Sourcery assessment
Needs a human reviewer. A faulty fpga-as/toolchain transition or the new timing-allow-fail settings could produce bitstreams that configure successfully but fail on hardware, and removing the SLEW constraint could alter DDR3 signal behavior. Reverting restores the previous build path, while any already-flashed bad bitstreams would require a bounded reflash.
The chipdb derivation in the previous pin aborted on the second speed grade of
a footprint -- xc7a100tcsg324-1, -2, -2L and -3 all strip to xc7a100tcsg324 --
so every chipdb matrix job of this PR failed:
ln: failed to create symbolic link '.../xc7a100tcsg324.bin': File exists
The copy that the symlink replaced overwrote silently, which is why this only
surfaced on the first real build. Fixed in the toolchain-nix PR by linking
with -f; re-pinning supersedes the previous pin commit on this branch.
Assisted-by: deepseek/deepseek-flash
The chipdb derivation installs the per-part names as relative symlinks to the
die database, but the chipdb jobs staged the store output with
cp "$OUT"/*.bin "$GITHUB_WORKSPACE/stage/"
which dereferences them: artix7 staged 1011 MB of copies for 123 MB of data
(kintex7: 1.2 GB for 252 MB), and that is what the artifact carried. Review
comment on the toolchain-nix PR.
Tar the member list instead -- tar keeps the symlinks as symlinks -- upload the
single archive, and extract it in the three consumers (project, determinism,
regression) and in heavy.yml's project job. A tar member list is exactly what
the derivation installed, so the round trip no longer depends on how
upload-artifact treats symlinks either (v4.3.5 changed that behaviour and broke
pipelines).
Verified: artix7 tar is 123 MB for the same 25 entries, 0 broken symlinks after
extraction, every part name the two matrices use resolves, and
blinky-digilent-arty built from the extracted directory matches the committed
golden's normalized hash (ee4159f5...).
Assisted-by: deepseek/deepseek-flash
The toolchain revision carries the chipdb header correction and now tracks nextpnr's merge commit 5a0b7e41 on main instead of the #45 branch tip. The merge brought nothing else (empty tree diff) and the source hash is unchanged, so every derivation is unchanged: the chipdb and nextpnr store paths are the same as the previous pin's, nothing re-derives, and the chipdb cache stays warm. Assisted-by: deepseek/deepseek-flash
The comment claimed "23 designs, five families" compared frame by frame. The
designs here span four families (artix7, kintex7, spartan7, zynq7), and the
figures were not reproducible. Re-checked with fpga-as's own frame dump:
fpga-as --dump_frames_file=<out> --prjxray_db_path=... --part ... x.fasm
against fasm2frames' output, for every design that has a .fasm here:
- 20 of 21 designs: the frames are identical. fpga-as dumps only the frames
it sets (286 for blinky-digilent-arty) where fasm2frames lists the all-zero
ones too (4974), but every frame the two have in common is word-for-word
equal (value-diff=0, all 101-word frames).
- litex-sata-alientek-davincipro, the only GTP design: two transceiver frames
(0x2129e, 0x2129f) differ in two words each (77 and 78). Not explained; the
other 4688 frames agree, and nothing else in the repo shows a difference.
- its stale .fasm here predates the GTP common fix, so the reference pair
cannot read it at all (FasmLookupError on
GTP_COMMON.GTXE2_COMMON.IBUFDS_GTE2.CLKSWING_CFG); regenerating it with the
pinned engine emits GTP_COMMON_X97Y127.IBUFDS_GTE2_Y1.* and fasm2frames
accepts it. Independent confirmation that the merged fix is the right one.
Speed re-measured on 20 designs (assembler only, fasm2frames+xc7frames2bit vs
fpga-as): 9x (blinky-digilent-zybo) to 120x (blinky-ypcb003381p1, 60.6s vs
0.5s), where the comment said 8x to 112x.
The comment now names the families and the exception instead of the stale
counts.
Assisted-by: deepseek/deepseek-flash
|
Comment addressed in cf51c2a -- and the underlying claim did not survive the The comment said "23 designs, five families". The designs in this repo span Rather than re-word it from memory I re-ran the comparison the claim is about,
The comment now names the four families, states the comparison method so it can |
#20 is merged, so track main's merge commit instead of the PR-branch head. Nothing changes in what gets built: both trees are f86d564b7db47b5f7c0c8873cf41fd9c7894e5f, so the flake evaluates to identical outputs -- the chipdb and nextpnr store paths are unchanged and the chipdb caches stay warm. Assisted-by: deepseek/deepseek-flash
Makes the smoke and heavy matrices green again against the openXC7/nextpnr engine.
The run at 373b764 (smoke #81) failed 9 jobs for five distinct reasons; all of
them are addressed here and the whole matrix was rebuilt locally on the pinned
toolchain before pushing (results below).
What failed, and why
ERROR: Hold/min time violationInfo: Max frequency … FAILfor the same designs (run #80's logs). nextpnr-xilinx#165 records the same finding and that the FASM is identical with--timing-allow-fail.ERROR: Max frequency … FAILfasm2frames … FasmLookupError: GTP_COMMON.GTXE2_COMMON.IBUFDS_GTE2.CLKSWING_CFG not foundunrecognised option '--pre-place'BUILD_PYTHON=OFF, so the fork's python hooks are gone; and the_SING-tile pinning they did is obsolete (the current prjxray-db routes the design, ISERDES onLIOI3_SING_X0Y149and all).ISERDESE2 '…ISERDESE2_train' has disconnected D inputDfed by the OSERDESE2'sOFB, not the DDR3 example's shape (OFBinput fed,D/DDLYopen). Fixed in openXC7/nextpnr#45.ERROR: found multiple properties 'SLEW' … (on line 713)SLEW FASTandSLEW SLOWonddram0_reset_n; the new xdc.cc errors on a repeated property. Every other board XDC has FAST only.Commits
373b764 left half done (it still called
fasm2frames, which the engine's GTPFASM defeats), with the seven blinky goldens regenerated by the pinned fpga-as.
--timing-allow-failon the seven SoC demos thatmiss their derived clocks,
ddr3-test-arty-s7's hooks dropped (with the twoscripts), the stray
SLEW SLOWremoved from both enclustra XDCs.xilinx: fix the GTP common segment name and OFB-fed ISERDESE2 packing nextpnr#45, the fpga-as reference-parity revision and the chipdb
part-name symlinks.
The rev pins are pre-merge commits so this PR's CI exercises the whole stack;
#45 is merged; this branch now pins nextpnr's merge commit 5a0b7e41 through
toolchain-nix 3fa6f49 (derivation-identical -- identical store paths, nothing
re-derives). Re-pin to the toolchain-nix merge commit once #20 lands.
Verification (local, with the pinned toolchain + the engine patches)
normbit.pycompare → byte-identicalto the committed goldens, and the engine patches are therefore golden-neutral.
deterministic.
litex-ddr-hpcstore-k420t(heavy): all buildto
.bit,litex-satanow assemblingGTP_COMMON_X97Y127.GTPE2_COMMON….regression/run.sh: 16 ok / 2 skip (zynq7 chipdb is not uploaded), unchanged.Not touched: the working tree's
litex-ddr-arty-s7regeneration (--sys-clk-freq 110e6and its ~20 MB of regenerated netlist), which is a QoR experiment of itsown — the committed 60 MHz design still builds.
Assisted-by: deepseek/deepseek-flash
Summary by Sourcery
Restore green smoke and heavy FPGA CI matrices on the updated openXC7 toolchain.
Bug Fixes:
Enhancements:
Build:
CI:
Documentation:
Fix-up after the first CI run: re-pin to 07b9721
The chipdb stage of this PR's own first CI run failed on every family -- not in
the demos, but in the toolchain-nix pin:
The chipdb derivation installed the per-part names as symlinks with
ln -s,and the speed grades of one footprint (
xc7a100tcsg324-1,-2,-2L,-3)all collapse to the same part name, so the second link aborted the build. The
cpit replaced overwrote silently. Fixed withln -sfin the toolchain-nixPR (07b9721), and this branch now pins that revision; the pin commit is
therefore superseded by the later re-pin commits.
All five chipdb families were built locally with the fix and every part name
these two matrices use was checked against the resulting directory.
Review fixes
fpga-asparity comment (openXC7.mk) -- claimed "23 designs, fivefamilies". The designs here span four families (artix7, kintex7, spartan7,
zynq7) and the figures were not reproducible, so the check was re-run using
fpga-as's own frame dump:
against
fasm2framesoutput for every design with a.fasm:for
blinky-digilent-arty) wherefasm2framesalso lists the all-zero ones(4974); every frame the two share is word-for-word equal (101-word frames,
value-diff=0).litex-sata-alientek-davincipro(the only GTP design): two transceiverframes (0x2129e, 0x2129f) differ in two words each (77/78). Unexplained, and
the only frame-content difference found anywhere in the repo.
.fasmin a dirty tree can predate the GTP common fix, inwhich case the reference pair cannot read it at all (
FasmLookupErroronGTP_COMMON.GTXE2_COMMON.IBUFDS_GTE2.CLKSWING_CFG); regenerated with thepinned engine it emits
GTP_COMMON_X97Y127.IBUFDS_GTE2_Y1.*andfasm2framesaccepts it -- independent confirmation of the merged fix.The comment now names the four families and the exception; the speed range was
re-measured the same way (9x-120x on 20 designs, previously 8x-112x).
Chipdb artifacts carried dereferenced copies (raised on the toolchain-nix
PR): the chipdb jobs staged with
cp "$OUT"/*.bin, which dereferences theper-part symlinks -- artix7 staged 1011 MB for 123 MB of data, kintex7 1.2 GB
for 252 MB. Both workflows now archive the member list with
tarand thefour consumers extract it, so the round trip no longer depends on
upload-artifact's symlink handling (v4.3.5 changed it and broke pipelines:actions/upload-artifact#590).
CI on the previous head
a15593eran smoke green: 29/29 jobs -- 4 chipdb, 4 determinism,regression, all 21 projects, and the 7 golden comparisons. The run at
a15593eis the one that matters for the original failure report: every jobthat failed at 373b764 passes.