☰
数字IC后端实战:ICC中复杂模块Floorplan与Powerplan设计要点
2026/10/7 13:48:00 网站建设 项目流程

做数字IC后端的人,应该都听过这句话:floorplan定生死,powerplan定成败。夸张吗?一点都不夸张。我接手过不少复杂模块,有些项目看起来代码逻辑没什么问题,综合出来时序也还凑合,结果一到后端,floorplan没做好,后面place和route全是坑,修congestion修到怀疑人生,甚至最后为了收时序把整颗芯片的频率都拉低。而这一切,往往在最初定floorplan的那两天就已经埋下了。

今天这篇就围绕ICC(Synopsys IC Compiler)这个工具,聊聊复杂模块的floorplan和powerplan到底该怎么做。文章不会去重复那些已经写烂了的工具手册内容,而是把我实际跑过项目后的思考、计算方式、命令用法,以及踩过的坑,尽量完整地记录下来。适合正在做数字后端、准备入门后端的工程师,还有那些从模拟后端转数字后端的同学参考。如果你已经在用Innovus,很多思路同样是通用的,工具只是实现手段。

1. floorplan设计思路:从die area到macro摆放的全局拆解

1.1 为什么floorplan决定后端成败

很多人刚做后端时,会把floorplan简单理解为“把memory和大模块摆一摆”。实际远不止这些。floorplan的核心任务是在物理层面上还原设计的数据流和控制流,让信号走的路径尽量短、相互干扰尽量小,同时为时钟树、电源网络留出足够的空间。

我做复杂模块时,有个很深的体会:floorplan真正难的地方在于平衡。你要同时照顾时序、拥塞、电源完整性、可布线性、甚至后端之后的物理验证。这些指标之间经常相互打架。举个最直白的例子,macro摆得太集中,短距离绕线方便了,但局部congestion会直接爆掉,CTS阶段插完buffer之后更是雪上加霜;macro摆得太散,看起来每个区域都宽松了,但关键路径的net长度变长,时序收不回来。所以floorplan从来不追求某一个指标做到极致,而是追求整体不出大问题。

还有一点必须提醒:floorplan阶段的设计决策,后期改起来成本极高。我也见过有同事过了placement才发现某个memory放歪了,想挪一下位置,结果动一个macro,周边几百条net全部重绕,一连串的时序violation冒出来,白白浪费两三周时间。所以在floorplan阶段宁可多花两天仔细推敲,也不要赶进度。

1.2 拿到复杂模块后我的第一轮布局思路

拿到一个复杂模块的netlist,我先不看具体逻辑,而是做三件事:看数据流方向、看memory分布、看关键路径约束。这三件事的输出,直接决定我下面怎么定core面积和macro摆放。

数据流方向怎么看?一般是从综合后的sdc和网表中提取模块间的连接关系,复杂设计也可以看设计文档里的block diagram。把数据通路的方向标出来后,macro摆放就有一个基本逻辑了:一组有大量数据交互的macro,它们在floorplan上应该尽量靠近,且数据的入口和出口要对齐到对应的IO端口方向。

举个例子,一个通信基带模块,通常包含多个FIFO、几块大SRAM、一些乘加运算单元。FIFO往往是数据缓冲,SRAM是中间结果存储,乘加单元是计算核心。数据流一般是从接口进来,进FIFO,然后给到运算单元,中间结果写SRAM,最后再出去。那我在摆macro时,会让FIFO靠近输入端口,SRAM放在运算单元附近,避免数据在芯片上“绕远路”。

EM(Electromigration,电迁移)和IR drop是powerplan的关注点,但floorplan阶段就要提前考虑。macro多、面积大、功耗高的模块,电源网络必须足够密。所以我定macro位置的时候,会顺手看一下每个macro的功耗估算(通过之前的功耗分析报告),把功耗高的区域空出足够的power stripe通道,避免后期这里电压降得厉害。

核心的摆放原则可以先归纳成几句话:数据流方向贯穿整个floorplan,高交互模块就近摆放,SM(标准单元)区域保持相对完整连续,时钟敏感模块避开电磁干扰源。

1.3 用congestion评估反馈闭环来打磨方案

摆完第一版macro之后,我习惯尽快跑一个快速placement(ICC里就是create_placement之类的流程,可以先做congestion map),哪怕时序还没有优化,也先把congestion看一遍。这一步非常有用,它能把“我感觉这样摆挺好”变成“实际绕线资源吃不吃紧”。

怎么读congestion map?重点关注三类区域:macro之间的channel、macro与block边界之间的区域、以及标准单元密集区。这些地方如果出现大片红色,说明绕线资源可能不够,要么增加channel宽度,要么调整macro的相对位置。注意,congestion map有方向性,竖着走线的层和横着走线的层拥塞程度不一样,要结合工艺的金属层方向和pin density一起看。

ICC里可以直接生成congestion report和map。我一般看两个值:全局拥塞度和局部拥塞度。如果某个局部区域超过105%甚至110%,就说明这个区域很可能成为后期的瓶颈,一定要在floorplan阶段处理掉。我曾经遇到过一个模块,全局拥塞度只有92%,看起来很不错,但实际上chip corner附近一块很小的区域拥塞度到了120%,结果route阶段在那里浪费了整整四天。从那以后,我每个floorplan都会专门检查“局部热点”,而不是只盯着平均指标。

2. powerplan设计:电源环、stripe与std cell供电的完整推导

2.1 电源环宽度计算与金属层选择

powerplan很多人觉得就是把VDD和VSS铺上去,没什么技术含量。这是大错特错。powerplan设计的目标是:在芯片工作的所有工况下,每个标准单元的供电电压都落在允许范围内,同时电源网络本身的电流密度不超出金属层的可靠性上限。这里面的每一步都是计算出来的,不是拍脑袋决定的。

先讲core ring(电源环)。core ring是围绕core区域的一圈环形电源走线,作用是把外部供电导入core内部的power stripe网络中。计算core ring总宽度时,最基础的方法是:先估算整个模块的平均电流和峰值电流,再根据目标IR drop和金属层方阻算出所需的总电阻,进而推算出金属宽度。

打个比方,模块峰值电流I_peak假设为5A,允许的IR drop是30mV,那core ring本身的等效电阻就应该控制在6mΩ以下(R = V / I = 0.03V / 5A)。金属的方块电阻和厚度、宽度有关,如果用的是顶层厚金属M9,方块电阻可能在0.1Ω/sq量级,那么选择合适的宽度和层数让总电阻满足要求。

还需要注意EM的影响。金属在过高电流密度下会发生电迁移,时间长了会断路。这个在powerplan设计时就需要用电流密度上限来约束:宽度的选择必须同时满足IR drop和EM两个约束,取两者中更大的那个宽度。很多人在这一步只算IR drop,项目后期EM signoff不过,回来改powerplan,代价非常大。

2.2 mesh与stripe的规划:EM、IR drop与绕线资源平衡

core ring只是第一步,真正给标准单元供电的是power stripe网络(也叫电源rail或电源mesh)。stripe的间距、宽度、层数,直接影响IR drop和绕线资源之间的平衡。

stripe太密,电源网络好看了,但信号绕线资源被大量占用,congestion出问题;stripe太疏,IR drop超标,标准单元供电不足,时序直接恶化。业界一般怎么定?先根据功耗和电压降目标做一次粗略的IR drop分析,看需要多密的网络,再结合信号绕线资源做折中。比如在7nm工艺下,M4/M5作为局部电源层,M6/M7作为中层stripe,顶层M8/M9作为全局电源层,每一层stripe的间距从几十微米到一两百微米不等,需要根据block大小和功耗密度具体算。

这里我分享一个我的经验值参考表(注意,这只是参考,具体工艺和库需要重新算):

  • 标准单元功耗密度较低的设计:stripe间距取40μm~60μm,M4/M5即可
  • 功耗密度中等:stripe间距取30μm~40μm,M4/M5加M6/M7双层
  • 高功耗密度:stripe间距20μm~30μm,配合顶层厚金属M8/M9做电源主干

ICC里相关的命令是create_power_stripes,需要在定义好power network之后执行。这个命令的参数很多,包括layer、width、pitch、direction、nets等,我后面实操部分会给出一个可参考的脚本。

再补充一个mesh的细节:电源网络最好做成格状结构,也就是横向和纵向都有stripe连接。格状结构的好处是电流可以从多个路径流向负载点,降低等效电阻,提高EM容限。哪怕某个局部区域有一个stripe断了,电流也能从旁边绕过去,不至于立刻出问题。这就像城市路网,有横有纵,单条路堵了还能绕行,如果只有一条主干道,一旦出事就整片瘫痪。

2.3 PG connection与follow pin的落实细节

power网络规划好了之后,还要把它真正连接到标准单元上。这里涉及两个概念:follow pin和PG connection。

Follow pin是标准单元行上的电源轨,一般由工艺库自动连接。在ICC里,通过derive_pg_connection命令,工具会自动把std cell的VDD/VSS连接到对应的power stripe网络上。这里有个细节:如果你的设计有多个电压域,比如VDD和VDD_SRAM,一定要确保derive_pg_connection的-power_net、-ground_net参数设置正确。我曾经见过一种情况,两个电压域的名字写错,导致SRAM的cell被接到了错误的电源网络上,虽然LVS没报问题(因为PG属性还在),但实际仿真时SRAM供电电压不对,功能直接错误。

另外还有一类特殊cell:endcap cell和welltap cell。Endcap是放在标准单元行两端、用来满足工艺规则(比如N-well边界要求)的单元,welltap是提供衬底偏置连接的单元。这些cell的PG连接容易被忽略,但它们如果不接好,DRC会报出一堆问题,LVS也会出错。所以在floorplan之后,一定要先加endcap和welltap,再做电源网络连接,顺序搞反了后面检查很麻烦。

3. 实操过程:ICC命令级流程与关键检查点

3.1 初始化数据与design planning的启动

ICC操作的起点是准备好所有输入数据:netlist、SDC约束、LEF/Milkyway reference library、TLU+寄生参数文件、以及IO约束文件(如果模块有IO pin)。在启动ICC之前,我习惯把数据清单列出来逐项确认,少任何一个文件,后面都有可能卡住。

启动ICC有两种方式:图形界面和tcl shell。实际做复杂模块,我更多用tcl脚本跑流程,图形界面主要用于看congestion map和macro位置。用命令行跑的好处是可重复、可回归,改一个参数重跑一遍非常方便。

进入工具后,第一步是读入库和设计。ICC里一般用Milkyway格式的物理库,通过set_mw_cel_ref_library和open_mw_lib来指定。读入netlist后,需要做elaborate和link,把设计和库关联起来。这个阶段如果报出unresolved reference,说明netlist里有些instance引用的cell在库里找不到,一定要先解决,不能带着错误往下走。

初始化完成后,我会用report_design和report_power先看一下设计的基本情况:总cell数量、macro数量、功耗估算。这些数字帮助我在后面做面积估算和powerplan参数选择时有个底。

3.2 macro placement与pin assignment的操作要点

复杂模块的macro placement,我建议用“手动初摆+工具自动摆放辅助验证”的方式,而不是完全依赖工具的自动macro摆放功能。手动摆放时,参考线(guideline)用得上:可以先把数据流方向用虚拟的矩形框画出来,再把macro放进对应的框内。

ICC里调整macro位置可以用move_placement或set_macro_pin_connection等命令。实际操作中,我一般这样操作:先把所有macro按理想位置放好,用refine_placement(或create_placement)跑一遍快速placement,看一下congestion map,然后根据热点反复微调macro位置。这个过程可能要迭代好几轮。

Pin assignment(IO pin分配)也很关键。复杂模块通常有几百甚至上千个IO pin,它们的顺序和位置会影响整个block的绕线难度。ICC里可以用edit_pad或者place_pins命令来摆pin。一个原则是先满足时序关键信号的路径最优,再考虑非关键信号。实际中,pin的位置需要和顶层(top level)的规划对齐,不能只顾着模块内部绕线方便,结果到了顶层发现连线交叉严重。如果模块有pin的relative order约束(比如总线pin要连续排列),需要在floorplan阶段就和前端/架构确认清楚,避免后面改pin位置引发大面积重绕。

3.3 powerplan创建:create_rect_rings与create_power_stripes实战命令

接下来是powerplan的落地环节。先创建core ring,再打stripe,最后做std cell区域内的PG连接。

创建一个core ring的ICC命令示范(具体参数以你的工艺和设计为准):

create_rect_rings \ -nets {VDD VSS} \ -left_offset 2 \ -right_offset 2 \ -top_offset 2 \ -bottom_offset 2 \ -left_segment_layer M9 \ -right_segment_layer M9 \ -top_segment_layer M8 \ -bottom_segment_layer M8 \ -width 4 \ -spacing 0.2

这条命令的意思是:在core的四周创建VDD和VSS的电源环,宽度4μm,M9走左右两边,M8走上两边,距离core边界2μm。这里width和spacing怎么定,我在前面已经讲过了,一定要结合IR drop和EM计算。注意,左右两边的M9宽度和上下两边的M8宽度可以不同,因为不同层的电流承载能力不一样。

创建power stripe的命令示范:

create_power_stripes \ -nets {VDD VSS} \ -layer M6 \ -direction vertical \ -width 1.2 \ -pitch 40 \ -set_to_set_distance 20 \ -extend_to_boundary

这条命令会在M6层上沿垂直方向创建VDD/VSS交替排列的stripe,宽度1.2μm,间距40μm。set_to_set_distance表示VDD与VSS stripe之间的距离。

这里我要特别提醒stripe的起点和终点设置。很多新人用create_power_stripes时,stripe延伸到了core ring外面,结果DRC报出一堆short问题。最好用-extend_to_boundary把stripe限定在core区域内,或者手动指定-延伸范围。

为了让VDD和VSS在多个金属层之间形成完整的电源mesh,还需要在横向的M8、M9层上也打stripe或ring。各层之间通过via阵列连接,via的数量要足够承载电流,否则会在via处形成EM热点。via密度不够是非常常见的EM问题来源。

接下来是standard cell的PG连接,ICC里用derive_pg_connection:

derive_pg_connection \ -power_net VDD \ -power_pin VDD \ -ground_net VSS \ -ground_pin VSS \ -create_ports top

如果设计里有多个电源域,需要分别为每个域执行derive_pg_connection,并指定对应的power pin。执行完以后,用report_pg_pin或check_pg_power_structure检查有没有漏接的pin。

3.4 用check_pg和编译前检查堵住时间炸弹

电源网络创建完不代表就结束了,必须要做检查。ICC里有专门的检查命令:check_pg_power_structure、check_pg_connectivity等。我每次跑完powerplan,都会认真过一遍这些检查,哪怕报出来全是WARNING也要一条条看。

常见的检查结果有几种:

  • 某些instance没有连接到电源网络
  • VDD和VSS网络之间有short
  • 某些层的stripe断开,形成浮空网络
  • 多电压域之间的isolation cell缺少PG连接

这些问题在powerplan阶段发现,改起来几分钟;如果等到place之后才发现,可能要把整个PG网络重做,代价完全不同。

除了PG检查,还要跑一个快速placement,验证congestion是否在预期范围内。我的习惯是:floorplan和powerplan做完后,先跑一个只含placement的阶段(不做时钟树),看congestion和时序大概情况。这一步能花半天时间,但能提前发现50%以上的后期问题。

4. 常见问题与排查技巧:congestion、IR drop、DRC的连环坑

4.1 congestion爆掉时先别急着调floorplan

很多工程师一看到congestion map上一片红,第一反应就是挪macro。这个反应不一定对。congestion高有两种原因:一种是macro布局不合理,另一种是标准单元的摆放密度在某个区域过高,还有可能是pin access问题。

排查时,我会先用report_congestion看具体是哪些层、哪些区域拥塞。如果是局部区域标准单元太多,可以考虑调整utilization,给这个区域留出更多空白;如果是pin access导致绕线资源被blockage占用,需要检查是不是macro的pin朝向了错误的方向。

还有一种特殊原因:module的端口位置和macro的pin位置冲突。数据从macro的pin出来,要走很长一段才能绕到block的边界port,这段路径如果经过标准单元密集区,congestion就会很高。这时候与其挪macro,不如调整pin assignment,把block的IO pin放在更靠近对应macro的方向,让数据流少穿越标准单元区域。

另外一个容易被忽视的角度:SDC约束太乐观或太悲观,会导致工具在优化时过度修时序,插入大量buffer,间接推高congestion。如果congestion高同时时序violation也多,可以试着放宽不关键路径的约束,让工具别在这条路径上浪费资源。

4.2 IR drop与EM仿真不过的定位方法

IR drop问题在静态分析阶段往往不会暴露,因为早期功耗估算不够准确。等做完signoff IR分析时发现电压降超标,已经进入了项目的后半段。这时候定位问题,我一般按照从全局到局部的思路来:

第一,先看全局IR drop map,判断是整体压降大还是局部热点。整体压降大,说明power stripe网络整体偏稀疏,或者core ring宽度不够,需要加密全局电源网络。局部热点,一般集中在功耗密度高的macro附近,尤其是一些高频翻转的SRAM、register file周围。

第二,看EM检查结果。EM问题经常出现在via阵列和stripe拐角位置。如果某个via array报EM violation,不要只是增大via数量,还要看金属宽度是否足够,因为电流瓶颈在窄金属段和via上。

第三,结合功耗分析报告,确认高峰值电流窗口。有些IR drop问题只在特定测试向量下有,如果向量覆盖不到,静态分析可能永远发现不了。这时候需要跑动态IR分析(比如RedHawk/Voltus),把峰值电流窗口找出来,再针对性地加强相应区域的电源网络。

4.3 实际流片案例中的经验教训

分享一个我早期踩过的真实教训。当时做的模块有十几个macro,我为了追求congestion数字好看,把所有macro摆放得很“整齐”,memory全部对齐到一个方向。表面上看,模块内部通道很宽裕,congestion也很好。结果在CTS阶段发现,时钟网络要穿过好几块memory之间的窄通道,好几条clock path因为绕线距离过长,latency差异巨大,setup和hold同时出问题。

后来我在floorplan评审时,被资深工程师一句话点醒:“你摆的是memory,不是士兵列队。对齐是好看,但数据和时钟不会因为你对齐就走直线。”从那以后,我摆macro不再追求视觉上的整齐,而是尽量让每一组高交互的module之间的物理距离最短。有些地方看起来歪歪扭扭,但实际绕线反而短、拥塞也低。

还有一个关于powerplan的教训:有一次为了节约绕线资源,把M6的stripe间距从默认的30μm拉大到了60μm。结果功耗分析的时候,IR drop直接从3%飙到了8%,标准单元供电不足,时序大面积violation。后来不得不增加一层M7的stripe,把M6抽掉的部分补回来,前后折腾了一周多。这件事让我明白了一个道理:powerplan的参数不是拍脑袋定的,要用数据说话。省这一点点绕线资源,远远不够弥补IR drop带来的损失。

5. 避坑指南:从工具脚本到团队协作的工程素养

5.1 ICC使用中的脚本规范与版本差异

ICC的命令在不同版本之间差别比较大,尤其是从ICC到ICC2(现在叫Fusion Compiler)的迁移过程。如果你的项目还在用老版本的ICC,需要特别注意:create_rect_rings和create_power_stripes这类命令的参数在ICC2中已经变了。如果是新项目,建议直接用Fusion Compiler的流程,别在新项目上继续用旧版本的脚本,否则工具迟早要逼你升级,到时候全部脚本重写,成本和风险都不小。

脚本管理上,我强烈建议把floorplan和powerplan的脚本做成参数化、模块化的结构。比如统一使用变量定义所有macro的名字、位置、尺寸,用变量定义stripe的层、宽、间距。这样换一个模块或者改一版floorplan的时候,只需要修改参数区,不需要动核心代码逻辑。

另外,ICC的脚本一定要用tcl的source方式逐段执行,不要一次性把上千行脚本全部跑完。每一段脚本之间加report和checkpoint,方便定位是哪一步出了问题。我的习惯是每完成一个阶段就存一个milkyway library的cell view,比如fp_start、fp_macro_placed、pg_created、place_done,这样随时可以回滚到任意阶段。

5.2 复杂模块floorplan评审清单

一份好的floorplan方案,不应该只存在于EDA工具里,还应该能通过团队评审。我每次做复杂模块floorplan,都会准备一份简短的评审清单,在评审会议上逐项过:

  • 模块面积和utilization:是否留有足够缓冲,能否应对后端优化带来的面积增加
  • Macro摆放vs数据流/时钟路径:关键路径是否会被迫绕远路
  • Congestion热点:是否存在局部拥塞超过100%的区域
  • 电源网络:IR drop目标、EM裕量、多电压域连接方式
  • IO pin分配:是否和顶层规划对齐,differential pair、bus pin是否成组
  • 特殊单元:endcap、welltap、decap的初步规划
  • DRC风险:比如macro间的间距是否满足最小channel宽度、N-well边界规则

评审清单看似繁琐,但它的价值在于倒逼你把每一步都想过、算过。很多floorplan的后期问题,在评审阶段就能被提前发现。

工具脚本写得再漂亮,也只是执行你的思路。真正的后端功力,体现在你是否理解设计数据流的本质、是否摸清了工艺和库的特性、是否愿意在前期多花时间推敲每一步决策。

5.3 新人上手ICC的3个实操建议

最后给刚接触ICC做floorplan的新人三个实操建议。

第一,找一个已有的项目脚本作为起点,不要从零开始写。很多公司内部都有可复用的floorplan模板脚本,这些脚本经过了流片验证,里面的参数和检查点比工具默认设置更贴近实际需求。照着模板改,比自己在man page里翻命令高效得多。

第二,养成随手截图和记录的习惯。每次调整一个参数,记录下调整前后的congestion、timing、IR drop数据。时间久了,你会积累出一套属于自己团队的“参数经验表”,而不是每次遇到问题都从头试。

第三,遇到问题先看log文件。我见过太多人在群里问“congestion为什么爆了”,实际上log文件里已经清清楚楚写着哪个区域、哪一层资源不够。学会读log、读report,是后端工程师的基本功,别让工具替你思考,工具只是把你的思考变成物理实现。

做floorplan和powerplan这件事,我一直觉得它很像城市规划。路网怎么留、水电怎么铺、商业区居住区怎么摆,都会影响一座城市未来几十年的运转效率。放在芯片上,这些决定会在后面place、CTS、route的每个阶段加倍奉还。前期想得越细,后期越省心。希望这篇关于ICC复杂模块floorplan与powerplan的实操记录,能给正在做后端或者准备入行后端的你一些参考。

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

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

立即咨询