2018-01-17 23:39:37 +01:00
|
|
|
#!/usr/bin/env python3
|
2020-04-16 09:29:20 +02:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
#
|
|
|
|
|
# Copyright (C) 2017-2020 The Project X-Ray Authors.
|
|
|
|
|
#
|
|
|
|
|
# Use of this source code is governed by a ISC-style
|
|
|
|
|
# license that can be found in the LICENSE file or at
|
|
|
|
|
# https://opensource.org/licenses/ISC
|
|
|
|
|
#
|
|
|
|
|
# SPDX-License-Identifier: ISC
|
2018-01-17 23:39:37 +01:00
|
|
|
|
2018-10-19 17:33:31 +02:00
|
|
|
from __future__ import print_function
|
2019-01-11 04:47:55 +01:00
|
|
|
|
2019-02-13 02:37:30 +01:00
|
|
|
import fasm
|
2018-10-19 17:33:31 +02:00
|
|
|
import argparse
|
2019-02-13 02:37:30 +01:00
|
|
|
import json
|
2018-01-17 23:39:37 +01:00
|
|
|
import os
|
2018-10-19 17:33:31 +02:00
|
|
|
import os.path
|
2019-12-10 17:29:28 +01:00
|
|
|
import csv
|
|
|
|
|
|
|
|
|
|
from collections import defaultdict
|
2018-01-17 23:39:37 +01:00
|
|
|
|
2020-06-16 02:28:42 +02:00
|
|
|
from prjxray import fasm_assembler, util
|
|
|
|
|
from prjxray.db import Database
|
|
|
|
|
from prjxray.roi import Roi
|
2022-03-15 10:47:58 +01:00
|
|
|
from prjxray.util import OpenSafeFile
|
2019-01-11 04:47:55 +01:00
|
|
|
|
2019-12-16 13:40:35 +01:00
|
|
|
import sys
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def eprint(*args, **kwargs):
|
|
|
|
|
print(*args, file=sys.stderr, **kwargs)
|
|
|
|
|
|
2019-01-11 04:47:55 +01:00
|
|
|
|
|
|
|
|
class FASMSyntaxError(SyntaxError):
|
|
|
|
|
pass
|
|
|
|
|
|
2018-10-20 01:19:22 +02:00
|
|
|
|
2018-01-17 23:39:37 +01:00
|
|
|
def dump_frames_verbose(frames):
|
|
|
|
|
print()
|
|
|
|
|
print("Frames: %d" % len(frames))
|
|
|
|
|
for addr in sorted(frames.keys()):
|
|
|
|
|
words = frames[addr]
|
|
|
|
|
print(
|
2018-06-23 00:15:59 +02:00
|
|
|
'0x%08X ' % addr + ', '.join(['0x%08X' % w for w in words]) +
|
|
|
|
|
'...')
|
2018-01-17 23:39:37 +01:00
|
|
|
|
2018-10-20 01:19:22 +02:00
|
|
|
|
2018-01-17 23:39:37 +01:00
|
|
|
def dump_frames_sparse(frames):
|
|
|
|
|
print()
|
|
|
|
|
print("Frames: %d" % len(frames))
|
|
|
|
|
for addr in sorted(frames.keys()):
|
|
|
|
|
words = frames[addr]
|
|
|
|
|
|
|
|
|
|
# Skip frames without filled words
|
|
|
|
|
for w in words:
|
|
|
|
|
if w:
|
|
|
|
|
break
|
|
|
|
|
else:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
print('Frame @ 0x%08X' % addr)
|
|
|
|
|
for i, w in enumerate(words):
|
|
|
|
|
if w:
|
|
|
|
|
print(' % 3d: 0x%08X' % (i, w))
|
|
|
|
|
|
2018-10-20 01:19:22 +02:00
|
|
|
|
2018-01-17 23:39:37 +01:00
|
|
|
def dump_frm(f, frames):
|
|
|
|
|
'''Write a .frm file given a list of frames, each containing a list of 101 32 bit words'''
|
|
|
|
|
for addr in sorted(frames.keys()):
|
|
|
|
|
words = frames[addr]
|
|
|
|
|
f.write(
|
|
|
|
|
'0x%08X ' % addr + ','.join(['0x%08X' % w for w in words]) + '\n')
|
|
|
|
|
|
2018-10-20 01:19:22 +02:00
|
|
|
|
2019-10-15 01:38:02 +02:00
|
|
|
def find_pudc_b(db):
|
|
|
|
|
""" Find PUDC_B pin func in grid, and return the tile and site prefix.
|
|
|
|
|
|
|
|
|
|
The PUDC_B pin is a special 7-series pin that controls unused pin pullup.
|
|
|
|
|
|
|
|
|
|
If the PUDC_B is unused, it is configured as an input with a PULLUP.
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
grid = db.grid()
|
|
|
|
|
|
|
|
|
|
pudc_b_tile_site = None
|
|
|
|
|
for tile in grid.tiles():
|
|
|
|
|
gridinfo = grid.gridinfo_at_tilename(tile)
|
|
|
|
|
|
|
|
|
|
for site, pin_function in gridinfo.pin_functions.items():
|
|
|
|
|
if 'PUDC_B' in pin_function:
|
|
|
|
|
assert pudc_b_tile_site == None, (
|
|
|
|
|
pudc_b_tile_site, (tile, site))
|
|
|
|
|
iob_y = int(site[-1]) % 2
|
|
|
|
|
|
|
|
|
|
pudc_b_tile_site = (tile, 'IOB_Y{}'.format(iob_y))
|
|
|
|
|
|
|
|
|
|
return pudc_b_tile_site
|
|
|
|
|
|
2019-12-11 09:22:46 +01:00
|
|
|
|
2019-12-10 17:29:28 +01:00
|
|
|
def get_iob_sites(db, tile_name):
|
|
|
|
|
"""
|
|
|
|
|
Yields prjxray site names for given IOB tile name
|
|
|
|
|
"""
|
|
|
|
|
grid = db.grid()
|
|
|
|
|
gridinfo = grid.gridinfo_at_tilename(tile_name)
|
|
|
|
|
|
|
|
|
|
for site in gridinfo.sites:
|
|
|
|
|
site_y = int(site[-1]) % 2
|
|
|
|
|
yield "IOB_Y{}".format(site_y)
|
2019-10-15 01:38:02 +02:00
|
|
|
|
2019-12-11 09:22:46 +01:00
|
|
|
|
2019-10-15 01:38:02 +02:00
|
|
|
def run(
|
|
|
|
|
db_root,
|
2019-12-10 13:49:51 +01:00
|
|
|
part,
|
2019-10-15 01:38:02 +02:00
|
|
|
filename_in,
|
|
|
|
|
f_out,
|
|
|
|
|
sparse=False,
|
|
|
|
|
roi=None,
|
|
|
|
|
debug=False,
|
|
|
|
|
emit_pudc_b_pullup=False):
|
2020-01-15 17:34:33 +01:00
|
|
|
db = Database(db_root, part)
|
2019-02-13 02:37:30 +01:00
|
|
|
assembler = fasm_assembler.FasmAssembler(db)
|
|
|
|
|
|
2019-12-10 17:29:28 +01:00
|
|
|
set_features = set()
|
2019-12-11 09:22:46 +01:00
|
|
|
|
2019-12-10 17:29:28 +01:00
|
|
|
def feature_callback(feature):
|
|
|
|
|
set_features.add(feature)
|
|
|
|
|
|
2019-12-11 09:22:46 +01:00
|
|
|
assembler.set_feature_callback(feature_callback)
|
2019-12-10 17:29:28 +01:00
|
|
|
|
|
|
|
|
# Build mapping of tile to IO bank
|
|
|
|
|
tile_to_bank = {}
|
|
|
|
|
bank_to_tile = defaultdict(lambda: set())
|
|
|
|
|
|
|
|
|
|
if part is not None:
|
2022-03-15 10:47:58 +01:00
|
|
|
with OpenSafeFile(os.path.join(db_root, part, "package_pins.csv"), "r") as fp:
|
2019-12-10 17:29:28 +01:00
|
|
|
reader = csv.DictReader(fp)
|
|
|
|
|
package_pins = [l for l in reader]
|
|
|
|
|
|
2022-03-15 10:47:58 +01:00
|
|
|
with OpenSafeFile(os.path.join(db_root, part, "part.json"), "r") as fp:
|
2019-12-16 13:40:35 +01:00
|
|
|
part_data = json.load(fp)
|
|
|
|
|
|
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>
2026-05-29 11:13:53 +02:00
|
|
|
# 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.
|
2019-12-16 13:40:35 +01:00
|
|
|
for bank, loc in part_data["iobanks"].items():
|
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>
2026-05-29 11:13:53 +02:00
|
|
|
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
|
2019-12-16 13:40:35 +01:00
|
|
|
|
2019-12-10 17:29:28 +01:00
|
|
|
for pin in package_pins:
|
|
|
|
|
bank_to_tile[pin["bank"]].add(pin["tile"])
|
|
|
|
|
tile_to_bank[pin["tile"]] = pin["bank"]
|
|
|
|
|
|
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>
2026-05-29 11:13:53 +02:00
|
|
|
# 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
|
|
|
|
|
|
2019-10-15 01:38:02 +02:00
|
|
|
if emit_pudc_b_pullup:
|
|
|
|
|
pudc_b_in_use = False
|
|
|
|
|
|
|
|
|
|
def check_for_pudc_b(set_feature):
|
2019-12-16 13:07:48 +01:00
|
|
|
feature_callback(set_feature)
|
2019-10-15 01:38:02 +02:00
|
|
|
parts = set_feature.feature.split('.')
|
|
|
|
|
|
|
|
|
|
if parts[0] == pudc_b_tile_site[0] and parts[
|
|
|
|
|
1] == pudc_b_tile_site[1]:
|
|
|
|
|
nonlocal pudc_b_in_use
|
|
|
|
|
pudc_b_in_use = True
|
|
|
|
|
|
2019-10-15 22:45:48 +02:00
|
|
|
if pudc_b_tile_site is not None:
|
|
|
|
|
assembler.set_feature_callback(check_for_pudc_b)
|
2019-10-15 01:38:02 +02:00
|
|
|
|
2019-02-14 17:27:43 +01:00
|
|
|
extra_features = []
|
2019-02-13 02:37:30 +01:00
|
|
|
if roi:
|
2022-03-15 10:47:58 +01:00
|
|
|
with OpenSafeFile(roi) as f:
|
2019-02-13 02:37:30 +01:00
|
|
|
roi_j = json.load(f)
|
|
|
|
|
x1 = roi_j['info']['GRID_X_MIN']
|
|
|
|
|
x2 = roi_j['info']['GRID_X_MAX']
|
|
|
|
|
y1 = roi_j['info']['GRID_Y_MIN']
|
|
|
|
|
y2 = roi_j['info']['GRID_Y_MAX']
|
|
|
|
|
|
|
|
|
|
assembler.mark_roi_frames(Roi(db=db, x1=x1, x2=x2, y1=y1, y2=y2))
|
|
|
|
|
|
2019-02-14 17:27:43 +01:00
|
|
|
if 'required_features' in roi_j:
|
2019-12-16 10:53:17 +01:00
|
|
|
extra_features = list(
|
|
|
|
|
fasm.parse_fasm_string('\n'.join(roi_j['required_features'])))
|
2019-02-13 02:37:30 +01:00
|
|
|
|
2019-12-10 13:20:44 +01:00
|
|
|
# Get required extra features for the part
|
2019-12-10 13:49:51 +01:00
|
|
|
required_features = db.get_required_fasm_features(part)
|
2019-12-16 10:53:17 +01:00
|
|
|
extra_features += list(
|
|
|
|
|
fasm.parse_fasm_string('\n'.join(required_features)))
|
2019-12-09 13:40:05 +01:00
|
|
|
|
2019-02-13 02:37:30 +01:00
|
|
|
assembler.parse_fasm_filename(filename_in, extra_features=extra_features)
|
2019-10-15 01:38:02 +02:00
|
|
|
|
2019-10-15 22:45:48 +02:00
|
|
|
if emit_pudc_b_pullup and not pudc_b_in_use and pudc_b_tile_site is not None:
|
2019-10-15 01:38:02 +02:00
|
|
|
# Enable IN-only and PULLUP on PUDC_B IOB.
|
|
|
|
|
#
|
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>
2026-05-29 11:13:53 +02:00
|
|
|
# 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.
|
2019-10-15 01:38:02 +02:00
|
|
|
missing_features = []
|
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>
2026-05-29 11:13:53 +02:00
|
|
|
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("""
|
2020-05-07 15:51:55 +02:00
|
|
|
{tile}.{site}.LVCMOS12_LVCMOS15_LVCMOS18_LVCMOS25_LVCMOS33_LVTTL_SSTL135_SSTL15.IN_ONLY
|
2019-10-15 01:38:02 +02:00
|
|
|
{tile}.{site}.LVCMOS25_LVCMOS33_LVTTL.IN
|
|
|
|
|
{tile}.{site}.PULLTYPE.PULLUP
|
|
|
|
|
""".format(
|
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>
2026-05-29 11:13:53 +02:00
|
|
|
tile=pudc_b_tile_site[0],
|
|
|
|
|
site=pudc_b_tile_site[1],
|
|
|
|
|
)):
|
|
|
|
|
assembler.add_fasm_line(line, missing_features)
|
2019-10-15 01:38:02 +02:00
|
|
|
|
|
|
|
|
if missing_features:
|
|
|
|
|
raise fasm_assembler.FasmLookupError('\n'.join(missing_features))
|
|
|
|
|
|
2019-12-10 17:29:28 +01:00
|
|
|
if part is not None:
|
|
|
|
|
# Make a set of all used IOB tiles and sites. Look for the "STEPDOWN"
|
|
|
|
|
# feature. If one is set for an IOB then set it for all other IOBs of
|
|
|
|
|
# the same bank.
|
2019-12-16 13:40:35 +01:00
|
|
|
stepdown_tags = defaultdict(lambda: set())
|
2019-12-10 17:29:28 +01:00
|
|
|
stepdown_banks = set()
|
|
|
|
|
used_iob_sites = set()
|
|
|
|
|
|
|
|
|
|
for set_feature in set_features:
|
2019-12-16 13:40:35 +01:00
|
|
|
if set_feature.value == 0:
|
|
|
|
|
continue
|
|
|
|
|
|
2019-12-10 17:29:28 +01:00
|
|
|
feature = set_feature.feature
|
2019-12-11 16:13:07 +01:00
|
|
|
parts = feature.split(".")
|
|
|
|
|
if len(parts) >= 3:
|
|
|
|
|
tile, site, tag = feature.split(".", maxsplit=2)
|
|
|
|
|
if "IOB33" in tile:
|
|
|
|
|
used_iob_sites.add((
|
|
|
|
|
tile,
|
|
|
|
|
site,
|
|
|
|
|
))
|
2019-12-16 13:40:35 +01:00
|
|
|
|
|
|
|
|
# Store STEPDOWN related tags.
|
2019-12-11 16:13:07 +01:00
|
|
|
if "STEPDOWN" in tag:
|
2019-12-16 13:40:35 +01:00
|
|
|
bank = tile_to_bank[tile]
|
|
|
|
|
stepdown_banks.add(bank)
|
|
|
|
|
stepdown_tags[bank].add(tag)
|
2019-12-10 17:29:28 +01:00
|
|
|
|
2019-12-16 13:40:35 +01:00
|
|
|
# Set the feature for unused IOBs, loop over all banks which were
|
|
|
|
|
# observed to have the STEPDOWN feature set.
|
2019-12-10 17:29:28 +01:00
|
|
|
missing_features = []
|
|
|
|
|
|
|
|
|
|
for bank in stepdown_banks:
|
|
|
|
|
for tile in bank_to_tile[bank]:
|
|
|
|
|
|
2019-12-16 13:40:35 +01:00
|
|
|
# This is an IOB33 tile. Set the STEPDOWN feature in it but
|
|
|
|
|
# only if it is unused.
|
|
|
|
|
if "IOB33" in tile:
|
|
|
|
|
for site in get_iob_sites(db, tile):
|
|
|
|
|
|
|
|
|
|
if (tile, site) in used_iob_sites:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
for tag in stepdown_tags[bank]:
|
|
|
|
|
feature = "{}.{}.{}".format(tile, site, tag)
|
|
|
|
|
for line in fasm.parse_fasm_string(feature):
|
|
|
|
|
assembler.add_fasm_line(line, missing_features)
|
|
|
|
|
|
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>
2026-05-29 11:13:53 +02:00
|
|
|
# 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_"):
|
2019-12-16 13:40:35 +01:00
|
|
|
feature = "{}.STEPDOWN".format(tile)
|
|
|
|
|
for line in fasm.parse_fasm_string(feature):
|
|
|
|
|
assembler.add_fasm_line(line, missing_features)
|
2019-12-10 17:29:28 +01:00
|
|
|
|
|
|
|
|
if missing_features:
|
|
|
|
|
raise fasm_assembler.FasmLookupError('\n'.join(missing_features))
|
|
|
|
|
|
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>
2026-05-29 11:13:53 +02:00
|
|
|
# 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.
|
|
|
|
|
|
2018-10-19 17:33:31 +02:00
|
|
|
frames = assembler.get_frames(sparse=sparse)
|
2018-01-17 23:39:37 +01:00
|
|
|
|
|
|
|
|
if debug:
|
|
|
|
|
dump_frames_sparse(frames)
|
|
|
|
|
|
|
|
|
|
dump_frm(f_out, frames)
|
|
|
|
|
|
|
|
|
|
|
2018-10-19 17:33:31 +02:00
|
|
|
def main():
|
2018-01-17 23:39:37 +01:00
|
|
|
parser = argparse.ArgumentParser(
|
|
|
|
|
description=
|
|
|
|
|
'Convert FPGA configuration description ("FPGA assembly") into binary frame equivalent'
|
|
|
|
|
)
|
|
|
|
|
|
2020-01-15 16:55:12 +01:00
|
|
|
util.db_root_arg(parser)
|
|
|
|
|
util.part_arg(parser)
|
2018-01-17 23:39:37 +01:00
|
|
|
parser.add_argument(
|
|
|
|
|
'--sparse', action='store_true', help="Don't zero fill all frames")
|
2019-02-13 02:37:30 +01:00
|
|
|
parser.add_argument(
|
|
|
|
|
'--roi',
|
|
|
|
|
help="ROI design.json file defining which tiles are within the ROI.")
|
2019-10-15 01:38:02 +02:00
|
|
|
parser.add_argument(
|
|
|
|
|
'--emit_pudc_b_pullup',
|
|
|
|
|
help="Emit an IBUF and PULLUP on the PUDC_B pin if unused",
|
|
|
|
|
action='store_true')
|
2018-01-17 23:39:37 +01:00
|
|
|
parser.add_argument(
|
|
|
|
|
'--debug', action='store_true', help="Print debug dump")
|
2018-10-20 01:19:22 +02:00
|
|
|
parser.add_argument('fn_in', help='Input FPGA assembly (.fasm) file')
|
2018-01-18 21:42:45 +01:00
|
|
|
parser.add_argument(
|
|
|
|
|
'fn_out',
|
|
|
|
|
default='/dev/stdout',
|
|
|
|
|
nargs='?',
|
|
|
|
|
help='Output FPGA frame (.frm) file')
|
2018-01-17 23:39:37 +01:00
|
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
run(
|
2018-10-19 17:33:31 +02:00
|
|
|
db_root=args.db_root,
|
2019-12-10 13:49:51 +01:00
|
|
|
part=args.part,
|
2018-10-19 17:33:31 +02:00
|
|
|
filename_in=args.fn_in,
|
|
|
|
|
f_out=open(args.fn_out, 'w'),
|
2018-01-17 23:39:37 +01:00
|
|
|
sparse=args.sparse,
|
2019-02-13 02:37:30 +01:00
|
|
|
roi=args.roi,
|
2019-10-15 01:38:02 +02:00
|
|
|
debug=args.debug,
|
|
|
|
|
emit_pudc_b_pullup=args.emit_pudc_b_pullup)
|
2018-10-20 01:19:22 +02:00
|
|
|
|
2018-10-19 17:33:31 +02:00
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
main()
|