Files
Myfro9andClaude Opus 4.8 88f96fa5fa vivado: resolve install path from ~/skills_env.md instead of hardcoding D:\Xilinx
The Vivado install root differs per machine (C:\Xilinx here, D:\Xilinx on the
box these skills were written on), so every hardcoded path was already wrong
on this machine.

- new fpga_flash/scripts/vivado_env.py: resolves --vivado-dir > env var >
  VIVADO_ROOT (falling back to VIVADO_PATH) from ~/skills_env.md
- gen_mcs / program_flash / check_flash_csv: --vivado-dir now optional
- fpga_update/gen_update_mcs.py: same precedence for --vivado
- fpga_flash / smod_atsc_dev / vivado-prj-create SKILL.md: document the
  lookup instead of naming a drive letter
- skills_env template: VIVADO_ROOT/VIVADO_PATH are now blanks to fill in,
  so a new machine can't inherit a wrong default

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 07:48:04 -05:00

120 lines
3.6 KiB
Python

#!/usr/bin/env python3
"""
Steps 4+5: Connect hardware target, configure cfgmem device, and program Flash.
Calls Vivado with step4_5_program.tcl (located in the same scripts/ directory)
via -tclargs so no temporary script files are created.
Usage:
python program_flash.py \
--flash-part "w25q128bv-spi-x1_x2_x4" \
--bit-file "E:/project/impl_1/RU_golden_top.bit" \
--mcs-file "E:/project/impl_1/RU_golden_smod.mcs" \
[--ltx-file "E:/project/impl_1/RU_golden_top.ltx"]
If the design has no ILA (no .ltx file), omit --ltx-file or pass an
empty string; the TCL template will skip the PROBES.FILE settings.
Supported flash parts:
Micron : mt25ql128-spi-x1_x2_x4
Winbond : w25q128bv-spi-x1_x2_x4
Exit codes:
0 = success ("End of startup status: HIGH" in output)
1 = failure
"""
import argparse
import os
import subprocess
import sys
from vivado_env import resolve_vivado_dir
def norm(path: str) -> str:
"""Normalize path to forward slashes (Vivado on Windows accepts both)."""
return path.replace("\\", "/")
def main():
parser = argparse.ArgumentParser(
description="Program FPGA SPI Flash via Vivado Hardware Manager"
)
parser.add_argument(
"--vivado-dir",
default=None,
help="Vivado install root; defaults to VIVADO_ROOT from ~/skills_env.md",
)
parser.add_argument(
"--flash-part",
required=True,
help="Vivado Flash part name, e.g. w25q128bv-spi-x1_x2_x4",
)
parser.add_argument(
"--bit-file",
required=True,
help="Full path to the .bit file",
)
parser.add_argument(
"--mcs-file",
required=True,
help="Full path to the .mcs file (from Step 3)",
)
parser.add_argument(
"--ltx-file",
default="",
help="Full path to the .ltx probes file (optional; omit if no ILA)",
)
args = parser.parse_args()
vivado_dir = norm(resolve_vivado_dir(args.vivado_dir))
bit_file = norm(args.bit_file)
mcs_file = norm(args.mcs_file)
ltx_file = norm(args.ltx_file) if args.ltx_file else ""
# Locate the TCL template alongside this script
scripts_dir = os.path.dirname(os.path.abspath(__file__))
tcl_template = os.path.join(scripts_dir, "step4_5_program.tcl").replace("\\", "/")
# Validate inputs
vivado_exe = os.path.join(vivado_dir, "bin", "vivado.bat")
if not os.path.isfile(vivado_exe):
print(f"ERROR: Vivado not found: {vivado_exe}", file=sys.stderr)
sys.exit(1)
for label, path in [("bit", bit_file), ("mcs", mcs_file)]:
if not os.path.isfile(path):
print(f"ERROR: .{label} file not found: {path}", file=sys.stderr)
sys.exit(1)
if ltx_file and not os.path.isfile(ltx_file):
print(f"ERROR: .ltx file not found: {ltx_file}", file=sys.stderr)
sys.exit(1)
if not os.path.isfile(tcl_template):
print(f"ERROR: TCL template not found: {tcl_template}", file=sys.stderr)
sys.exit(1)
cmd = [
vivado_exe,
"-mode", "batch",
"-source", tcl_template,
"-tclargs", args.flash_part, bit_file, mcs_file, ltx_file,
]
print(f"[program_flash] Vivado : {vivado_exe}")
print(f"[program_flash] Flash part: {args.flash_part}")
print(f"[program_flash] bit : {bit_file}")
print(f"[program_flash] mcs : {mcs_file}")
if ltx_file:
print(f"[program_flash] ltx : {ltx_file}")
else:
print(f"[program_flash] ltx : (none - no ILA)")
print()
result = subprocess.run(cmd)
sys.exit(result.returncode)
if __name__ == "__main__":
main()