4、综合(Yosys + ABC):Yosys 逻辑综合流程、ABC 技术映射、面积与时序优化策略、综合脚本编写
综合,说白了就是把 RTL 代码翻译成门级网表。这一步做不好,后面 P&R 再怎么折腾也救不回来。我见过不少新手,RTL 仿真跑得欢,一综合就崩,其实就是没搞懂 Yosys 和 ABC 到底在干什么。
这一章,咱们就聊聊 OpenROAD 里的综合流程。我会把 Yosys 的逻辑综合、ABC 的技术映射,以及面积和时序的平衡策略,掰开揉碎了讲清楚。
4.1 Yosys 逻辑综合流程
Yosys 是 OpenROAD 的前端综合工具。它的核心任务就两个:读入 RTL 和 做逻辑优化。
我个人习惯把 Yosys 的流程分成三步:
- 读入设计:把 Verilog 或 VHDL 吃进来,解析成内部的数据结构。
- 高层次优化:做常量传播、资源共享、状态机编码等操作。
- 逻辑综合:把行为级描述转换成布尔逻辑表达式。
这里有个关键点:Yosys 默认不会做太多面积优化。它更擅长把 RTL 翻译成 通用逻辑,然后交给 ABC 去做技术映射。所以,别指望 Yosys 一步到位给你最优网表。
proc 和 opt 命令。特别是 opt_clean -purge,能帮你干掉那些没用的线网和模块。有一次我接手一个老项目,综合出来的网表比预期大了 30%,一查发现是遗留的 debug 逻辑没清理干净。跑一遍 opt_clean,面积直接降下来了。
4.2 ABC 技术映射
Yosys 做完逻辑综合后,会生成一个 与或图。这个图是抽象的,跟具体的工艺库没关系。ABC 的作用,就是把这个抽象图,映射到你的目标工艺库上。
ABC 的核心是 标准单元库。它会把 Yosys 生成的逻辑节点,拆成一个个标准单元,比如 AND、OR、NAND、NOR、MUX 等等。这个过程叫 技术映射。
我刚开始用 ABC 时,总觉得它是个黑盒子。后来踩过几次坑,才摸清楚它的脾气。ABC 的优化策略,说白了就三个方向:
| 优化方向 | ABC 命令 | 效果 |
|---|---|---|
| 面积优先 | strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf -K 6; &put |
减少标准单元数量,但可能牺牲时序 |
| 时序优先 | strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf -K 8; &put |
优化关键路径延迟,但面积会变大 |
| 平衡模式 | strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf -K 6; &put -m |
在面积和时序之间取折中 |
你看,命令里有个 -K 参数,它控制的是 LUT 大小。K 值越大,ABC 越倾向于用更复杂的逻辑门,时序会更好,但面积会更大。K 值越小,逻辑门越简单,面积小,但路径延迟可能变长。
4.3 面积与时序优化策略
综合阶段的优化,说白了就是 面积和时序的博弈。你不可能既要马儿跑,又要马儿不吃草。但我们可以通过一些策略,找到那个平衡点。
我总结了几条实战经验:
- 先跑一遍面积优化:用
synth -top <module>做一次基础综合,看看面积基线是多少。 - 再跑一遍时序优化:用
synth -top <module> -timing,看看时序瓶颈在哪。 - 对比两次结果:如果面积差在 10% 以内,但时序改善了 20%,那时序优化就是值得的。
- 手动干预关键路径:对于特别关键的路径,可以在 RTL 里手动实例化一些特殊单元,比如时钟门控、多路选择器,让 Yosys 和 ABC 少做决策。
为什么会这样?因为自动综合工具再聪明,也猜不到你的设计意图。你告诉它“这里要快”,它只能通过增加逻辑门来缩短路径。但如果你在 RTL 里直接写清楚“这里用 MUX 而不是 if-else”,它就能少走弯路。
case 语句,综合工具把它优化成了一个巨大的优先级编码器。改成 parallel_case 后,面积没变,时序直接达标。所以,写 RTL 时就要想着综合工具的感受。
4.4 综合脚本编写
在 OpenROAD 里,综合脚本通常用 Tcl 写。我习惯把脚本分成几个部分:读入设计、设置约束、运行综合、输出结果。
下面是一个我常用的脚本模板:
# 读入设计
read_verilog rtl/top.v
read_verilog rtl/sub_module.v
# 设置顶层模块
synth -top top
# 设置时序约束
create_clock -name clk -period 10 [get_ports clk]
set_input_delay -clock clk 2 [all_inputs]
set_output_delay -clock clk 2 [all_outputs]
# 运行综合
synth -top top -timing
# 输出网表
write_verilog -noexpr outputs/top_synth.v
# 输出时序报告
report_timing -max_paths 10 > outputs/timing.rpt
# 输出面积报告
report_area > outputs/area.rpt
这个脚本看起来简单,但有几个细节要注意:
- 时钟约束一定要准确:周期设错了,后面所有优化都是白费。
- 输入输出延迟要合理:设得太紧,综合工具会拼命优化,面积爆炸;设得太松,时序可能不达标。
- 多跑几次报告:综合完成后,一定要看时序报告和面积报告。别偷懒,这一步能帮你发现很多问题。
嗯,这里还要提一句。OpenROAD 的 Yosys 和 ABC 是深度集成的,你不需要手动调用 ABC。但如果你想精细控制,可以在脚本里加 abc -script <script> 命令,指定 ABC 的优化脚本。不过,对于大多数项目,默认配置已经够用了。
最后,我建议你把综合脚本和 RTL 代码一起纳入版本管理。这样,每次综合的结果都能复现,出了问题也能快速回滚。