3、物理约束基础:位置约束、区域约束、I/O约束、电源约束、物理约束与布局布线

各位同学,咱们今天聊聊物理约束。说实话,很多做数字前端的兄弟觉得物理约束是后端的事,跟自己没关系。我以前也这么想,直到有一次项目里,我随手写了个位置约束,结果后端同事跑过来跟我说:「你那个约束把标准单元全挤到角落里了,布线根本布不通。」嗯,从那以后我才明白——物理约束这东西,前端也得懂个七七八八。

3.1 位置约束:把单元「钉」在哪儿

位置约束,说白了就是告诉工具:这个模块、这个单元,你给我放在芯片的哪个位置。我个人习惯把它分成两类:硬位置约束和软位置约束。

  • 硬位置约束:用 set_fixed 或 set_location 把单元钉死。工具不能动它。
  • 软位置约束:用 set_keep_out 或 set_region 给个建议位置。工具可以酌情调整。

你想想看,什么时候需要用硬位置约束?我遇到过一种情况:芯片里有个高速 SerDes 模块,它的模拟部分和数字部分必须紧挨着,否则信号延迟会超标。这时候我就把 SerDes 的数字控制逻辑用 set_fixed 钉在模拟模块旁边。效果立竿见影,时序直接收敛了。

重要提醒:位置约束不是越多越好。我曾经在一个项目里加了 200 多个硬位置约束,结果布局器直接罢工了——它找不到合法的摆放位置。后来我删掉了一半,工具才跑通。

3.2 区域约束:给模块画个「地盘」

区域约束比位置约束更灵活。你不需要指定每个单元放哪儿,只需要画个矩形区域,告诉工具:「这个模块的单元,只能放在这个框里。」

常用的命令是 create_region。举个例子:

# 给 CPU 核心模块画一个区域
create_region -name CPU_CORE -type soft \
  -rect {100 100 500 500} \
  -exclude {100 200 300 400}  # 排除中间一块,留给其他模块

这里有个坑,我踩过。区域约束的 -type 参数有 soft、hard、exclusive 三种。用 hard 时,工具会把区域内所有不属于该模块的单元都移走。有一次我用了 hard,结果把时钟树的 buffer 全赶出去了,时钟延迟直接翻倍。所以我的建议是:先用 soft,等布局稳定了再考虑改成 hard。

小技巧:区域约束可以嵌套。比如你先给整个 CPU 子系统画个大区域,再给里面的 L2 Cache 画个小区域。工具会自动处理层级关系。

3.3 I/O 约束:管脚怎么放

I/O 约束是物理约束里最容易被忽视的。很多人觉得管脚位置是封装工程师定的,跟设计没关系。其实不然。I/O 约束直接影响芯片的 信号完整性 和 电源完整性。

常用的 I/O 约束包括:

  • 管脚位置:用 set_pin_physical_constraints 指定每个信号从哪个管脚出
  • 驱动强度:用 set_drive 或 set_output_delay 控制输出驱动能力
  • 压摆率:用 set_slew 限制信号上升/下降时间

我记得有个项目,DDR 接口的时序怎么都修不好。后来发现是 I/O 约束里把输出驱动设得太强了,导致信号过冲严重,接收端误判。把驱动强度从 12mA 降到 8mA,问题就解决了。所以你看,I/O 约束不只是「放哪儿」,还关系到「怎么驱动」。

注意:I/O 约束和芯片封装是联动的。你改了管脚位置,封装工程师就得重新画封装图。所以最好在项目早期就定下来,后期改起来成本很高。

3.4 电源约束:给芯片「供电」

电源约束是物理约束里最「物理」的部分。它决定了芯片的电源网络怎么走、电压降怎么控制。

核心命令是 create_power_domain 和 create_supply_net。比如:

# 创建一个 0.9V 的电源域
create_power_domain -name VDD_CORE -default_voltage 0.9

# 创建电源网络
create_supply_net -name VDD -domain VDD_CORE
create_supply_net -name VSS -domain VDD_CORE

# 连接电源管脚
connect_supply_net -net VDD -ports {VDD_PAD}
connect_supply_net -net VSS -ports {VSS_PAD}

这里有个关键点:电源域不能重叠。我见过有人把两个不同电压的电源域画在一起,结果工具报了一堆短路错误。后来查了半天才发现是区域重叠了。

另外,电源约束还涉及 电压降分析(IR Drop)。说白了就是检查芯片最远的单元能不能得到足够的电压。我习惯在布局后先跑一遍 IR Drop,如果发现某个区域电压降超过 5%,就调整电源网络或者加一些去耦电容。

实战经验:电源约束最好在布局前就定义好。我曾经在一个项目里,布局都跑完了才发现电源域没定义对,结果全部重来。那感觉,就像盖好了房子才发现地基打歪了。

3.5 物理约束与布局布线

好了,前面讲了各种约束,现在说说它们怎么影响布局布线。

布局布线(Place & Route)是芯片设计的「施工阶段」。物理约束就是施工图纸。没有图纸,施工队只能瞎干。有了图纸,他们才知道墙砌在哪儿、水管走哪条路。

我画了一张图,帮你理解它们的关系:

物理约束与布局布线关系图 位置约束 set_fixed / set_location 区域约束 create_region I/O 约束 set_pin_physical_constraints 电源约束 create_power_domain 布局布线引擎 Place & Route 读取所有物理约束 生成合法布局 优化时序/功耗/面积 检查 DRC 违例 输出 GDSII 布局结果 .def / .gds 迭代优化

从这张图你能看到,物理约束是布局布线的「输入」。工具读入这些约束后,会尝试生成一个合法的布局。如果约束之间冲突了(比如位置约束和区域约束矛盾),工具就会报错或者给出次优解。

我遇到过最典型的冲突是:位置约束要求某个单元放在左下角,但区域约束说这个模块只能放在右上角。工具直接罢工了。解决办法是——检查约束的优先级。一般来说,硬位置约束 > 区域约束 > 软位置约束。但具体哪个优先,还得看工具的实现。

我的习惯:在跑布局布线之前,先用 check_physical_constraints 命令检查一遍约束。这个命令会列出所有冲突和警告。我每次都会仔细看一遍,确认没有明显问题再往下走。

3.6 小结

物理约束这东西,说难不难,说简单也不简单。核心就一句话:给工具足够的指导,但别把它绑死。位置约束、区域约束、I/O 约束、电源约束,它们共同决定了芯片的物理实现质量。

我个人觉得,初学者最容易犯的错误是「过度约束」。总想着把所有东西都钉死,结果工具反而跑不出好结果。我的建议是:先松后紧。先用软约束跑一版,看看工具怎么摆。如果某个模块的位置确实不合理,再慢慢收紧约束。

好了,这一章就到这里。记住,物理约束不是后端工程师的专利,前端工程师也得懂。下次你写 RTL 的时候,想想你的代码最终会变成芯片上的哪个位置——这感觉,挺奇妙的。

一句话总结:物理约束是连接逻辑设计和物理实现的桥梁。桥搭好了,芯片才能顺利流片。

可可精品资料库