fix: use xsct 'targets -name $t' — universally available across 2018–2023

'jtag targets' may not exist in all xsct versions (2018.3, etc.).
Switch to 'targets -name $t' which works in every Xilinx SDK/Vitis
version. Output format: DEVICE:xc7z100, DEVICE:ARM Cortex-A9 MPCore #0

Also broadened _ARM_DAP_RE to match both 'arm_dap' and 'ARM Cortex-A9'
patterns for PS detection across different xsct versions.
This commit is contained in:
2026-06-11 16:49:59 +08:00
parent dd35ab0846
commit 796887952d
+20 -24
View File
@@ -52,18 +52,14 @@ class ZynqCheckResult:
error: str = "" # Error message if detection failed error: str = "" # Error message if detection failed
# ── Patterns for parsing xsct "jtag targets" output ────────────────── # ── Patterns for parsing xsct "targets" output ──────────────────────
# Each line: " 1 xc7z100 (idcode 03736093 irlen 4)" # From "targets -name $t": bare device names like "xc7z100", "ARM Cortex-A9 MPCore #0"
_JTAG_LINE_RE = re.compile(
r"^\s*(\d+)\s+(\S+)\s+\(idcode\s+([0-9A-Fa-f]+)\s+irlen\s+(\d+)\)",
re.IGNORECASE,
)
# Zynq PL part: "xc7z100", "xc7z010", etc. # Zynq PL device: "xc7z100", "xc7z010", "xc7z020", etc.
_ZYNQ_DEVICE_RE = re.compile(r"^xc\d+z\d+[a-z]?\d+$", re.IGNORECASE) _ZYNQ_DEVICE_RE = re.compile(r"^xc\d+z\d+[a-z]?\d+$", re.IGNORECASE)
# ARM DAP (PS side): "arm_dap" # ARM DAP / PS indicators: "arm_dap", "ARM Cortex-A9 MPCore", "Cortex-A9", etc.
_ARM_DAP_RE = re.compile(r"^arm_dap$", re.IGNORECASE) _ARM_DAP_RE = re.compile(r"(?:^arm_dap$|ARM\s+Cortex|Cortex-A\d)", re.IGNORECASE)
# hw_server default port # hw_server default port
HW_SERVER_PORT = 3121 HW_SERVER_PORT = 3121
@@ -191,16 +187,17 @@ def check_zynq_jtag(config: Config, callback: Callable | None = None) -> ZynqChe
def _build_jtag_query_tcl() -> str: def _build_jtag_query_tcl() -> str:
"""Build TCL script for xsct JTAG device query. """Build TCL script for xsct JTAG device query.
Uses 'jtag targets' (not 'targets') to get raw JTAG chain devices Uses 'targets -name $id' to enumerate all hardware targets on the
with IDCODE, irlen — the same info that hw_server exposes. JTAG chain. Compatible with Xilinx 2018.32023.2.
Returns: Returns:
TCL script content as string (semicolon-delimited for -eval mode). TCL script content (semicolon-delimited for -eval mode).
""" """
return ( return (
"connect; " "connect; "
'puts "===JTAG_START==="; ' 'puts "===JTAG_START==="; '
"jtag targets; " "set all [targets]; "
'foreach t $all { puts "DEVICE:[targets -name $t]" }; '
'puts "===JTAG_END==="; ' 'puts "===JTAG_END==="; '
"disconnect; " "disconnect; "
"quit" "quit"
@@ -208,17 +205,18 @@ def _build_jtag_query_tcl() -> str:
def _parse_jtag_chain(output: str) -> list[JtagDevice]: def _parse_jtag_chain(output: str) -> list[JtagDevice]:
"""Parse xsct 'jtag targets' output into JtagDevice list. """Parse xsct 'targets -name' output into JtagDevice list.
Expected format (one line per JTAG device): Expected format (one DEVICE: line per target):
1 xc7z100 (idcode 03736093 irlen 4) DEVICE:xc7z100
2 arm_dap (idcode 4BA00477 irlen 4) DEVICE:ARM Cortex-A9 MPCore #0
DEVICE:ARM Cortex-A9 MPCore #1
Args: Args:
output: Combined stdout/stderr from xsct. output: Combined stdout/stderr from xsct.
Returns: Returns:
List of JtagDevice objects for all devices on the JTAG chain. List of JtagDevice objects for all targets on the JTAG chain.
""" """
devices: list[JtagDevice] = [] devices: list[JtagDevice] = []
section = _extract_section(output, "===JTAG_START===", "===JTAG_END===") section = _extract_section(output, "===JTAG_START===", "===JTAG_END===")
@@ -229,12 +227,10 @@ def _parse_jtag_chain(output: str) -> list[JtagDevice]:
line = line.strip() line = line.strip()
if not line: if not line:
continue continue
match = _JTAG_LINE_RE.match(line) if line.startswith("DEVICE:"):
if match: name = line[len("DEVICE:"):].strip()
_idx = match.group(1) if name:
name = match.group(2) devices.append(_classify_jtag_device(name))
idcode = match.group(3)
devices.append(_classify_jtag_device(name, idcode))
return devices return devices