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>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
fbfa060b67
commit
88f96fa5fa
+8
-8
@@ -52,16 +52,18 @@ python "$USERPROFILE/.claude/skills/fpga_flash/scripts/<script>.py" [参数...]
|
||||
调用 `check_flash_csv.py`,检查 `xicom_cfgmem_part_table.csv` 中是否已包含 `w25q128bv-spi-x1_x2_x4`:
|
||||
|
||||
```bash
|
||||
python "$USERPROFILE/.claude/skills/fpga_flash/scripts/check_flash_csv.py" \
|
||||
--vivado-dir "D:/Xilinx/Vivado/2018.1"
|
||||
python "$USERPROFILE/.claude/skills/fpga_flash/scripts/check_flash_csv.py"
|
||||
```
|
||||
|
||||
**返回值含义:**
|
||||
- 退出码 `0`:器件已存在,直接进入第二步
|
||||
- 退出码 `2`:已成功添加器件行,需提示用户**重启 Vivado** 后才能识别
|
||||
- 退出码 `1`:CSV 未找到,询问用户提供正确的 Vivado 安装目录后重试
|
||||
- 退出码 `1`:CSV 未找到,检查 `~/skills_env.md` 的 `VIVADO_ROOT` 是否指向有效的 Vivado 安装
|
||||
|
||||
若 Vivado 不在默认路径 `D:/Xilinx/Vivado/2018.1`,询问用户后替换 `--vivado-dir` 的值。
|
||||
**Vivado 安装路径不写死在本 skill 里**:三个脚本都通过 `scripts/vivado_env.py`
|
||||
按 `--vivado-dir` > 环境变量 > `~/skills_env.md` 的 `VIVADO_ROOT`(退化到 `VIVADO_PATH`)
|
||||
的顺序解析。换机器只改 `~/skills_env.md`,不改 skill。仅在需要临时用另一套 Vivado
|
||||
时才显式传 `--vivado-dir`。
|
||||
|
||||
---
|
||||
|
||||
@@ -88,12 +90,11 @@ python "$USERPROFILE/.claude/skills/fpga_flash/scripts/check_flash_csv.py" \
|
||||
|
||||
```bash
|
||||
python "$USERPROFILE/.claude/skills/fpga_flash/scripts/gen_mcs.py" \
|
||||
--vivado-dir "D:/Xilinx/Vivado/2018.1" \
|
||||
--bit-file "E:/Xilinx_design/smod/SMOD_DTMB_CG/RU_golden/RU_golden.runs/impl_1/RU_golden_top.bit" \
|
||||
--mcs-file "E:/Xilinx_design/smod/SMOD_DTMB_CG/RU_golden/RU_golden.runs/impl_1/RU_golden_smod.mcs"
|
||||
```
|
||||
|
||||
将示例路径替换为用户实际的 Vivado 安装路径、.bit 文件路径、.mcs 输出路径。
|
||||
将示例路径替换为用户实际的 .bit 文件路径、.mcs 输出路径(Vivado 路径自动解析,见第一步)。
|
||||
|
||||
**验证成功的标志:** 输出中包含 `write_cfgmem completed successfully` 且显示 `0 Errors`。
|
||||
|
||||
@@ -105,7 +106,6 @@ python "$USERPROFILE/.claude/skills/fpga_flash/scripts/gen_mcs.py" \
|
||||
|
||||
```bash
|
||||
python "$USERPROFILE/.claude/skills/fpga_flash/scripts/program_flash.py" \
|
||||
--vivado-dir "D:/Xilinx/Vivado/2018.1" \
|
||||
--flash-part "w25q128bv-spi-x1_x2_x4" \
|
||||
--bit-file "E:/Xilinx_design/smod/SMOD_DTMB_CG/RU_golden/RU_golden.runs/impl_1/RU_golden_top.bit" \
|
||||
--mcs-file "E:/Xilinx_design/smod/SMOD_DTMB_CG/RU_golden/RU_golden.runs/impl_1/RU_golden_smod.mcs" \
|
||||
@@ -149,7 +149,7 @@ ILA core 的 `Dropping logic core` WARNING 是正常现象(载入 loader/golde
|
||||
|
||||
| 现象 | 可能原因 | 解决方法 |
|
||||
|------|----------|----------|
|
||||
| `check_flash_csv.py` 退出码 1 | Vivado 不在默认路径 | 询问用户,更换 `--vivado-dir` 参数 |
|
||||
| `check_flash_csv.py` 退出码 1 | `VIVADO_ROOT` 未配置或指错 | 修正 `~/skills_env.md` 的 `VIVADO_ROOT`;临时可传 `--vivado-dir` 覆盖 |
|
||||
| Vivado 中找不到 w25q128bv | CSV 已修改但 Vivado 未重启 | 提示用户重启 Vivado 后重新执行 |
|
||||
| `No hardware target` 错误 | JTAG 未连接或板卡未上电 | 检查连接后重新执行第四步 |
|
||||
| DONE 灯不亮 | 启动模式跳线错误 | 检查 MODE 引脚电平,确认为 SPI 启动模式 |
|
||||
|
||||
@@ -6,7 +6,8 @@ Checks whether 'w25q128bv-spi-x1_x2_x4' is present in Vivado's
|
||||
xicom_cfgmem_part_table.csv. If not, appends the correct row.
|
||||
|
||||
Usage:
|
||||
python check_flash_csv.py --vivado-dir "D:/Xilinx/Vivado/2018.1"
|
||||
python check_flash_csv.py # Vivado path from ~/skills_env.md
|
||||
python check_flash_csv.py --vivado-dir "<install root>" # or override it
|
||||
|
||||
Exit codes:
|
||||
0 = device already present (no changes made)
|
||||
@@ -17,6 +18,8 @@ import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
from vivado_env import resolve_vivado_dir
|
||||
|
||||
DEVICE_NAME = "w25q128bv-spi-x1_x2_x4"
|
||||
# Fields: NAME, MEM_DEVICE, MEM_TYPE, MEM_DENSITY, DATA_WIDTH,
|
||||
# MEM_MANUFACTURER, NUM_CFG_FILES, MEM_DEVICE_ALIAS, MEM_FAMILY
|
||||
@@ -29,13 +32,14 @@ def main():
|
||||
)
|
||||
parser.add_argument(
|
||||
"--vivado-dir",
|
||||
required=True,
|
||||
help="Vivado install root, e.g. D:/Xilinx/Vivado/2018.1",
|
||||
default=None,
|
||||
help="Vivado install root; defaults to VIVADO_ROOT from ~/skills_env.md",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
csv_path = os.path.join(
|
||||
args.vivado_dir, "data", "xicom", "xicom_cfgmem_part_table.csv"
|
||||
resolve_vivado_dir(args.vivado_dir),
|
||||
"data", "xicom", "xicom_cfgmem_part_table.csv"
|
||||
)
|
||||
csv_path = csv_path.replace("\\", "/")
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ via -tclargs so no temporary script files are created.
|
||||
|
||||
Usage:
|
||||
python gen_mcs.py \
|
||||
--vivado-dir "D:/Xilinx/Vivado/2018.1" \
|
||||
--bit-file "E:/project/RU_golden/RU_golden.runs/impl_1/RU_golden_top.bit" \
|
||||
--mcs-file "E:/project/RU_golden/RU_golden.runs/impl_1/RU_golden_smod.mcs"
|
||||
|
||||
@@ -20,6 +19,8 @@ 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)."""
|
||||
@@ -32,8 +33,8 @@ def main():
|
||||
)
|
||||
parser.add_argument(
|
||||
"--vivado-dir",
|
||||
required=True,
|
||||
help="Vivado install root, e.g. D:/Xilinx/Vivado/2018.1",
|
||||
default=None,
|
||||
help="Vivado install root; defaults to VIVADO_ROOT from ~/skills_env.md",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--bit-file",
|
||||
@@ -47,7 +48,7 @@ def main():
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
vivado_dir = norm(args.vivado_dir)
|
||||
vivado_dir = norm(resolve_vivado_dir(args.vivado_dir))
|
||||
bit_file = norm(args.bit_file)
|
||||
mcs_file = norm(args.mcs_file)
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ via -tclargs so no temporary script files are created.
|
||||
|
||||
Usage:
|
||||
python program_flash.py \
|
||||
--vivado-dir "D:/Xilinx/Vivado/2018.1" \
|
||||
--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" \
|
||||
@@ -29,6 +28,8 @@ 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)."""
|
||||
@@ -41,8 +42,8 @@ def main():
|
||||
)
|
||||
parser.add_argument(
|
||||
"--vivado-dir",
|
||||
required=True,
|
||||
help="Vivado install root, e.g. D:/Xilinx/Vivado/2018.1",
|
||||
default=None,
|
||||
help="Vivado install root; defaults to VIVADO_ROOT from ~/skills_env.md",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--flash-part",
|
||||
@@ -66,7 +67,7 @@ def main():
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
vivado_dir = norm(args.vivado_dir)
|
||||
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 ""
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Resolve the machine-local Vivado install path.
|
||||
|
||||
The install path differs per machine (C:\\Xilinx here, D:\\Xilinx elsewhere), so it
|
||||
is never hardcoded in a skill. It lives in ~/skills_env.md, which stays out of git.
|
||||
Precedence: explicit --vivado-dir > OS env var > ~/skills_env.md.
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
def env_lookup(key, default=None):
|
||||
"""Read KEY from the OS environment, else from a `KEY = value` line in
|
||||
~/skills_env.md. Trailing `# comments` are stripped."""
|
||||
v = os.environ.get(key)
|
||||
if v:
|
||||
return v
|
||||
path = os.path.join(os.path.expanduser("~"), "skills_env.md")
|
||||
try:
|
||||
with open(path, encoding="utf-8") as f:
|
||||
for line in f:
|
||||
m = re.match(rf"\s*{re.escape(key)}\s*=\s*(.+?)\s*(?:#.*)?$", line)
|
||||
if m:
|
||||
val = m.group(1).strip()
|
||||
# Placeholders like `<未安装>` mean "not configured on this machine".
|
||||
if val and not val.startswith("<"):
|
||||
return val
|
||||
except OSError:
|
||||
pass
|
||||
return default
|
||||
|
||||
|
||||
def resolve_vivado_dir(cli_value=None):
|
||||
"""Vivado install ROOT (the dir containing bin/vivado.bat)."""
|
||||
if cli_value:
|
||||
return cli_value
|
||||
root = env_lookup("VIVADO_ROOT")
|
||||
if root:
|
||||
return root
|
||||
exe = env_lookup("VIVADO_PATH")
|
||||
if exe:
|
||||
# .../<root>/bin/vivado.bat -> <root>
|
||||
return os.path.dirname(os.path.dirname(exe))
|
||||
sys.exit(
|
||||
"Vivado path not configured. Add `VIVADO_ROOT = <install root>` to "
|
||||
"~/skills_env.md, set it as an env var, or pass --vivado-dir."
|
||||
)
|
||||
|
||||
|
||||
def resolve_vivado_exe(cli_value=None):
|
||||
"""Full path to bin/vivado.bat."""
|
||||
if cli_value:
|
||||
return cli_value
|
||||
exe = env_lookup("VIVADO_PATH")
|
||||
if exe:
|
||||
return exe
|
||||
return os.path.join(resolve_vivado_dir(), "bin", "vivado.bat")
|
||||
@@ -34,7 +34,41 @@ IMPL = os.path.join(REPO, "my_exciter.runs", "impl_1")
|
||||
POST_BITSTREAM = os.path.join(TCL_DIR, "post_bitstream.tcl")
|
||||
GEN_RU = os.path.join(TCL_DIR, "runScript_GenRu.tcl")
|
||||
PERL_SCRIPT = os.path.join(TCL_DIR, "MakeSpiFlashProgrammerMcsFiles_backup.pl")
|
||||
DEFAULT_VIVADO = r"D:\Xilinx\Vivado\2018.1\bin\vivado.bat"
|
||||
|
||||
|
||||
def _env_lookup(key, default=None):
|
||||
"""Machine-local values (paths, IPs) live in ~/skills_env.md, never in git.
|
||||
An OS environment variable of the same name overrides the file."""
|
||||
v = os.environ.get(key)
|
||||
if v:
|
||||
return v
|
||||
path = os.path.join(os.path.expanduser("~"), "skills_env.md")
|
||||
try:
|
||||
with open(path, encoding="utf-8") as f:
|
||||
for line in f:
|
||||
m = re.match(rf"\s*{re.escape(key)}\s*=\s*(.+?)\s*(?:#.*)?$", line)
|
||||
if m:
|
||||
val = m.group(1).strip()
|
||||
if val and not val.startswith("<"):
|
||||
return val
|
||||
except OSError:
|
||||
pass
|
||||
return default
|
||||
|
||||
|
||||
def resolve_vivado():
|
||||
"""Vivado's install path differs per machine -- never hardcode it."""
|
||||
exe = _env_lookup("VIVADO_PATH")
|
||||
if exe:
|
||||
return exe
|
||||
root = _env_lookup("VIVADO_ROOT")
|
||||
if root:
|
||||
return os.path.join(root, "bin", "vivado.bat")
|
||||
sys.exit(
|
||||
"Vivado path not configured. Add `VIVADO_PATH = <...>/bin/vivado.bat` to "
|
||||
"~/skills_env.md, set it as an env var, or pass --vivado."
|
||||
)
|
||||
|
||||
|
||||
# runScript_GenRu.tcl hardcodes this name.
|
||||
BASE_MCS = "atsc_exciter.mcs"
|
||||
@@ -66,10 +100,12 @@ def first_ela(path):
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
ap.add_argument("--vivado", default=DEFAULT_VIVADO)
|
||||
ap.add_argument("--vivado", default=None,
|
||||
help="path to vivado.bat; defaults to VIVADO_PATH from ~/skills_env.md")
|
||||
ap.add_argument("--tag", help="rename the result to <tag>_update.mcs so it survives the next run")
|
||||
ap.add_argument("--keep-byproducts", action="store_true")
|
||||
args = ap.parse_args()
|
||||
args.vivado = args.vivado or resolve_vivado()
|
||||
|
||||
for path, what in ((args.vivado, "vivado"), (POST_BITSTREAM, "post_bitstream.tcl"),
|
||||
(GEN_RU, "runScript_GenRu.tcl"), (PERL_SCRIPT, "perl script")):
|
||||
|
||||
@@ -29,7 +29,7 @@ FPGA 做 8VSB 调制 / DPD / AGC / TS 前处理,imx6 跑 `atsc_app`(配置 A
|
||||
| 激励器 Vivado 工程 | `E:\Xilinx_design\smod\SMOD_ATSC\my_exciter\my_exciter.xpr`(top = `smod_top`,也是 **git 仓库根**) |
|
||||
| 打底 golden 工程 | `E:\Xilinx_design\smod\SMOD_ATSC\RU_golden\RU_golden.xpr`(top = `RU_golden_top`) |
|
||||
| FPGA / Flash | `xc7a200tfbg676-2` / Winbond **w25q128bv**(128 Mbit = 16 MB,SPIx1) |
|
||||
| Vivado | `D:\Xilinx\Vivado\2018.1`(`bin\vivado.bat`) |
|
||||
| Vivado | 见 `~\skills_env.md` 的 `VIVADO_ROOT`(其下 `bin\vivado.bat`)——路径因机器而异,不要写死盘符 |
|
||||
| imx6 源码 | `my_exciter\imx6\src\atsc_app`(Makefile 在该目录根) |
|
||||
| imx6 设备 | `192.168.1.143`,用户 `root`,密码见 `~\skills_env.md` 的 `SMOD_SSH_PASS`(网页 + SSH;Windows 主机 `192.168.1.125` 同网段) |
|
||||
| 交叉编译 VM | `bowei@192.168.223.128`,密码见 `~\skills_env.md` 的 `CROSS_VM_PASS`,构建目录 `~/atsc_head_build` |
|
||||
|
||||
@@ -27,7 +27,8 @@ CONDA_LANGGRAPH_PYTHON = C:\Users\<user>\.conda\envs\langgraph\python.exe
|
||||
## EDA / 硬件工具
|
||||
|
||||
```
|
||||
VIVADO_PATH = D:\Xilinx\Vivado\2018.1\bin\vivado.bat
|
||||
VIVADO_ROOT = <Vivado 安装根目录,如 C:\Xilinx\Vivado\2018.1 —— 必须实测,不同机器盘符不同>
|
||||
VIVADO_PATH = <上一行 + \bin\vivado.bat>
|
||||
KICAD_PYTHONPATH = C:\Program Files\KiCad\10.0\bin\Lib\site-packages
|
||||
MATLAB_MCP_EXE = C:\Users\<user>\.matlab\agentic-toolkits\bin\matlab-mcp-server.exe
|
||||
```
|
||||
|
||||
@@ -28,23 +28,28 @@ This skill helps you generate TCL scripts for automatically creating Xilinx Viva
|
||||
|
||||
## IMPORTANT: Vivado Installation Check (Step 0 - REQUIRED)
|
||||
|
||||
**Before asking any questions, you MUST first check if Vivado is installed at the default location.**
|
||||
**Before asking any questions, you MUST first resolve and verify the Vivado install path.**
|
||||
|
||||
Use the Bash tool to check if the default Vivado installation path exists:
|
||||
The install path is machine-local and is **never hardcoded in this skill**. Read
|
||||
`VIVADO_ROOT` from `~/skills_env.md` (an env var of the same name overrides it),
|
||||
then verify it:
|
||||
|
||||
```bash
|
||||
test -d "d:/Xilinx/Vivado/2018.1/bin" && echo "EXISTS" || echo "NOT_FOUND"
|
||||
VIVADO_ROOT=$(sed -n 's/^[[:space:]]*VIVADO_ROOT[[:space:]]*=[[:space:]]*//p' ~/skills_env.md | head -1)
|
||||
test -d "$VIVADO_ROOT/bin" && echo "EXISTS: $VIVADO_ROOT" || echo "NOT_FOUND"
|
||||
```
|
||||
|
||||
- If the result is `EXISTS`: Proceed to Step 1 (interactive questions)
|
||||
- If the result is `EXISTS`: use that value as `{{VIVADO_PATH}}`, proceed to Step 1
|
||||
- If the result is `NOT_FOUND`: **Stop and report error to the user:**
|
||||
|
||||
```
|
||||
错误 / Error: Vivado 没有正确安装!
|
||||
错误 / Error: 找不到 Vivado 安装!
|
||||
|
||||
请确认 Vivado 已安装在默认路径: d:\Xilinx\Vivado\2018.1\bin\
|
||||
请在 ~/skills_env.md 中把 VIVADO_ROOT 设为实际的 Vivado 安装根目录
|
||||
(该目录下应有 bin\vivado.bat)。
|
||||
|
||||
Please ensure Vivado is installed at: d:\Xilinx\Vivado\2018.1\bin\
|
||||
Please set VIVADO_ROOT in ~/skills_env.md to your actual Vivado install root
|
||||
(the directory containing bin\vivado.bat).
|
||||
```
|
||||
|
||||
## IMPORTANT: Interactive Question Requirements
|
||||
@@ -549,7 +554,7 @@ Replace the template variables with user-provided values:
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `{{VIVADO_PATH}}` | Vivado installation path (always: `D:/Xilinx/Vivado/2018.1`) |
|
||||
| `{{VIVADO_PATH}}` | Vivado installation path — resolved in Step 0 from `VIVADO_ROOT` in `~/skills_env.md`; never hardcode a drive letter |
|
||||
| `{{PROJECT_NAME}}` | Project name |
|
||||
| `{{DEVICE_PART}}` | FPGA part number |
|
||||
| `{{TIMESTAMP}}` | Current date/time |
|
||||
|
||||
Reference in New Issue
Block a user