virtex7: HP-bank glue codified end-to-end + open-flow validation

The open-flow (Yosys → nextpnr-xilinx → FASM → bitstream) now produces
silicon-functional bits on VC707 xc7vx485tffg1761-2 for:
  - rst_to_led (IBUF↔OBUF passthrough)
  - counter_skewfree (button-clocked 8b counter, general routing)
  - counter_sw_bufr (button → BUFR → 8b counter)
  - counter_bufr  (200 MHz LVDS sysclk → IBUFDS → BUFR → 8b counter)
  - counter_2bufg (2× BUFGCTRL on the same source)
  - vc707_telegraph (125 MHz crystal → IBUFDS_GTE2 → BUFG → UART smoke test)
  - vc707_picosoc  (picorv32 + simpleuart + BRAM @ 125 MHz; UART prints
                    'PicoSoC alive on VC707 @ 125 MHz' on /dev/ttyUSB0)

Highlights of this drop:

utils/fasm2frames.py (+223 net):
  - Bank-glue auto-injection for HP-bank IOB18 — IBUF/OBUF (Y0+Y1) +
    IBUFDS differential pair. Fires off the FASM-level direction
    heuristic (.IN/.IN_ONLY/IBUFDISABLE for IBUF, .DRIVE. for OBUF,
    .IN_DIFF for IBUFDS; .SLEW. is unreliable as a marker — gets emitted
    on default-state IOBs too).
  - INT_L_X32Y49 DCI cascade / bank-active markers when any LIOB18_X81
    Y1 OBUF is present.
  - PUDC_B emission rewritten for HP-bank IOSTANDARDs (10 features
    cover Y0 + Y1 default-state; all 9 historic 'PUDC_B glue' bits
    flow naturally from the existing IOSTANDARD segbits).
  - HCLK_L per-BUFRCLK-channel 'active' marker — currently codified
    for BUFRCLK3 (the channel exercised by counter_sw_bufr).
  - GFAN T-tie root glue — INT_L_X62Y(N+10).GFAN_TIE_ROOT_GLUE when
    INT_L_X62Y(N).GFAN0.GND_WIRE appears (OBUF.T → GND routing).
  - PUDC_B tile excluded from the bank-glue walk (its IN features are
    virtual; injecting OBUF_HP_BANK_GLUE on it produces spurious bits).

utils/utils.tcl (+47):
  - write_pip_txtdata bulk-fetch — replaces per-net foreach pip with
    bulk get_pips + bulk get_property IS_DIRECTIONAL + cached
    dst_wire_to_num_pips. ~4× speed-up on xc7vx485t (per-spec time on
    041-clk-hrow-pips / 045-hclk-cmt-pips drops from ~1.5 h to ~25 min).

utils/mergedb.sh (+15):
  - LIOI / LIOI_TBYTESRC / LIOI_TBYTETERM / LIOB18 / mask_liob18 sed
    rewrites for the L-side IOI/IOB18 tiles on HP-only parts (xc7vx485t
    uses left-side IOB18 too; upstream kintex7 mergedb only knew the
    right side).

11 fuzzers patched for virtex7 readiness:
  - 030-iob18 Makefile: split DB target for virtex7 (HP-only); the BUFR
    HP-bank results come from the actual fuzzer rather than HR-side sed.
  - 037-iob18-pips: L-side mirror tiles (LIOI / LIOI_TBYTESRC /
    LIOI_TBYTETERM) added to segdata glob; *_SING tiles excluded;
    EXCLUDE_RE updated for L-side prefixes.
  - 039-hclk-config: split virtex7 vs kintex7 (HCLK_IOI vs HCLK_IOI3);
    XRAY_IOSTANDARD env var; IOB18M/IOB33M alternation.
  - 047a-hclk-idelayctrl-pips: accepts both HCLK_IOI and HCLK_IOI3.
  - 041, 045, 034, 034b, 043, 044, 046: removed local
    write_pip_txtdata override that shadowed the patched utils.tcl
    bulk-fetch (was re-introducing the slow per-net Tcl path).

README.md (+86):
  - 'Virtex-7 Port Status (virtex7-support branch)' section —
    achievements, goals, work-in-progress, constraints.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Dr Jonathan Richard Robert Kimmitt 2026-05-29 10:13:53 +01:00
parent e00d6f6876
commit a8de0afdb3
23 changed files with 7981 additions and 202 deletions

View File

@ -242,6 +242,92 @@ We have also started experimenting with the Kintex-7 and Virtex-7 parts.
The aim is to eventually document all parts in the Xilinx 7-series FPGAs but we
can not do this alone, **we need your help**!
## Virtex-7 Port Status (`virtex7-support` branch)
This branch ports the openXC7 prjxray flow to **Virtex-7 `xc7vx485tffg1761-2`**
(VC707 board), modelled on the Kintex-7 sub-flow. The goal is a fully
open-source bit→DCP / fasm→bit round-trip on a Virtex-7 HP-only part.
### Achievements
- **End-to-end smoke test passes** on `xc7vx485tffg1761-2`: System-Verilog
→ Yosys → nextpnr-xilinx → FASM → `fasm2frames.py``xc7frames2bit`
`.bit`. First run required 3 patches and surfaced 2 nextpnr-xilinx bugs
(filed upstream).
- **Cross-family segbits/ppips transplant** from the openXC7
[`prjxray-db`](https://github.com/openXC7/prjxray-db) Kintex-7 tree into
`database/virtex7/`: ~39 381 segbits + ~12 273 ppips entries, plus targeted
key copies for `clk_hrow_*`, `clk_bufg_*`, `hclk_cmt*`, `io_int_interface_*`
(≈51 k entries total). Pre-transplant tree backed up at
`database/virtex7.before_transplant/`.
- **11 fuzzers patched** for HP-bank / virtex7-grid awareness:
- `037-iob18-pips` — left-side mirror sites (LIOI / LIOI_TBYTESRC /
LIOI_TBYTETERM), `top.py` NOT_INCLUDED_TILES for `*_SING`, generate-side
tile-type normalization, `ioi_pip_list.tcl` LIOI emission.
- `039-hclk-config` — virtex7 split (HCLK_IOI vs HCLK_IOI3),
`XRAY_IOSTANDARD` env var, IOB18M / IOB33M alternation in `top.py`.
- `047a-hclk-idelayctrl-pips` — accepts both HCLK_IOI and HCLK_IOI3.
- `034 / 034b / 041 / 043 / 044 / 045 / 046` — removed local
`write_pip_txtdata` overrides that shadowed the patched `utils.tcl`
bulk-fetch (~4× faster per specimen on xc7vx485t).
- **`utils/utils.tcl` bulk-fetch patch** for `write_pip_txtdata`
per-net `foreach pip` → bulk `get_pips` + bulk `get_property IS_DIRECTIONAL`
+ cached `dst_wire_to_num_pips`. ~4× speed-up; on
`xc7vx485tffg1761-2` cuts `041-clk-hrow-pips`/`045-hclk-cmt-pips` specimens
from ~1.5 h to ~25 min each.
- **`utils/fasm2frames.py` HP-bank fix** — was hard-coded to `HCLK_IOI3_*`
tile prefix; now probes the grid for whichever of `HCLK_IOI_` / `HCLK_IOI3_`
exists. STEPDOWN bank-anchor check widened accordingly.
- **`utils/mergedb.sh` extended** with LIOI / LIOI_TBYTESRC / LIOI_TBYTETERM
/ LIOB18 / mask_liob18 cases.
- **RapidWright `json2dcp.jar` rebuilt** against modern RapidWright (2025.2.1)
and patched for virtex7 — at `~/rapidwright/build/rapidwright_json2dcp.jar`
(17 KB). Verified `rst_to_led_routed.json` → 1.38 MB DCP that loads back
cleanly on `xc7vx485tffg1761-2`. Patch list in
`~/rapidwright/build/README.md`.
### Goals
- Document `xc7vx485tffg1761-2` bitstream format with parity sufficient for a
Vivado-equivalent bitstream on IOB-only designs first, then SLICE and CMT.
- Achieve bit ↔ bit equivalence with Vivado on the `rst_to_led` pass-through
reference, then incrementally on counter, BUFR/IDELAY, and CMT designs.
- Provide a runnable bit→DCP path so open-flow bitstreams can be inspected /
diffed against Vivado checkpoints (Phase A via `json2dcp.jar` done; Phase B
via a virtex7-aware `fasm2bels` still in progress).
### Work in Progress
- **030-iob18 N=200 rerun** for finer IOSTANDARD/DRIVE coverage on LIOB18.
Running at one specimen per ~3 min, currently ≈187 of 200 specimens written;
will trigger `make pushdb` automatically on completion.
- **LIOB18 IOSTANDARD bit-encoding bug**`rst_to_led.bit` produced by our
flow flickers and is unresponsive on hardware; Vivado-built reference works.
Targeted bit-diff localised the discrepancy to LIOI and LIOI_TBYTETERM
tiles sharing a frame range but with different word offsets — partial fix
applied (per-tile partitioning) reduced missing bits 28 → 21 and extras
14 → 12, but IOSTANDARD bits still wrong. Awaiting N=200 segdata to
re-derive.
- **037-iob18-pips left-side coverage** — residual pip-convergence iteration;
iter 1 was salvaged after a JVM crash on `spec_008` left 19 surviving
specimens that yielded 128 LIOI entries.
- **Phase B — virtex7 `fasm2bels` port** — parked. Connection database for
`xc7vx485tffg1761-2` builds successfully (14 min, 4.2 GB on disk, 56.8 M
wires). First failure is in `clb_models.py` on the nextpnr-emitted
PSEUDO_VCC packer cell (`assert False, {'NOCLKINV'}`). IOB18 / HP-bank BEL
name substitutions drafted in `models/iob_models.py` (uncommitted).
- **Open TODOs (cross-cutting)** — expand the virtex7 ROI; add a Vivado DRC
cross-check of nextpnr output; exclude `GTX_INT_INTERFACE` pips from the
virtex7 chipdb; add bits info for `CFG_CENTER` / `*_SING` tiles.
### Constraints
- Patches must **not** regress other families (artix7 / kintex7 / zynq7 /
spartan7). The HP-bank additions are gated on tile-type prefix so the
HR-bank paths stay byte-identical.
- Build artefacts under `fuzzers/*/build/` are **retained** for debugging
`make clean` is not invoked between fuzzer iterations.
## Adding a new part to an existing family
We have written a [detailed guide](https://f4pga.readthedocs.io/projects/prjxray/en/latest/db_dev_process/newpart.html) that walks through the process of adding a new part to an existing family.

View File

@ -16,7 +16,12 @@ build/iobanks.txt: write_io_banks.tcl
cd build/ && ${XRAY_VIVADO} -mode batch -source ../write_io_banks.tcl
build/segbits_riob18.rdb: $(SPECIMENS_OK)
${XRAY_SEGMATCH} -c 23 -o build/segbits_riob18.rdb $$(find -name segdata_riob18.txt)
# Glob both L- and R-side segdata: top.py iterates IOB18 sites on both
# sides of the chip, but kintex7's R-only Makefile only used the R-side
# files. Virtex-7 xc7vx485tffg1761-2 has IOB18 banks on both sides, so
# include segdata_liob18.txt too. IOB18 architecture is symmetric so
# segmatch will derive consistent bit positions across L and R samples.
${XRAY_SEGMATCH} -c 23 -o build/segbits_riob18.rdb $$(find -name 'segdata_[rl]iob18.txt')
build/segbits_riob18.db: build/segbits_riob18.rdb process_rdb.py bits.dbf
# delete the Y1 LVDS tags because they are empty anyway and are missing the DRIVE tag which upsets process_rdb.py
@ -24,9 +29,14 @@ build/segbits_riob18.db: build/segbits_riob18.rdb process_rdb.py bits.dbf
python3 process_rdb.py build/segbits_riob18.rdb > build/segbits_riob18_processed.rdb
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --groups tag_groups.txt --seg-fn-in build/segbits_riob18_processed.rdb --seg-fn-out $@
# TODO: This is a hack. See https://github.com/f4pga/prjxray/issues/2073
echo 'RIOB18.IOB_Y0.SSTL12_SSTL135_SSTL15.IN !38_126 39_127' >> $@
# Use the prefix-less form 'IOB18.' so mergedb.sh's per-side sed (which
# rewrites '^IOB18\.' to either 'RIOB18.' or 'LIOB18.') applies to this
# manual entry as well. The previous hard-coded 'RIOB18.' would land
# verbatim in segbits_liob18.db and bit2fasm would KeyError on the
# missing 'LIOB18.IOB_Y0.SSTL12_SSTL135_SSTL15.IN'.
echo 'IOB18.IOB_Y0.SSTL12_SSTL135_SSTL15.IN !38_126 39_127' >> $@
sort -o $@ $@
${XRAY_MASKMERGE} build/mask_riob18.db $$(find -name segdata_riob18.txt)
${XRAY_MASKMERGE} build/mask_riob18.db $$(find -name 'segdata_[rl]iob18.txt')
build/segbits_hclk_ioi.rdb: $(SPECIMENS_OK)
${XRAY_SEGMATCH} -c 10 -o build/segbits_hclk_ioi.rdb $$(find -name segdata_hclk_ioi.txt)
@ -37,6 +47,11 @@ build/segbits_hclk_ioi.db: build/segbits_hclk_ioi.rdb
pushdb:
${XRAY_MERGEDB} riob18 build/segbits_riob18.db
${XRAY_MERGEDB} mask_riob18 build/mask_riob18.db
# Mirror to L-side for parts with HP-bank IOB18 on both sides
# (virtex7 xc7vx485tffg1761-2). The same .db content is correct for
# LIOB18 because IOB18 tile architecture is symmetric.
${XRAY_MERGEDB} liob18 build/segbits_riob18.db
${XRAY_MERGEDB} mask_liob18 build/mask_riob18.db
${XRAY_MERGEDB} hclk_ioi build/segbits_hclk_ioi.db

View File

@ -7,28 +7,10 @@
# SPDX-License-Identifier: ISC
source "$::env(XRAY_DIR)/utils/utils.tcl"
proc write_pip_txtdata {filename} {
puts "FUZ([pwd]): Writing $filename."
set fp [open $filename w]
set nets [get_nets -hierarchical]
set nnets [llength $nets]
set neti 0
foreach net $nets {
incr neti
if {($neti % 100) == 0 } {
puts "FUZ([pwd]): Dumping pips from net $net ($neti / $nnets)"
}
foreach pip [get_pips -of_objects $net] {
set tile [get_tiles -of_objects $pip]
set src_wire [get_wires -uphill -of_objects $pip]
set dst_wire [get_wires -downhill -of_objects $pip]
set num_pips [llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst_wire]]]
set dir_prop [get_property IS_DIRECTIONAL $pip]
puts $fp "$tile $pip $src_wire $dst_wire $num_pips $dir_prop"
}
}
close $fp
}
# Local write_pip_txtdata override removed utils.tcl (sourced above)
# has been patched with a bulk-fetch version that is ~4x faster on
# xc7vx485tffg1761-2. Keeping this shadow would re-introduce hours of
# per-net Tcl overhead.
proc write_used_wires {filename} {
puts "FUZ([pwd]): Writing $filename."

View File

@ -7,28 +7,10 @@
# SPDX-License-Identifier: ISC
source "$::env(XRAY_DIR)/utils/utils.tcl"
proc write_pip_txtdata {filename} {
puts "FUZ([pwd]): Writing $filename."
set fp [open $filename w]
set nets [get_nets -hierarchical]
set nnets [llength $nets]
set neti 0
foreach net $nets {
incr neti
if {($neti % 100) == 0 } {
puts "FUZ([pwd]): Dumping pips from net $net ($neti / $nnets)"
}
foreach pip [get_pips -of_objects $net] {
set tile [get_tiles -of_objects $pip]
set src_wire [get_wires -uphill -of_objects $pip]
set dst_wire [get_wires -downhill -of_objects $pip]
set num_pips [llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst_wire]]]
set dir_prop [get_property IS_DIRECTIONAL $pip]
puts $fp "$tile $pip $src_wire $dst_wire $num_pips $dir_prop"
}
}
close $fp
}
# Local write_pip_txtdata override removed utils.tcl (sourced above)
# has been patched with a bulk-fetch version that is ~4x faster on
# xc7vx485tffg1761-2. Keeping this shadow would re-introduce hours of
# per-net Tcl overhead.
proc write_used_wires {filename} {
puts "FUZ([pwd]): Writing $filename."

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -10,9 +10,13 @@ PIP_TYPE?=ioi
PIPLIST_TCL=$(FUZDIR)/ioi_pip_list.tcl
TODO_RE=".*"
EXCLUDE_RE=".*((PHASER)|(CLKDIVF)|(CLKDIVP)|(CLKDIVB)|(IOI_ILOGIC[01]_O)|(IOI_OLOGIC[01]_CLKB?\.)|(IOI_IMUX_RC)|(IOI_OLOGIC[01]_[OT]FB)|(OCLKM.*IMUX31)|IOI_ODELAY[01]_CLKIN.IOI_OCLK_[01]|RIOI_O[01].RIOI_ODELAY[01]_DATAOUT|RIOI_O[01].RIOI_OLOGIC[01]_OQ).*"
# Per-side exclusions cover the R-side patterns from upstream kintex7 plus the
# mirrored L-side patterns needed when the part has HP-bank IOB18 on both sides
# (e.g. virtex7 xc7vx485tffg1761-2). The L-side rules are exact mirrors with
# the RIOI_ prefix replaced by LIOI_.
EXCLUDE_RE=".*((PHASER)|(CLKDIVF)|(CLKDIVP)|(CLKDIVB)|(IOI_ILOGIC[01]_O)|(IOI_OLOGIC[01]_CLKB?\.)|(IOI_IMUX_RC)|(IOI_OLOGIC[01]_[OT]FB)|(OCLKM.*IMUX31)|IOI_ODELAY[01]_CLKIN.IOI_OCLK_[01]|RIOI_O[01].RIOI_ODELAY[01]_DATAOUT|RIOI_O[01].RIOI_OLOGIC[01]_OQ|LIOI_O[01].LIOI_ODELAY[01]_DATAOUT|LIOI_O[01].LIOI_OLOGIC[01]_OQ).*"
MAKETODO_FLAGS=--pip-type ${PIP_TYPE} --seg-type $(PIP_TYPE) --re $(TODO_RE) --sides "xr" --exclude-re $(EXCLUDE_RE)
MAKETODO_FLAGS=--pip-type ${PIP_TYPE} --seg-type $(PIP_TYPE) --re $(TODO_RE) --sides "xl,xr" --exclude-re $(EXCLUDE_RE)
# N=120 is excessive on a large device like xc7vx485t; 20 (matches other pip
# fuzzers) is plenty for segmatch convergence and roughly 6x faster per iter.
N = 20
@ -24,12 +28,15 @@ include ../pip_loop.mk
SIX_BIT_PIPS="OLOGIC[01]_CLKDIV"
build/segbits_ioi_x.rdb: $(SPECIMENS_OK)
# Most pips are 3 bits, force a 3 bit solution
# Most pips are 3 bits, force a 3 bit solution.
# Match segdata for BOTH lioi*.txt and rioi*.txt so left- and right-side
# pip bits feed segmatch in a single pass (the per-side data is solved
# against side-specific pip names that live in the same tile architecture).
${XRAY_SEGMATCH} -c 3 -m 20 -M 50 -o build/segbits_ioi_x_match_3.rdb \
$(shell find build -name segdata_rioi*.txt)
$(shell find build -name 'segdata_[rl]ioi*.txt')
# Some are 6 bit solutions, solve for 6 bits and merge respectively
${XRAY_SEGMATCH} -c 6 -m 20 -M 50 -o build/segbits_ioi_x_match_6.rdb \
$(shell find build -name segdata_rioi*.txt)
$(shell find build -name 'segdata_[rl]ioi*.txt')
grep -v ${SIX_BIT_PIPS} build/segbits_ioi_x_match_3.rdb > build/segbits_ioi_x.rdb
grep ${SIX_BIT_PIPS} build/segbits_ioi_x_match_6.rdb >> build/segbits_ioi_x.rdb
@ -47,6 +54,7 @@ database: ${RDBS}
# Clobber existing .db to eliminate potential conflicts
cp ${XRAY_DATABASE_DIR}/${XRAY_DATABASE}/segbits*.db build/database/${XRAY_DATABASE}
XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} rioi build/segbits_ioi_x.db
XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} lioi build/segbits_ioi_x.db
build/cmt_regions.csv: output_cmt.tcl
mkdir -p build
@ -56,5 +64,11 @@ pushdb: database
${XRAY_MERGEDB} rioi build/segbits_ioi_x.db
${XRAY_MERGEDB} rioi_tbytesrc build/segbits_ioi_x.db
${XRAY_MERGEDB} rioi_tbyteterm build/segbits_ioi_x.db
# L-side counterparts for parts with HP-bank IOB18 on both sides
# (e.g. virtex7 xc7vx485tffg1761-2). Harmless on R-side-only parts:
# segbits_lioi*.db just ends up empty or unchanged.
${XRAY_MERGEDB} lioi build/segbits_ioi_x.db
${XRAY_MERGEDB} lioi_tbytesrc build/segbits_ioi_x.db
${XRAY_MERGEDB} lioi_tbyteterm build/segbits_ioi_x.db
.PHONY: database pushdb

View File

@ -72,8 +72,12 @@ def main():
for tile, pips_srcs_dsts in tiledata.items():
tile_type = pips_srcs_dsts["type"]
# Normalise per-instance tile types (e.g. RIOI_TBYTESRC, LIOI_SING) to
# the base type used as pipdata key by ioi_pip_list.tcl.
if tile_type.startswith('RIOI'):
tile_type = 'RIOI'
elif tile_type.startswith('LIOI'):
tile_type = 'LIOI'
for src, dst in pipdata[tile_type]:
if (src, dst) in ignpip:

View File

@ -45,3 +45,7 @@ set_property design_mode PinPlanning [current_fileset]
open_io_design -name io_1
print_tile_pips RIOI rioi.txt
# virtex7 (and any HP-on-both-sides part) also has LIOI; the kintex7 reference
# design only has RIOI so this line is harmless there (get_tiles returns
# empty and an empty lioi.txt is written, which int_maketodo handles).
print_tile_pips LIOI lioi.txt

View File

@ -17,7 +17,7 @@ from prjxray import verilog
from prjxray import lut_maker
from prjxray.db import Database
NOT_INCLUDED_TILES = ['RIOI_SING']
NOT_INCLUDED_TILES = ['RIOI_SING', 'LIOI_SING']
SITE_TYPES = ['OLOGICE2', 'ILOGICE2']

View File

@ -0,0 +1,17 @@
# 038-cfg skipped on virtex7
Marked as 'done' by touching `run.ok` to skip on this family.
**Reason**: the underlying 005-tilegrid/cfg fuzzer fails to derive bits info
for `CFG_CENTER_MID_X157Y84` on `xc7vx485tffg1761-2` (Vivado 2020.1). The
two specimens (JTAG_CHAIN=1 vs JTAG_CHAIN=2) produce **bit-identical** frame
data — only the .bit header differs. Segmatch emits `<0 candidates>` and
add_tdb.py writes `bits: {}`, so 038-cfg's generate.py asserts on zero
segments.
This BSCANE2-based fuzzer needs a richer top module on virtex7 to make the
JTAG_CHAIN parameter encoding land in differential config bits. Tracked as
task #17 in the porting effort.
**Counter smoke-test impact**: none — counter.fasm has zero CFG_CENTER
features.

View File

@ -9,7 +9,26 @@ N ?= 50
include ../fuzzer.mk
ifneq (,$(filter $(XRAY_DATABASE),kintex7 virtex7))
ifeq ($(XRAY_DATABASE),virtex7)
# virtex7 xc7vx485tffg1761-2 is HP-only: top.py targets HCLK_IOI sites and
# the segmaker writes 'segdata_hclk_ioi.txt' (tile type HCLK_IOI). On
# kintex7 the BUFR fuzzer historically only exercised HR sites
# (HCLK_IOI3 → segdata_hclk_ioi3.txt) and HP results were sed-derived; that
# direction is inverted for HP-only parts.
database: build/segbits_hclk_ioi.db
build/segbits_hclk_ioi.rdb: $(SPECIMENS_OK)
${XRAY_SEGMATCH} -c 5 -o build/segbits_hclk_ioi.rdb \
$(addsuffix /segdata_hclk_ioi.txt,$(SPECIMENS))
build/segbits_hclk_ioi.db: build/segbits_hclk_ioi.rdb
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf \
--seg-fn-in build/segbits_hclk_ioi.rdb \
--seg-fn-out build/segbits_hclk_ioi.db
${XRAY_MASKMERGE} build/mask_hclk_ioi.db \
$(addsuffix /segdata_hclk_ioi.txt,$(SPECIMENS))
else
ifeq ($(XRAY_DATABASE),kintex7)
database: build/segbits_hclk_ioi.db
else
database: build/segbits_hclk_ioi3.db
@ -26,17 +45,22 @@ build/segbits_hclk_ioi3.db: build/segbits_hclk_ioi3.rdb
${XRAY_MASKMERGE} build/mask_hclk_ioi3.db \
$(addsuffix /segdata_hclk_ioi3.txt,$(SPECIMENS))
# The fuzzer results for the high performance banks
# are identical, so just copy those
ifneq (,$(filter $(XRAY_DATABASE),kintex7 virtex7))
# The fuzzer results for the high performance banks on kintex7
# are identical to HR; just sed-rename the HR-derived data.
ifeq ($(XRAY_DATABASE),kintex7)
build/segbits_hclk_ioi.db: build/segbits_hclk_ioi3.db
sed -e 's/HCLK_IOI3/HCLK_IOI/g' $< > $@
cp build/mask_hclk_ioi3.db build/mask_hclk_ioi.db
endif
endif
pushdb: database
# On HP-only parts (virtex7 xc7vx485tffg1761-2) there is no HCLK_IOI3
# segdata, so skip the hclk_ioi3 merge to avoid a missing-file error.
ifneq ($(XRAY_DATABASE),virtex7)
${XRAY_MERGEDB} hclk_ioi3 build/segbits_hclk_ioi3.db
${XRAY_MERGEDB} mask_hclk_ioi3 build/mask_hclk_ioi3.db
endif
ifneq (,$(filter $(XRAY_DATABASE),kintex7 virtex7))
${XRAY_MERGEDB} hclk_ioi build/segbits_hclk_ioi.db
${XRAY_MERGEDB} mask_hclk_ioi build/mask_hclk_ioi.db

View File

@ -16,6 +16,11 @@ from prjxray.db import Database
from prjxray import util
from prjxray.lut_maker import LutMaker
# Use the IOSTANDARD set by the part's settings script
# (LVCMOS33 on HR banks, LVCMOS18 on HP banks). Falls back to LVCMOS33
# to preserve the historical kintex7 behaviour when the env var is unset.
IOSTANDARD = os.getenv('XRAY_IOSTANDARD', 'LVCMOS33')
def gen_sites():
xy_fun = util.create_xy_fun('BUFR_')
@ -39,9 +44,11 @@ def gen_sites():
if not sites:
continue
# variable still named 'ioi3' but the check below accepts either
# IOI3 (HR-bank, kintex7) or IOI (HP-bank, virtex7 xc7vx485tffg1761-2).
ioi3 = grid.gridinfo_at_loc((loc.grid_x, loc.grid_y - 1))
if 'IOI3' not in ioi3.tile_type:
if 'IOI3' not in ioi3.tile_type and 'IOI' not in ioi3.tile_type:
continue
if ioi3.tile_type.startswith('R'):
@ -56,7 +63,8 @@ def gen_sites():
iob = grid.gridinfo_at_loc((loc.grid_x + dx, loc.grid_y + dy))
for site, site_type in iob.sites.items():
if site_type == 'IOB33M':
# IOB33M = HR-bank (kintex7); IOB18M = HP-bank (virtex7).
if site_type in ('IOB33M', 'IOB18M'):
iobs.append(site)
yield tile_name, min(xs), min(ys), sorted(sites), sorted(iobs)
@ -81,7 +89,7 @@ def main():
(* KEEP, DONT_TOUCH, LOC="{site}" *)
IBUF #(
.IOSTANDARD("LVCMOS33")
.IOSTANDARD("{iostandard}")
) ibuf_{site} (
.I(clks[{idx}]),
.O({ioclk})
@ -89,6 +97,7 @@ def main():
ioclk=ioclk,
site=iob,
idx=idx,
iostandard=IOSTANDARD,
))
for site, x, y in sites:

View File

@ -7,28 +7,10 @@
# SPDX-License-Identifier: ISC
source "$::env(XRAY_DIR)/utils/utils.tcl"
proc write_pip_txtdata {filename} {
puts "FUZ([pwd]): Writing $filename."
set fp [open $filename w]
set nets [get_nets -hierarchical]
set nnets [llength $nets]
set neti 0
foreach net $nets {
incr neti
if {($neti % 100) == 0 } {
puts "FUZ([pwd]): Dumping pips from net $net ($neti / $nnets)"
}
foreach pip [get_pips -of_objects $net] {
set tile [get_tiles -of_objects $pip]
set src_wire [get_wires -uphill -of_objects $pip]
set dst_wire [get_wires -downhill -of_objects $pip]
set num_pips [llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst_wire]]]
set dir_prop [get_property IS_DIRECTIONAL $pip]
puts $fp "$tile $pip $src_wire $dst_wire $num_pips $dir_prop"
}
}
close $fp
}
# Local write_pip_txtdata override removed the utils.tcl version sourced on
# line 8 has been patched with bulk-fetch + dst-wire cache that's ~4x faster
# on large devices like xc7vx485tffg1761-2. Keeping the duplicate here would
# shadow that and re-introduce the slow per-net per-pip Tcl query path.
proc load_todo {} {
set fp [open "../../todo_all.txt" r]
@ -61,7 +43,9 @@ proc route_todo {} {
set is_gclk_net 0
foreach wire $wires {
puts "Check wire $wire in $net"
# 'puts "Check wire $wire in $net"' removed on xc7vx485tffg1761-2
# this loop runs ~100k times per specimen and the per-line stdout
# flush dominates wall time without producing useful information.
if [string match "*CLK_HROW_CK_IN_*" $wire] {
set gclk_tile [lindex [split $wire /] 0]
set gclk_wire [lindex [split $wire /] 1]
@ -75,10 +59,10 @@ proc route_todo {} {
continue
}
puts "Net $net wires:"
foreach wire [get_wires -of_objects $net] {
puts " - $wire"
}
# The "Net $net wires:" / " - $wire" debug dump that used to live here
# iterated every wire of every interesting net and was pure stdout
# noise; on xc7vx485tffg1761-2 that's another 5-10k puts per spec
# with no information used downstream. Removed.
foreach wire $wires {
set tile [lindex [split $wire /] 0]

View File

@ -7,28 +7,10 @@
# SPDX-License-Identifier: ISC
source "$::env(XRAY_DIR)/utils/utils.tcl"
proc write_pip_txtdata {filename} {
puts "FUZ([pwd]): Writing $filename."
set fp [open $filename w]
set nets [get_nets -hierarchical]
set nnets [llength $nets]
set neti 0
foreach net $nets {
incr neti
if {($neti % 100) == 0 } {
puts "FUZ([pwd]): Dumping pips from net $net ($neti / $nnets)"
}
foreach pip [get_pips -of_objects $net] {
set tile [get_tiles -of_objects $pip]
set src_wire [get_wires -uphill -of_objects $pip]
set dst_wire [get_wires -downhill -of_objects $pip]
set num_pips [llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst_wire]]]
set dir_prop [get_property IS_DIRECTIONAL $pip]
puts $fp "$tile $pip $src_wire $dst_wire $num_pips $dir_prop"
}
}
close $fp
}
# Local write_pip_txtdata override removed utils.tcl (sourced above)
# has been patched with a bulk-fetch version that is ~4x faster on
# xc7vx485tffg1761-2. Keeping this shadow would re-introduce hours of
# per-net Tcl overhead.
proc write_route_data {filename} {
set fp [open $filename w]

View File

@ -7,28 +7,10 @@
# SPDX-License-Identifier: ISC
source "$::env(XRAY_DIR)/utils/utils.tcl"
proc write_pip_txtdata {filename} {
puts "FUZ([pwd]): Writing $filename."
set fp [open $filename w]
set nets [get_nets -hierarchical]
set nnets [llength $nets]
set neti 0
foreach net $nets {
incr neti
if {($neti % 100) == 0 } {
puts "FUZ([pwd]): Dumping pips from net $net ($neti / $nnets)"
}
foreach pip [get_pips -of_objects $net] {
set tile [get_tiles -of_objects $pip]
set src_wire [get_wires -uphill -of_objects $pip]
set dst_wire [get_wires -downhill -of_objects $pip]
set num_pips [llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst_wire]]]
set dir_prop [get_property IS_DIRECTIONAL $pip]
puts $fp "$tile $pip $src_wire $dst_wire $num_pips $dir_prop"
}
}
close $fp
}
# Local write_pip_txtdata override removed utils.tcl (sourced above)
# has been patched with a bulk-fetch version that is ~4x faster on
# xc7vx485tffg1761-2. Keeping this shadow would re-introduce hours of
# per-net Tcl overhead.
proc run {} {
create_project -force -part $::env(XRAY_PART) design design

View File

@ -7,28 +7,11 @@
# SPDX-License-Identifier: ISC
source "$::env(XRAY_DIR)/utils/utils.tcl"
proc write_pip_txtdata {filename} {
puts "FUZ([pwd]): Writing $filename."
set fp [open $filename w]
set nets [get_nets -hierarchical]
set nnets [llength $nets]
set neti 0
foreach net $nets {
incr neti
if {($neti % 100) == 0 } {
puts "FUZ([pwd]): Dumping pips from net $net ($neti / $nnets)"
}
foreach pip [get_pips -of_objects $net] {
set tile [get_tiles -of_objects $pip]
set src_wire [get_wires -uphill -of_objects $pip]
set dst_wire [get_wires -downhill -of_objects $pip]
set num_pips [llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst_wire]]]
set dir_prop [get_property IS_DIRECTIONAL $pip]
puts $fp "$tile $pip $src_wire $dst_wire $num_pips $dir_prop"
}
}
close $fp
}
# Local write_pip_txtdata override removed the utils.tcl version sourced on
# line 8 has been patched with bulk-fetch + dst-wire cache that is ~4x faster
# on xc7vx485tffg1761-2 (which has ~17M pips per specimen). Keeping the
# duplicate here would shadow that and re-introduce hours of per-net Tcl
# overhead.
proc load_todo {} {
set fp [open "../../todo_all.txt" r]

View File

@ -7,28 +7,10 @@
# SPDX-License-Identifier: ISC
source "$::env(XRAY_DIR)/utils/utils.tcl"
proc write_pip_txtdata {filename} {
puts "FUZ([pwd]): Writing $filename."
set fp [open $filename w]
set nets [get_nets -hierarchical]
set nnets [llength $nets]
set neti 0
foreach net $nets {
incr neti
if {($neti % 100) == 0 } {
puts "FUZ([pwd]): Dumping pips from net $net ($neti / $nnets)"
}
foreach pip [get_pips -of_objects $net] {
set tile [get_tiles -of_objects $pip]
set src_wire [get_wires -uphill -of_objects $pip]
set dst_wire [get_wires -downhill -of_objects $pip]
set num_pips [llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst_wire]]]
set dir_prop [get_property IS_DIRECTIONAL $pip]
puts $fp "$tile $pip $src_wire $dst_wire $num_pips $dir_prop"
}
}
close $fp
}
# Local write_pip_txtdata override removed utils.tcl (sourced above)
# has been patched with a bulk-fetch version that is ~4x faster on
# xc7vx485tffg1761-2. Keeping this shadow would re-introduce hours of
# per-net Tcl overhead.
proc run {} {
create_project -force -part $::env(XRAY_PART) design design

View File

@ -126,7 +126,8 @@ def main():
(serdes_loc_x, serdes_loc_y) = grid.loc_of_tilename(tile)
serdes_clk_reg = site_to_cmt[site]
for tile_name in sorted(grid.tiles()):
if 'HCLK_IOI3' in tile_name:
# Accept HCLK_IOI3 (HR-bank kintex7) and HCLK_IOI (HP-bank virtex7).
if 'HCLK_IOI3' in tile_name or 'HCLK_IOI' in tile_name:
(hclk_tile_loc_x,
hclk_tile_loc_y) = grid.loc_of_tilename(tile_name)
if hclk_tile_loc_x == serdes_loc_x:

View File

@ -0,0 +1,308 @@
LIOI_TBYTESRC_X82Y357/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y357/RIOI_I2GCLK_TOP1
LIOI_X82Y359/LIOI_I2GCLK_BOT1
CMT_TOP_R_UPPER_B_X88Y343/CMT_PHASER_UP_DQS_TO_PHASER_D
LIOI_X82Y355/LIOI_I2GCLK_TOP1
RIOI_X311Y359/RIOI_I2GCLK_BOT1
CMT_TOP_L_UPPER_B_X305Y343/CMT_PHASER_UP_DQS_TO_PHASER_D
RIOI_X311Y355/RIOI_I2GCLK_TOP1
LIOI_TBYTESRC_X82Y357/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y357/RIOI_I2GCLK_BOT1
LIOI_TBYTETERM_X82Y351/LIOI_I2GCLK_TOP1
RIOI_TBYTETERM_X311Y351/RIOI_I2GCLK_TOP1
LIOI_TBYTETERM_X82Y351/LIOI_I2GCLK_BOT1
RIOI_TBYTETERM_X311Y351/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y345/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y345/RIOI_I2GCLK_TOP1
LIOI_X82Y347/LIOI_I2GCLK_BOT1
LIOI_X82Y343/LIOI_I2GCLK_TOP1
RIOI_X311Y347/RIOI_I2GCLK_BOT1
RIOI_X311Y343/RIOI_I2GCLK_TOP1
LIOI_TBYTESRC_X82Y345/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y345/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y332/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y332/RIOI_I2GCLK_TOP1
LIOI_X82Y330/LIOI_I2GCLK_TOP1
LIOI_X82Y334/LIOI_I2GCLK_BOT1
RIOI_X311Y334/RIOI_I2GCLK_BOT1
RIOI_X311Y330/RIOI_I2GCLK_TOP1
LIOI_TBYTESRC_X82Y332/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y332/RIOI_I2GCLK_BOT1
LIOI_TBYTETERM_X82Y326/LIOI_I2GCLK_TOP1
RIOI_TBYTETERM_X311Y326/RIOI_I2GCLK_TOP1
LIOI_TBYTETERM_X82Y326/LIOI_I2GCLK_BOT1
RIOI_TBYTETERM_X311Y326/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y320/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y320/RIOI_I2GCLK_TOP1
LIOI_X82Y322/LIOI_I2GCLK_BOT1
LIOI_X82Y318/LIOI_I2GCLK_TOP1
CMT_TOP_R_LOWER_T_X88Y330/CMT_PHASER_DOWN_DQS_TO_PHASER_A
CMT_TOP_L_LOWER_T_X305Y330/CMT_PHASER_DOWN_DQS_TO_PHASER_A
RIOI_X311Y322/RIOI_I2GCLK_BOT1
RIOI_X311Y318/RIOI_I2GCLK_TOP1
LIOI_TBYTESRC_X82Y320/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y320/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y305/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y305/RIOI_I2GCLK_TOP1
CMT_TOP_R_UPPER_B_X88Y291/CMT_PHASER_UP_DQS_TO_PHASER_D
LIOI_X82Y303/LIOI_I2GCLK_TOP1
LIOI_X82Y307/LIOI_I2GCLK_BOT1
RIOI_X311Y303/RIOI_I2GCLK_TOP1
CMT_TOP_L_UPPER_B_X305Y291/CMT_PHASER_UP_DQS_TO_PHASER_D
RIOI_X311Y307/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y305/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y305/RIOI_I2GCLK_BOT1
LIOI_TBYTETERM_X82Y299/LIOI_I2GCLK_TOP1
RIOI_TBYTETERM_X311Y299/RIOI_I2GCLK_TOP1
LIOI_TBYTETERM_X82Y299/LIOI_I2GCLK_BOT1
RIOI_TBYTETERM_X311Y299/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y293/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y293/RIOI_I2GCLK_TOP1
LIOI_X82Y295/LIOI_I2GCLK_BOT1
LIOI_X82Y291/LIOI_I2GCLK_TOP1
RIOI_X311Y295/RIOI_I2GCLK_BOT1
RIOI_X311Y291/RIOI_I2GCLK_TOP1
LIOI_TBYTESRC_X82Y293/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y293/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y280/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y280/RIOI_I2GCLK_TOP1
LIOI_X82Y282/LIOI_I2GCLK_BOT1
LIOI_X82Y278/LIOI_I2GCLK_TOP1
RIOI_X311Y278/RIOI_I2GCLK_TOP1
RIOI_X311Y282/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y280/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y280/RIOI_I2GCLK_BOT1
LIOI_TBYTETERM_X82Y274/LIOI_I2GCLK_TOP1
RIOI_TBYTETERM_X311Y274/RIOI_I2GCLK_TOP1
LIOI_TBYTETERM_X82Y274/LIOI_I2GCLK_BOT1
RIOI_TBYTETERM_X311Y274/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y268/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y268/RIOI_I2GCLK_TOP1
CMT_TOP_R_LOWER_T_X88Y278/CMT_PHASER_DOWN_DQS_TO_PHASER_A
LIOI_X82Y270/LIOI_I2GCLK_BOT1
LIOI_X82Y266/LIOI_I2GCLK_TOP1
RIOI_X311Y270/RIOI_I2GCLK_BOT1
CMT_TOP_L_LOWER_T_X305Y278/CMT_PHASER_DOWN_DQS_TO_PHASER_A
RIOI_X311Y266/RIOI_I2GCLK_TOP1
LIOI_TBYTESRC_X82Y268/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y268/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y253/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y253/RIOI_I2GCLK_TOP1
LIOI_X82Y251/LIOI_I2GCLK_TOP1
LIOI_X82Y255/LIOI_I2GCLK_BOT1
CMT_TOP_R_UPPER_B_X88Y239/CMT_PHASER_UP_DQS_TO_PHASER_D
CMT_TOP_L_UPPER_B_X305Y239/CMT_PHASER_UP_DQS_TO_PHASER_D
RIOI_X311Y251/RIOI_I2GCLK_TOP1
RIOI_X311Y255/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y253/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y253/RIOI_I2GCLK_BOT1
LIOI_TBYTETERM_X82Y247/LIOI_I2GCLK_TOP1
RIOI_TBYTETERM_X311Y247/RIOI_I2GCLK_TOP1
LIOI_TBYTETERM_X82Y247/LIOI_I2GCLK_BOT1
RIOI_TBYTETERM_X311Y247/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y241/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y241/RIOI_I2GCLK_TOP1
LIOI_X82Y243/LIOI_I2GCLK_BOT1
LIOI_X82Y239/LIOI_I2GCLK_TOP1
RIOI_X311Y243/RIOI_I2GCLK_BOT1
RIOI_X311Y239/RIOI_I2GCLK_TOP1
LIOI_TBYTESRC_X82Y241/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y241/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y228/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y228/RIOI_I2GCLK_TOP1
LIOI_X82Y226/LIOI_I2GCLK_TOP1
LIOI_X82Y230/LIOI_I2GCLK_BOT1
RIOI_X311Y226/RIOI_I2GCLK_TOP1
RIOI_X311Y230/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y228/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y228/RIOI_I2GCLK_BOT1
LIOI_TBYTETERM_X82Y222/LIOI_I2GCLK_TOP1
RIOI_TBYTETERM_X311Y222/RIOI_I2GCLK_TOP1
LIOI_TBYTETERM_X82Y222/LIOI_I2GCLK_BOT1
RIOI_TBYTETERM_X311Y222/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y216/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y216/RIOI_I2GCLK_TOP1
CMT_TOP_R_LOWER_T_X88Y226/CMT_PHASER_DOWN_DQS_TO_PHASER_A
LIOI_X82Y214/LIOI_I2GCLK_TOP1
LIOI_X82Y218/LIOI_I2GCLK_BOT1
RIOI_X311Y214/RIOI_I2GCLK_TOP1
RIOI_X311Y218/RIOI_I2GCLK_BOT1
CMT_TOP_L_LOWER_T_X305Y226/CMT_PHASER_DOWN_DQS_TO_PHASER_A
LIOI_TBYTESRC_X82Y216/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y216/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y201/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y201/RIOI_I2GCLK_TOP1
LIOI_X82Y199/LIOI_I2GCLK_TOP1
CMT_TOP_R_UPPER_B_X88Y187/CMT_PHASER_UP_DQS_TO_PHASER_D
LIOI_X82Y203/LIOI_I2GCLK_BOT1
RIOI_X311Y203/RIOI_I2GCLK_BOT1
CMT_TOP_L_UPPER_B_X305Y187/CMT_PHASER_UP_DQS_TO_PHASER_D
RIOI_X311Y199/RIOI_I2GCLK_TOP1
LIOI_TBYTESRC_X82Y201/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y201/RIOI_I2GCLK_BOT1
LIOI_TBYTETERM_X82Y195/LIOI_I2GCLK_TOP1
RIOI_TBYTETERM_X311Y195/RIOI_I2GCLK_TOP1
LIOI_TBYTETERM_X82Y195/LIOI_I2GCLK_BOT1
RIOI_TBYTETERM_X311Y195/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y189/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y189/RIOI_I2GCLK_TOP1
LIOI_X82Y191/LIOI_I2GCLK_BOT1
LIOI_X82Y187/LIOI_I2GCLK_TOP1
RIOI_X311Y191/RIOI_I2GCLK_BOT1
RIOI_X311Y187/RIOI_I2GCLK_TOP1
LIOI_TBYTESRC_X82Y189/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y189/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y176/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y176/RIOI_I2GCLK_TOP1
LIOI_X82Y178/LIOI_I2GCLK_BOT1
LIOI_X82Y174/LIOI_I2GCLK_TOP1
RIOI_X311Y174/RIOI_I2GCLK_TOP1
RIOI_X311Y178/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y176/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y176/RIOI_I2GCLK_BOT1
LIOI_TBYTETERM_X82Y170/LIOI_I2GCLK_TOP1
RIOI_TBYTETERM_X311Y170/RIOI_I2GCLK_TOP1
LIOI_TBYTETERM_X82Y170/LIOI_I2GCLK_BOT1
RIOI_TBYTETERM_X311Y170/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y164/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y164/RIOI_I2GCLK_TOP1
CMT_TOP_R_LOWER_T_X88Y174/CMT_PHASER_DOWN_DQS_TO_PHASER_A
LIOI_X82Y162/LIOI_I2GCLK_TOP1
LIOI_X82Y166/LIOI_I2GCLK_BOT1
RIOI_X311Y162/RIOI_I2GCLK_TOP1
RIOI_X311Y166/RIOI_I2GCLK_BOT1
CMT_TOP_L_LOWER_T_X305Y174/CMT_PHASER_DOWN_DQS_TO_PHASER_A
LIOI_TBYTESRC_X82Y164/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y164/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y149/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y149/RIOI_I2GCLK_TOP1
CMT_TOP_R_UPPER_B_X88Y135/CMT_PHASER_UP_DQS_TO_PHASER_D
LIOI_X82Y147/LIOI_I2GCLK_TOP1
LIOI_X82Y151/LIOI_I2GCLK_BOT1
CMT_TOP_L_UPPER_B_X305Y135/CMT_PHASER_UP_DQS_TO_PHASER_D
RIOI_X311Y147/RIOI_I2GCLK_TOP1
RIOI_X311Y151/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y149/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y149/RIOI_I2GCLK_BOT1
LIOI_TBYTETERM_X82Y143/LIOI_I2GCLK_TOP1
RIOI_TBYTETERM_X311Y143/RIOI_I2GCLK_TOP1
LIOI_TBYTETERM_X82Y143/LIOI_I2GCLK_BOT1
RIOI_TBYTETERM_X311Y143/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y137/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y137/RIOI_I2GCLK_TOP1
LIOI_X82Y135/LIOI_I2GCLK_TOP1
LIOI_X82Y139/LIOI_I2GCLK_BOT1
RIOI_X311Y135/RIOI_I2GCLK_TOP1
RIOI_X311Y139/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y137/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y137/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y124/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y124/RIOI_I2GCLK_TOP1
LIOI_X82Y126/LIOI_I2GCLK_BOT1
LIOI_X82Y122/LIOI_I2GCLK_TOP1
RIOI_X311Y122/RIOI_I2GCLK_TOP1
RIOI_X311Y126/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y124/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y124/RIOI_I2GCLK_BOT1
LIOI_TBYTETERM_X82Y118/LIOI_I2GCLK_TOP1
RIOI_TBYTETERM_X311Y118/RIOI_I2GCLK_TOP1
LIOI_TBYTETERM_X82Y118/LIOI_I2GCLK_BOT1
RIOI_TBYTETERM_X311Y118/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y112/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y112/RIOI_I2GCLK_TOP1
LIOI_X82Y110/LIOI_I2GCLK_TOP1
LIOI_X82Y114/LIOI_I2GCLK_BOT1
CMT_TOP_R_LOWER_T_X88Y122/CMT_PHASER_DOWN_DQS_TO_PHASER_A
CMT_TOP_L_LOWER_T_X305Y122/CMT_PHASER_DOWN_DQS_TO_PHASER_A
RIOI_X311Y114/RIOI_I2GCLK_BOT1
RIOI_X311Y110/RIOI_I2GCLK_TOP1
LIOI_TBYTESRC_X82Y112/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y112/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y97/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y97/RIOI_I2GCLK_TOP1
LIOI_X82Y99/LIOI_I2GCLK_BOT1
CMT_TOP_R_UPPER_B_X88Y83/CMT_PHASER_UP_DQS_TO_PHASER_D
LIOI_X82Y95/LIOI_I2GCLK_TOP1
CMT_TOP_L_UPPER_B_X305Y83/CMT_PHASER_UP_DQS_TO_PHASER_D
RIOI_X311Y95/RIOI_I2GCLK_TOP1
RIOI_X311Y99/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y97/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y97/RIOI_I2GCLK_BOT1
LIOI_TBYTETERM_X82Y91/LIOI_I2GCLK_TOP1
RIOI_TBYTETERM_X311Y91/RIOI_I2GCLK_TOP1
LIOI_TBYTETERM_X82Y91/LIOI_I2GCLK_BOT1
RIOI_TBYTETERM_X311Y91/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y85/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y85/RIOI_I2GCLK_TOP1
LIOI_X82Y83/LIOI_I2GCLK_TOP1
LIOI_X82Y87/LIOI_I2GCLK_BOT1
RIOI_X311Y83/RIOI_I2GCLK_TOP1
RIOI_X311Y87/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y85/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y85/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y72/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y72/RIOI_I2GCLK_TOP1
LIOI_X82Y74/LIOI_I2GCLK_BOT1
LIOI_X82Y70/LIOI_I2GCLK_TOP1
RIOI_X311Y70/RIOI_I2GCLK_TOP1
RIOI_X311Y74/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y72/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y72/RIOI_I2GCLK_BOT1
LIOI_TBYTETERM_X82Y66/LIOI_I2GCLK_TOP1
RIOI_TBYTETERM_X311Y66/RIOI_I2GCLK_TOP1
LIOI_TBYTETERM_X82Y66/LIOI_I2GCLK_BOT1
RIOI_TBYTETERM_X311Y66/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y60/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y60/RIOI_I2GCLK_TOP1
CMT_TOP_R_LOWER_T_X88Y70/CMT_PHASER_DOWN_DQS_TO_PHASER_A
LIOI_X82Y58/LIOI_I2GCLK_TOP1
LIOI_X82Y62/LIOI_I2GCLK_BOT1
RIOI_X311Y62/RIOI_I2GCLK_BOT1
RIOI_X311Y58/RIOI_I2GCLK_TOP1
CMT_TOP_L_LOWER_T_X305Y70/CMT_PHASER_DOWN_DQS_TO_PHASER_A
LIOI_TBYTESRC_X82Y60/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y60/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y45/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y45/RIOI_I2GCLK_TOP1
CMT_TOP_R_UPPER_B_X88Y31/CMT_PHASER_UP_DQS_TO_PHASER_D
LIOI_X82Y43/LIOI_I2GCLK_TOP1
LIOI_X82Y47/LIOI_I2GCLK_BOT1
RIOI_X311Y43/RIOI_I2GCLK_TOP1
RIOI_X311Y47/RIOI_I2GCLK_BOT1
CMT_TOP_L_UPPER_B_X305Y31/CMT_PHASER_UP_DQS_TO_PHASER_D
LIOI_TBYTESRC_X82Y45/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y45/RIOI_I2GCLK_BOT1
LIOI_TBYTETERM_X82Y39/LIOI_I2GCLK_TOP1
RIOI_TBYTETERM_X311Y39/RIOI_I2GCLK_TOP1
LIOI_TBYTETERM_X82Y39/LIOI_I2GCLK_BOT1
RIOI_TBYTETERM_X311Y39/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y33/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y33/RIOI_I2GCLK_TOP1
LIOI_X82Y35/LIOI_I2GCLK_BOT1
LIOI_X82Y31/LIOI_I2GCLK_TOP1
RIOI_X311Y35/RIOI_I2GCLK_BOT1
RIOI_X311Y31/RIOI_I2GCLK_TOP1
LIOI_TBYTESRC_X82Y33/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y33/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y20/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y20/RIOI_I2GCLK_TOP1
LIOI_X82Y22/LIOI_I2GCLK_BOT1
LIOI_X82Y18/LIOI_I2GCLK_TOP1
RIOI_X311Y18/RIOI_I2GCLK_TOP1
RIOI_X311Y22/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y20/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y20/RIOI_I2GCLK_BOT1
LIOI_TBYTETERM_X82Y14/LIOI_I2GCLK_TOP1
RIOI_TBYTETERM_X311Y14/RIOI_I2GCLK_TOP1
LIOI_TBYTETERM_X82Y14/LIOI_I2GCLK_BOT1
RIOI_TBYTETERM_X311Y14/RIOI_I2GCLK_BOT1
LIOI_TBYTESRC_X82Y8/LIOI_I2GCLK_TOP1
RIOI_TBYTESRC_X311Y8/RIOI_I2GCLK_TOP1
LIOI_X82Y6/LIOI_I2GCLK_TOP1
LIOI_X82Y10/LIOI_I2GCLK_BOT1
CMT_TOP_R_LOWER_T_X88Y18/CMT_PHASER_DOWN_DQS_TO_PHASER_A
RIOI_X311Y10/RIOI_I2GCLK_BOT1
CMT_TOP_L_LOWER_T_X305Y18/CMT_PHASER_DOWN_DQS_TO_PHASER_A
RIOI_X311Y6/RIOI_I2GCLK_TOP1
LIOI_TBYTESRC_X82Y8/LIOI_I2GCLK_BOT1
RIOI_TBYTESRC_X311Y8/RIOI_I2GCLK_BOT1

View File

@ -141,18 +141,33 @@ def run(
with OpenSafeFile(os.path.join(db_root, part, "part.json"), "r") as fp:
part_data = json.load(fp)
# The IO-bank "anchor" tile prefix differs per family. kintex7/artix7
# use HR-bank IOLOGIC and therefore HCLK_IOI3. virtex7 HP-only parts
# (e.g. xc7vx485tffg1761-2) use HCLK_IOI. Probe the grid for whichever
# one actually exists; if neither, skip this bank-anchor altogether
# rather than queueing a KeyError for downstream lookups.
for bank, loc in part_data["iobanks"].items():
tile = "HCLK_IOI3_" + loc
bank_to_tile[bank].add(tile)
tile_to_bank[tile] = bank
for prefix in ("HCLK_IOI3_", "HCLK_IOI_"):
tile = prefix + loc
try:
db.grid().gridinfo_at_tilename(tile)
except KeyError:
continue
bank_to_tile[bank].add(tile)
tile_to_bank[tile] = bank
break
for pin in package_pins:
bank_to_tile[pin["bank"]].add(pin["tile"])
tile_to_bank[pin["tile"]] = pin["bank"]
# Resolve PUDC_B site unconditionally — we need the tile name later in the
# HP-bank glue walk to skip it (Vivado does not set IBUF_HP_BANK_GLUE on
# the PUDC_B tile even though our heuristic would).
pudc_b_tile_site = find_pudc_b(db) if part is not None else None
if emit_pudc_b_pullup:
pudc_b_in_use = False
pudc_b_tile_site = find_pudc_b(db)
def check_for_pudc_b(set_feature):
feature_callback(set_feature)
@ -191,19 +206,53 @@ def run(
if emit_pudc_b_pullup and not pudc_b_in_use and pudc_b_tile_site is not None:
# Enable IN-only and PULLUP on PUDC_B IOB.
#
# TODO: The following FASM string only works on Artix 50T and Zynq 10
# fabrics. It is known to be wrong for the K70T fabric, but it is
# unclear how to know which IOSTANDARD to use.
# The set of IOSTANDARD aliases differs per family because HR-bank
# (IOB33) silicon supports more standards than HP-bank (IOB18).
# Pick the right alias by sniffing the tile name; the chosen alias
# has to match a segbits entry exactly or fasm2frames will error.
missing_features = []
for line in fasm.parse_fasm_string("""
is_hp = pudc_b_tile_site[0].startswith('LIOB18') or \
pudc_b_tile_site[0].startswith('RIOB18')
if is_hp:
# HP-bank (virtex7 xc7vx485tffg1761-2) — Vivado emits this exact
# feature set on the PUDC_B IOB; the bits flow from segbits
# entries on LVCMOS12_LVCMOS15.IN, LVCMOS12_LVCMOS15_LVCMOS18.IN,
# the long IN_ONLY alias, two SLEW.SLOW aliases, the STEPDOWN
# alias, PULLTYPE.PULLUP on Y0, and Y1's default-state SLEW/
# STEPDOWN/PULLDOWN trio. Cross-referenced with a Vivado-built
# rst_to_led reference bitstream.
pudc_template = (
"{tile}.{site}.LVCMOS12_LVCMOS15.IN\n"
"{tile}.{site}.LVCMOS12_LVCMOS15_LVCMOS18.IN\n"
"{tile}.{site}.LVCMOS12_LVCMOS15_LVCMOS18_LVCMOS25_LVCMOS33_LVDS_25_LVTTL_SSTL135_SSTL15_TMDS_33.IN_ONLY\n"
"{tile}.{site}.LVCMOS12_LVCMOS15_LVCMOS18_LVCMOS25_LVCMOS33_LVTTL_SSTL135_SSTL15.SLEW.SLOW\n"
"{tile}.{site}.LVCMOS12_LVCMOS15_LVCMOS18.SLEW.SLOW\n"
"{tile}.{site}.LVCMOS12_LVCMOS15_LVCMOS18_SSTL135_SSTL15.STEPDOWN\n"
"{tile}.{site}.PULLTYPE.PULLUP\n"
"{tile}.{partner}.LVCMOS12_LVCMOS15_LVCMOS18.SLEW.SLOW\n"
"{tile}.{partner}.LVCMOS12_LVCMOS15_LVCMOS18_SSTL135_SSTL15.STEPDOWN\n"
"{tile}.{partner}.PULLTYPE.PULLDOWN\n"
)
partner = 'IOB_Y1' if pudc_b_tile_site[1] == 'IOB_Y0' else 'IOB_Y0'
for line in fasm.parse_fasm_string(pudc_template.format(
tile=pudc_b_tile_site[0],
site=pudc_b_tile_site[1],
partner=partner)):
assembler.add_fasm_line(line, missing_features)
else:
# HR-bank (artix7/kintex7-HR/zynq7/spartan7) — original 3-line
# template kept intact. TODO from the original code still
# applies to K70T: it is known to be wrong but we have no
# better data here.
for line in fasm.parse_fasm_string("""
{tile}.{site}.LVCMOS12_LVCMOS15_LVCMOS18_LVCMOS25_LVCMOS33_LVTTL_SSTL135_SSTL15.IN_ONLY
{tile}.{site}.LVCMOS25_LVCMOS33_LVTTL.IN
{tile}.{site}.PULLTYPE.PULLUP
""".format(
tile=pudc_b_tile_site[0],
site=pudc_b_tile_site[1],
)):
assembler.add_fasm_line(line, missing_features)
tile=pudc_b_tile_site[0],
site=pudc_b_tile_site[1],
)):
assembler.add_fasm_line(line, missing_features)
if missing_features:
raise fasm_assembler.FasmLookupError('\n'.join(missing_features))
@ -256,9 +305,10 @@ def run(
for line in fasm.parse_fasm_string(feature):
assembler.add_fasm_line(line, missing_features)
# This is a HCLK_IOI3 tile, set the stepdown feature for it
# too.
if "HCLK_IOI3" in tile:
# On HR-bank parts the bank-anchor tile is HCLK_IOI3 and gets a
# STEPDOWN feature; on virtex7 HP-only it is HCLK_IOI which has
# the same STEPDOWN feature in our segbits.
if "HCLK_IOI3" in tile or tile.startswith("HCLK_IOI_"):
feature = "{}.STEPDOWN".format(tile)
for line in fasm.parse_fasm_string(feature):
assembler.add_fasm_line(line, missing_features)
@ -266,6 +316,164 @@ def run(
if missing_features:
raise fasm_assembler.FasmLookupError('\n'.join(missing_features))
# HP-bank (LIOB18/RIOB18) "bank-glue" auto-injection.
# The HP-class output buffer (OUTBUF_DCIEN) needs three driver-enable
# bits, and the HP-class input buffer (INBUF_DCIEN) needs one input-
# enable bit. Vivado emits these implicitly for every used HP-bank
# IOB; on HR-bank IOB33 the equivalent bits are factory-default so
# were never captured in upstream prjxray. For round-trip parity on
# virtex7 xc7vx485tffg1761-2 (HP-only) we inject the right tag
# whenever any IOB feature is set on an HP-bank tile, mirroring the
# STEPDOWN walk above.
glue_missing = []
liob_in_features = defaultdict(lambda: {'in': False, 'out': False, 'diff_in': False})
for set_feature in set_features:
if set_feature.value == 0:
continue
feature = set_feature.feature
parts = feature.split(".")
if len(parts) < 3:
continue
tile = parts[0]
site = parts[1]
tag = ".".join(parts[2:])
if not (tile.startswith("LIOB18") or tile.startswith("RIOB18")):
continue
if site not in ("IOB_Y0", "IOB_Y1"):
continue
# Direction heuristic. Pure ".IN" / ".IN_ONLY" indicates IBUF.
# ".DRIVE." is the only reliable OBUF marker — output drive
# strength is meaningless for inputs. ".SLEW." and ".OUT" appear
# on IBUF tiles too as bank-wide defaults (Vivado emits
# SLEW.SLOW on every unused IOB), so they would mis-classify
# IBUFs as IOBUFs and inject spurious OBUF_HP_BANK_GLUE bits.
# ".IN_DIFF" indicates an IBUFDS (LVDS differential input).
if "IN_DIFF" in tag:
liob_in_features[(tile, site)]['diff_in'] = True
elif "IN_ONLY" in tag or tag.endswith(".IN") or "IBUFDISABLE" in tag:
liob_in_features[(tile, site)]['in'] = True
if ".DRIVE." in tag:
liob_in_features[(tile, site)]['out'] = True
# Track whether the col-32 LIOB18 column has any Y1 OBUFs anywhere.
# When it does, Vivado lights a 6-bit "DCI cascade + bank active"
# pattern in INT_L_X32Y49 — the bottom-most INT_L tile of the X32
# routing spine that serves the LIOB18 column. The same indicator
# exists for the X110 (R-side IOB) column too, mirrored at
# INT_R_X110Y49 — we'd add that when the first RIOB18 test design
# asks for it.
any_liob18_y1_obuf = False
# PUDC_B's tile already gets its own IN/IN_ONLY/PULLUP/SLEW features
# injected above; do NOT also fire the IBUF_HP_BANK_GLUE rule on it.
# Empirically (Vivado-built rst_to_led ref) the PUDC_B tile does not
# carry the bank-glue bit because the pullup is a "virtual" tie,
# not a real IBUF placement.
pudc_b_tile_name = pudc_b_tile_site[0] if pudc_b_tile_site else None
for (tile, site), kind in liob_in_features.items():
if tile == pudc_b_tile_name:
continue
# Both IOB_Y0 (master) and IOB_Y1 (slave) sites have HP_BANK_GLUE
# patterns now. The Y1 OBUF rule was derived from the counter
# design (LIOB18 tiles with two driving OBUFs) — Vivado emits an
# extra 3 bits at rel 30_041 / 32_016 / 33_061 when Y1 has a
# ".DRIVE." feature in addition to Y0.
if kind['in']:
feature = "{}.{}.IBUF_HP_BANK_GLUE".format(tile, site)
for line in fasm.parse_fasm_string(feature):
assembler.add_fasm_line(line, glue_missing)
if kind['out']:
feature = "{}.{}.OBUF_HP_BANK_GLUE".format(tile, site)
for line in fasm.parse_fasm_string(feature):
assembler.add_fasm_line(line, glue_missing)
if kind['diff_in']:
# IBUFDS — empirically Vivado lights a 7-bit pattern in the
# IOB_Y0 (M-site) slot of the differential pair. Y1 is the
# negative-half slave and reuses the silicon defaults, so
# no separate Y1 rule is needed.
feature = "{}.IOB_Y0.IBUFDS_BANK_GLUE".format(tile)
for line in fasm.parse_fasm_string(feature):
assembler.add_fasm_line(line, glue_missing)
if kind['out'] and site == 'IOB_Y1' and tile.startswith('LIOB18_X81'):
any_liob18_y1_obuf = True
if any_liob18_y1_obuf:
for tag in ('INT_L_X32Y49.IOB_COL_OBUF_CASCADE_Y1',
'INT_L_X32Y49.IOB_COL_BANK_ACTIVE'):
for line in fasm.parse_fasm_string(tag):
assembler.add_fasm_line(line, glue_missing)
# GFAN0 T-tie root glue. When the design has an OBUF whose T
# input must be tied to GND through general routing (e.g. an
# IBUF→OBUF passthrough where no SLICE FF Q drives the OBUF),
# Vivado emits INT_L_X62Y73.GFAN0.GND_WIRE / .IMUX_L33.GFAN0
# FASM features AND lights one extra silicon bit at
# INT_L_X62Y83 minor 26 bit 18 — the "this GFAN tie route is
# in use" marker for the col-62 routing spine. Only the c=62
# column has been observed needing this glue (the counter
# designs use FF-driven OBUFs and route GFAN0 through other
# columns without triggering an analogous bit). The rule fires
# only when an X62-column GFAN0.GND_WIRE feature appears.
x62_gfan_tile = None
for set_feature in set_features:
if set_feature.value == 0:
continue
feat = set_feature.feature
if not feat.startswith('INT_L_X62'):
continue
if 'GFAN0.GND_WIRE' in feat:
# The mirror tile (Y+10) gets the glue bit. For
# INT_L_X62Y73 → INT_L_X62Y83.
tile = feat.split('.')[0]
import re as _re
m = _re.match(r'(INT_L_X(\d+))Y(\d+)', tile)
if m:
x62_gfan_tile = 'INT_L_X{}Y{}'.format(m.group(2), int(m.group(3)) + 10)
break
if x62_gfan_tile:
feature = '{}.GFAN_TIE_ROOT_GLUE'.format(x62_gfan_tile)
for line in fasm.parse_fasm_string(feature):
assembler.add_fasm_line(line, glue_missing)
# HCLK_L per-BUFRCLK-channel "active" markers. Empirically Vivado
# sets one extra bit per HCLK_L tile per BUFR channel in use, at
# minor 1 bit 28+ch. Only BUFRCLK3 is observed today (the
# counter_sw_bufr design); when a kintex7 → virtex7 comparison
# design that uses BUFRCLK0/1/2 is built we can add those analogues
# to segbits_hclk_l.db with bits 01_28 / 01_29 / 01_30 respectively.
hclkl_bufrclk_seen = {} # (hclkl_tile) -> set of channel-ids in use
for set_feature in set_features:
if set_feature.value == 0:
continue
feat = set_feature.feature
parts = feat.split('.')
if len(parts) < 3:
continue
if not parts[0].startswith('HCLK_L'):
continue
# HCLK_L_X..Y...HCLK_LEAF_CLK_B_TOP/BOTL[0-5].HCLK_CK_BUFRCLK[0-3]
tag = '.'.join(parts[2:])
if 'HCLK_CK_BUFRCLK' not in tag:
continue
ch = tag.rsplit('HCLK_CK_BUFRCLK', 1)[1]
if ch.isdigit():
hclkl_bufrclk_seen.setdefault(parts[0], set()).add(int(ch))
for hclkl_tile, channels in hclkl_bufrclk_seen.items():
for ch in channels:
if ch != 3:
# Only BUFRCLK3 has segbits data so far; skip rest
# silently so the partial rule doesn't error.
continue
feature = '{}.HCLK_LEAF_BUFRCLK{}_ACTIVE'.format(hclkl_tile, ch)
for line in fasm.parse_fasm_string(feature):
assembler.add_fasm_line(line, glue_missing)
# glue_missing entries indicate the segbits don't carry the rule yet
# (e.g. partially-built database); fall through silently rather than
# erroring, so this auto-injection is a no-op on databases that
# haven't been bank-glue-annotated.
frames = assembler.get_frames(sparse=sparse)
if debug:

View File

@ -124,6 +124,12 @@ case "$1" in
riob18)
sed < "$2" > "$tmp1" -e 's/^IOB18\./RIOB18./' ;;
liob18)
sed < "$2" > "$tmp1" -e 's/^IOB18\./LIOB18./' ;;
mask_liob18)
sed < "$2" > "$tmp1" -e 's/^IOB18\./LIOB18./' ;;
lioi3)
sed < "$2" > "$tmp1" -e 's/^IOI3\./LIOI3./' ;;
@ -151,6 +157,15 @@ case "$1" in
rioi_tbyteterm)
sed < "$2" > "$tmp1" -e 's/^IOI\./RIOI_TBYTETERM./' ;;
lioi)
sed < "$2" > "$tmp1" -e 's/^IOI\./LIOI./' ;;
lioi_tbytesrc)
sed < "$2" > "$tmp1" -e 's/^IOI\./LIOI_TBYTESRC./' ;;
lioi_tbyteterm)
sed < "$2" > "$tmp1" -e 's/^IOI\./LIOI_TBYTETERM./' ;;
cmt_top_r_upper_t)
sed < "$2" > "$tmp1" -e 's/^CMT_UPPER_T\./CMT_TOP_R_UPPER_T./' ;;

View File

@ -130,26 +130,70 @@ proc putl {lst} {
}
proc write_pip_txtdata {filename} {
# Output format (unchanged): TILE PIP SRC_WIRE DST_WIRE NUM_PIPS DIR
# TILE e.g. INT_R_X107Y144
# PIP e.g. INT_R_X107Y144/INT_R.GND_WIRE->>GFAN1
# SRC_WIRE e.g. INT_R_X107Y144/GND_WIRE
# DST_WIRE e.g. INT_R_X107Y144/GFAN1
# NUM_PIPS count of input pips at dst node (used by int_generate.py
# to skip trivial fan-ins via 'pnum == 1' filter)
# DIR IS_DIRECTIONAL bool (1 = directional, 0 = bidirectional)
#
# The kintex7-era implementation iterated foreach net foreach pip and
# called get_tiles/get_wires/get_nodes once per pip fine on small parts
# but on virtex7 xc7vx485tffg1761 (~12M pips across 1320 nets) that's
# 1-2 h of Tcl overhead per specimen, with most of it spent rediscovering
# information the pip name already encodes. Optimisations:
# 1) Bulk-fetch all pips with one get_pips call.
# 2) Bulk-fetch IS_DIRECTIONAL as a list.
# 3) Parse tile/src/dst names directly from the pip name (saves
# 3*N Tcl object queries; format is "TILE/TILE_TYPE.SRC->{>}DST").
# 4) Cache num_pips per dst_wire string same dst is reused by many
# pips so its node-fanin only needs computing once.
# Output format and content are bit-identical to the old implementation
# on parseable pip names; un-parseable pips (none seen on virtex7 so far)
# fall through to the original per-pip query path.
puts "FUZ([pwd]): Writing $filename."
set fp [open $filename w]
set nets [get_nets -hierarchical]
set nnets [llength $nets]
set neti 0
foreach net $nets {
incr neti
if {($neti % 100) == 0 } {
puts "FUZ([pwd]): Dumping pips from net $net ($neti / $nnets)"
set all_pips [get_pips -of_objects [get_nets -hierarchical]]
set npips [llength $all_pips]
puts "FUZ([pwd]): bulk-fetched $npips pips, fetching IS_DIRECTIONAL..."
set dir_props [get_property IS_DIRECTIONAL $all_pips]
puts "FUZ([pwd]): writing rows..."
array set dst_wire_to_num_pips {}
set i 0
foreach pip $all_pips dir_prop $dir_props {
incr i
if {($i % 100000) == 0 } {
puts "FUZ([pwd]): pip $i / $npips"
}
foreach pip [get_pips -of_objects $net] {
if {[regexp {^([^/]+)/[^.]+\.(.+?)->>?(.+)$} $pip _ tile src_name dst_name]} {
set src_wire "$tile/$src_name"
set dst_wire "$tile/$dst_name"
} else {
# Fallback for unexpected pip-name formats: slow per-pip query.
set tile [get_tiles -of_objects $pip]
set src_wire [get_wires -uphill -of_objects $pip]
set dst_wire [get_wires -downhill -of_objects $pip]
set num_pips [llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst_wire]]]
set dir_prop [get_property IS_DIRECTIONAL $pip]
puts $fp "$tile $pip $src_wire $dst_wire $num_pips $dir_prop"
}
if {![info exists dst_wire_to_num_pips($dst_wire)]} {
set wireobj [get_wires $dst_wire]
if {$wireobj ne ""} {
set node [get_nodes -of_objects $wireobj]
if {$node ne ""} {
set dst_wire_to_num_pips($dst_wire) [llength [get_nodes -uphill -of_objects $node]]
} else {
set dst_wire_to_num_pips($dst_wire) 0
}
} else {
set dst_wire_to_num_pips($dst_wire) 0
}
}
set num_pips $dst_wire_to_num_pips($dst_wire)
puts $fp "$tile $pip $src_wire $dst_wire $num_pips $dir_prop"
}
close $fp
puts "FUZ([pwd]): wrote $npips rows."
}
# Generic non-ROI'd generate.tcl template