Skip to content

cmt, hclk_cmt: CLK_PERF and PHSR_PERFCLK rows with all their bits - #30

Merged
cavearr merged 3 commits into
openXC7:masterfrom
gHashTag:perfclk-enable-code
Oct 6, 2026
Merged

cavearr merged 3 commits into
openXC7:masterfrom
gHashTag:perfclk-enable-code

Conversation

@gHashTag

@gHashTag gHashTag commented Oct 2, 2026 •

Copy link
Copy Markdown

Follows openXC7/nextpnr#24 and cavearr's two PERFCLK populations:

The checking scripts are at https://gist.github.com/gHashTag/3c9216880b77946385dfc5bea317d927.

What changes

The third commit (c030ed6) supersedes the rows of the first two. The rows below are the same in all four families (artix7, kintex7, spartan7, zynq7) and on both sides.

CMT_TOP_{L,R}_LOWER_B: 20 rows per tile. Each CLK_PERFn mux has an enable bit E, two code bits A and B, and a feedback bit F:

mux E A B F
CLK_PERF0 29_1023 28_997 29_997 29_996
CLK_PERF1 28_1023 29_995 28_996 28_995
CLK_PERF2 29_1022 28_994 29_994 29_993
CLK_PERF3 28_1022 29_992 28_993 28_992

The rows are CLKFBOUT = E F, CLKOUT0 = E !A !B !F, CLKOUT1 = E !A B, CLKOUT2 = E A !B and CLKOUT3 = E A B. The ! bits keep the rows exclusive.

This replaces three wrong rows:

  • CLK_PERF0.CLKOUT2 = 28_997 29_1023 (master since ae4770b) also fires on every CLKOUT3 route: 268 tile samples in 2026-10.
  • CLK_PERF1.CLKOUT3 = 28_996 and CLK_PERF2.CLKOUT3 = 29_994 leave the enable bit and one code bit clear. 29_994 alone also fires on every CLKOUT1 route of CLK_PERF2: 204 samples in 2026-09.

The other 17 rows are new, among them the remaining CLK_PERF0 and CLK_PERF1 positions. zynq7 CMT_TOP_R_LOWER_B had no CLK_PERF0 row at all.

HCLK_CMT / HCLK_CMT_L: 8 rows per tile. PERFCLKp <- MUXEDm sets three bits:

  • the pip bit (26+p)_(176+(m&1));
  • the used bit (26+p)_180;
  • the select bit of m: 29_134, 28_134, 29_133 or 28_133 for MUXED0..3.

There are rows for PERFCLK0/1 <- MUXED0/1 and for PERFCLK2/3 <- MUXED2/3. Before this PR, kintex7, spartan7 and zynq7 had no PHSR_PERFCLK rows, and artix7 had six rows: some left out the used or the select bit, and PERFCLK0.MUXED0 and PERFCLK3.MUXED2 were missing.

No ppips. Every position sets its enable bit, so no position is a default.

Rows that the third commit adds or changes carry origin 039c-perfclk01-forced-mux. Rows from the first two commits that it leaves alone keep 039b.

How it was checked

This check is independent of the campaigns' own scripts and segdata.

  1. Every specimen design.bit was read with bitread and mapped to tile bits through this repo's tilegrid.
  2. Every row set was evaluated against every CMT_TOP_*_LOWER_B and HCLK_CMT* tile of every specimen, used or not.
    • Decode works the way bit2fasm does: a row fires when its bits are set and its ! bits are clear. The result is compared with the pips Vivado routed.
    • Encode works the way fasm2frames does: it takes the positive bits of the rows for the routed pips. The result is compared with the bitstream over all 16 bits of the mux group.
campaign tile samples a7/k7/s7/z7 (CMT and HCLK each) rows of this PR
2026-09 912/912/456/608 0 false, 0 missed, encode exact
2026-10 1464/1464/912/1164 0 false, 0 missed, 0 routed pips with no row, encode exact

Under the same check, the rows at 0a07070 (the head of this PR before c030ed6) give these results on 2026-10:

  • 268 false hits;
  • 2969 routed pips with no row;
  • encode short in 1409 CMT and 2304 HCLK samples.

A correction to this description's earlier version. It said that encode was exact "over every bit any row mentions" in all 2888 HCLK samples. That was true, but it was measured over the wrong set: a bit that no row names cannot show up as missing. Over all 16 bits, those HCLK rows are short in 1230 of the 2888 samples. The difference was always missing bits, never extra ones. The check now compares the whole group.

Negative control. I removed 29_1022 from CLK_PERF2.CLKOUT1. Decode stays clean, and encode flags 80/80/44/56 samples.

utils/parsedb.py --strict passes on all 16 changed segbits_*.db.

Not measured

  • Silicon.
  • The real bit2fasm / fasm2frames round trip with these rows. The check models those tools; it does not call them.
  • The PHASERIN_RCLK side of PERFCLK.
  • virtex7 is untouched. There is no population for it. Its CLK_PERF0.CLKOUT3 = 28_997 looks like a subset row of the same kind.
  • mask_hclk_cmt{,_l}.db. It lists none of the 16 PERFCLK bits, and master is the same. It is left as it is.

🤖 Generated with Claude Code

gHashTag and others added 2 commits October 2, 2026 12:15
Each CMT_LR_LOWER_B_CLK_PERFn mux is set by an enable bit plus a 2-bit
code, not by one bit per source. The rows before this change named a
single code bit, so in both directions they were wrong:

  decode  CLK_PERF2.CLKOUT3 = 29_994 fires on every CLKOUT1 mux too
          (29_994 is the low code bit): 204 false hits in the 039b
          campaign across the four families;
  encode  CLK_PERF1.CLKOUT3 = 28_996 and CLK_PERF2.CLKOUT3 = 29_994
          leave the enable bit and the other code bit clear, which
          Vivado sets for the same pip.

New rows, the same in all four families and on both CMT sides:

  CLK_PERF2  enable 29_1022, code 28_994 29_994, CLKFBOUT 29_993
  CLK_PERF3  enable 28_1022, code 29_992 28_993, CLKFBOUT 28_992
  CLK_PERF1  enable 28_1023, code 29_995 28_996 (CLKOUT2, CLKOUT3 only)

CLK_PERF0.CLKOUT2 is unchanged, and is added to zynq7 CMT_TOP_R_LOWER_B
where it was missing.

Checked against cavearr's perfclk-campaign-2026-09 (152 specimens per
family): bits read from each design.bit through the tilegrid, compared
with the pips Vivado routed, in every CMT tile of every specimen, used
or not. Every row decodes with 0 false and 0 missed hits, and the rows
for the routed pips reproduce the bitstream exactly over every bit the
rows mention: artix7 912/912, kintex7 912/912, spartan7 456/456,
zynq7 608/608 tile samples.

No pseudo-pips: every source sets bits, CLKOUT0 included (the enable).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HCLK_CMT_MUX_PHSR_PERFCLKn rows existed only in artix7, and there the
PERFCLK3 <- MUXED2 row was missing. Added it, and added the six measured
rows to kintex7, spartan7 and zynq7 (HCLK_CMT and HCLK_CMT_L):

  PERFCLK0.MUXED1  26_177 26_180
  PERFCLK1.MUXED0  27_176 29_134
  PERFCLK2.MUXED2  28_176 29_133
  PERFCLK2.MUXED3  28_177
  PERFCLK3.MUXED2  29_133 29_176 29_180   (new in artix7 too)
  PERFCLK3.MUXED3  29_177 29_180

29_180 is set whenever PERFCLK3 is used; 29_133 whenever either PERFCLK
mux selects MUXED2. Checked the same way as the CMT rows, against
cavearr's perfclk-campaign-2026-09: 0 false, 0 missed, encode exact in
all 2888 HCLK tile samples. artix7's PERFCLK1.MUXED1 row (27_177) has no
sample in the campaign and is left where it was, artix7 only.

Not measured: in the campaign PERFCLK2 is never used without PERFCLK3,
so whether PERFCLK2 alone also needs 29_180 is open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Extends and corrects CMT performance-clock database coverage across artix7, kintex7, spartan7, and zynq7 by encoding complete CLK_PERF mux conditions and adding HCLK_CMT PERFCLK/PHSR_PERFCLK rows, with matching origin metadata. The changes were validated against 407,166 measured tile bits: decode produced no false or missed routes, encode matched all tested bits, and strict database parsing passed.

File-Level Changes

Change Details Files
Correct and complete CLK_PERF mux bit rows for the sampled CMT lower tiles across all four supported families.
  • Replace incomplete CLK_PERF1/2 route rows with enable, two-bit source-code, and applicable CLKFBOUT bits, using negative constraints for unset code bits.
  • Preserve CLK_PERF0 mappings and add the missing zynq7 CMT_TOP_R_LOWER_B CLK_PERF0.CLKOUT2 mapping.
  • Update corresponding origin metadata.
artix7/segbits_cmt_top_l_lower_b.db
artix7/segbits_cmt_top_l_lower_b.origin_info.db
artix7/segbits_cmt_top_r_lower_b.db
artix7/segbits_cmt_top_r_lower_b.origin_info.db
kintex7/segbits_cmt_top_l_lower_b.db
kintex7/segbits_cmt_top_l_lower_b.origin_info.db
kintex7/segbits_cmt_top_r_lower_b.db
kintex7/segbits_cmt_top_r_lower_b.origin_info.db
spartan7/segbits_cmt_top_l_lower_b.db
spartan7/segbits_cmt_top_l_lower_b.origin_info.db
spartan7/segbits_cmt_top_r_lower_b.db
spartan7/segbits_cmt_top_r_lower_b.origin_info.db
zynq7/segbits_cmt_top_l_lower_b.db
zynq7/segbits_cmt_top_l_lower_b.origin_info.db
zynq7/segbits_cmt_top_r_lower_b.db
zynq7/segbits_cmt_top_r_lower_b.origin_info.db
Add missing HCLK performance-clock mux and phase-shifter performance-clock bit mappings.
  • Add artix7 PERFCLK3.MUXED2 mapping.
  • Add six PHSR_PERFCLK rows for kintex7, spartan7, and zynq7, including shared PERFCLK3 and MUXED2 conditions.
  • Update corresponding origin metadata.
artix7/segbits_hclk_cmt.db
artix7/segbits_hclk_cmt.origin_info.db
artix7/segbits_hclk_cmt_l.db
artix7/segbits_hclk_cmt_l.origin_info.db
kintex7/segbits_hclk_cmt.db
kintex7/segbits_hclk_cmt.origin_info.db
kintex7/segbits_hclk_cmt_l.db
kintex7/segbits_hclk_cmt_l.origin_info.db
spartan7/segbits_hclk_cmt.db
spartan7/segbits_hclk_cmt.origin_info.db
spartan7/segbits_hclk_cmt_l.db
spartan7/segbits_hclk_cmt_l.origin_info.db
zynq7/segbits_hclk_cmt.db
zynq7/segbits_hclk_cmt.origin_info.db
zynq7/segbits_hclk_cmt_l.db
zynq7/segbits_hclk_cmt_l.origin_info.db

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Checked against cavearr's perfclk-campaign-2026-10 (1083 specimens,
every CLK_PERFn and PERFCLKn source forced), the rows of the two
previous commits are incomplete, and one row they carried is wrong.

  CLK_PERF0.CLKOUT2 = 28_997 29_1023, on master since ae4770b, also
  fires on every CLKOUT3 mux: 268 false hits (artix7 83, kintex7 83,
  spartan7 45, zynq7 57). 28_997 is one bit of the 2-bit code.

  CLK_PERF0 and CLK_PERF1 have the same enable + 2-bit code layout as
  CLK_PERF2/3, but only CLK_PERF0.CLKOUT2 and CLK_PERF1.CLKOUT2/3 had
  rows.

  The PERFCLK rows leave out two bits Vivado sets with every pip:
  used(p) = (26+p)_180, and selected(m) = 29_134, 28_134, 29_133,
  28_133 for MUXED0..3. PERFCLK0 <- MUXED0 had no row.

The previous commit's "encode exact in all 2888 HCLK tile samples" was
measured only over the bits some row names, so it could not see a bit
that no row names. Over all 16 PERFCLK bits, the encode of those rows is
short in 1230 of the 2888 samples.

New rows, the same in all four families and on both sides. Per CMT
tile, 20 rows (4 muxes x 5 sources), enable E, code A B, feedback F:

             E        A       B       F
  CLK_PERF0  29_1023  28_997  29_997  29_996
  CLK_PERF1  28_1023  29_995  28_996  28_995
  CLK_PERF2  29_1022  28_994  29_994  29_993
  CLK_PERF3  28_1022  29_992  28_993  28_992

  CLKFBOUT E F;  CLKOUT0 E !A !B !F;  CLKOUT1 E !A B;
  CLKOUT2  E A !B;  CLKOUT3 E A B

Per HCLK_CMT{,_L} tile, 8 rows: PERFCLKp <- MUXEDm sets
(26+p)_(176+(m&1)), (26+p)_180 and selected(m), for PERFCLK0/1 <-
MUXED0/1 and PERFCLK2/3 <- MUXED2/3.

Rows added or changed carry origin 039c-perfclk01-forced-mux; the 104
rows that did not change keep 039b.

Checked as before: bits read from each design.bit through the tilegrid
and compared with the pips Vivado routed, in every CMT_TOP_*_LOWER_B and
HCLK_CMT tile of every specimen, used or not. Encode is now measured
over every bit of the mux, not just the bits a row names.

  campaign  tile samples a7/k7/s7/z7   CMT and HCLK rows
  2026-09   912/912/456/608            0 false, 0 missed, encode exact
  2026-10   1464/1464/912/1164         0 false, 0 missed, 0 pips with
                                       no row, encode exact

The rows before this change, same check, 2026-10: 268 false (above),
2969 routed pips with no row, encode short in 1409 CMT and 2304 HCLK
samples. utils/parsedb.py --strict passes on all 16 changed segbits
files.

No pseudo-pips: every source sets at least the enable or the used bit.

Not measured: none of this has run on silicon yet. The PHASERIN_RCLK
side of PERFCLK is not covered by either campaign. mask_hclk_cmt*.db
lists none of the 16 PERFCLK bits, here or on master; left as it is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gHashTag added a commit to Trinity-S-AI-DNA/trinity that referenced this pull request Oct 3, 2026
A post on the board half of openXC7/prjxray-db#30: a BUFR counter
clocked through CLK_PERF2 <- CLKOUT3 and PERFCLK2 <- MUXED2 runs on
the AX7203 with the c030ed6 rows and stays dead with the master rows;
the two bitstreams differ in three bits, and clearing any one of them
stops the counter again. It also records the stale nextpnr-xilinx build
(#191 and #205 missing) and the edit-to-board loop going from about
104-111 s to about 19-28 s.

Two recordings published under t27.ai/term/ and replayed in the post:
perf2-knockouts (the three bits named, the knockout bitstreams rebuilt
byte-identical to the flashed ones) and perf2-loop (router1 to SRAM,
19.06 s in that run, at load average ~110).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gHashTag added a commit to Trinity-S-AI-DNA/trinity that referenced this pull request Oct 4, 2026
A post on the board half of openXC7/prjxray-db#30: a BUFR counter
clocked through CLK_PERF2 <- CLKOUT3 and PERFCLK2 <- MUXED2 runs on
the AX7203 with the c030ed6 rows and stays dead with the master rows;
the two bitstreams differ in three bits, and clearing any one of them
stops the counter again. It also records the stale nextpnr-xilinx build
(#191 and #205 missing) and the edit-to-board loop going from about
104-111 s to about 19-28 s.

Two recordings published under t27.ai/term/ and replayed in the post:
perf2-knockouts (the three bits named, the knockout bitstreams rebuilt
byte-identical to the flashed ones) and perf2-loop (router1 to SRAM,
19.06 s in that run, at load average ~110).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gHashTag added a commit to Trinity-S-AI-DNA/trinity that referenced this pull request Oct 4, 2026
)

A post on the board half of openXC7/prjxray-db#30: a BUFR counter
clocked through CLK_PERF2 <- CLKOUT3 and PERFCLK2 <- MUXED2 runs on
the AX7203 with the c030ed6 rows and stays dead with the master rows;
the two bitstreams differ in three bits, and clearing any one of them
stops the counter again. It also records the stale nextpnr-xilinx build
(#191 and #205 missing) and the edit-to-board loop going from about
104-111 s to about 19-28 s.

Two recordings published under t27.ai/term/ and replayed in the post:
perf2-knockouts (the three bits named, the knockout bitstreams rebuilt
byte-identical to the flashed ones) and perf2-loop (router1 to SRAM,
19.06 s in that run, at load average ~110).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
github-actions Bot added a commit to Trinity-S-AI-DNA/trinity that referenced this pull request Oct 4, 2026
docs(blog): three bits, each one necessary - CLK_PERF2 on silicon (#1309)

A post on the board half of openXC7/prjxray-db#30: a BUFR counter
clocked through CLK_PERF2 <- CLKOUT3 and PERFCLK2 <- MUXED2 runs on
the AX7203 with the c030ed6 rows and stays dead with the master rows;
the two bitstreams differ in three bits, and clearing any one of them
stops the counter again. It also records the stale nextpnr-xilinx build
(#191 and #205 missing) and the edit-to-board loop going from about
104-111 s to about 19-28 s.

Two recordings published under t27.ai/term/ and replayed in the post:
perf2-knockouts (the three bits named, the knockout bitstreams rebuilt
byte-identical to the flashed ones) and perf2-loop (router1 to SRAM,
19.06 s in that run, at load average ~110).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@cavearr

cavearr commented Oct 6, 2026

Copy link
Copy Markdown

@gHashTag we ran #30 (together with #31) on the bench before merging. The short version; the full tables are folded below.

  • Chipdb. With your rows the chipdb of all ten dies changes (same size), and every pip that goes from "no row" to "has a row" (25 to 51 per die) is named by one of your rows; none goes the other way. artix7, kintex7, spartan7, zynq7: DSP48E1 AREG_1 and BREG_1 #31 alone changes none of the ten.
  • Nothing else moves. The regression suite (58 of 58 canonical FASM and .bit) and the 37-part end-to-end are identical with and without the two PRs.
  • MMCM output → BUFR / BUFIO, 20 runs on a35, a200, s50 and z010: 5 build with master's rows, 14 with yours. In all 14, fasm2frames, xc7frames2bit and bit2fasm return 0 with no unknown feature.
  • The 5 that already build with master (CLKOUT3 → BUFR/BUFIO on a35 and a200; your case of nextpnr#24 is one of them, the engine routes it now) write a bitstream that, read back with your rows, does not contain the CLK_PERF1.CLKOUT3 and PERFCLKn ← MUXED1 pips. From the other side, 11 of the 20 Vivado bitstreams of these cases show CLK_PERFn / PERFCLKn pips only when read with your rows, and no unknown bit with either db. So the rows also fix builds that complete today.
  • Against Vivado on the same placement: in the tiles of the clock path the differences are which of the four PERF lanes each router picked (each one consistent end to end), the defaults of unused MMCM outputs, and a far-side HCLK_CMT_L…BUFRCLKn_USED that nextpnr writes with master's rows too.

Not measured: silicon with this engine (the AX7203 test used the classic one), the BUFR divider (BYPASS only), CLKOUT1/2/4/5/6 and CLKFBOUT, PLLE2, the upper CMT, kintex7 and virtex7. A BUFR does not place on spartan7 and zynq7 in either arm, which is an engine matter and not the db.

This is enough for us to merge it. Thank you for the rows and for the board test.

Full validation tables (prjxray-db #30 and #31, prjxray #27 and #28)

Validation of prjxray-db #30 and #31 and prjxray #27 and #28 before merging

Every row below was run, not read. Linux x86-64 only; nothing was tried on silicon by us.

What was compared

arm contents
db master openXC7/prjxray-db master 517d66a3, tree 67226051c8b1b7460e66f94232b1d668edbf8fc1
db master + #31 master + #31 (82cb7d85), merged locally, tree be8e936ec2d958eebb3f44282ae70dd723ef9561
db master + #30 + #31 master + #30 (c030ed66) + #31, merged locally, tree 94ae019667e29c99d38e4ada5547d95fd269e803
tools openXC7/prjxray master 9553f1ad; #27 (55cac2da) and #28 (d731949e) built alone and together (tree f686d0dc for the pair)

One factor changes at a time. The engine is openXC7/nextpnr c68c1358 plus eight of our PRs (#72, #71, #70, #69, #68, #66, #67, #65; #71 has been merged since),
the same binaries and the same fasm2frames/xc7frames2bit/bitread in every db arm; only the db files, and the chipdb
generated from them, change. The same yosys (0.69+154, 30d62572e, oss-cad-suite 2026-09-27) synthesised every netlist, and
each netlist file is fed to the arms from the same path. "FASM" comparisons use the canonical FASM (comments and blank lines
dropped, LC_ALL=C sort). A .bit is compared field by field, ignoring only the header's design name, date and time.
The packaged toolchain of each db arm passes the package validator (structure, binaries, inventory against chipdb files,
engine opens every chipdb from --device alone): both PACKAGE VALID.

db #31 — DSP48E1 AREG_1 and BREG_1

The PR adds 32 rows to the DSP segbits (artix7 +8, kintex7 +8, spartan7 +8, zynq7 +8; segbits_dsp_l.db and segbits_dsp_r.db, plus their origin_info) and removes 0; it touches 16 files and nothing else.

Chipdb regenerated with the engine's generator for the ten dies (SHA-256, first 12 hex digits):

die bytes master master + #31 master + #30 + #31
xc7a100t 40104101 9206e3d71cdb 9206e3d71cdb dcdd9257af9b
xc7a200t 60816292 7b6b4a949810 7b6b4a949810 9af6a090522b
xc7a50t 30491033 f875b15c4807 f875b15c4807 f708dacc1045
xc7s25 22033751 315d2dfdffc4 315d2dfdffc4 82f539fbd534
xc7s50 29757535 270e5c046074 270e5c046074 9c7fd24f4d57
xc7z010 21834289 a30aa993e89f a30aa993e89f 434bd51e8dc3
xc7z020 39838438 c19e8fa16e22 c19e8fa16e22 bc50b369687d
xc7z030 49186438 52f0369cfa4b 52f0369cfa4b ff8b05c117b0
xc7z045 65240318 bfda448bf564 bfda448bf564 78883aefdc34
xc7z100 76918990 21feccaf0e21 21feccaf0e21 bf2ffc91b176

With #31 alone, 10 of 10 chipdb files are byte-identical to master's. In the generator's census of pips, #31 turns 0 pips from "no row" to "has a row" on any die: its eight rows name no pip.

What the suite and the e2e say about #31 and #30 together

The builder's regression suite (59 entries) and the 37-part blinky e2e, run once per db arm (master vs master + #30 + #31):

master vs master + #30 + #31
suite netlists identical 59 of 59
suite entries with FASM, canonical FASM identical 58 of 58
suite .bit equal, every field 58 of 58
suite status changes 0
e2e parts, canonical FASM identical 37 of 37
e2e parts, .bit equal, every field 37 of 37

The suite entries that contain a cell the two PRs have rows for: dsp48 (DSP48E1), pll (PLLE2_BASE). None uses a BUFR, a BUFIO, or an MMCM output through the performance clock lanes, so the suite shows that nothing else moved; the proof of #30 is the next section.
The suite's overall verdict is FAIL in both arms for the same single entry (bram, a guard that expects the flow to fail and the flow now completes); it does not depend on the db.

What this does not cover for #31: the new rows were not compared with a Vivado bitstream here (no DSP48E1 with AREG/BREG = 1 in the corpus).

db #30 — complete CLK_PERF0..3 and PERFCLK0..3 rows

On top of #31, the PR touches 32 files (the CMT and HCLK_CMT segbits and their origin_info, in artix7, kintex7, spartan7 and zynq7; nothing else). Segbits rows added / removed: artix7 +56 -18, kintex7 +56 -6, spartan7 +56 -6, zynq7 +56 -5. Some of the removed rows are existing rows that the PR rewrites with more bits, for example CMT_R_LOWER_B_CLK_PERF1.CMT_LR_LOWER_B_MMCM_CLKOUT3 (28_996 becomes 28_996 28_1023 29_995) and HCLK_CMT_MUX_PHSR_PERFCLK0.HCLK_CMT_MUX_MMCM_MUXED1 (26_177 26_180 becomes 26_177 26_180 28_134).

The chipdb changes, and the generator's pip census explains each change

The generator offers the router only the pips that have a row. Per die, pips going from "no row" to "has a row" with db master → master + #30 + #31, and how many of them an added row names:

die chipdb bytes (both) sha master sha master + #30 + #31 pips without a row, before → after flipped named by an added row back to no row tile types of the flipped pips
xc7a100t 40104101 9206e3d71cdb dcdd9257af9b 1869 → 1831 38 38 0 CMT_TOP_L_LOWER_B 17, CMT_TOP_R_LOWER_B 17, HCLK_CMT 2, HCLK_CMT_L 2
xc7a200t 60816292 7b6b4a949810 9af6a090522b 2097 → 2059 38 38 0 CMT_TOP_L_LOWER_B 17, CMT_TOP_R_LOWER_B 17, HCLK_CMT 2, HCLK_CMT_L 2
xc7a50t 30491033 f875b15c4807 f708dacc1045 1869 → 1831 38 38 0 CMT_TOP_L_LOWER_B 17, CMT_TOP_R_LOWER_B 17, HCLK_CMT 2, HCLK_CMT_L 2
xc7s25 22033751 315d2dfdffc4 82f539fbd534 1992 → 1942 50 50 0 CMT_TOP_L_LOWER_B 17, CMT_TOP_R_LOWER_B 17, HCLK_CMT 8, HCLK_CMT_L 8
xc7s50 29757535 270e5c046074 9c7fd24f4d57 1992 → 1942 50 50 0 CMT_TOP_L_LOWER_B 17, CMT_TOP_R_LOWER_B 17, HCLK_CMT 8, HCLK_CMT_L 8
xc7z010 21834289 a30aa993e89f 434bd51e8dc3 1548 → 1523 25 25 0 CMT_TOP_L_LOWER_B 17, HCLK_CMT_L 8
xc7z020 39838438 c19e8fa16e22 bc50b369687d 2353 → 2302 51 51 0 CMT_TOP_L_LOWER_B 17, CMT_TOP_R_LOWER_B 18, HCLK_CMT 8, HCLK_CMT_L 8
xc7z030 49186438 52f0369cfa4b ff8b05c117b0 2469 → 2418 51 51 0 CMT_TOP_L_LOWER_B 17, CMT_TOP_R_LOWER_B 18, HCLK_CMT 8, HCLK_CMT_L 8
xc7z045 65240318 bfda448bf564 78883aefdc34 2469 → 2418 51 51 0 CMT_TOP_L_LOWER_B 17, CMT_TOP_R_LOWER_B 18, HCLK_CMT 8, HCLK_CMT_L 8
xc7z100 76918990 21feccaf0e21 bf2ffc91b176 2469 → 2418 51 51 0 CMT_TOP_L_LOWER_B 17, CMT_TOP_R_LOWER_B 18, HCLK_CMT 8, HCLK_CMT_L 8

So the chipdb of every die changes (same size, different content), and every changed pip is one that a row of #30 names; none goes the other way.
The db at a90f27c1 (the one the current package carries) and master give a byte-identical chipdb for the three artix7 dies and a different one for the other seven.

An MMCM output feeding a BUFR or a BUFIO, end to end

Designs (top = clock pad → MMCME2_ADV → one output → BUFR in BYPASS or BUFIO → 32 registers fed by a counter; the pad-fed BUFR and the MMCM → BUFG are controls). Parts: xc7a35tcsg324-1 (a35), xc7a200tfbg484-1 (a200), xc7s50csga324-1 (s50), xc7z010clg400-1 (z010). The same netlist and the same placement in both db arms where both place.

design what it is
mb0 MMCM CLKOUT0 → BUFR
mb3 MMCM CLKOUT3 → BUFR (the case of nextpnr#24)
mbi3 MMCM CLKOUT3 → BUFR and BUFIO
mi0 MMCM CLKOUT0 → BUFIO
mi3 MMCM CLKOUT3 → BUFIO
ctl-bufr-pad control: pad → BUFR
ctl-mmcm-bufg control: MMCM → BUFG

Result of each run (rc 0 = nextpnr, fasm2frames with no unknown feature, xc7frames2bit and bit2fasm all returned 0):

design part db master db master + #30 + #31
mb0 a35 rc 125: ERROR: Failed to route arc 0.0 of net 'c', from X8Y147/MMCME2_ADV_X0Y0.CLKOUT0 to X1Y130/BUFR_X0Y1.I. rc 0
mb0 a200 rc 125: ERROR: Failed to route arc 0.0 of net 'c', from X8Y147/MMCME2_ADV_X0Y0.CLKOUT0 to X1Y130/BUFR_X0Y0.I. rc 0
mb0 s50 rc 125: ERROR: Unable to place cell 'c38_BUFR', no BELs remaining to implement cell type 'BUFR_BUFR' rc 125: ERROR: Unable to place cell 'c38_BUFR', no BELs remaining to implement cell type 'BUFR_BUFR'
mb0 z010 rc 125: ERROR: Unable to place cell 'c38_BUFR', no BELs remaining to implement cell type 'BUFR_BUFR' rc 125: ERROR: Unable to place cell 'c38_BUFR', no BELs remaining to implement cell type 'BUFR_BUFR'
mb3 a35 rc 0 rc 0
mb3 a200 rc 0 rc 0
mb3 s50 rc 125: ERROR: Unable to place cell 'c38_BUFR', no BELs remaining to implement cell type 'BUFR_BUFR' rc 125: ERROR: Unable to place cell 'c38_BUFR', no BELs remaining to implement cell type 'BUFR_BUFR'
mb3 z010 rc 125: ERROR: Unable to place cell 'c38_BUFR', no BELs remaining to implement cell type 'BUFR_BUFR' rc 125: ERROR: Unable to place cell 'c38_BUFR', no BELs remaining to implement cell type 'BUFR_BUFR'
mbi3 a35 rc 0 rc 0
mbi3 a200 rc 125: ERROR: Failed to route arc 1.0 of net 'c', from X8Y147/MMCME2_ADV_X0Y0.CLKOUT3 to X1Y130/BUFIO_X0Y1.I. rc 0
mbi3 s50 rc 125: ERROR: Unable to place cell 'c41_BUFR', no BELs remaining to implement cell type 'BUFR_BUFR' rc 125: ERROR: Unable to place cell 'c41_BUFR', no BELs remaining to implement cell type 'BUFR_BUFR'
mbi3 z010 rc 125: ERROR: Unable to place cell 'c41_BUFR', no BELs remaining to implement cell type 'BUFR_BUFR' rc 125: ERROR: Unable to place cell 'c41_BUFR', no BELs remaining to implement cell type 'BUFR_BUFR'
mi0 a35 rc 125: ERROR: Failed to route arc 0.0 of net 'c', from X8Y147/MMCME2_ADV_X0Y0.CLKOUT0 to X1Y130/BUFIO_X0Y3.I. rc 0
mi0 a200 rc 125: ERROR: Failed to route arc 0.0 of net 'c', from X8Y147/MMCME2_ADV_X0Y0.CLKOUT0 to X1Y130/BUFIO_X0Y2.I. rc 0
mi0 s50 rc 125: ERROR: Failed to route arc 0.0 of net 'c', from X8Y147/MMCME2_ADV_X0Y0.CLKOUT0 to X1Y130/BUFIO_X0Y3.I. rc 0
mi0 z010 rc 125: ERROR: Failed to route arc 0.0 of net 'c', from X119Y95/MMCME2_ADV_X0Y0.CLKOUT0 to X126Y78/BUFIO_X0Y3.I. rc 0
mi3 a35 rc 0 rc 0
mi3 a200 rc 0 rc 0
mi3 s50 rc 125: ERROR: Failed to route arc 0.0 of net 'c', from X8Y147/MMCME2_ADV_X0Y0.CLKOUT3 to X1Y130/BUFIO_X0Y3.I. rc 0
mi3 z010 rc 125: ERROR: Failed to route arc 0.0 of net 'c', from X119Y95/MMCME2_ADV_X0Y0.CLKOUT3 to X126Y78/BUFIO_X0Y3.I. rc 0
ctl-bufr-pad a35 rc 0 rc 0
ctl-bufr-pad a200 rc 0 rc 0
ctl-bufr-pad s50 rc 125: ERROR: Unable to place cell 'c14_BUFR', no BELs remaining to implement cell type 'BUFR_BUFR' rc 125: ERROR: Unable to place cell 'c14_BUFR', no BELs remaining to implement cell type 'BUFR_BUFR'
ctl-bufr-pad z010 rc 125: ERROR: Unable to place cell 'c14_BUFR', no BELs remaining to implement cell type 'BUFR_BUFR' rc 125: ERROR: Unable to place cell 'c14_BUFR', no BELs remaining to implement cell type 'BUFR_BUFR'
ctl-mmcm-bufg a35 rc 0 rc 0
ctl-mmcm-bufg a200 rc 0 rc 0
ctl-mmcm-bufg s50 rc 0 rc 0
ctl-mmcm-bufg z010 rc 0 rc 0

Of the 20 MMCM → BUFR/BUFIO runs, 5 build with db master and 14 with db master + #30 + #31. The ones that still fail in both arms are the BUFR cases on spartan7 and zynq7 ("no BELs remaining to implement cell type BUFR_BUFR", also with a pad-fed BUFR: an engine matter, not the db).
Where both arms build, the placement is byte-identical.

What a build with db master is. Five runs build with db master (mb3 on a35 and a200, mbi3 on a35, mi3 on a35 and a200). They route CLKOUT3 through CMT_R_LOWER_B_CLK_PERF1 and HCLK_CMT_MUX_PHSR_PERFCLKn ← MUXED1, pips whose rows #30 rewrites. The .bit nextpnr wrote with them, read back with the rows of #30, no longer contains those pips (< = with master's rows, > = with #30's):

run pips read back with master's rows and not with #30's
mb3/a200 CMT_R_LOWER_B_CLK_PERF1.CMT_LR_LOWER_B_MMCM_CLKOUT3; HCLK_CMT_MUX_PHSR_PERFCLK0.HCLK_CMT_MUX_MMCM_MUXED1
mb3/a35 CMT_R_LOWER_B_CLK_PERF1.CMT_LR_LOWER_B_MMCM_CLKOUT3; HCLK_CMT_MUX_PHSR_PERFCLK0.HCLK_CMT_MUX_MMCM_MUXED1
mbi3/a35 CMT_R_LOWER_B_CLK_PERF1.CMT_LR_LOWER_B_MMCM_CLKOUT3; HCLK_CMT_MUX_PHSR_PERFCLK0.HCLK_CMT_MUX_MMCM_MUXED1; HCLK_CMT_MUX_PHSR_PERFCLK1.HCLK_CMT_MUX_MMCM_MUXED1
mi3/a200 CMT_R_LOWER_B_CLK_PERF1.CMT_LR_LOWER_B_MMCM_CLKOUT3; HCLK_CMT_MUX_PHSR_PERFCLK0.HCLK_CMT_MUX_MMCM_MUXED1
mi3/a35 CMT_R_LOWER_B_CLK_PERF1.CMT_LR_LOWER_B_MMCM_CLKOUT3; HCLK_CMT_MUX_PHSR_PERFCLK1.HCLK_CMT_MUX_MMCM_MUXED1

So the five builds that work today carry bits that, read with #30's rows, are not those pips. Whether such a clock path runs on silicon is not measured. From the other side, the Vivado bitstream of each case read back with each db (same bit2fasm, same file; Vivado placed and routed it itself):

run read only with master's rows read only with #30's rows unknown bits (master / #30)
mb0/a200 none CMT_R_LOWER_B_CLK_PERF3.CMT_LR_LOWER_B_MMCM_CLKOUT0 0 / 0
mb0/a35 none CMT_R_LOWER_B_CLK_PERF3.CMT_LR_LOWER_B_MMCM_CLKOUT0 0 / 0
mb3/a200 none CMT_R_LOWER_B_CLK_PERF3.CMT_LR_LOWER_B_MMCM_CLKOUT3 0 / 0
mb3/a35 none CMT_R_LOWER_B_CLK_PERF3.CMT_LR_LOWER_B_MMCM_CLKOUT3 0 / 0
mbi3/a200 none CMT_R_LOWER_B_CLK_PERF3.CMT_LR_LOWER_B_MMCM_CLKOUT3 0 / 0
mi0/a200 none CMT_R_LOWER_B_CLK_PERF1.CMT_LR_LOWER_B_MMCM_CLKOUT0 0 / 0
mi0/a35 none CMT_R_LOWER_B_CLK_PERF1.CMT_LR_LOWER_B_MMCM_CLKOUT0 0 / 0
mi0/s50 none CMT_R_LOWER_B_CLK_PERF1.CMT_LR_LOWER_B_MMCM_CLKOUT0; HCLK_CMT_MUX_PHSR_PERFCLK1.HCLK_CMT_MUX_MMCM_MUXED1 0 / 0
mi0/z010 none CMT_L_LOWER_B_CLK_PERF1.CMT_LR_LOWER_B_MMCM_CLKOUT0; HCLK_CMT_MUX_PHSR_PERFCLK1.HCLK_CMT_MUX_MMCM_MUXED1 0 / 0
mi3/s50 none HCLK_CMT_MUX_PHSR_PERFCLK1.HCLK_CMT_MUX_MMCM_MUXED1 0 / 0
mi3/z010 none HCLK_CMT_MUX_PHSR_PERFCLK1.HCLK_CMT_MUX_MMCM_MUXED1 0 / 0

11 of 20 Vivado bitstreams read differently; the runs not shown read the same. Every difference is a CLK_PERFn.CLKOUTm or PERFCLKn ← MUXEDm pip that only #30's rows name. No unknown bit appears with either db.

Against Vivado, same placement

For every run that builds with db master + #30 + #31 (20 runs), Vivado 2026.1 was given the same netlist with every cell fixed where nextpnr placed it (LOC/BEL, LUT pins), routed freely, and both bitstreams went through bit2fasm. Window = the tiles that carry the clock path (CMT_TOP_*, HCLK_CMT*, HCLK_IOI*, HCLK_L/R) plus every placed cell's tile. SITE features decide; pips are routing and are listed. Unknown bits in either bitstream: 0 in all 20 runs, and 0 in the 11 runs of db master.

run clock pips: same chain as Vivado site features only nextpnr writes (path tiles) site features only Vivado writes (path tiles)
ctl-bufr-pad/a200 identical pips HCLK_CMT_L_X256Y130.HCLK_CMT_CK_BUFRCLK0_USED, HCLK_CMT_L_X256Y130.HCLK_CMT_CK_BUFRCLK1_USED, LIOI3_X0Y147.ILOGIC_Y1.IFF.ZSRVAL_Q1, LIOI3_X0Y147.ILOGIC_Y1.IFF.ZSRVAL_Q2, LIOI3_X0Y147.ILOGIC_Y1.IFF.ZSRVAL_Q3, LIOI3_X0Y147.ILOGIC_Y1.IFF.ZSRVAL_Q4 HCLK_CMT_X8Y130.HCLK_CMT_CCIO1_ACTIVE
ctl-bufr-pad/a35 identical pips HCLK_CMT_L_X106Y26.HCLK_CMT_CK_BUFRCLK0_USED, HCLK_CMT_L_X106Y26.HCLK_CMT_CK_BUFRCLK1_USED, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q1, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q2, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q3, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q4 HCLK_CMT_X8Y26.HCLK_CMT_CCIO1_ACTIVE
ctl-mmcm-bufg/a200 identical pips HCLK_CMT_L_X256Y130.HCLK_CMT_CK_BUFHCLK0_USED, HCLK_CMT_X8Y130.HCLK_CMT_CK_BUFHCLK0_USED, HCLK_R_X12Y130.ENABLE_BUFFER.HCLK_CK_BUFHCLK0 HCLK_CMT_X8Y130.HCLK_CMT_CK_BUFHCLK8_USED, HCLK_L_X11Y130.ENABLE_BUFFER.HCLK_CK_BUFHCLK8
ctl-mmcm-bufg/a35 identical pips HCLK_CMT_L_X106Y78.HCLK_CMT_CK_BUFHCLK0_USED, HCLK_CMT_X8Y78.HCLK_CMT_CK_BUFHCLK0_USED, HCLK_R_X12Y78.ENABLE_BUFFER.HCLK_CK_BUFHCLK0 HCLK_CMT_X8Y78.HCLK_CMT_CK_BUFHCLK8_USED, HCLK_L_X11Y78.ENABLE_BUFFER.HCLK_CK_BUFHCLK8
ctl-mmcm-bufg/s50 identical pips HCLK_CMT_L_X106Y78.HCLK_CMT_CK_BUFHCLK0_USED, HCLK_CMT_X8Y78.HCLK_CMT_CK_BUFHCLK0_USED, HCLK_R_X12Y78.ENABLE_BUFFER.HCLK_CK_BUFHCLK0 HCLK_CMT_X8Y78.HCLK_CMT_CK_BUFHCLK8_USED, HCLK_L_X11Y78.ENABLE_BUFFER.HCLK_CK_BUFHCLK8
ctl-mmcm-bufg/z010 identical pips HCLK_CMT_L_X119Y78.HCLK_CMT_CK_BUFHCLK0_USED, HCLK_R_X116Y78.ENABLE_BUFFER.HCLK_CK_BUFHCLK0 HCLK_CMT_L_X119Y78.HCLK_CMT_CK_BUFHCLK8_USED, HCLK_L_X115Y78.ENABLE_BUFFER.HCLK_CK_BUFHCLK8
mb0/a200 a different, internally consistent lane HCLK_CMT_L_X256Y130.HCLK_CMT_CK_BUFRCLK2_USED MMCME2_ADV.CLKOUT3_CLKOUT1_HIGH_TIME[0], MMCME2_ADV.CLKOUT3_CLKOUT1_LOW_TIME[0], MMCME2_ADV.CLKOUT3_CLKOUT2_NO_COUNT[0]
mb0/a35 a different, internally consistent lane HCLK_CMT_L_X106Y26.HCLK_CMT_CK_BUFRCLK3_USED MMCME2_ADV.CLKOUT3_CLKOUT1_HIGH_TIME[0], MMCME2_ADV.CLKOUT3_CLKOUT1_LOW_TIME[0], MMCME2_ADV.CLKOUT3_CLKOUT2_NO_COUNT[0]
mb3/a200 a different, internally consistent lane HCLK_CMT_L_X256Y130.HCLK_CMT_CK_BUFRCLK2_USED none
mb3/a35 a different, internally consistent lane HCLK_CMT_L_X106Y26.HCLK_CMT_CK_BUFRCLK3_USED none
mbi3/a200 a different, internally consistent lane HCLK_CMT_L_X256Y130.HCLK_CMT_CK_BUFRCLK3_USED, LIOI3_X0Y147.ILOGIC_Y1.IFF.ZSRVAL_Q1, LIOI3_X0Y147.ILOGIC_Y1.IFF.ZSRVAL_Q2, LIOI3_X0Y147.ILOGIC_Y1.IFF.ZSRVAL_Q3, LIOI3_X0Y147.ILOGIC_Y1.IFF.ZSRVAL_Q4 none
mbi3/a35 a different, internally consistent lane HCLK_CMT_L_X106Y26.HCLK_CMT_CK_BUFRCLK0_USED, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q1, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q2, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q3, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q4 none
mi0/a200 identical pips LIOI3_X0Y147.ILOGIC_Y1.IFF.ZSRVAL_Q1, LIOI3_X0Y147.ILOGIC_Y1.IFF.ZSRVAL_Q2, LIOI3_X0Y147.ILOGIC_Y1.IFF.ZSRVAL_Q3, LIOI3_X0Y147.ILOGIC_Y1.IFF.ZSRVAL_Q4 MMCME2_ADV.CLKOUT3_CLKOUT1_HIGH_TIME[0], MMCME2_ADV.CLKOUT3_CLKOUT1_LOW_TIME[0], MMCME2_ADV.CLKOUT3_CLKOUT2_NO_COUNT[0]
mi0/a35 identical pips LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q1, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q2, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q3, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q4 MMCME2_ADV.CLKOUT3_CLKOUT1_HIGH_TIME[0], MMCME2_ADV.CLKOUT3_CLKOUT1_LOW_TIME[0], MMCME2_ADV.CLKOUT3_CLKOUT2_NO_COUNT[0]
mi0/s50 identical pips LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q1, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q2, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q3, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q4 MMCME2_ADV.CLKOUT3_CLKOUT1_HIGH_TIME[0], MMCME2_ADV.CLKOUT3_CLKOUT1_LOW_TIME[0], MMCME2_ADV.CLKOUT3_CLKOUT2_NO_COUNT[0]
mi0/z010 identical pips RIOI3_X31Y47.ILOGIC_Y1.IFF.ZSRVAL_Q1, RIOI3_X31Y47.ILOGIC_Y1.IFF.ZSRVAL_Q2, RIOI3_X31Y47.ILOGIC_Y1.IFF.ZSRVAL_Q3, RIOI3_X31Y47.ILOGIC_Y1.IFF.ZSRVAL_Q4 MMCME2_ADV.CLKOUT3_CLKOUT1_HIGH_TIME[0], MMCME2_ADV.CLKOUT3_CLKOUT1_LOW_TIME[0], MMCME2_ADV.CLKOUT3_CLKOUT2_NO_COUNT[0]
mi3/a200 identical pips LIOI3_X0Y147.ILOGIC_Y1.IFF.ZSRVAL_Q1, LIOI3_X0Y147.ILOGIC_Y1.IFF.ZSRVAL_Q2, LIOI3_X0Y147.ILOGIC_Y1.IFF.ZSRVAL_Q3, LIOI3_X0Y147.ILOGIC_Y1.IFF.ZSRVAL_Q4 none
mi3/a35 identical pips LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q1, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q2, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q3, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q4 none
mi3/s50 identical pips LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q1, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q2, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q3, LIOI3_X0Y47.ILOGIC_Y1.IFF.ZSRVAL_Q4 none
mi3/z010 identical pips RIOI3_X31Y47.ILOGIC_Y1.IFF.ZSRVAL_Q1, RIOI3_X31Y47.ILOGIC_Y1.IFF.ZSRVAL_Q2, RIOI3_X31Y47.ILOGIC_Y1.IFF.ZSRVAL_Q3, RIOI3_X31Y47.ILOGIC_Y1.IFF.ZSRVAL_Q4 none

Reading of the lists (each point was checked on every row they appear in):

  • The clock path itself: in the 14 MMCM → BUFR/BUFIO runs the only Vivado-only SITE features in the path tiles are the CLKOUT3 defaults below; the HCLK_CMT_CK_BUFRCLKn_USED, ENABLE_BUFFER.HCLK_CK_BUFRCLKn, BUFR_Yn.IN_USE and BUFR_DIVIDE.BYPASS features are written by both. The pips differ only in WHICH of the four performance lanes (PERF0..3) the router picked; each tool's lane is consistent from CLKOUTn to the BUFR/BUFIO (the same index in the four tiles).
  • nextpnr-only HCLK_CMT_L.HCLK_CMT_CK_BUFRCLKn_USED (the HCLK_CMT tile on the other side of the die): present with db master and in the pad-fed control, so cmt, hclk_cmt: CLK_PERF and PHSR_PERFCLK rows with all their bits #30 does not cause it. Vivado does not write it. Whether it matters on silicon is not known.
  • nextpnr-only ILOGIC_Y1.IFF.ZSRVAL_Q1..Q4: the IDDR of the stimulus, also in the pad-fed control; unrelated to the clock lanes.
  • Vivado-only CLKOUT3_* of the MMCM in mb0 and mi0: these designs do not use CLKOUT3, and Vivado writes the defaults of the unused outputs (the control shows the same 22 features for the outputs it does not use).
  • CCIO1_ACTIVE only Vivado, in the pad-fed control, and the BUFHCLK rows of the MMCM → BUFG control: the global clock path, which cmt, hclk_cmt: CLK_PERF and PHSR_PERFCLK rows with all their bits #30 does not touch.
  • The 22 MMCM features Vivado writes and nextpnr does not (CLKOUTn default timing registers and ZINV_*) are the same in the MMCM → BUFG control.

With db master, the 11 runs that build show the same classes of difference against Vivado; the lists are in the artifacts.

Read back

Features nextpnr wrote in the CMT, HCLK_CMT, HCLK_IOI and HCLK tiles, against what bit2fasm reads back from the .bit (20 runs): 1181 written, 0 lost (a feature with a row whose bits are not read back), 150 not read back because they have no row in the db (pips that set no bit, e.g. HCLK_IOI_RCLK2RCLK3 → HCLK_IOI_RCLK_OUT3).

What this does not cover: only CLKOUT0 and CLKOUT3 of the MMCM, BUFR in BYPASS only (no divider), no PLLE2, the lower-half CMT only, the artix7 parts a35 and a200 for BUFR (spartan7 and zynq7 for BUFIO only), and nothing on silicon. Timing is not modelled. The rows of #30 for CLKOUT1/2/4/5/6 and CLKFBOUT were read from the diff, not exercised.

prjxray #27 and #28 — xc7frames2bit

#27 touches lib/include/prjxray/xilinx/frames.h, lib/xilinx/tests/xc7series/frames_test.cc and tools/xc7frames2bit.cc; #28 touches tools/xc7frames2bit.cc only. Neither touches fasm2frames or bitread.

xc7frames2bit of master, of #27, of #28 and of both, on the same .frames file, the same --part_file and the same relative path for --frm_file. Frames files: every design of the suite in both db arms, the 37-part e2e, and every case of the table above that reached fasm2frames.

source frames files rc 0 in all four tools .bit equal to master's (every field) with #27 / #28 / both "not in the part"
suite 116 116 116 / 116 / 116 0
e2e 37 37 37 / 37 / 37 0
MMCM → BUFR/BUFIO cases 31 31 31 / 31 / 31 0
total 184 184

The suite designs include bram, dsp48, pll, srl, srl-cascade, lutram, tristate, carry64, congestion-local, demo-zybo, spartan7-blinky; the parts are artix7, spartan7 and zynq7. No frames file was rejected.

What this does not cover: kintex7 and virtex7 frames (no part of the manifest and no design here); a .frames file with an address that really is not in the part (the PRs' own unit tests cover the rejection); the loaded .bit on a board.

What was not measured, in one list

@cavearr
cavearr merged commit 2df1165 into openXC7:master Oct 6, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants