4、综合(Synthesis)实战:Yosys与ABC工具链、逻辑综合策略、面积与时序的权衡

综合,说白了就是把我们写的 RTL 代码,翻译成门级网表。这一步很关键,它直接决定了你的芯片最终能跑多快、占多大面积、功耗怎么样。我刚开始接触 OpenROAD 的时候,觉得综合就是跑个脚本完事,后来踩了不少坑才明白——综合的学问深着呢。

4.1 Yosys 与 ABC 工具链:开源综合的黄金搭档

在 OpenROAD 流程里,综合这活儿主要由 Yosys 和 ABC 两个工具配合完成。Yosys 负责前端处理,把 Verilog 解析、展开、优化;ABC 则负责后端逻辑综合与工艺映射。

我个人习惯把 Yosys 看作「翻译官」,把 ABC 看作「工匠」。翻译官把高级语言转成内部表示,工匠再根据你给的工艺库,把它雕琢成真正的门级电路。

Yosys 的基本流程

一个典型的综合脚本长这样:

# 读取设计文件
read_verilog my_design.v
read_verilog -sv my_interface.sv

# 读取工艺库(Liberty 格式)
read_liberty -lib my_tech.lib

# 层次化展开
hierarchy -check -top my_top

# 逻辑综合与优化
proc; opt; fsm; opt; memory; opt

# 技术映射到工艺库
techmap; opt

# 输出网表
write_verilog synth_netlist.v

这里面的 proc、fsm、memory 这些命令,分别处理过程块、状态机和存储器。每次 opt 都是一轮优化。我在项目中遇到过,有人一口气把所有优化跑完,结果综合出来的面积大得离谱。后来发现,优化要分步走,每一步都看看中间结果,这样更容易定位问题。

ABC 的介入时机

Yosys 做完技术映射后,会调用 ABC 做更精细的逻辑优化。ABC 的核心是 strash(结构化哈希)和 resyn2(重综合)等命令。你可以通过 Yosys 的 abc 命令来调用它:

# 调用 ABC 进行逻辑优化
abc -liberty my_tech.lib -script +strash;scorr;ifraig;retime;strash;dch,-f;map,-M,1,-F,2

# 或者使用预定义的脚本
abc -liberty my_tech.lib -script my_abc_script.abc
我的小技巧:ABC 的脚本参数很灵活。我一般会准备 3-4 个不同策略的脚本,分别侧重面积、时序和平衡。综合时跑一遍对比结果,选最优的那个。

4.2 逻辑综合策略:面积与时序的博弈

综合策略说白了就是怎么在面积和时序之间找平衡。你想想看,一个电路想跑得快,就得用更大的驱动单元,面积自然就上去了。反过来,想省面积,就得用小单元,但时序可能就崩了。

我总结了几种常见的策略:

策略名称 核心思路 适用场景 风险点
面积优先 使用最小面积的单元,减少逻辑深度 成本敏感、频率要求不高的设计 时序容易违规
时序优先 使用大驱动单元,优化关键路径 高频设计、性能关键模块 面积膨胀严重
平衡策略 关键路径用大单元,非关键路径用小单元 大多数通用设计 需要精细调参
低功耗策略 使用低功耗单元,减少翻转活动 电池供电、IoT 设备 时序和面积都可能变差

在 Yosys 里,你可以通过 setattr 命令给特定模块或路径设置不同的综合策略。比如:

# 对关键路径模块使用时序优先
select -module critical_path_module
setattr -mod -set keep_hierarchy 1
abc -liberty my_tech.lib -script +strash;ifraig;retime;map,-M,1,-F,4

# 对非关键路径模块使用面积优先
select -module non_critical_module
abc -liberty my_tech.lib -script +strash;dch,-f;map,-M,0,-F,1
注意:我曾经在一个项目中,对全芯片统一用了时序优先策略,结果面积比预期大了 40%。后来发现,只有约 20% 的路径是真正的关键路径。从那以后,我学会了先跑一次默认综合,分析时序报告,再针对性地调整策略。

4.3 面积与时序的权衡:实战中的取舍

做综合最头疼的就是面积和时序的权衡。这里我分享几个实战经验。

4.3.1 从时序报告入手

综合完成后,第一件事就是看时序报告。Yosys 可以生成详细的时序信息:

# 生成时序报告
report_timing -path end -max_paths 10 -nworst 5 > timing_report.rpt

# 查看面积报告
stat -liberty my_tech.lib > area_report.rpt

拿到报告后,我一般会关注三点:

  • 最差负时序裕量(WNS):负值越大,说明时序越差
  • 总负时序裕量(TNS):所有违规路径的裕量总和,反映整体情况
  • 面积利用率:当前面积占目标面积的百分比

4.3.2 迭代优化的思路

我不会指望一次综合就搞定所有问题。我的做法是:

  1. 第一次综合:用默认策略,拿到基线数据
  2. 分析关键路径:找出 WNS 最差的 10 条路径,看看是什么原因导致的
  3. 调整策略:对关键路径模块使用时序优先,其他模块保持面积优先
  4. 再次综合:对比面积和时序的变化
  5. 重复 2-4 步:直到满足约束

核心原则:不要试图一次把所有路径都修好。每次只修最差的几条,看看面积变化,再决定下一步。我曾经在一个项目中,花了三天时间反复迭代,最终在面积只增加 5% 的情况下,把 WNS 从 -0.5ns 修到了 +0.1ns。

4.3.3 使用 retime 进行时序重分配

ABC 的 retime 命令是个好东西。它可以在不改变逻辑功能的前提下,重新分配寄存器之间的组合逻辑,从而改善时序。

# 在 ABC 脚本中使用 retime
retime -o 1  # 向后移动寄存器
retime -i 1  # 向前移动寄存器

嗯,这里要注意,retime 会改变寄存器的位置,可能会影响仿真和验证。我一般会在综合完成后,用形式验证工具确认功能一致性。

4.4 综合后的检查清单

综合跑完后,别急着往下走。我习惯做一遍检查:

  • 网表完整性:有没有悬空引脚、未连接的线网?
  • 时序收敛性:所有路径的 setup/hold 都满足了吗?
  • 面积合理性:和预估的差距大不大?有没有异常大的模块?
  • 功耗预估:用 report_power 看看动态功耗和静态功耗
  • DRC 检查:有没有扇出过大、过渡时间过长的问题?
避坑指南:我曾经有一次综合完直接跑布局布线,结果在后端发现大量时序违规。回头一查,原来是综合时忘了加输入输出延迟约束。从那以后,我每次综合前都会检查 SDC 约束文件,确保所有端口都有合理的延迟设置。

4.5 本章知识体系

下面这张图总结了综合阶段的核心流程和决策点:

综合阶段知识体系与决策流程 输入:RTL + 工艺库 + 约束 Yosys 前端处理 解析 → 展开 → 优化 → 技术映射 ABC 逻辑综合与工艺映射 strash → ifraig → retime → map 策略决策:面积 vs 时序 vs 功耗 关键路径 → 大驱动单元 | 非关键路径 → 小驱动单元 输出:门级网表 + 时序报告 迭代优化 综合后检查清单 网表完整性 ✓ | 时序收敛 ✓ | 面积合理 ✓ | 功耗预估 ✓ | DRC 检查 ✓

综合不是一锤子买卖,而是一个反复迭代、不断调优的过程。掌握了 Yosys 和 ABC 的工具链,理解了面积与时序的权衡,你就能在开源流程中做出不输商业工具的结果。

可可精品资料库