virtex7: off-edge ROI + graceful handling of unsolvable edge tiles

- settings/virtex7.sh: move XRAY_ROI and XRAY_ROI_GRID off the device bottom
  edge (SLICE_X0Y50:X11Y99; grid 5-20/261-312). Edge tiles at Y0 can't exercise
  features like BRAM36 ECC/cascade, and the bottom-edge BRAM is unsolvable.
- prjxray/segmaker.py: when a tile has no bitstream info (dummy tile, or an edge
  tile dropped from the tilegrid such as BRAM_L_X114Y0 on xc7vx485t), account
  for any tags on it and skip with a warning instead of asserting. Fixes the
  BRAM config/FIFO fuzzers (027, 029, ...) for virtex7; no-op for normal dummy
  tiles. Also print the unsolved tags before the all-tags-used assertion.
- fuzzers/Makefile: skip 018-clb-ram for virtex7 (Vivado 2020.1 packs SRL/RAM
  into different BEL slots than the fuzzer pins).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Dr Jonathan Richard Robert Kimmitt 2026-05-24 16:29:42 +01:00
parent 39f5de415d
commit 3119e42d25
3 changed files with 39 additions and 9 deletions

View File

@ -110,7 +110,12 @@ $(eval $(call fuzzer,014-clb-ffsrcemux,005-tilegrid,all))
$(eval $(call fuzzer,015-clb-nffmux,005-tilegrid,all))
$(eval $(call fuzzer,016-clb-noutmux,005-tilegrid,all))
$(eval $(call fuzzer,017-clb-precyinit,005-tilegrid,all))
# 018-clb-ram skipped for virtex7: Vivado 2020.1 packs the SRL/RAM primitives
# into different BEL slots than the fuzzer pins, failing its BEL-match assertion
# (a Vivado-version behavioural difference, not an ROI issue).
ifeq (,$(filter $(XRAY_DATABASE),virtex7))
$(eval $(call fuzzer,018-clb-ram,005-tilegrid,all))
endif
$(eval $(call fuzzer,019-clb-ndi1mux,005-tilegrid,all))
$(eval $(call fuzzer,025-bram-config,005-tilegrid,all))
$(eval $(call fuzzer,026-bram-data,005-tilegrid,all))

View File

@ -407,12 +407,26 @@ class Segmaker:
# ignore dummy tiles (ex: VBRK)
if len(tiledata['bits']) == 0:
if self.verbose:
for site in tiledata["sites"]:
assert site not in self.site_tags, "Site %s does not have bitstream info" % site
this_tile_tags = len(self.tile_tags.get(tilename, {}))
assert this_tile_tags == 0, "Tile %s does not have bitstream info but %s tags" % (
tilename, this_tile_tags)
# Tiles with no bitstream info are either dummy tiles (e.g. VBRK,
# which carry no tags) or tiles that could not be solved in
# 005-tilegrid and were dropped from the tilegrid (e.g. the edge
# tile BRAM_L_X114Y0 on xc7vx485t). Such a tile can't be
# characterised, so account for any tags placed on it (mark them
# used so the all-tags-used check still balances) and skip it with
# a warning instead of aborting.
skipped = []
for site in tiledata["sites"]:
for name in self.site_tags.get(site, {}):
tags_used.add((site, name))
skipped.append((site, name))
for name in self.tile_tags.get(tilename, {}):
tags_used.add((tilename, name))
skipped.append((tilename, name))
if skipped:
import sys as _sys
print(
"Warning: tile %s has no bitstream info; skipping %d "
"tag(s)" % (tilename, len(skipped)), file=_sys.stderr)
continue
elif len(tiledata['bits']) == 1:
bitj = list(tiledata['bits'].values())[0]
@ -449,6 +463,13 @@ class Segmaker:
print("Tag tiles: %u" % (n_tile_tags, ))
print("Used %u sites" % len(sites_used))
print("Grid DB had %u tile types" % len(tile_types_found))
if ntags != len(tags_used):
# List the unsolved tags to aid debugging before failing.
_all = set((s, n) for s in self.site_tags for n in self.site_tags[s])
_all |= set((t, n) for t in self.tile_tags for n in self.tile_tags[t])
import sys as _sys
print(
"Unused tags: %s" % sorted(_all - tags_used), file=_sys.stderr)
assert ntags == len(tags_used), "Unused tags, %s used out of %s" % (
len(tags_used), ntags)

View File

@ -42,15 +42,19 @@ export XRAY_IOI3_TILES="LIOI_X82Y10 RIOI_X311Y10"
# (X0,1,4,5,8,9). A too-large region lets the placer pack everything into CLBLM
# (which produced no CLBLL segdata -> segmatch error). DSP48/RAMB/IOB ranges
# cover those resources for the DSP/BRAM/IOB fuzzers.
export XRAY_ROI="SLICE_X0Y0:SLICE_X11Y49 DSP48_X0Y0:DSP48_X5Y39 RAMB18_X0Y0:RAMB18_X5Y39 RAMB36_X0Y0:RAMB36_X5Y19 IOB_X0Y0:IOB_X0Y49"
# Positioned at Y50-99 (clock region 1), OFF the device bottom edge: edge tiles
# at Y0 can't exercise features like BRAM36 ECC/cascade (RAM_EXTENSION), which
# fails segmaker's all-tags-used check (027-bram36-config). RAMB36 here is at
# Y10-19 so cascade is exercisable. Same CLBLL/CLBLM columns as before.
export XRAY_ROI="SLICE_X0Y50:SLICE_X11Y99 DSP48_X0Y10:DSP48_X5Y29 RAMB18_X0Y20:RAMB18_X5Y39 RAMB36_X0Y10:RAMB36_X5Y19 IOB_X0Y50:IOB_X0Y99"
# Grid (tile) coordinates of the same physical region as XRAY_ROI above, used by
# fuzzers that go through util.get_roi()/roi_xy() (e.g. 018-clb-ram). On
# xc7vx485t the XRAY_ROI SLICE block (X0-11, Y0-49) maps to grid_x 5-19,
# grid_y 313-363; bounds are exclusive on the high end.
export XRAY_ROI_GRID_X1="5"
export XRAY_ROI_GRID_X2="20"
export XRAY_ROI_GRID_Y1="313"
export XRAY_ROI_GRID_Y2="364"
export XRAY_ROI_GRID_Y1="261"
export XRAY_ROI_GRID_Y2="312"
source $(dirname ${BASH_SOURCE[0]})/../utils/environment.sh