Vivado增量编译:提高实现与综合效率
FPGA 工程改一行代码就要跑一次全量编译,等半小时是常事。增量编译能让这个等待降到几分钟。
本文覆盖 Vivado 增量实现和增量综合的 GUI / Tcl 操作、工作原理、适用边界和常见陷阱。
一、增量编译解决什么问题
Vivado 全量编译走完 synth → place → route → bitgen 一条线,设计越大等待越久。增量编译(Incremental Compile)的思路很简单:上一次成功的结果存为参考 Checkpoint(.dcp),本次只对改过的部分重新处理,没改的部分直接复用。
Vivado 把增量编译拆成两个独立的维度:
| 维度 | 作用阶段 | 做了什么 |
|---|---|---|
| 增量综合(Incremental Synthesis) | 综合 | 未修改的模块复用上次综合结果,只重综合变化的模块 |
| 增量实现(Incremental Implementation) | 布局布线 | 参考已布线的 .dcp,优先保持未修改逻辑的布局,只重新布局布线修改部分 |
实践中增量实现是主力——综合本身占总编译时间的比例不大,真正慢的是 place 和 route。
二、使用前提
增量编译不是无条件开箱即用的,满足以下条件才能生效:
| # | 前提 | 说明 |
|---|---|---|
| 1 | 有一次成功的全量基线 | 必须有一次完整的 synth→impl 成功运行,且时序已收敛 |
| 2 | 改动量不大 | 建议修改不超过总逻辑的 20%。改动太大,增量退化为变相全量,甚至比全量更差 |
| 3 | 参考 Checkpoint 可用 | 综合需要 synth.dcp,实现需要 routed.dcp。别让 Vivado 自动清理掉 |
| 4 | 顶层结构不变 | 模块实例化层次、接口、顶层端口未发生结构性变化 |
三、增量实现(主力场景)
增量实现参考上一次的 routed.dcp,对未修改的逻辑尽量保持原位,只挪动改过的部分。
3.1 工程模式 — GUI 三步
前提:routed.dcp 已经在 <project>.runs/impl_1/ 下。
- Settings → Project Settings → Implementation
- 找到 Incremental compile 选项,点右侧文件选择按钮
- 选择上一次实现的
<设计名>_routed.dcp→ OK → 正常 Run Implementation
Vivado 检测到参考 .dcp 后自动切换增量模式,不需要额外勾选。
3.2 非工程模式 — Tcl
脚本化流程更干净,适合 CI/回归:
# 增量布局
place_design -incremental <reference_routed.dcp>
# 增量布线
route_design -incremental <reference_routed.dcp>
# 报告
report_timing_summary
report_utilization
place_design 和 route_design 都建议加 -incremental,只做一步收益打折。
3.3 工作原理
全量实现(基线) 增量实现(迭代)
┌─────────────┐ ┌─────────────┐
│ 综合 │ │ 综合 │
└──────┬──────┘ └──────┬──────┘
│ │
┌──────▼──────┐ ┌──────▼──────┐
│ 布局 (place) │ │ 增量布局 │ ← 参考基线,只挪改动部分
└──────┬──────┘ └──────┬──────┘
│ │
┌──────▼──────┐ ┌──────▼──────┐
│ 布线 (route) │ │ 增量布线 │ ← 参考基线,只重布改动路径
└──────┬──────┘ └──────┬──────┘
│ │
┌──────▼──────┐ ┌──────▼──────┐
│ routed.dcp │ │ routed.dcp │
└─────────────┘ └─────────────┘
Vivado 通过对比参考 Checkpoint 和当前网表,识别哪些 cell/net 发生了变化,只对这些做增量处理。
四、增量综合(辅助场景)
增量综合对未修改的模块跳过综合步骤,直接复用参考 Checkpoint 的结果。只适用于 RTL 改动很小且想保持综合一致性的场景。
4.1 工程模式
Settings → Project Settings → Synthesis → Incremental compile → 选择 synth.dcp → Run Synthesis。
4.2 非工程模式
synth_design -incremental <reference_synth.dcp>
4.3 为什么增量综合不如增量实现实用
| 原因 | 说明 |
|---|---|
| 综合时间占比小 | 整体编译的瓶颈在 place & route,不在 synth |
| RTL 改动敏感 | 一个 always 块的改动可能导致大量逻辑重新综合,复用率低于预期 |
| 质量风险 | 参考 Checkpoint 与当前设计不完全匹配时,Vivado 做保守处理,综合结果可能比全量差 |
结论: 先把增量实现用好。增量综合只在修改量极小(改了几个参数常量、改了一行赋值)时才考虑开。
五、Incremental Compile 选项速查
| 设置 | 行为 | 什么时候用 |
|---|---|---|
| 不指定(默认) | 全量编译 | 首次运行、设计大改、基线未收敛 |
| 指定 .dcp 路径 | 增量模式,参考该 Checkpoint | 小改动迭代调试 |
| 自动获取(部分版本支持) | 自动用上一次运行的 Checkpoint | 连续增量迭代 |
六、最佳实践
- 全量和增量轮流来:每 3~5 次增量后跑一次全量,避免增量退化累积——布局质量每次增量都会轻微下降
- 备份参考 .dcp:全量成功后将
routed.dcp复制到工程外目录,防止被reset_project或 IDE 清理 - 基线必须收敛:参考 Checkpoint 本身有时序违例的话,增量结果只会继承这些违例
- 先看改动范围:跑增量前用 Report 对比 LUT/FF 变化量,超过 20% 直接上全量
- CI/CD 用 Tcl 脚本:非工程模式控制更精细,适合自动化回归
七、常见问题速查
| 问题 | 原因 | 解决 |
|---|---|---|
| 增量实现后时序反而变差 | 改动量过大或参考基线未收敛 | 跑一次全量实现,换新的参考 .dcp |
| 报 "Reference checkpoint not found" | .dcp 路径错误或文件被清理 | 检查路径,确认文件可访问 |
| 增量结果与预期不一致 | RTL 结构性变化(接口改名、层次变化) | 跑全量验证,确认顶层结构未变 |
| 增量综合后面积变大 | 参考与当前逻辑不匹配,Vivado 保守处理 | 改用全量综合 |
| 增量优化的效果不明显 | 增量模式下 Vivado 优化策略偏保守 | 最终发布版本用全量跑 |
八、总结
Vivado 增量编译的精髓就一句:用上次的布局布线结果当锚点,这次只搬动过的东西。
- 增量实现是主力,GUI 选个 .dcp 就行,Tcl 加个
-incremental参数 - 增量综合是添头,收益有限,别抱太大期望
- 前提是基线时序收敛 + 改动不超过 20% + 顶层结构不变
- 每几次增量后跑一次全量,防止退化累积
掌握这个节奏,FPGA 迭代调试的等待时间能砍掉一大半。
浙公网安备 33010602011771号