🐛 fix: Step 1 JTAG check uses shared vivado path finder + build_tool_command

Root cause (2 bugs):
1. check_zynq_jtag() used config.vitis_path which no longer exists
   (config now uses xilinx_path) → always got empty path → 'Vivado not found'
2. _get_vivado_path() only checked hardcoded Linux paths, no version
   scanning, no .bat support on Windows

Fix:
- Added get_vivado_path() in vitis_checker.py (consistent with
  get_xsct_path, get_program_flash_path, etc.)
- Uses _find_executable() shared logic: scans Vivado/*/bin +
  Vitis/*/bin, picks newest version, supports .bat on Windows
- zynq_checker.py now uses get_vivado_path() + build_tool_command()
  for proper environment setup (settings64 sourcing on Linux)
- Removed obsolete _get_vivado_path() + unused shutil import
This commit is contained in:
2026-06-11 15:30:43 +08:00
parent 6d686964e2
commit 61f0e6cd2b
2 changed files with 20 additions and 35 deletions
+13
View File
@@ -317,6 +317,19 @@ def get_bootgen_path(vitis_path: str = "", xilinx_root: str = "") -> str | None:
return _find_executable("bootgen", vitis_path, platform.system().lower(), xilinx_root) return _find_executable("bootgen", vitis_path, platform.system().lower(), xilinx_root)
def get_vivado_path(vitis_path: str = "", xilinx_root: str = "") -> str | None:
"""Find the Vivado executable (JTAG operations via hw_server).
Args:
vitis_path: Legacy Vitis installation directory.
xilinx_root: Xilinx root directory.
Returns:
Path to vivado executable, or None.
"""
return _find_executable("vivado", vitis_path, platform.system().lower(), xilinx_root)
# ── Tool version detection ─────────────────────────────────────────── # ── Tool version detection ───────────────────────────────────────────
+7 -35
View File
@@ -10,13 +10,13 @@ from __future__ import annotations
import os import os
import re import re
import shutil
import subprocess import subprocess
from dataclasses import dataclass, field from dataclasses import dataclass, field
from pathlib import Path from pathlib import Path
from typing import Callable from typing import Callable
from config_manager import Config from config_manager import Config
from vitis_checker import get_vivado_path, build_tool_command
@dataclass @dataclass
@@ -86,9 +86,10 @@ def check_zynq_jtag(config: Config, callback: Callable | None = None) -> ZynqChe
if callback: if callback:
callback("start", "Connecting to hw_server...") callback("start", "Connecting to hw_server...")
# Find vivado executable # Find vivado executable via Xilinx root scan
vivado_path = _get_vivado_path( vivado_path = get_vivado_path(
config.vitis_path if hasattr(config, 'vitis_path') else "" vitis_path=getattr(config, "vitis_path", ""),
xilinx_root=getattr(config, "xilinx_path", ""),
) )
if not vivado_path: if not vivado_path:
return ZynqCheckResult( return ZynqCheckResult(
@@ -110,8 +111,8 @@ def check_zynq_jtag(config: Config, callback: Callable | None = None) -> ZynqChe
if callback: if callback:
callback("progress", "Scanning JTAG chain...") callback("progress", "Scanning JTAG chain...")
# Run Vivado in batch mode # Run Vivado in batch mode (with environment setup)
cmd = [vivado_path, "-mode", "batch", "-source", str(tcl_path)] cmd = build_tool_command(vivado_path, "-mode", "batch", "-source", str(tcl_path))
result = subprocess.run( result = subprocess.run(
cmd, cmd,
capture_output=True, capture_output=True,
@@ -322,35 +323,6 @@ def _parse_zynq_device(device_name: str) -> ZynqDevice | None:
) )
def _get_vivado_path(vitis_path: str) -> str | None:
"""Find the Vivado executable path.
Args:
vitis_path: Vitis installation path.
Returns:
Path to Vivado executable, or None if not found.
"""
path = shutil.which("vivado")
if path:
return path
if vitis_path:
candidate = Path(vitis_path) / "bin" / "vivado"
if candidate.exists():
return str(candidate)
candidate = Path(vitis_path) / "bin" / "vivado.exe"
if candidate.exists():
return str(candidate)
common_paths = [
"/opt/xilinx/bin/vivado",
os.path.expanduser("~/Xilinx/Vivado/bin/vivado"),
]
for p in common_paths:
if os.path.isfile(p):
return p
return None
def get_zynq_status_dict(result: ZynqCheckResult) -> dict: def get_zynq_status_dict(result: ZynqCheckResult) -> dict:
"""Convert a ZynqCheckResult to a serializable dictionary. """Convert a ZynqCheckResult to a serializable dictionary.