设计输入与数据准备:把芯片设计的“食材”备齐

各位同学,咱们正式开始动手之前,得先把“食材”备齐。做后端设计,说白了就是拿着前端同事给的图纸,去工厂里把芯片造出来。图纸是什么?就是 Verilog 网表。工厂的工艺参数是什么?就是 Liberty、LEF 这些库文件。还有你的设计目标——频率、面积、功耗,这些都写在 SDC 约束里。

我刚开始用 OpenROAD 的时候,就犯过一个低级错误:库文件版本没对齐,结果跑出来的时序全是乱的。排查了两天才发现,原来是 Liberty 和 LEF 的 PVT 条件不一致。从那以后,我每次建新项目,第一件事就是核对这四类文件的版本和匹配关系。

好,咱们一个一个来看。

Verilog 网表输入:设计的“骨架”

Verilog 网表,就是前端综合后的门级网表。它描述了标准单元、宏单元以及它们之间的连线关系。OpenROAD 读入网表很简单,一条命令搞定:

read_verilog ./results/synth/design.v

但这里有几个坑,我帮你列出来:

  • 网表必须综合后:RTL 代码不能直接拿来用,必须经过逻辑综合,映射到目标工艺库的标准单元。
  • 避免黑盒:网表里如果出现未定义的模块(黑盒),OpenROAD 会报 warning,但不会停。不过到了布局布线阶段,这些黑盒会变成障碍物,影响时序和面积。
  • 层次化 vs 扁平化:我个人习惯用扁平化网表,调试起来方便。如果设计太大,可以用层次化,但要注意顶层和子模块的端口匹配。
小技巧:读入网表后,用 check_design 命令快速验证一下。它能帮你发现悬空引脚、未连接端口这类低级问题。

Liberty 库文件配置:时序的“标尺”

Liberty 文件(.lib)是工艺厂提供的时序库。它定义了每个标准单元的延迟、功耗、转换时间等参数。OpenROAD 读入 Liberty 的命令是:

read_liberty ./lib/slow.lib
read_liberty ./lib/fast.lib

为什么需要多个库?因为芯片在不同电压、温度、工艺角下,表现不一样。我们通常需要至少两个库:

库类型 PVT 条件 用途
slow.lib 低电压、高温、慢工艺 建立时间检查(setup)
fast.lib 高电压、低温、快工艺 保持时间检查(hold)

嗯,这里要注意:读入顺序不重要,但你必须确保所有库的 PVT 条件与你的设计目标一致。我曾经见过有人把 0.9V 的库和 1.2V 的库混在一起用,结果时序分析完全不准。

避坑指南:如果你用的是多电压域设计,每个电压域都要有对应的 Liberty 库。OpenROAD 支持多库同时读入,但你要在 SDC 里明确指定每个域的电压值。

LEF/DEF 文件解析:物理的“蓝图”

LEF(Library Exchange Format)描述的是单元的物理信息:尺寸、引脚位置、布线阻挡层等。DEF(Design Exchange Format)描述的是整个芯片的物理布局:单元的位置、走线、电源网络等。

读入命令很简单:

read_lef ./lib/tech.lef
read_lef ./lib/cells.lef
read_def ./results/floorplan/design.def

这里我展开讲讲 LEF 文件的层级:

  • 技术 LEF(tech.lef):定义工艺信息,比如金属层数、最小线宽、间距规则。这是所有设计的基础。
  • 单元 LEF(cells.lef):定义每个标准单元和宏单元的物理尺寸、引脚位置。这个文件通常很大,几万行是常事。

DEF 文件呢,是随着设计流程不断更新的。刚开始只有 floorplan 信息,到了布局阶段会加上单元坐标,布线阶段会加上走线细节。OpenROAD 的每个步骤都会输出一个新的 DEF,你可以用它来恢复现场。

核心要点:LEF 和 Liberty 必须来自同一个工艺版本。如果 LEF 里定义的引脚位置和 Liberty 里的时序弧对不上,工具会报错,或者更糟——悄无声息地给出错误结果。

SDC 约束文件加载:设计的“规矩”

SDC(Synopsys Design Constraints)是时序约束的行业标准。它告诉工具:时钟频率是多少、输入输出延迟是多少、哪些路径是假的(false path)。OpenROAD 读入 SDC 的命令是:

read_sdc ./constraints/design.sdc

一个典型的 SDC 文件长这样:

create_clock -name clk -period 10 [get_ports clk]
set_input_delay -clock clk 2 [get_ports data_in]
set_output_delay -clock clk 3 [get_ports data_out]
set_false_path -from [get_clocks clk] -to [get_clocks clk2]

写 SDC 的时候,我建议你注意这几点:

  • 时钟定义要完整:包括时钟周期、占空比、抖动(jitter)。如果忘了定义抖动,工具会默认没有抖动,结果流片回来发现时序裕量不够。
  • 输入输出延迟要合理:这些值通常来自芯片的 datasheet 或者系统级仿真。我见过有人随便填个 0.5ns,结果工具为了满足这个约束,把 I/O 单元推得乱七八糟。
  • false path 别乱设:只有确定不会影响功能的路径才能设为 false path。比如测试模式下的时钟、异步复位信号。设错了,功能可能直接挂掉。
个人经验:SDC 文件最好用版本管理工具(比如 git)跟踪。每次修改都写清楚原因,方便后面回溯。我吃过一次亏:改了一个 false path,结果忘了通知团队,最后 tapeout 前才发现时序违例。

知识体系总览

下面这张图,帮你把本章的知识点串起来。它展示了设计输入阶段,四类文件如何协同工作,最终进入 OpenROAD 的数据库:

设计输入与数据准备流程 设计输入与数据准备流程 Verilog 网表 Liberty 库 LEF/DEF 文件 SDC 约束 OpenROAD 数据库(db) 后续流程:Floorplan → Placement → CTS → Routing ⚠️ 关键检查点 1. 所有文件版本对齐(Liberty ↔ LEF ↔ 工艺) 2. SDC 约束完整且合理(时钟、IO、false path)

你看,这四类文件就像四个齿轮,必须啮合在一起才能让 OpenROAD 正常运转。任何一个文件出问题,后面的流程都会跟着跑偏。

本章小结

咱们这一章,把设计输入的四个核心文件都过了一遍:

  • Verilog 网表:设计的逻辑骨架,必须综合后使用。
  • Liberty 库:时序和功耗的标尺,多 PVT 条件要配齐。
  • LEF/DEF 文件:物理蓝图,LEF 定义单元,DEF 定义布局。
  • SDC 约束:设计的规矩,时钟和 IO 延迟是重点。

我个人觉得,数据准备阶段花的时间,后面都能省回来。文件没对齐就往下跑,最后返工的成本更高。所以,别急,先把“食材”备好,再开火做饭。