mirror of https://github.com/openXC7/prjxray.git
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:
parent
e00d6f6876
commit
a8de0afdb3
86
README.md
86
README.md
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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."
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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']
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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./' ;;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue