3、设计输入:理解RTL到GDSII的流程、设计数据准备
好,咱们进入第三章。说实话,很多初学者一上来就急着跑Flow,结果卡在最开始的数据准备上。我见过不少项目,因为一个文件格式不对,整个团队等了两天。所以这一章,咱们把“输入”这件事彻底聊透。
3.1 RTL到GDSII:一张图看懂全流程
先别管OpenROAD具体怎么用,你得先知道芯片设计从代码到光罩,到底经历了什么。我习惯把这过程分成四大阶段:前端逻辑设计、后端物理实现、验证签核、流片。OpenROAD主要覆盖的是后端物理实现这一块。
下面这张图,是我自己总结的“RTL到GDSII核心流程”,你把它存脑子里,后面学起来会顺很多。
说白了,OpenROAD就是帮你把中间那几大步(布图、布局、CTS、布线)自动化跑通。但前提是——你得把“原料”准备好。
3.2 设计数据准备:三大核心文件
我个人习惯把输入文件分成三类:逻辑描述、时序约束、物理库。缺一个,流程就跑不起来。
| 文件类型 | 扩展名 | 内容 | 谁生成 |
|---|---|---|---|
| Verilog | .v | 门级网表(综合后) | 逻辑综合工具 |
| SDC | .sdc | 时序约束(时钟、IO延迟) | 前端设计工程师 |
| LEF | .lef | 工艺库(单元尺寸、引脚位置) | 晶圆厂/PDK |
| DEF | .def | 设计交换(初始布局、电源网格) | 布图规划/IO规划 |
3.2.1 Verilog:你的“电路图纸”
OpenROAD读入的Verilog,必须是综合后的门级网表。不是RTL代码!我刚开始用OpenROAD时犯过这个错,直接把RTL扔进去,结果工具报了一堆“undefined module”。
一个标准的门级网表长这样:
module top (clk, rst, data_in, data_out);
input clk, rst;
input [7:0] data_in;
output [7:0] data_out;
wire [7:0] net1;
DFF_X1 ff1 (.D(data_in[0]), .CK(clk), .Q(data_out[0]));
// ... 其他标准单元例化
endmodule
3.2.2 SDC:给芯片定“规矩”
SDC文件定义了你的芯片要跑多快。没有它,OpenROAD不知道该怎么优化。我见过最惨的案例,就是SDC里忘了约束异步时钟域,结果芯片流片回来,跨时钟域的数据全是乱的。
核心约束就这几条:
# 创建时钟
create_clock -name clk -period 10.0 [get_ports clk]
# 输入延迟
set_input_delay -max 2.0 -clock clk [get_ports data_in]
# 输出延迟
set_output_delay -max 3.0 -clock clk [get_ports data_out]
# 伪路径(异步时钟域)
set_false_path -from [get_clocks clk_a] -to [get_clocks clk_b]
3.2.3 LEF/DEF:物理世界的“地图”
LEF是工艺库的抽象视图。它告诉工具每个标准单元有多大、引脚在哪层、走线规则是什么。DEF则是你的设计在物理空间上的初始布局。
这两者配合使用。LEF是“字典”,DEF是“文章”。
- LEF文件:通常由晶圆厂提供,包含所有标准单元、宏单元、IO单元的物理信息。
- DEF文件:在布图规划阶段生成,定义了芯片尺寸、IO位置、电源网络、以及初始的单元摆放。
OpenROAD读入LEF/DEF的顺序有讲究。我建议:
- 先读LEF(工艺库)
- 再读DEF(设计布局)
- 最后读Verilog(网表)
为什么?因为DEF里可能已经包含了某些单元的初始位置,后读Verilog可以确保网表和物理位置对应上。
3.3 OpenROAD的输入文件格式:别踩这些坑
OpenROAD对文件格式的要求,说白了就一个字:严。它不像商业工具那么“宽容”,格式不对直接报错退出。
| 文件 | 常见坑点 | 我的避坑方法 |
|---|---|---|
| Verilog | 模块名大小写敏感;未定义的cell | 用“read_verilog -golden”检查 |
| SDC | 不支持Tcl过程;时钟名拼错 | 先用“report_clocks”确认 |
| LEF | 版本不匹配(5.7 vs 5.8) | 统一用LEF 5.7格式 |
| DEF | 坐标单位不一致(micron vs 1000) | 检查“UNITS DISTANCE”字段 |
核心原则:所有输入文件必须来自同一个PDK版本。我曾经因为LEF和Verilog的单元定义不一致,查了三天才找到问题——原来是PDK更新后,某个标准单元的引脚名变了。
3.4 一个完整的输入示例
假设你有一个设计叫“my_design”,在OpenROAD里加载它的标准流程是:
# 1. 读入LEF(工艺库)
read_lef /path/to/sky130_fd_sc_hd__lef_tech.lef
read_lef /path/to/sky130_fd_sc_hd__lef_cells.lef
# 2. 读入DEF(初始布局)
read_def /path/to/my_design.def
# 3. 读入Verilog(门级网表)
read_verilog /path/to/my_design.v
# 4. 读入SDC(时序约束)
read_sdc /path/to/my_design.sdc
# 5. 链接设计(把网表和物理库绑定)
link_design my_design
嗯,这里要注意:link_design这一步很容易被忽略。如果不做,后面所有操作都会报“design not linked”。我刚开始就吃过这个亏。
3.5 小结:数据准备清单
在你开始跑OpenROAD之前,对照这个清单检查一遍:
- ✅ 门级网表(.v)—— 综合后,无未定义模块
- ✅ 时序约束(.sdc)—— 时钟、IO延迟、伪路径都写了
- ✅ 工艺LEF(.lef)—— 版本匹配,包含所有用到的单元
- ✅ 设计DEF(.def)—— 坐标单位正确,IO位置已定义
- ✅ 所有文件路径无中文、无空格