☰
数字后端PPPR电源规划实战:从IR Drop根源到Innovus脚本详解
2026/10/6 10:43:55 网站建设 项目流程

做了这么多年数字后端,每次看到IR Drop违例列表里那一长串红色,心里都会咯噔一下。其实大部分IR Drop问题根源不在最后分析那一步,而在最开始电源规划没做扎实——也就是PPPR(Pre-Placement Power Routing)阶段偷了懒。PPPR说白了就是布局之前先把电源网络骨架搭好,很多新手容易把它理解成“跑个脚本加几条Stripe就完事”,实际操作中这活儿其实是个策略活,既要管住功耗,还得给信号绕线留够空间,稍有不慎后患无穷。

这次我把Innovus里做PPPR的完整思路、脚本和调参经验一起整理出来,脚本可以直接抄去改参数用。无论你是刚接手后端流程的工程师,还是准备把PPPR纳入现有flow的团队,这篇文章都能帮你少踩几个坑。

1. 先说清楚:PPPR和IR Drop到底是什么关系

很多朋友把PPPR当作一个简单的“加电源环、加电源条”动作,实际上PPPR要解决的是“芯片在物理上拿到电”这件事。IR Drop的本质是电流流过电源网络时,在金属电阻上产生了压降,离供电点远的cell实际电压低于标准值,cell延迟变慢,时序就崩了。

这个原理可以拿高楼供水来打比方:水泵在楼顶,越往下水压越大,越往上水流越小。芯片里也一样,power stripe太窄、间距太大,远端cell拿到的电压就会打折扣。PPPR干的事情,就是在摆放逻辑单元之前,先规划好哪几层金属走电源、走多宽、隔多远,确保整个芯片范围内每个标准单元都能“喝到水”。

PPPR在Innovus里的位置很明确:floorplan做完、标准单元还没摆放之前。这个阶段你手中已经是带macro摆放的floorplan,可以评估功耗密度和热点区域,趁早把power mesh的架构敲定。如果拖到place之后才发现电源网络不行,改起来成本成倍上涨,而且很多地方根本没空间再改。

它能解决的问题主要有三个:一是保证steady state时全芯片电压降在可接受范围;二是给后续dynamic IR分析打一个靠谱的基础;三是在早期就把电源网络和信号绕线资源的矛盾暴露出来,避免后期大改。适合谁看?准备入门后端物理实现的同学,以及正在被IR Drop反复折磨、想系统梳理PPPR流程的工程师。

2. 动手之前,三个关键决策要想清楚

2.1 电压域划分:一张图还是多张图

PPPR第一步不是画线,而是搞清楚你的芯片到底要通几路电。单电压域设计(只有VDD和VSS)最简单,直接全芯片统一打stripe就行。多电压域设计就麻烦不少,比如SoC里常见的1.0V核心逻辑加1.8V IO,两套PG网络互相独立,PPPR时要分别创建voltage domain,不同域之间的stripe不能混用,边界处还要处理隔离和电平转换单元的供电连接。

我见过团队在domain边界处理上栽过跟头:两个电压域挨得太近,addStripe的时候没设好boundary,结果一路电串到了另一路,IR分析出来一片乱。所以在动手前,先把SPEC里的power domain map拿过来,确认每个domain的bounding box和对应PG网络,这一步偷懒后面全是债。

2.2 PG网络的“主通道”选哪层

选层取决于工艺节点和金属层资源。常规做法是高层厚金属做全局stripe,因为电阻小、电流承载能力强;中低层金属做标准单元的Follow Pin和一个局部短连接。到先进工艺,有些设计连Backside Power Delivery都开始用了,电源直接走晶圆背面,PPPR思路又会不一样,但基本原理没变——用最宽的金属、最短的距离把电送进去。

选层的矛盾点在于:高层金属同时也是长距离信号绕线的主力,stripe铺多了信号没地方走线。我一般先用M7/M8做一条主stripe验证可行性,再根据IR结果决定要不要加密。别一上来就把所有高层金属全给电源,留给钟线和高速数据一些空间,否则后面CTS和route阶段你会发现根本绕不动。

2.3 IR Drop目标值怎么定

做PPPR之前要明确“做到什么程度算合格”。通常静态IR约束在3% VDD以内,动态IR约束在10% VDD以内,具体数值看芯片类型和代工厂建议,手机芯片比服务器芯片要严格,因为动态功耗波动大。目标值决定了stripe密度和宽度:目标越严,stripe就越宽、越密,绕线资源消耗越大,所以要找一个平衡点。

实际操作里,我会把IR目标和绕线资源一起权衡。比如PPA要求很紧的模块,我不追求全局最严IR,而是重点区域重点加固,普通区域满足基本约束就行。这种“局部特供”策略在高端设计里非常常见,省下来的就是实实在在的面积和绕线资源。

3. 完整PPPR脚本逐段拆解

3.1 脚本整体框架与变量设置

给大家的这套脚本是基于Innovus Tcl接口写的,核心命令包括globalNetConnect、addRing、addStripe、addFollowPin、sroute这几板斧。脚本我实际跑过,芯片级和模块级都能用,但是金属层、宽度、间距这些参数必须根据自己的PDK改,不能直接照搬。

# ============================================ # PPPR Master Script for Innovus # Author: Backend Engineer # Usage: # 1. load design (LEF/DEF/Netlist) # 2. source $PPPR_HOME/pppr.tcl # ============================================ # ---------- User Config ---------- set DESIGN_NAME chip_top set VDD_NET VDD set VSS_NET VSS set CORE_IR_TARGET 0.03 # Global Stripe Parameters set STRIPE_LAYER_TOP M8 set STRIPE_LAYER_BOT M7 set STRIPE_WIDTH 0.6 set STRIPE_SPACING 0.6 set STRIPE_PITCH 40.0 set RING_LAYER_H M7 set RING_LAYER_V M6 set RING_WIDTH 1.2 set RING_SPACING 0.5 set RING_OFFSET 1.0 set FOLLOW_PIN_LAYER M1 # Decap / Welltap set DECAP_RATIO 0.05 set WELLTAP_DISTANCE 20.0 # ------------------------------------------- # ---------- Initial Check ---------- if {![file exists $DESIGN_NAME.def]} { puts "Error: $DESIGN_NAME.def not found!" return -code error } loadDesign $DESIGN_NAME.enc.dat

这段脚本开头把所有可调参数集中在一个区域,方便后面对不同方案做批量扫描。PDK不同,M1能不能做Follow Pin、高层金属用什么宽度合适,参数都会变。我习惯把参数独立成vars文件,这样每次换工艺节点只要改一个文件,不用在脚本里翻来翻去。

3.2 第一步:全局电源连接

PPPR的第一步是把设计里每个标准单元的VDD/VSS引脚,逻辑上和全局PG网络连起来。注意这时候物理连线还没发生,只是建立了一种“应该连到同一网络”的关系,真正的金属线后面才画。

# ---------- Global Net Connect ---------- globalNetConnect $VDD_NET -type pgpin -pin $VDD_NET -inst * -override globalNetConnect $VSS_NET -type pgpin -pin $VSS_NET -inst * -override globalNetConnect $VDD_NET -type tiehi -inst * -override globalNetConnect $VSS_NET -type tielo -inst * -override

这里重点说一下-override这个选项。为什么加它?因为设计里可能存在一些多电源domain或者isolated cell,在综合阶段或upf定义时PG连接可能已经部分指定了,没有-override的话,Innovus遇到已连接的网络会跳过,容易产生“某些单元没被连上PG网络”的隐患。加了它,等于强制把规则刷新一遍,保证所有instance都背着VDD/VSS标签。

tiehi和tielo也不能忘。标准单元内部有些输入固定接高或接低(比如扫描使能、测试模式信号),这些引脚需要真正连到PG网络而不是跑信号线。很多新手只设pgpin,漏了tiehi/tielo,结果DRC风平浪静,一跑IR分析,一堆floating引脚冒出来。

3.3 第二步:创建PG电压属性

globalNetConnect把网络关系绑定了,但Innovus还不知道VDD是几伏电压,所以下一步要用createPG告诉工具每个PG网络的电压值。有了电压属性,后面IR分析工具才能计算IR Drop,没有电压配置,功耗分析工具直接用默认值会算出完全错误的结果。

# ---------- Create PG ---------- createPG -net $VDD_NET -voltage 1.00 createPG -net $VSS_NET -voltage 0.00

多电压域设计就多写几行,比如:

createPG -net VDD_1V0 -voltage 1.00 createPG -net VDD_1V8 -voltage 1.80 createPG -net VSS -voltage 0.00

这里要特别提醒:电压值必须和UPF、SDC里的电压信息保持一致,一旦对不上,后端的功耗分析、时序分析会横竖都对不上账。我在项目里吃过一次亏,SDC里写的是0.8V内核电压,createPG写了个0.85V,结果IR分析报出来的droop比例看上去不高,换算成绝对电压偏了5%,后面查了半天才发现是这种低级不一致造成的。

3.4 第三步:电源环和电源条

这是PPPR的主体工作,也是参数最多、最容易翻车的地方。

# ---------- Add Ring ---------- addRing -nets "$VDD_NET $VSS_NET" \ -around core \ -layer {top $RING_LAYER_H bottom $RING_LAYER_H left $RING_LAYER_V right $RING_LAYER_V} \ -width $RING_WIDTH \ -spacing $RING_SPACING \ -offset $RING_OFFSET # ---------- Add Stripe ---------- addStripe -nets "$VDD_NET $VSS_NET" \ -layer $STRIPE_LAYER_TOP -direction horizontal \ -width $STRIPE_WIDTH -spacing $STRIPE_SPACING \ -set_to_set_distance $STRIPE_PITCH \ -max_same_color_joglength 4 addStripe -nets "$VDD_NET $VSS_NET" \ -layer $STRIPE_LAYER_BOT -direction vertical \ -width $STRIPE_WIDTH -spacing $STRIPE_SPACING \ -set_to_set_distance $STRIPE_PITCH \ -max_same_color_joglength 4

先说addRing。电源环的作用是把芯片核心区域的四周围一圈厚金属,相当于给整个core区域一个外围供电干线。层选择上至少要有两层金属交叉(横向一层、纵向一层),这样环形路径在转角处不会断。width取多少?我是从供电需求估算的:整个block峰值电流除以金属单位宽度的电流承载能力,再留出30%的裕量。比如一个100mA电流的block,高层金属1um宽大约能安全走1mA到2mA(跟工艺和温升有关),那环形总宽度至少得有50um,分摊到电源和地两条环,每条25um。如果ring设得太窄,相当于供水总管的管径不够,末端水压肯定上不去。

再说addStripe。Stripe是贯穿core内部的电源条,真正给内部cell供电的就靠这些条。set_to_set_distance是条与条之间的中心距,这个值直接决定IR Drop好坏。间距小,电阻小,IR好,但绕线资源被占得多;间距大,省资源,IR容易超。经验法则是第一阶段先用20~40um试跑一轮,再根据IR结果加密或减稀,不要一上来就贪。

还有一个关键操作是横向和纵向两层stripe都要打,形成网格状结构。为什么?因为只走单方向,供电路径长,IR压降会显著增加。纵横交错相当于给电流多修了几条路,电流可以从多个方向汇入,整体压降成倍改善。很多刚入门的朋友打完M8一条方向就觉得完事了,分析出来的IR惨不忍睹,其实就是网格没做完整。

3.5 第四步:Follow Pin与标准单元供电

Stripe是供电干线,但标准单元的电源引脚在最底层的M1上,怎么办?靠Follow Pin连接。Follow Pin就是在标准单元行的电源轨道上直接画一根细长金属,把这一行所有cell的VDD/VSS串起来,再通过via把Follow Pin引到上面的stripe。

# ---------- Add Follow Pin ---------- addFollowPin -nets "$VDD_NET $VSS_NET" -layer $FOLLOW_PIN_LAYER

这个命令会沿着每个标准单元row自动生成电源轨道。需要注意FOLLOW_PIN_LAYER一定要选标准单元PG rail所在的金属层,通常就是M1。如果选错了层,DRC不会立刻报错,但后续sroute会乱成一团,via打不下去,单元取不到电。

打完Follow Pin之后,Innovus里其实还有一个容易忽视的操作:加via。Follow Pin在M1,Stripe在M7/M8,中间M2到M6层层都要靠via阵列打下去。via不够,电流只能挤在几个点上,IR照样炸。addStripe的时候用默认设置,Innovus会在Stripe和Follow Pin重叠区域自动加via,但有些情况下via密度不够,此时可以在Stripe的交叉点手动加via array,或者用addViasToPin把关键连接点补齐。

3.6 第五步:SRoute连接所有供电节点

到这里,电源网络还是“概念图”:globalNetConnect建立了逻辑关系,Ring和Stripe是物理走线,Follow Pin是标准单元轨道。但三者之间还没形成完整的通路。SRoute就是做这个最终缝合工作的命令——把Ring、Stripe、Follow Pin以及block的PG pin全部连起来。

# ---------- SRoute ---------- sroute -nets "$VDD_NET $VSS_NET" \ -allowJogging 1 \ -allowLayerChange 1 \ -blockPinTarget 1 \ -corePinTarget 1

allowLayerChange和allowJogging必须打开,否则SRoute只走直线,遇到跨层连接会直接失败。blockPinTarget和corePinTarget意味着macro的电源引脚和core区域的引脚都要被连接,如果这里没开,memory的电源脚就会漏掉,IR分析的时候那片区域会艳红一片。

SRoute跑完,PPPR主体工作基本结束,回到脚本开头看那一段收尾操作:

# ---------- Add Welltap & Decap ---------- addWellTap -cell FILL0 -prefix WELLTAP -betweenDistance $WELLTAP_DISTANCE addDecap -cell DECAP_8T -prefix DECAP -ratio $DECAP_RATIO

WellTap是给衬底和阱接电的,防止latch-up。Decap是去耦电容,用空闲面积填一些decap cell,能有效抑制动态IR Drop的瞬时电压塌陷。这两个操作虽然不直接画电源线,但和IR Drop深度相关,尤其是dynamic IR场景,decap密度太少,开关噪声瞬间拉低电压,后果比静态IR超一点还严重。我一般先在floorplan阶段填5%~8%面积的decap,然后根据IR分析结果调整,不建议上来就堆满,decap堆太多影响面积和绕线密度。

最后可以做一次检查和存档:

# ---------- Check & Save ---------- check_pg_routing saveDesign $DESIGN_NAME.pppr.enc

3.7 多电压域脚本的常见变体

如果设计里存在多个电压域,脚本就不会这么线性了,得为每个domain单独创建PG环和Stripe。习惯写法是先建domain再单独操作:

createVoltageDomain -name CORE -boundary {0 0 1000 1000} -primaryPowerDomain createVoltageDomain -name IO -boundary {1000 0 1200 1000}

然后分别对CORE和IO添加Ring和Stripe,加Stripe的时候用-selected或者先用addRing/addStripe -domain指定作用范围。我不建议用-selected这种方式来试错,因为在Innovus里选中区域的操作容易受GUI影响,脚本化的时候不可控。多电压域的脚本一定要把domain名称写到addStripe参数里,明确边界,查起来也方便。

4. 做完PPPR,怎么快速验证IR Drop

4.1 静态和动态分析的区别

脚本跑完,别急着开香槟,关键一步是验证。有些团队习惯等place和route全部结束后再做IR分析,发现IR超过目标值再回来改PPPR,那时候要重新跑一遍完整PR流程,成本非常大。建议PPPR阶段就做一轮快速静态IR检查,早发现问题早改。

常见的分析工具是Voltus或RedHawk。Innovus通常和Voltus深度集成,用起来比较顺手。静态和动态分析本质区别在输入数据:静态分析默认给一个固定的翻转率(比如20%),去估算全芯片的电流分布,优点是快,缺点是不够精确;动态分析吃VCD波形或SPEF寄生参数,能精确到时钟沿翻转瞬间的电压塌陷,精度高但流程重,需要仿真数据。

PPPR阶段用静态分析足够,数据格式也简单,输入是DEF+database,加上功耗估算文件(通常从UPF/CPF或SAIF拿)。动态分析等place之后再做,拿着寄生参数算,才不会被“预估值”误导。

4.2 Voltus快速验证操作步骤

在Innovus窗口里操作比较典型的流程是这样:先跑一次powerAnalysis工具抽象出电网结构,然后配置功耗输入,最后运行分析。下面给出一个最精简可跑的静态IR分析命令序列,具体版本命令名可能会有差异,但流程不变:

# ---------- Quick Static IR Check ---------- set_power_analysis_options -output_dir ir_check_output -report_format text,ascii set_dynamic_power_analysis_options -cycle_time 2.0 -toggle_rate 0.2 set_power_analysis_options -analysis_type static run_power_analysis -design $DESIGN_NAME

toggle_rate 0.2是默认功耗估算,意思是平均每个时钟周期内信号翻转20%。如果你功耗模型清晰,可以用更精确的值,或者直接导入SAIF文件,分析结果会更可信。

跑完后重点看两个指标:一是最差IR Drop的压降百分比,是否在CORE_IR_TARGET以内;二是热点位置在哪里,是否集中在某些高功耗区域。如果报告里最差压降在某个macro附近,那大概率是Stripe密度不够或者welltap/decap不够,回过去在对应区域局部加密Stripe即可。

4.3 IR Drop超限怎么办

发现超限后,先判断是全局性问题还是局部性问题。全局超限通常是Stripe整体密度不足或Ring宽度不够,这时候把addStripe的set_to_set_distance从40调到30或20,重新跑;局部超限则在一个区域附近手动加几根短Stripe,不要全局一起加密,浪费资源。

两个常见补充手段也值得一说。第一,在热点区域的空闲地方填decap,缓解动态IR;第二,把热点周围的标准单元电源轨道做加宽处理(M1末端加宽或加宽Follow Pin的供电入口)。这些手段都是手术刀式操作,精确打击,效果比无脑全局铺金属要好得多。

5. 实战中的高频坑和排查技巧速查

5.1 高频问题速查表

我整理了一张自己在项目中反复遇到的PPPR问题对照表,先列出来给大家参考:

现象直接原因排查方向
大量标准单元PG引脚floatingglobalNetConnect漏配或没加override检查pgpin配置,确认instance数量是否匹配
IR Drop分析出来整片是红色Stripe网格缺失或via密度不足检查addStripe的横纵方向是否都有,via阵列是否有效
SRoute报错无法完成Ring/Stripe层选错或重叠区域为零检查Ring offset和Stripe layer是否在同一组金属层
特殊区域IR特别差macro附近Stripe密度不足或decap缺失局部加Stripe或decap,不要全局动
多电压域边界IR异常Domain边界重叠或PG网络被误连检查createVoltageDomain边界和globalNetConnect作用范围
DRC报出大量WellTap违例WellTap间距过大或密度不足确认addWellTap的betweenDistance是否符合规则

这类问题之所以高频出现,是因为PPPR错误往往不是立即报错,而是潜伏到后续IR分析或DRC阶段才爆发。排查时用Innovus的GUI可视化PG网络最直观——Stripe和Ring是否闭合、Follow Pin是否和Stripe交叉点有via,一看便知。

5.2 那些文档里不会写清楚的经验

  • 经验一:PPPR阶段就要跑一遍快速IR,别等route完 这是我最想强调的一点。Route完的IR分析当然精确,但改起来成本太高。PPPR阶段跑静态IR虽然粗糙,但趋势判断完全够用。我在实际项目里形成一个习惯:place之后马上跑一轮临时IR,标记热点区域,然后回头在PPPR脚本里把热点区域单独加固,再重新跑place。两轮下来,最终route收出来的IR普遍很干净。

  • 经验二:Stripe参数用变量扫描,别手改 把set_to_set_distance和width做成变量,写一个两层循环,批量试试不同组合的IR结果,选一个在IR、面积、绕线拥挤度三方面都均衡的方案。这比来回手动改脚本快得多,也更容易发现参数变化的趋势。之前我团队里一位工程师就是用这个办法,把全芯片IR从4.2%压到2.7%,只牺牲了不到1%的绕线资源。

  • 经验三:ECO阶段加buffer千万别忘PG连接 Run到后期做功能性ECO或Timing ECO时,有时候会直接手工在版图上插buffer来修复时序。新插入的buffer如果没走globalNetConnect那套流程,它的PG引脚就是floating的,跑到IR分析阶段会突然冒出几十个未连接引脚。很多人在这个位置卡了一整个下午,查到最后发现是说“为什么PPPR都做了红彤彤还是一片”的根源,其实是后期ECO单元没连电源。顺手在ECO脚本末尾加一句globalNetConnect刷新就能避免这个问题。

  • 经验四:留好转角空间和信号通道 最后一个实用心得是:不要把Stripe铺得密不透风。一个网格均匀的电源网络确实能压住IR,但如果所有可绕线层都被电源占满,信号绕线只能绕远路,时序反而变差。给clock和高速数据留些横跨芯片的专用通道,IR稍微差一点点但整体PPA可能反而更好。电源规划和时序规划是同一套资源上的博弈,谁都想多占一点,最后出来的方案一定是妥协的结果。

我这些年在后端项目上最深的体会是,PPPR这个阶段看起来平淡无奇,其实对整个芯片的收敛节奏影响极大。前期多花两三个小时把电源网络规划扎实,后期IR分析就能省出两三天来回折腾的时间。脚本只是一个起点,把网格密度、层选择和decap比例配合好,才是真正的功力所在。如果大家在实际项目里遇到其他奇怪的电源规划问题,也建议先回到这几个基础环节去排查,大概率能少走不少弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询