后端的日子,说穿了就是一边盯着 congestion 热力图,一边掐着 short 数量过日子。Innovus 和 ICC2 这两个主流程工具,平时用得再顺,到了修 short 这一步也免不了要跟工具反复拉扯。尤其是规模稍微大点的 block,几十万上百万 instance 摊在那里,一跑完布线,verifyConnectivity 报出来几千个 short,那感觉相信做过 PR 的人都懂。这篇东西我想把自己在 Innovus 和 ICC2 里做自动化修 short 的完整套路整理出来,包括命令怎么敲、选项怎么配、哪些 short 工具根本不会碰、哪些问题修完还会反复,尽量把我在项目里踩过的坑和试出来的有效手段讲清楚。不管你是刚转后端的新人,还是被 short 报表折磨到想摔键盘的老工程师,这篇内容都值得对着项目实际操作一遍。
1. 修 short 前必须搞懂的事:工具为什么留 short,以及哪些 short 能自动修
1.1 short 的物理本质与两个工具的判定差异
先把这个最基础的问题说透。物理上 short 的定义很简单:两个本应电气隔离的 net,在某一层金属或 via 上,图形发生了物理接触。但 PR 工具里报出来的 short,远远不止"两根线碰到一起"这么简单。你在 Innovus 和 ICC2 里看到的 short 报告,可能来自 pin shape 的重叠、via pad 与相邻走线的粘连、PG rail 与信号线的短接,甚至可能是 division 之后图形边界没对齐造成的假错。
两个工具的检测机制其实思路一致,都是把整个版图按 net 做图形 merge,找不同 net 的图形覆盖关系。差异主要体现在报告粒度和分类逻辑上。Innovus 的 verifyConnectivity 会把 PG short 和 signal short 混在一起给你列出来,只是用 net 名区分;而 ICC2 更倾向于把 PG 相关检查和信号网络的 DRC 检查分开查,check_routes 和 verify_pg_drc 各管一摊。这个差异直接影响了脚本的第一步该怎么写——在 Innovus 里我习惯先跑一次全量 verifyConnectivity,把 short 总数摸清楚;在 ICC2 里我会先 check_routes -type short,再单独看 PG 网络的状态。
注意:两个工具报 short 的坐标,指的是图形交集区域的某一点,不一定是问题真正产生的"根"。排查时一定要把报告坐标放到版图里,结合周围的 floorplan 和 routing guide 一起看,别对着坐标盲改。
1.2 常见成因分类:先定位再动手
我在项目里总结下来,PR 阶段的 short 大致逃不出下面这几类:
| short 类型 | 典型成因 | 自动修复适用性 |
|---|---|---|
| 区域拥挤型 | detour 空间不足,布线器被迫在不同层硬挤 | 较适用,但容易反复 |
| pin access 型 | macro 或 blockage 边缘 pin 出不来,布线器强行搭线 | 低,需要人工干预 |
| PG 短接型 | rail 错位、power switch 连接不当、endcap 撞线 | 低,需专门处理 |
| 图形残留型 | cell 抽象不完整、off-grid 图形、fracture 边界问题 | 基本不可自动修 |
| Metal fill 引入型 | fill polygon 跨过两条不同 net 的间隙 | 可预防,不可盲目修 |
这里面最关键的一点是:工具能自动修的 short,绝大多数是"布线器可以通过 reroute 绕开"的 short。如果 short 的根因是 floorplan 阶段就埋下的 pin access 问题,或者 PG 网络的连接方式问题,你让布线器跑多少轮都没有用,它甚至会把线路绕得更乱。
1.3 理解工具的修复边界,省下至少一半无用功
我刚带项目的时候吃过一次亏:Innovus 里看到 3000 多个 short,上来就开自动修复跑全局布线,跑了一整夜,第二天一早看结果——short 从 3000 变成了 2800,修复过程中还引入了大量 timing violation。后来把报告按坐标在版图里一摊,发现相当一部分 short 集中在两个大 macro 中间那条 10 微米宽的通道里,那里本身的 track 数量就不够信号穿过去,布线器再怎么 reroute 都是在做无米之炊。
从那之后我的习惯变成:不管 Innovus 还是 ICC2,拿到 short 报告的第一件事不是跑修复命令,而是先做分类统计,按 net 类型分、按 metal layer 分、按坐标区域分,然后再决定哪些区域可以交给工具自动修,哪些区域需要先调整 floorplan 或 blockage。这一步看着麻烦,实际上能帮你省下大量无效迭代的时间。
2. Innovus 里把 short 压到 0 的自动化修复流程
2.1 检测与定位:先把问题摊开看
Innovus 下常用的 short 检测命令是 verifyConnectivity,这个命令我会在执行的时候把 error 和 warning 的数量上限拉到很大,避免中途报错截断:
verifyConnectivity -type all -error 100000 -warning 100000跑完之后 short 会出现在 violation browser 里。如果你更喜欢命令行工作流,可以直接用高亮命令把 short 压到版图界面上:
highlightShort -allNets -allLayers这个命令会按不同颜色把 short 相关的 pin 和走线标出来。我建议在修之前先截一张完整的 short 分布图,修完一轮之后再用同样的参数高亮一次,前后对比着看,比单纯看数字变化直观得多。
其实 Innovus 的 GUI 里也有 "Mark Shorts" 这个按钮,位置在 Verify 菜单下,点一下就能把所有 short 以高亮形式显示。实测下来,当 short 数量超过 1000 个的时候,全量高亮对 GUI 性能影响很大,旋转缩放都会卡;这种情况我一般关掉 GUI,直接用报告文件在文本里分析,或者用下面的脚本按区域统计:
set f [open "short_summary.txt" w] foreach_violation v -type short { set bbox [get_attribute $v bbox] set net [get_attribute $v net] set layer [get_attribute $v layer] puts $f "$net $layer $bbox" } close $f有了这个按 net 和 layer 分类的统计表,你就能快速判断 short 的集中区域。如果某个 layer 上的 short 数量异常多,多半是这一层的 track 资源或 pin access 出了问题,而不是布线器不行。
2.2 核心修复开关:NanoRoute 的 DRC 修复机制
Innovus 的布线器 NanoRoute 提供了几个专门针对 short 的修复开关,核心的修 short 流程通常是这样的:
setNanoRouteMode -routeWithEco true setNanoRouteMode -drouteFixShort true setNanoRouteMode -routeEcoShort true globalDetailRoute逐个解释一下这些开关在干什么。-routeWithEco true是让 NanoRoute 以 ECO 模式运行,在这个模式下布线器不会推翻整块区域的布线,而是尽量在现有走线基础上做局部调整,这对修 short 来说很重要——全量重布虽然理论上更干净,但会引入大量非必要的 timing 变化。-drouteFixShort true打开的是详细布线阶段的 short 修复选项,布线器会把检测到的 short 区域抓出来做 rip-up 和 reroute。-routeEcoShort true则是专门针对 ECO 阶段的 short 修复逻辑。
实际跑的时候,我通常不会只跑一轮。修复 short 是一个迭代过程,一轮 globalDetailRoute 往往只能解决一部分,剩下的需要调整参数再跑。推荐的迭代次数是 3 到 5 轮,每轮之间用 verifyConnectivity 复查,直到 short 数量进入平台期——也就是连续两轮数字都不再明显下降,说明剩余的部分已经不是 NanoRoute 自动 reroute 能解决的了。
提示:
-routeWithEco true不是万能的。如果当前 short 数量巨大,比如超过 5000 个,我建议先跑一轮不带 ECO 的 globalDetailRoute,让布线器把整个区域的布线秩序重建起来,然后再切回 ECO 模式做精细修复。先大后小,收敛速度反而更快。
2.3 局部修复:用 bbox 缩小战场
全 chip 跑 globalDetailRoute 很耗时,而且容易把原本干净的区域的时序和布线搅乱。如果 short 集中在几个特定区域,我强烈建议用局部修复的方式。
Innovus 的 ecoRoute 命令支持带 bbox 的 DRC 修复:
setNanoRouteMode -routeWithEco true setNanoRouteMode -drouteFixShort true ecoRoute -fixDrc -bbox {100 200 150 250}这里的 bbox 坐标我用的是当前 floorplan 的坐标系,四组数分别是左下角和右上角的坐标。你可以从 short 报告里把高密度区域的坐标提取出来,稍微外扩一点生成 bbox。局部修复跑一轮通常只需要几分钟,远比全 chip 的几小时高效。
我习惯的做法是先全 chip 跑两轮完整修复,把大面上的 short 清掉,然后把剩余的 short 按区域聚类,每个聚类生成一个 bbox,用 ecoRoute 定点清除。这样做的好处不仅是快,还能精细控制哪些区域被布线器动过,方便后续做 timing 对比。
2.4 别只修 short:联动 congestion 热点一起处理
如果你发现某个区域的 short 总是修完又冒出来,那说明这里的布线资源饱和了,short 只是症状,congestion 才是病根。Innovus 里可以用下面的命令查看 congestion 分布:
reportCongestion -hotspotGUI 里对应的是 Display → Congestion 菜单,可以按层显示 overflow 的分布图。
对于 congestion 热点区域,单纯靠布线器修 short 是治标不治本。我的经验是:如果某一块区域 short 重复出现超过三轮,就该停下来看看这里的 density 是不是超过了 85%,或者周围有没有不必要的 routing blockage。常见的处理手段包括:调整 halo / keepout 范围、移动部分 instance 到周边密度较低的区域、在这个区域临时增加 routing layer 的可用 track。这些手段属于 placement 层面的操作,做完之后你会发现 short 数量会断崖式下降,比你在布线阶段死磕高效得多。
3. ICC2 侧:从 check_routes 到 optimize_route 的完整修复链
3.1 检测命令与报告解读
ICC2 的 short 检测和 Innovus 的哲学不太一样,它把信号层的 short 检查和 PG 的检查分得很开。信号网络的 short 用这组命令:
check_routes -type short如果不想全 chip 跑,可以加 bbox 或 net 范围限制。跑完之后可以用 report_routes 把详细结果导出来:
report_routes -type short -columns {net layer bbox} -report_prefix short_rep这样会生成一份 short_rep 前缀的报告文件,里面每条 short 都会列出涉及的 net、layer 和坐标。这里我想特别提醒一下:ICC2 的 check_routes 报告里,字段 pnet 和 net_name 的区别要分清楚。pnet 是物理上连在一起的网络集合,如果报告里显示两个不同 net 同时出现在同一个 pnet 里,那说明它们电气上已经短接到一起了。看报告的时候,重点关注的应该是 net_name 不同的条目,因为那是真正需要修的。
两个工具的检测命令大致可以对照成这样:
| 操作 | Innovus | ICC2 |
|---|---|---|
| 全量 short 检测 | verifyConnectivity -type all | check_routes -type short |
| short 报告导出 | get_attribute + 自定义脚本 | report_routes -type short |
| PG short 检测 | verifyConnectivity 里看 pnet | verify_pg_drc |
| 高亮 short | highlightShort | GUI 里 highLight DRC |
3.2 optimize_route 和 route_eco:怎么选
ICC2 里修 short 的核心命令是 optimize_route,带 -fix_drc 参数:
optimize_route -fix_drc true -max_drc_iterations 20这个命令的作用是让工具在优化时序和拥塞的同时修复 DRC 违例,适用于布线完成后的整体性 DRC 清理。-max_drc_iterations参数控制修复迭代的上限,我建议从 10 开始,看效果再往上加。跑完之后用 check_routes 复查,如果 short 数量持续减少但还没到底,就继续跑;如果连续两轮没有明显变化,就不要盲目加大迭代次数了,说明剩下的问题不是这个命令能解决的。
如果是局部区域的 short,用 route_eco 更合适:
route_eco -fix_drc true -bbox [get_bbox -of_objects [get_cells inst_name_x]]这里我通常会把 bbox 指定到具体 instance 或 macro 周围,只针对问题区域做 ECO 布线。局部修复的好处跟 Innovus 那边一样,速度快、影响面小,而且方便做回归对比。
3.3 关键选项配置与版本差异
ICC2 的 DRC 修复行为很大程度上受 app option 控制。我常用的几个选项如下:
set_app_options -name route.drc.max_drc_iterations -value 15 set_app_options -name route.drc.fix_drc_short -value true set_app_options -name route.common.global_route_effort -value high这里要提醒一句:ICC2 的 app option 名字在不同版本之间有差异,尤其 route.drc 选项组,13.x 和 19.x、21.x 的写法都不完全一样。我自己的习惯是每次换版本之后先用下面的命令确认选项是否存在:
get_app_options -pattern route.drc.*这能列出当前版本下所有 route.drc 相关的选项名和当前值,比翻手册快得多。实测过一次项目从 18 版切到 21 版,修 DRC 的选项从route.drc.fix_drc_repair调整成了带 short 的更细分选项,如果不提前确认,脚本里的 set_app_options 会直接报 unknown option,甚至整个流程卡住。
3.4 PG short 在 ICC2 里的单独处理
信号 short 和 PG short 在 ICC2 里完全是两套处理思路。PG short 的表现通常是 VDD 网络和 VSS 网络在某个区域物理接触,或者 PG 网络和信号网络短接。先用 verify_pg_drc 确认范围:
verify_pg_drcPG short 的成因和信号 short 很不一样。我遇到过最多的情况是:placement 阶段做完 standard cell 的 PG 连接(create_pg_std_cell_conn)之后,rail 和旁边的信号线绕在一起,或者 power switch cell 的连接图形跟 adjacent cell 的 pin 发生冲突。
这种问题靠 optimize_route 修不了,因为 PG 网络的连接逻辑不是布线器说了算的,是 PG 连接流程决定的。正确的处理路径是:先定位短接的具体图形,手动把这些错误连接断掉,然后重新执行 PG 连接步骤。我在处理 PG short 时一般不会写死一个命令解决,而是逐条分析短接图形的来源——是 via 打偏了、rail 没对齐,还是 power switch 的驱动连接方式不对——然后对症下药。这里的核心原则是:PG 的问题不要用信号布线的手段去修,断掉重连比绕来绕去可靠得多。
4. 自动修复失效时怎么办:兜底手段与假 short 识别
4.1 工具不修的 short 长什么样
自动化不是银弹,这一点在 short 修复上体现得淋漓尽致。下面这些场景,工具基本不会碰,或者修了也是白修:
| 场景 | 具体表现 | 兜底策略 |
|---|---|---|
| off-grid 图形 | 某条 metal 不在 track 网格上,布线器无法处理 | 手工对齐或删除重画 |
| cell 抽象异常 | 标准单元 LEF 抽象缺 pin shape,导致短接疑似 | 回到库侧检查 LEF 和 GDS |
| macro 边界 pin access | macro 引脚密集,布线器无法把线引出到可用 track | 调整 macro 位置或加引导 blockage |
| PG rail 层短接 | VDD rail 和 VSS rail 图形相接 | 删除图形、修正 rail 连接后重新 PG |
| 跨子模块边界 short | 两个子模块单独看都干净,拼一起就 short | 在顶层统一修或协调两边的 blockage |
判断工具能不能修,我有一个快速标准:看这个 short 是不是来自"布线决策"。如果是布线器自己在布线过程中因为空间不够把线挤到一起了,那布线器就能通过 reroute 修掉;如果是 floorplan、库、PG 连接这些"布线之前就定死的事情"出了问题,布线器修不了,你得回到源头。
4.2 手工修复的理性操作:别上来就删线
手工修 short 最忌讳的就是看到 short 就 editDelete 把线删掉。我之前见过年轻工程师手动删掉一条线之后,short 确实没了,但整条 net 就变成了 open,而且因为是 ECO 阶段,他删完线根本没有重新布线,留着 open 就去跑签核,结果被后端 review 打回来重做。
正确的手工处理思路是这样:先在 GUI 里高亮 short 涉及的两条 net,看清楚短接的图形发生在哪一层、是什么形状。如果是两条走线因为间距不足碰到了一起,最理性的做法不是删线,而是先看能不能通过移动其中一条线的 segment 来拉开距离。Innovus 里可以用 editModify 移动线段,ICC2 里可以用 move_route 或者精确编辑工具调整。如果短接的图形比较复杂,无法通过移动解决,再考虑删除一部分线段然后重布——但记住,删完一定要立刻对这条 net 做局部布线,确保不会引入新的 open。
4.3 Metal fill 新增 short 的预防
这个坑特别想单独拎出来说。很多人信号层的 short 明明修到 0 了,结果加完 Metal fill 一看,short 又冒出来几十个,心态直接崩掉。
fill 引入 short 的机制是这样的:fill 命令在生成金属填充块的时候,会试图把填充块放到空余区域,但"空余"的判断依据是 DRC 规则检查的 spacing 值。如果 fill 块和旁边信号线之间的距离没有设置足够的 margin,fill 块就会以很小的间距贴近信号线;当 fill 块的图形跨过两条不同 net 的走线间隙时,就相当于用一块金属把两个 net 桥接起来了,物理验证时自然就报 short。
预防的思路有两个层面。第一,在 addMetalFill 之前把 long short 修干净,给 fill 创造一个干净的版图环境。第二,设置更保守的 fill 间距,让 fill 块远离已有的信号线。大多数填充工具都支持设置一个额外的 一个"margin"参数,比如用 addMetalFill 时把间距规则从原有的 DRC 最小值加大 0.02 到 0.05 微米。代价是填充率会略降,但换来的是省掉一轮因为 fill 引起的 short 修复迭代,整体上还是划算的。
注意:如果 fill 已经加完了才发现 short,千万不要直接在版图里一张一张删 fill 块。正确做法是用工具的反标功能把 fill 块的 ID 提取出来,批量删除后再重新填充。这样可追溯、可回归,避免手工删漏。
5. 把自动化修复跑顺的工程化要领
5.1 让自动修复不反复的 3 个前置条件
第一,修 short 之前先确认当前是在一个"时序已经基本收敛"的基线上。如果时序还很乱,布线器在修 short 的同时会做大量 timing-driven 的调整,你会分不清 short 数量的波动到底是修复生效还是时序调整带来的副作用。第二,把 PG 网络的状态先确认清楚。PG 有 short 的时候,所有信号的参考地都是乱的,修出来的结果也不可信。第三,确认当前库的 DRC 规则文件完整,有些 short 是假的——工具拿到的规则文件和 signoff 不一致,报了本来不该报的错。
这三个前置条件看着简单,但在实际项目里真的有很多人忽略。我印象很深的一次,一个 block 修 short 修了三天,数字一直在 2000 上下徘徊,最后发现是库里的 LEF abstract 和真实 GDS 不一致,有一层 metal 在 LEF 里没定义完整,工具怎么修都修不对。换正确的库之后,一轮就干净了。
5.2 迭代次数的边界与时序副作用
自动化修 short 有一个隐藏成本:每一次 reroute 都可能改变布线拓扑,进而改变 delay 和 crosstalk。所以修 short 不是跑得越狠越好,而是要有一个清晰的迭代终止条件。
我的经验做法是:
- 第一轮全量修复:Innovus 用 globalDetailRoute,ICC2 用 optimize_route,拿当前 short 总数的 80% 作为预期目标;
- 第二轮复查:如果数量降幅超过 50%,说明剩余问题可修,继续迭代;如果降幅小于 20%,说明进入了平台期,停止自动迭代,转入手工分析;
- 每轮修复后保存一个单独的设计快照,一旦后续发现 timing 恶化无法接受,可以随时回退到上一版。
这里有一个小技巧:修 short 的轮次之间,不要只比较 short 的数字,还要顺手看一版总的 DRC 数量、antenna 数量和 setup/hold TNS。如果 short 少了 500 个但 DRC 总量反而多了 800,那这一轮就很可能是负优化。
5.3 双工具脚本抽象与团队流程沉淀
我所在的环境里,同一个项目组既有用 Innovus 的 block,也有用 ICC2 的 block。两套工具的修 short 流程虽然思路相同,但命令和选项差异明显。要让团队的 flow 可维护,最好的做法是写一层封装脚本,对外暴露统一接口。
比如,团队内部定一个repair_short.tcl,内部用变量区分工具平台:
set TOOL [get_eda_tool_name] if {$TOOL == "innovus"} { setNanoRouteMode -routeWithEco true setNanoRouteMode -drouteFixShort true setNanoRouteMode -routeEcoShort true globalDetailRoute } elseif {$TOOL == "icc2"} { set_app_options -name route.drc.fix_drc_short -value true optimize_route -fix_drc true -max_drc_iterations 10 }脚本里再统一封装 verify、report、log 归档等动作。这样一来,新来的同事不需要同时精通两套工具的所有命令,只需要维护好这层封装即可。这个方法在我们团队里用了快一年,修 short 的平均迭代轮次从 6 轮降到了 3 轮以内,主要是脚本统一了收敛判据和报告归档格式,分析效率明显上来了。
5.4 与 signoff 工具交叉验证
最后一条经验,也是我用真金白银换来的教训:PR 工具里的 short 检测结果,和 signoff 物理验证工具(比如 Calibre、ICV)的结果不一定完全一致。有些 short 在 Innovus 或 ICC2 里报不出来,到了 signoff 阶段才暴露,反过来也有 PR 工具报了 short 但 signoff 工具认为没问题的假错。
所以我的流程里有一个固定动作:每当自动修复进入平台期,就抽一个短时间窗口,把当前版图导出去做一轮快速的 signoff LVS 和 DRC 交叉检查,而不是等到项目最后才去做 signoff。这样做的好处是能尽早发现工具之间判定不一致的区域,避免最后的 surprise。
再分享一个更细的经验:修 short 的时候随手记一份"断点笔记"。记录每一轮修复命令的参数、short 数量的变化、主要分布区域的变化、还有手工处理了哪些点。这份笔记不需要多正式,自己能看懂就行,但它的价值在项目后期翻出来复盘的时候才会体现——你会发现很多 short 的根因其实早在 floorplan 阶段就埋下了。
这个内容后面其实还能延伸到 antenna 修复和 EM 违例的自动处理,这两个问题和 short 修复共享同一套 ECO 思路,但各自的约束和判定逻辑差别很大。如果大家感兴趣,我后面可以再单独整理一篇,把这两个方向的自动化实践也展开讲讲。