跳转到内容
新建笔记

Vivado 终端命令与 Tcl 批处理

flowchart LR
A["CMD / PowerShell"] -->|"vivado -mode ..."| B["Vivado 启动器"]
B --> C["Vivado Tcl 解释器"]
C --> D["工程、设计对象与实现流程"]
  • vivado -mode batch -source build.tcl 是操作系统终端中的启动命令。
  • open_project、synth_design、get_cells 等是 Vivado 启动后执行的 Tcl 命令。
  • GUI 底部的 Tcl Console 与 -mode tcl、-mode batch 使用同一套 Vivado Tcl 命令。

本文以 Vivado 2020.2 为基准。不同版本的命令选项可能变化,先用本机帮助确认:

终端窗口
vivado -version
vivado -h
模式命令行为适用场景
GUIvivado 或 vivado -mode gui打开图形界面建工程、查看原理图和报告、交互调试
Tclvivado -mode tcl进入交互式 Tcl Shell,不打开 GUI探索命令、检查对象和属性
Batchvivado -mode batch -source build.tcl执行脚本后退出重复构建、CI、批量生成报告

直接打开工程或设计检查点:

终端窗口
vivado D:\work\demo\demo.xpr
vivado D:\work\demo\post_route.dcp
参数作用使用建议
-mode gui、-mode tcl 或 -mode batch选择启动模式,默认 GUI自动化必须明确写 batch
-source script.tcl启动后执行 Tcl 脚本Batch 模式的主要入口
-tclargs ...把后续参数传入脚本的 argc/argv放在命令末尾,避免后续启动参数被当成脚本参数
-init加载 Vivado 的 vivado.tcl 初始化文件只放通用交互设置;可重复构建不要暗中依赖它
-log file指定日志文件,默认 vivado.log自动构建为每次任务指定独立路径
-journal file指定命令日志,默认 vivado.jou.jou 适合回看或重放 Tcl 命令
-nolog / -nojournal不生成对应文件临时查询可用,正式构建通常保留日志
-applog / -appjournal追加而不是覆盖日志需要连续记录时使用,CI 通常更适合每次新文件
-tempDir dir指定临时目录并行任务使用不同且可写的目录
-verbose暂停消息数量限制深度排错时使用,输出会显著增加
-version输出版本并退出环境自检
-robot jar指定 Robot JAR特殊自动化集成,普通 FPGA 流程很少使用
project.xpr / design.dcp打开工程或设计检查点通常用于 GUI/Tcl 交互检查
终端窗口
rem 打开 GUI
vivado -mode gui
rem 进入 Tcl Shell
vivado -mode tcl
rem 执行批处理脚本并分别保存日志
if not exist build mkdir build
call vivado -mode batch -source scripts\build.tcl ^
-log build\vivado.log -journal build\vivado.jou ^
-tclargs xc7a35tfgg484-2 top
echo Exit code: %ERRORLEVEL%
终端窗口
New-Item -ItemType Directory -Force ./build | Out-Null
& vivado -mode batch `
-source scripts/build.tcl `
-log build/vivado.log `
-journal build/vivado.jou `
-tclargs xc7a35tfgg484-2 top
if ($LASTEXITCODE -ne 0) {
throw "Vivado 构建失败,退出码:$LASTEXITCODE"
}

-log 和 -journal 由启动器在执行 Tcl 之前打开,因此目录要先在外层终端创建;脚本里的 file mkdir 来不及补救已经失败的启动日志路径。上例 CMD 使用 call,使它复制到 .cmd/.bat 包装脚本后也会返回执行后面的退出码检查。

Vivado Tcl 对 / 路径分隔符支持良好,脚本和命令行中优先使用 D:/work/demo,可减少反斜杠转义问题。路径含空格时整体加引号:

终端窗口
& 'D:\Xilinx\Vivado\2020.2\bin\vivado.bat' `
-mode batch -source 'D:/FPGA Projects/demo/scripts/build.tcl'

安装程序通常会创建 “Vivado 2020.2 Tcl Shell” 快捷方式,其中已初始化环境。普通 CMD 可先调用安装目录的环境脚本:

终端窗口
call D:\Xilinx\Vivado\2020.2\settings64.bat
vivado -version
where vivado

也可以直接调用 vivado.bat 的完整路径。PowerShell 不能靠直接执行 .bat 永久修改父进程环境;只运行一次任务时,直接调用完整路径最清晰:

终端窗口
& 'D:\Xilinx\Vivado\2020.2\bin\vivado.bat' -version

命令行:

终端窗口
vivado -mode batch -source scripts/build.tcl -tclargs xc7a35tfgg484-2 top

build.tcl:

if {$argc != 2} {
puts stderr "Usage: build.tcl <part> <top>"
exit 2
}
lassign $argv part top
puts "part=$part top=$top"

-tclargs 后的两个值依次进入 argv,argc 为 2。脚本主动执行 exit 2 时,Vivado 2020.2 会把退出码 2 传回 CMD 或 PowerShell。

环境变量通过 Tcl 的全局 env 数组读取:

if {[info exists ::env(BUILD_NUMBER)]} {
puts "build=$::env(BUILD_NUMBER)"
}

敏感信息不要放进 -tclargs、日志或工程属性;命令行参数可能被进程列表和构建日志记录。

路径必须以脚本自身为基准

跳转到“路径必须以脚本自身为基准”

Vivado 的当前目录取决于从哪里启动。不要假定 pwd 就是脚本目录:

set script_dir [file dirname [file normalize [info script]]]
set project_dir [file normalize [file join $script_dir ..]]
set rtl_dir [file join $project_dir rtl]
set build_dir [file join $project_dir build]
file mkdir $build_dir
puts "project_dir=$project_dir"

常用路径命令:

Tcl 命令用途
pwd查看当前工作目录
cd path改变工作目录
info script当前脚本文件名;交互式控制台中可能为空
file normalize path转成规范化绝对路径
file join a b跨平台拼接路径
glob -nocomplain pattern查找文件,无匹配时返回空列表
终端窗口
vivado -mode tcl

进入后先用帮助和对象查询理解设计:

help
help open_project
help get_cells
open_project D:/work/demo/demo.xpr
get_projects
get_files
# 假定 synth_1 已成功完成;先打开综合网表才能查询设计单元。
open_run synth_1
get_cells -hierarchical -filter {REF_NAME =~ FD*}
get_property PART [current_project]
report_property [current_project]
close_project
exit

Vivado Tcl 不是传统 Shell。get_cells 返回设计对象集合,不是普通字符串列表;用 get_property 读属性,用 set_property 写属性,用 report_property 查看可用属性。

已有 .xpr 工程时,脚本只负责打开工程并驱动 run:

set script_dir [file dirname [file normalize [info script]]]
set project [file normalize [file join $script_dir ../demo.xpr]]
set build_dir [file normalize [file join $script_dir ../build]]
file mkdir $build_dir
open_project $project
reset_run synth_1
launch_runs synth_1 -jobs 4
wait_on_run synth_1
if {[get_property PROGRESS [get_runs synth_1]] ne "100%" ||
[get_property STATUS [get_runs synth_1]] ne "synth_design Complete!"} {
error "synth_1 did not complete: [get_property STATUS [get_runs synth_1]]"
}
launch_runs impl_1 -to_step write_bitstream -jobs 4
wait_on_run impl_1
if {[get_property PROGRESS [get_runs impl_1]] ne "100%" ||
[get_property STATUS [get_runs impl_1]] ne "write_bitstream Complete!"} {
error "impl_1 did not complete: [get_property STATUS [get_runs impl_1]]"
}
open_run impl_1
report_timing_summary -file [file join $build_dir timing_summary.rpt]
close_project
exit 0

上例会重置综合 run 及依赖实现结果,适用于由构建任务管理的工程副本;先保存需要保留的旧报告。状态字符串按这里的 Vivado 2020.2 流程核对,换版本或 run 步骤时应检查实际 STATUS。run 完成和 bitstream 生成依然不代表时序与系统验收已经通过。

-jobs 越大不一定越快,综合/实现会占用大量内存。并行任务应同时限制 Vivado 进程数和每个进程的 jobs。

不依赖 .xpr 时,脚本显式描述每个阶段,适合受版本控制的可重复构建:

if {$argc != 2} {
puts stderr "Usage: build.tcl <part> <top>"
exit 2
}
lassign $argv part top
set script_dir [file dirname [file normalize [info script]]]
set root [file normalize [file join $script_dir ..]]
set build_dir [file join $root build]
file mkdir $build_dir
set rtl_files [lsort [glob -nocomplain [file join $root rtl *.sv]]]
if {[llength $rtl_files] == 0} {
puts stderr "No RTL files found"
exit 3
}
if {[catch {
read_verilog -sv {*}$rtl_files
read_xdc [file join $root constraints top.xdc]
synth_design -top $top -part $part
write_checkpoint -force [file join $build_dir post_synth.dcp]
opt_design
place_design
route_design
write_checkpoint -force [file join $build_dir post_route.dcp]
report_timing_summary -file [file join $build_dir timing_summary.rpt]
report_utilization -file [file join $build_dir utilization.rpt]
write_bitstream -force [file join $build_dir ${top}.bit]
} message options]} {
puts stderr "Vivado failed: $message"
if {[dict exists $options -errorinfo]} {
puts stderr [dict get $options -errorinfo]
}
exit 1
}
exit 0

运行:

终端窗口
New-Item -ItemType Directory -Force ./build | Out-Null
& vivado -mode batch -source scripts/build.tcl `
-log build/vivado.log -journal build/vivado.jou `
-tclargs xc7a35tfgg484-2 top

这里的文件排序仅使发现次序稳定;含 package、include 或 IP 的工程还要显式处理源依赖、IP 输出产物和器件参数。

report_timing_summary 能生成报告,但负裕量、关键警告或未约束路径不一定自动让进程失败。正式自动化还应读取 timing/DRC 结果并按项目门槛主动 error 或 exit 1。

文件/输出重点用途
vivado.log完整消息、警告、错误和阶段摘要
vivado.jou执行过的 Tcl 命令,可辅助复现交互操作
.rpttiming、utilization、DRC、clock interaction 等签核报告
.dcp阶段性设计检查点,用于继续运行或定位问题

推荐为每次构建创建独立目录,不要让多个 Vivado 进程共用同一个 .log、.jou、临时目录或工程 run。正常自动构建不建议使用 -nolog -nojournal,否则失败后缺少证据。

PowerShell:

终端窗口
& vivado -mode batch -source scripts/build.tcl
$code = $LASTEXITCODE
if ($code -ne 0) { exit $code }

CMD:

终端窗口
call vivado -mode batch -source scripts\build.tcl
if errorlevel 1 exit /b %ERRORLEVEL%

脚本规则:

  • 参数不合法、源文件缺失和报告未达门槛时明确退出非零。
  • 预期可能失败的命令用 catch 包装,并输出 $message 和 -errorinfo。
  • WARNING 或 CRITICAL WARNING 不等于 Tcl 异常;必须根据项目标准单独判断。
  • 脚本末尾显式 exit 0,失败分支显式 exit 1,让 CI 结果可预测。
现象原因与处理
'vivado' 不是内部或外部命令使用 Vivado Tcl Shell、调用 settings64.bat,或直接运行 vivado.bat 完整路径
运行脚本却打开 GUI忘记 -mode batch
-source 找不到文件当前目录与预期不同;使用绝对路径或基于 [info script] 定位
脚本参数数量不对把 -tclargs 放在命令末尾,并打印 $argc、$argv 检查
生成了 bitstream 但 CI 仍应失败报告未设置硬门槛;增加 timing、DRC、未约束路径检查
GUI 与批处理结果不同比较 Vivado 版本、器件、源文件集合、XDC、策略、增量检查点和初始化脚本
工程被锁定或结果互相覆盖不要让多个进程同时写同一 .xpr、run、日志或临时目录
批处理返回非零从 vivado.log 最早的 ERROR 开始查,不要只看最后一行
  1. GUI 中探索流程,在 Tcl Console 观察对应命令。
  2. 用 write_project_tcl 导出工程创建脚本,作为理解工程配置的起点。
  3. 把器件、源文件、IP、XDC、策略和输出目录收敛到版本控制中的 Tcl。
  4. 终端始终显式给出 -mode、-source、日志路径和 -tclargs。
  5. 保存 .log、关键 .rpt 和退出码;对 timing、DRC 和未约束路径设置失败门槛。

完整 FPGA 阶段职责见 Vivado 从 RTL 到上板,时序报告的判读见 约束与时序收敛。