
1. 数字IC后端PR阶段Short修复的核心逻辑与脚本设计思路数字IC后端物理设计里PRPlace Route阶段最让人头疼的问题之一就是short也就是短路。尤其在先进工艺节点下金属层数多、布线密度高、标准单元pin间距小short几乎成了每个项目必经的坎。我做过从40nm到5nm的多个项目可以很负责任地说没有哪个项目能完全靠手工修完short必须靠脚本批量化处理。这篇内容就是把我这些年用Innovus、ICC、ICC2修short的脚本思路和实操经验完整拆开讲适合正在做PR、被short折磨的后端工程师也适合想建立系统化修short方法论的同行参考。先明确一个核心认知short的本质是两条不同net的金属或via在物理空间上发生了非预期的连接。在PR阶段short主要来源有几类绕线拥塞导致的metal short、pin access问题导致的via short、PGPower/Groundstripe与signal net之间的short、以及标准单元内部pin与外部绕线之间的short。不同工具Innovus、ICC、ICC2对short的report格式和修复命令不同但底层逻辑是一致的定位short坐标、判断short类型、选择修复策略、批量执行、验证收敛。为什么强调“脚本化”因为一个中大规模芯片在PR阶段初版绕线后short数量动辄几千甚至上万条。手工在GUI里一条条看、一条条修效率极低且容易遗漏。脚本的价值在于把short report解析成结构化数据按类型和优先级分类自动生成修复命令批量执行后重新检查形成闭环。我见过太多工程师只会用工具自带的verifyConnectivity或checkRoute看报告但不知道怎么把报告变成可执行的修复动作结果就是反复绕线、反复修、反复不收敛。脚本设计的整体思路分四层第一层是数据采集从工具里导出short的详细报告包括net name、layer、坐标、涉及的cell或wire第二层是分类与优先级排序把short按PG vs signal、same-layer vs cross-layer、cell内部 vs 绕线区域等维度分类第三层是修复策略生成针对不同类型调用不同的修复命令比如删线重绕、加via、挪线、改pin access第四层是迭代验证修完一轮后重新跑connectivity check看short数量是否下降如果没降或降得慢就要调整策略。这四层循环执行直到short收敛到可接受范围。这里要特别说明一个经验不要试图一次性修完所有short。我早期做项目时写了个脚本把所有short都生成修复命令结果工具执行时因为资源冲突和绕线顺序问题反而引入了新的short。后来我改成按区域分批修每次只处理一个floorplan区域内的short修完验证再进下一个区域收敛效果好很多。这个思路在Innovus里可以用-area选项配合在ICC2里可以用-boundary来限定修复范围。2. Innovus环境下Short修复脚本的完整实现与参数解析2.1 Innovus short report的解析与数据结构化Innovus里查看short最常用的命令是verifyConnectivity和checkRoute。verifyConnectivity会报出所有open和short但信息比较粗checkRoute可以给出更详细的short位置。我通常用verifyConnectivity -type all -error 10000 -warning 10000 -report short.rpt导出报告然后用脚本解析。报告格式大致是这样的Short: net1 net2 Layer: M3 Location: (123.456, 789.012) Cell: U1234 Type: signal-signal解析脚本用Python或Tcl都可以。我习惯用Tcl因为Innovus原生支持Tcl不需要额外环境。核心解析逻辑是逐行读取遇到“Short:”开头的行就新建一个记录后续的Layer、Location、Cell、Type行填充到该记录里。解析完得到一个列表每个元素是一个dict包含net1、net2、layer、x、y、cell、type。这里有个细节Innovus的short report里坐标单位是micron还是database unit取决于你的setPrecision设置。我一般统一用micron方便后续计算。如果报告里是database unit记得除以1000或2000取决于工艺。解析完的数据要按优先级排序。我的排序规则是PG-signal short优先级最高因为PG short可能导致整个电源网络失效其次是cell内部short因为可能涉及标准单元pin access问题最后是signal-signal short这类通常可以通过重绕解决。排序后写入一个CSV文件方便后续脚本读取和人工review。2.2 基于坐标的局部重绕脚本对于signal-signal short最直接的修复方法是删除short区域的绕线然后让工具重新绕。Innovus里可以用editDelete -type wire -layer M3 -box {x1 y1 x2 y2}删除指定区域的wire然后用routeDesign -selected或ecoRoute重新绕。脚本的关键是如何确定删除区域的大小。太小了删不干净太大了会破坏正常绕线。我的经验是以short坐标为中心向外扩展2-3个track的宽度。比如M3的track pitch是0.1um那就扩展0.3um。这个值可以通过getTrackPitch命令获取不要硬编码。具体脚本片段foreach short $short_list { set x [dict get $short x] set y [dict get $short y] set layer [dict get $short layer] set pitch [getTrackPitch $layer] set margin [expr {$pitch * 3}] set x1 [expr {$x - $margin}] set y1 [expr {$y - $margin}] set x2 [expr {$x $margin}] set y2 [expr {$y $margin}] editDelete -type wire -layer $layer -box [list $x1 $y1 $x2 $y2] } routeDesign -selected这里有个坑editDelete删除wire后原来的net会变成open如果直接routeDesign工具可能会把其他net也绕进来导致新的short。我的做法是先用editSelect -net $net1 -net $net2选中涉及的两个net然后只对这两个net做ecoRoute。这样影响范围可控。另外删除wire前一定要保存design。我踩过一次坑脚本跑了一半工具崩溃没保存半天的工作白费。现在我的脚本里强制在每修100条short后自动saveDesign一次。2.3 PG short的专用修复策略PG short比signal short麻烦得多因为PG网络通常很宽而且不允许随意删除。Innovus里PG short常见于PG stripe与signal wire交叉的地方或者标准单元的PG pin与相邻cell的signal pin short。修复PG short的首选方法是调整signal wire的绕线层或位置而不是动PG。可以用editMove -type wire -layer M3 -box {...} -delta {0 0.1}把signal wire挪开。如果挪不动就删掉signal wire让工具换层绕。脚本里要判断short类型如果是PG-signal就调用editMove或editDelete只针对signal net。判断方法是从short记录里看net1和net2哪个是PG net。PG net的名字通常包含VDD、VSS、GND、PWR等关键词可以用正则匹配。set pg_pattern {VDD|VSS|GND|PWR|VCC} if {[regexp $pg_pattern $net1]} { set signal_net $net2 } else { set signal_net $net1 } editSelect -net $signal_net editDelete -type wire -layer $layer -box [list $x1 $y1 $x2 $y2] ecoRoute -target注意PG short修复后一定要重新跑verifyPower确保PG网络没有因为signal wire的移动而出现新的open或电阻过大。2.4 迭代验证与收敛判断修完一轮后重新跑verifyConnectivity对比short数量。如果数量下降超过30%说明策略有效继续下一轮如果下降不明显就要检查是不是有大量short集中在某个区域需要调整floorplan或绕线策略。我的脚本里会记录每轮short数量输出一个趋势表轮次short总数PG-signalsignal-signalcell内部1500020045003002320050300015031800101700904800075050当short数量降到500以内就可以转手工精修了。剩下的通常是复杂case脚本处理不了。3. ICC与ICC2环境下Short修复脚本的差异与适配3.1 ICC的short report解析与修复命令ICCIC Compiler是老一代工具虽然现在用的人少了但很多成熟工艺项目还在用。ICC里查short用check_route -short或verify_zrt_route。报告格式和Innovus不同通常是Short between net1 and net2 Layer: M2 Coordinate: (100.5, 200.3)ICC的修复命令是remove_route和route_zrt_eco。remove_route可以按坐标删除绕线route_zrt_eco做增量绕线。脚本逻辑和Innovus类似但命令语法不同。ICC里有个特殊点remove_route默认删除整个net的绕线如果只想删局部要用-box选项。但ICC的-box选项对layer的支持不如Innovus灵活有时候需要先set_route_zrt_common_options调整绕线参数。foreach short $short_list { set x [lindex $short 0] set y [lindex $short 1] set layer [lindex $short 2] remove_route -box [list [expr {$x-0.3}] [expr {$y-0.3}] [expr {$x0.3}] [expr {$y0.3}]] -layer $layer } route_zrt_ecoICC的迭代验证用verify_zrt_route -short收敛判断和Innovus一致。3.2 ICC2的short修复脚本设计ICC2IC Compiler II是Synopsys的新一代工具命令体系和ICC完全不同。ICC2里查short用check_routes或verify_connectivity。报告格式是JSON或文本我一般用report_short -format csv -output short.csv导出CSV解析更方便。ICC2的修复命令是remove_routes和route_eco。remove_routes支持-bounding_box和-layer选项比ICC灵活。ICC2还支持-net选项可以直接指定要删除的net。set f [open short.csv r] set short_list [split [read $f] \n] close $f foreach line $short_list { set fields [split $line ,] set net1 [lindex $fields 0] set net2 [lindex $fields 1] set layer [lindex $fields 2] set x [lindex $fields 3] set y [lindex $fields 4] set bbox [list [expr {$x-0.3}] [expr {$y-0.3}] [expr {$x0.3}] [expr {$y0.3}]] remove_routes -bounding_box $bbox -layer $layer } route_ecoICC2的route_eco比ICC的route_zrt_eco更智能它会自动考虑DRC和时序但速度慢一些。我的经验是如果short数量超过2000先用route_eco -incremental快速修一轮再用route_eco -full精修。3.3 三工具脚本的通用化封装虽然Innovus、ICC、ICC2命令不同但脚本框架可以统一。我的做法是写一个主脚本用set tool [getToolName]判断当前工具然后调用对应的函数。这样一套脚本可以在三个工具里跑只需要维护一份逻辑。proc fix_short {short_list} { set tool [getToolName] if {$tool Innovus} { fix_short_innovus $short_list } elseif {$tool ICC} { fix_short_icc $short_list } elseif {$tool ICC2} { fix_short_icc2 $short_list } }这个封装的好处是项目迁移时不用重写脚本只需要确保各工具的函数实现正确。我做过一个项目从ICC迁移到ICC2脚本只改了函数内部命令主逻辑没动半天就搞定了。4. Short修复中的常见问题与排查技巧实录4.1 修复后short数量不降反升的原因分析这是最让人崩溃的情况跑了一轮脚本short从5000变成6000。原因通常有三个第一删除wire后工具重新绕线时因为绕线资源不足把其他net挤到了不该去的地方第二脚本删除区域过大破坏了正常绕线导致新的short第三PG short修复时移动了signal wire但没检查PG网络的完整性导致PG open被误报为short。排查方法先看新增的short是否集中在某个区域。如果是说明该区域绕线拥塞严重需要调整floorplan或降低绕线密度。如果新增short分散说明删除区域过大需要缩小margin。我一般把margin从3个track降到1个track再跑一轮看效果。实操心得修复short时宁可多跑几轮小范围修复也不要一次大范围删除。小步快跑比大步慢跑更稳。4.2 Cell内部short的定位与处理Cell内部short通常是因为标准单元的pin access问题。比如两个相邻cell的pin靠得太近绕线时via打到了对方的pin上。Innovus里可以用checkPinAccess查看pin access问题ICC2里用check_pin_access。处理cell内部short脚本能做的有限通常需要手动调整cell位置或换cell。我的做法是先用脚本把所有cell内部short的cell名字和坐标导出来然后人工判断是挪cell还是换cell。如果同一个cell反复出现short可能是cell本身的设计问题需要反馈给library team。set cell_short_list {} foreach short $short_list { if {[dict get $short type] cell} { lappend cell_short_list [dict get $short cell] } } set cell_short_list [lsort -unique $cell_short_list] puts Cells with internal short: $cell_short_list4.3 脚本执行效率优化与资源控制修short脚本跑起来很吃资源尤其是大规模设计。我遇到过脚本跑了8小时还没跑完的情况。优化方法有几个第一用-error和-warning限制report数量不要导出全部short第二分批处理每批500条处理完保存一次第三用多线程Innovus支持setMultiCpuUsageICC2支持set_host_options -num_processes。Innovus里设置多线程setMultiCpuUsage -localCpu 8ICC2里设置set_host_options -num_processes 8但要注意多线程对绕线命令的加速有限主要加速的是verify和report阶段。真正绕线时还是单线程为主。4.4 常见问题速查表问题现象可能原因排查方法解决方案修复后short增加删除区域过大检查新增short分布缩小margin到1个trackPG short反复出现PG stripe与signal冲突检查PG网络完整性调整signal绕线层cell内部shortpin access问题跑checkPinAccess挪cell或换cell脚本跑不完资源不足看CPU和内存占用分批处理多线程修复后open增加删除wire后未重绕跑verifyConnectivity加ecoRoute步骤short集中在某区域绕线拥塞看congestion map调整floorplan4.5 独家避坑技巧汇总技巧一先修PG short再修signal short。PG short会影响电源网络如果不先修后续signal绕线时工具可能会因为PG网络不稳定而做出错误决策。技巧二每轮修复后保存design并记录short数量。这样如果某一轮效果不好可以回退到上一轮不用从头再来。技巧三用-net选项限定修复范围。Innovus的ecoRoute -net和ICC2的route_eco -net可以只对指定net做增量绕线避免影响其他net。技巧四short report里的坐标要验证。有时候工具报的坐标是database unit不是micron直接拿来算box会出错。我一般先用getPrecision确认单位。技巧五脚本里加日志。每修一条short就写一行日志包括net、layer、坐标、修复命令、执行结果。这样出问题时可以追溯。set log [open short_fix.log a] puts $log Fix short: $net1 $net2 $layer ($x, $y) close $log技巧六不要忽略warning。有些short在report里是warning级别但可能是潜在的大问题。我一般把warning也纳入修复范围只是优先级低一些。技巧七修复完成后跑DRC和LVS。short修完不代表没问题可能会引入DRC violation或LVS mismatch。我一般修完short后跑一轮DRC和LVS确保没有引入新问题。5. 脚本实战从零搭建一套可复用的Short修复流程5.1 环境准备与工具版本确认在写脚本之前先确认工具版本。Innovus 20.1以上、ICC2 2019.03以上对short修复命令支持比较好。ICC因为版本老有些命令可能不支持需要查对应版本的command reference。环境变量要设置好尤其是PATH和LD_LIBRARY_PATH。我习惯在脚本开头加一段检查if {[catch {getToolName} tool]} { puts Error: Not in a supported tool environment exit 1 } puts Running in $tool5.2 完整脚本框架与执行流程一套完整的short修复脚本包含以下模块报告导出模块调用工具命令导出short report解析模块把report解析成结构化数据分类模块按PG/signal、cell/wire分类修复模块生成并执行修复命令验证模块重新检查short数量日志模块记录每轮修复详情执行流程是导出→解析→分类→修复→验证→判断是否收敛→未收敛则循环。set max_iter 10 set iter 0 while {$iter $max_iter} { export_short_report parse_short_report classify_short fix_short verify_short if {[get_short_count] 500} { break } incr iter }5.3 参数调优与收敛加速脚本里有几个关键参数需要调优margin大小、每批处理数量、ecoRoute的target。margin我一般从3个track开始如果效果不好降到1个track。每批处理数量从500开始如果工具资源充足可以加到1000。ecoRoute的target设为-target或-full看short复杂度。收敛加速的技巧先修简单case再修复杂case。简单case修完后绕线资源会释放出来复杂case可能自动消失。我一般把short按涉及net数量排序先修只涉及2个net的再修涉及多个net的。5.4 脚本维护与版本管理脚本要纳入版本管理用git或svn。每次修改都要记录改了什么、为什么改。我见过太多人脚本改乱了最后不知道哪个版本能用。我的做法是主脚本fix_short.tcl配置文件fix_short.cfg日志目录logs/每次跑之前先git commit。配置文件里放工艺相关参数比如track pitch、layer list、PG net pattern。这样换工艺时只改配置文件不用改脚本。# fix_short.cfg set track_pitch(M1) 0.05 set track_pitch(M2) 0.05 set track_pitch(M3) 0.1 set pg_pattern {VDD|VSS|GND|PWR|VCC} set max_iter 10 set batch_size 500这套流程我在多个项目里跑过从40nm到5nm都适用。5nm下short更多、更复杂但脚本框架不变只是参数需要调。比如5nm下margin要更小因为track pitch更小batch_size要更小因为工具资源更紧张。最后分享一个我个人体会修short不是目的收敛才是。不要追求一轮修完要追求每轮都有进步。脚本只是工具真正重要的是对short成因的理解和对修复策略的判断。我见过有人脚本写得很漂亮但short越修越多就是因为没理解short的本质。先把原理搞清楚再写脚本事半功倍。