4、综合入门:Yosys 与 OpenROAD 的集成。运行逻辑综合。查看综合后的网表与报告。
逻辑综合,说白了就是把我们写的 RTL 代码(Verilog/VHDL)翻译成门级网表。这个过程里,工具会做两件大事:一是把行为级描述映射到标准单元库里的具体逻辑门,二是根据你给的时序约束去优化路径。
我个人习惯把综合看作是芯片后端的第一道关卡。这步要是没做好,后面布局布线再怎么折腾也救不回来。今天我们就来走一遍 OpenROAD 里的综合流程,看看 Yosys 是怎么跟 OpenROAD 配合的。
4.1 Yosys 在 OpenROAD 中的角色
OpenROAD 并没有自己重新发明一个综合引擎,它直接集成了 Yosys 作为前端综合工具。Yosys 是一个开源的、可扩展的 Verilog 综合框架,在学术界和工业界都有不少用户。
在 OpenROAD 流程里,Yosys 负责把 RTL 转换成门级网表,然后交给后续的布局布线工具。这个集成做得挺巧妙的——你不需要单独去学 Yosys 的命令行,OpenROAD 的 Tcl 脚本会帮你调用它。
核心流程:
- 输入:RTL 文件(.v)、时序约束(.sdc)、工艺库文件(.lib)
- 工具:Yosys(内嵌于 OpenROAD)
- 输出:门级网表(.v)、综合报告(.rpt)
我曾经在一个项目里遇到过 Yosys 把某个组合逻辑优化过头了,导致功能仿真通过但实际芯片行为不对。后来查了半天,发现是综合时没加 keep 属性。嗯,这里要提醒大家:综合不是越优化越好,功能正确永远是第一位的。
4.2 准备综合环境
在跑综合之前,你得先准备好三样东西:RTL 代码、工艺库、时序约束。OpenROAD 对这三样东西的格式有明确要求。
4.2.1 工艺库文件(.lib)
工艺库是综合的基础。它描述了每个标准单元的延迟、面积、功耗等信息。OpenROAD 使用 Liberty 格式的库文件(.lib)。
对于教学和实验,OpenROAD 官方提供了一个 45nm 的 NangateOpenCellLibrary。你可以在 OpenROAD 的安装目录下找到它。我个人建议初学者先用这个库练手,等熟悉了流程再换自己的工艺库。
| 文件 | 说明 |
|---|---|
NangateOpenCellLibrary_typical.lib |
典型工艺角下的库文件 |
NangateOpenCellLibrary_fast.lib |
快速工艺角下的库文件 |
NangateOpenCellLibrary_slow.lib |
慢速工艺角下的库文件 |
4.2.2 时序约束文件(.sdc)
时序约束告诉综合工具你的设计要跑多快。最基本的约束就是时钟周期。比如你设计的目标频率是 100MHz,那时钟周期就是 10ns。
一个最简单的 SDC 文件长这样:
# 创建时钟
create_clock -name clk -period 10.0 [get_ports clk]
# 设置输入延迟
set_input_delay -clock clk 2.0 [all_inputs]
# 设置输出延迟
set_output_delay -clock clk 2.0 [all_outputs]
你想想看,如果没有时序约束,Yosys 就不知道该怎么优化路径,综合出来的网表可能时序一团糟。我建议你在写约束时,先给一个宽松的周期,等综合通过后再逐步收紧。
4.3 运行综合:Yosys 与 OpenROAD 的集成
在 OpenROAD 里跑综合,你只需要写一个 Tcl 脚本。下面是一个完整的综合脚本示例:
# 读取工艺库
read_liberty /path/to/NangateOpenCellLibrary_typical.lib
# 读取 RTL 文件
read_verilog ./src/top.v
read_verilog ./src/sub_module.v
# 指定顶层模块
link_design top
# 读取时序约束
read_sdc ./constraints/top.sdc
# 运行综合
synth -top top
# 优化
opt
# 写出网表
write_verilog ./results/top_synth.v
# 写出报告
report_area > ./reports/area.rpt
report_timing > ./reports/timing.rpt
report_power > ./reports/power.rpt
这个脚本看起来简单,但每一步都有讲究。我来拆解一下:
- read_liberty:加载工艺库。如果有多个工艺角,可以加载多个库文件。
- read_verilog:读取你的 RTL 代码。注意要按依赖顺序读取,先读底层模块,再读顶层模块。
- link_design:把各个模块连接起来,形成一个完整的设计。
- read_sdc:加载时序约束。
- synth:这是 Yosys 的综合命令。它会做逻辑综合、技术映射。
- opt:优化。Yosys 会做一些简单的优化,比如删除冗余逻辑、合并门单元。
- write_verilog:写出综合后的门级网表。
- report_*:生成面积、时序、功耗报告。
小技巧:如果你在综合时遇到奇怪的错误,可以试试在 synth 命令后面加 -verbose 参数,Yosys 会输出更详细的日志,方便你定位问题。
4.4 综合后的网表长什么样?
综合完成后,你会得到一个门级网表。这个网表不再是 always @(posedge clk) 这样的行为级描述,而是由具体的标准单元组成的结构级描述。
举个例子,一个简单的 D 触发器在综合后的网表里可能是这样的:
DFF_X1 u_dff0 (
.D(net_data),
.CK(clk),
.Q(net_q),
.QN(net_qn)
);
这里的 DFF_X1 就是工艺库里的一个标准单元,X1 表示它的驱动能力。你想想看,同样的功能,用 X1 和 X4 的单元,面积和功耗差别很大。综合工具会根据你的约束自动选择合适的驱动强度。
我曾经在一个低功耗项目里,发现综合工具给所有路径都选了最小尺寸的单元,结果时序完全跑不过。后来加了时序约束,工具才乖乖地给关键路径换上大驱动单元。所以说,约束的质量直接决定了综合结果的好坏。
4.5 解读综合报告
综合完成后,一定要仔细看报告。报告里藏着很多信息,能帮你判断综合结果是否合理。
4.5.1 面积报告
面积报告会告诉你设计用了多少标准单元、组合逻辑面积、时序逻辑面积、总芯片面积。比如:
=== Area Report ===
Combinational area: 12345.67 um^2
Sequential area: 8765.43 um^2
Total area: 21111.10 um^2
Number of cells: 1234
这个数字能帮你判断设计规模。如果面积比你预期的大很多,可能是综合时没加合适的约束,或者 RTL 代码写得不合理。
4.5.2 时序报告
时序报告会列出所有路径的建立时间和保持时间检查结果。重点关注最差的 slack(时序裕量)。如果 slack 是负数,说明这条路径时序不满足。
=== Timing Report ===
Startpoint: u_reg0/CK
Endpoint: u_reg1/D
Path type: setup
Slack: 0.12 ns
Data path delay: 9.88 ns
Clock period: 10.00 ns
这个例子里 slack 是 0.12ns,是正的,说明时序满足。如果 slack 是负的,比如 -0.5ns,那就说明这条路径慢了 0.5ns,需要优化。
4.5.3 功耗报告
功耗报告会给出动态功耗、静态功耗和总功耗。对于低功耗设计,这个报告尤其重要。
=== Power Report ===
Dynamic power: 12.34 mW
Static power: 0.56 mW
Total power: 12.90 mW
注意:综合阶段的功耗估算比较粗略,因为它还没有考虑布局布线的寄生参数。但你可以用它来做相对比较,比如对比不同综合策略下的功耗差异。
4.6 综合流程知识图谱
下面这张图总结了 Yosys 与 OpenROAD 集成的综合流程,以及各阶段的输入输出关系:
4.7 常见问题与避坑指南
综合这一步看着简单,实际跑起来坑不少。我把自己踩过的坑整理了一下:
- 库文件路径问题:OpenROAD 对库文件路径很敏感,建议用路径。我曾经因为用了相对路径,结果换了个目录就跑不通了。
- RTL 代码风格:Yosys 对某些 Verilog 语法支持有限。比如
for循环里的变量声明,有些版本会报错。我建议写 RTL 时尽量用可综合的风格。 - 时序约束不完整:如果忘了加
set_input_delay和set_output_delay,综合工具会默认端口延迟为 0,这会导致综合结果过于乐观。 - 综合时间过长:如果设计很大,综合可能会跑很久。可以试试用
synth -flatten选项,把层次结构打平,有时能加快速度。
我的习惯:每次综合完,我都会先看一眼面积报告里的 cell count。如果这个数字跟预期差太多,我会先怀疑是不是 RTL 代码有问题,而不是急着调约束。
好了,综合这一步我们就讲到这里。你只要按照上面的步骤走一遍,应该能顺利跑通 Yosys 和 OpenROAD 的集成流程。拿到网表和报告后,多看看、多想想,慢慢就能积累出感觉来。