数字后端布图规划全解析:从芯片尺寸到电源规划的关键实践 1. 为什么后端学习要从布图规划开始第一次在Innovus里打开一个还没有任何摆件的空die屏幕上只有一条淡淡的芯片边框和一些IO pin的虚影时大多数人都会愣一下接下来要做什么这个空白区域就是芯片物理实现的起点而布图规划Floorplan就是在这个空白区域上画出第一笔也往往是决定整个项目成败的第一笔。我一直觉得布图规划是数字后端里最容易被低估、却又最影响全局的环节。逻辑综合出来的网表netlist只是一堆逻辑门和连线的抽象描述它不关心这些门物理上放在哪里、电源怎么送进去、时钟怎么走到每一个触发器。而这些不关心的问题恰恰是布图规划要回答的。换句话说综合告诉你了芯片要实现什么布图规划决定了芯片能不能做出来、做出来能不能跑得快、能不能按时收敛。很多新人在做后端项目时喜欢跳过布图规划直接去做布局觉得Floorplan嘛就是把芯片区域画出来、放几个宏单元macro就行了。实际上一次粗糙的布图规划可能会在后端流程里埋下一堆雷后面绕线时发现congestion爆红、做IR drop分析时发现某块区域电压降超标、时序收敛怎么修都修不动——这些问题往回追溯大概率都能在布图规划阶段找到根因。所以在后续流程里花再多时间优化都不如在布图规划阶段多做几个小时的功课。这篇笔记是数字后端学习笔记系列的第一篇我会从布图规划的核心目标讲起结合Innovus工具的实际操作把芯片尺寸估算、IO规划、宏单元摆放、电源规划这几个关键环节拆开来讲最后再聊聊我在实际项目里踩过的坑和常用的排查手段。写这些东西的初衷是希望正在学习数字IC后端设计基本概念的朋友能少走一点我当年走过的弯路。这个系列的内容不仅适用于还在学习阶段的学生和转行者也适合已经接触过后端流程、但觉得自己布图规划做得不够系统的工程师。布图规划这件事不同工艺节点、不同芯片类型纯数字、数模混合、SoC的做法会有些差异但底层的思考逻辑是一致的——你做的每一个决定都是在为后续的布局、时钟树综合、绕线、签核留出质量空间。2. 布图规划的核心本质与整体设计思路2.1 布图规划在数字后端流程中的位置在进一步讨论具体细节之前先厘清一个基本框架。一个完整的数字IC后端流程大致是下面这样的链路布图规划Floorplan→ 标准单元摆放Placement→ 时钟树综合Clock Tree Synthesis→ 布线Routing→ 签核验证Signoff。布图规划在最前面它的输入是综合后的门级网表、库单元信息、时序约束和IO约束输出是一个带有芯片边界、IO位置、宏单元位置、电源网络框架的物理规划。布图规划做得好不好直接影响后续所有步骤的质量。布局阶段会把标准单元std cell往剩余空间里摆如果布图规划阶段没有留下足够的绕线资源布局器再怎么优化也无济于事时钟树综合需要电源网络稳定如果布图规划阶段的电源网络设计有问题时钟树上的buffers会经历严重的电压波动时序收敛会变得很痛苦布线阶段更是直接受布图规划影响宏单元之间的通道channel宽度、IO pin与内部逻辑的相对位置决定了信号线有没有空间走通、走通之后会不会引入严重串扰。所以我们在做布图规划时本质上是在做三件事第一确定物理边界和可用资源——芯片有多大、有多少层金属可以用来走线、电源网络占掉多少资源第二确定关键模块的空间位置——哪些宏单元放哪里最有利于数据流走向和时序第三确定基础设施——IO怎么排、电源pad怎么分布、clock trunk怎么走。这三件事任何一件出了偏差都是后面所有问题的最初源头。2.2 布图规划的三个核心目标时序、拥塞、电源概括来说布图规划要同时伺候好三个大爷时序收敛、布通性、电源完整性。先说时序。数字芯片里的时序路径timing path通常分为四类输入到寄存器、寄存器到寄存器、寄存器到输出、输入到输出。寄存器到寄存器路径是后端工程师的主要关注点因为这条路径上每一段物理距离都会转换成实际延迟。如果两个模块本来在网表层面逻辑关系紧密但物理位置被隔得很远那么信号从一个模块传到另一个模块所需的线延迟就长为了修复setup违例要在中间插入很多buffer缓冲器这不仅增加了面积还制造了更多的时钟偏斜问题。布图规划就是要在物理上把逻辑相关的模块尽量放近减少这种长距离传输。再说拥塞congestion。拥塞的本质是绕线资源需求大于供给。在布图规划阶段我们要估算出每一块区域需要的绕线资源总量然后确保芯片面积能容纳这些资源。如果一个区域里面塞了太多逻辑哪怕标准单元能摆下去也没地方走线了布线阶段就会看到大片的红色congestion热点。这里有一个很多人容易忽略的点布局阶段看到的congestion是基于估算的布线阶段才是真实情况但如果你布图规划阶段给某个区域分配的绕线资源就已经不足那后面不管怎么优化局部placement都救不回来。最后是电源完整性power integrity。芯片要工作供电网络Power Grid必须把电源从pad或者bump稳定地送到每一个标准单元的电源引脚上。布图规划阶段要决定电源网络的拓扑结构——电源环power ring多宽、电源条stripe走几层、间距多大——这些参数直接决定了IR drop有多大。规则很简单导电通路的电阻越小走线越宽、高层金属用得越多IR drop越小但占用绕线资源也越多。所以要在成本和性能之间找平衡。2.3 布图规划的基本决策路径在实际做布图规划时我会按一个比较固定的路径来走先用IO数量、封装形式和pad焊盘信息确定芯片的尺寸候选值然后把宏单元memory、IP根据数据流和时序关系摆好之后在这个基础上跑一版快速布局trial placement看看拥塞热力图再根据拥塞情况回头调整宏单元位置和芯片尺寸最后一步才是搭电源网络。这个顺序不是拍脑袋定的因为每一步的决策都依赖上一步的输出更重要的是布图规划本身是一个迭代过程很少有项目能一次性敲定所有参数。这个路径里隐含了一条原则先定大骨架再填充细节。芯片尺寸和IO决定了天花板宏单元位置决定了内部数据流的主干道电源网络决定了电路能不能工作。如果一开始就在细节上纠结比如某个标准单元的朝向反而容易把整体结构搞乱。在后面的几个章节里我会详细介绍每一步是怎么做的参数是怎么算出来的以及遇到问题时要怎么调整。3. 核心参数解析与实操要点3.1 芯片尺寸估算不只是面积相除芯片尺寸是布图规划里最基础也最关键的参数。很多新手以为芯片面积就是把所有宏单元面积加上标准单元面积再除以一个利用率就完事了。这个理解方向是对的但实际操作远没有这么简单。片内标准单元总面积可以从综合后的报告里得到宏单元总面积可以从.lib文件里查到然后加在一起。但这里有几个因素必须在面积估算时考虑进去绕线通道、电源网络、宏单元之间的间距、预留的时钟buffer和hold buffer空间。绕线通道就是你金属走线的空间它不占标准单元的面积但占了芯片面积电源网络电源条、电源环也占面积宏单元和标准单元之间、宏单元和宏单元之间因为物理规则和时序要求要留出足够的间距。我在实际项目里估算芯片面积时一般会用一个三步走的方法。第一步统计所有physical cell标准单元宏单元的总面积得到A_cells。第二步根据工艺节点和金属层数设定一个初始利用率utilization一般是60%到75%之间面积按A_cells / utilization来算。第三步把IO ring、电源环、特殊区域的面积预留加上去得到最终的die面积。第三步经常被忽略设计出来的芯片尺寸偏小后面所有步骤都会变得异常拥挤。关于利用率有一个容易混淆的概念要澄清标准单元利用率和总面积利用率。标准单元利用率是标准单元面积除以标准单元可摆放区域面积这个值一般不包含宏单元总面积利用率则是所有单元总面积除以die总面积。项目管理上通常更关注后者因为后者才是决定芯片尺寸的因素。如果项目里寄存器flip-flop密度很高我会把利用率适当调低一些因为高密度寄存器的区域在时钟树综合之后会插入大量buffer这些buffer的面积在布图规划阶段是看不到的。3.2 Die width和height的选择逻辑确定了目标面积之后还有一个问题芯片做成什么形状是偏正方形还是长方形这个选择受封装形式、IO数量、内部模块的自然数据流方向共同影响。IO数量多的话芯片周长需要够长否则IO pad摆不下或者bandIO区域太挤导致信号出线困难。对于标准封装比如QFP、BGAIO pad是排在芯片四周的IO数量除以每毫米能放的pad数就能得出最小周长需求。然后结合算好的面积反推宽和高的合理范围。如果IO很多芯片就会偏向长方形因为周长比面积增长得慢。另一个影响宽高比的因素是宏单元的数据流方向。我做过一个包含8个memory的模块数据从左侧进入、经过运算逻辑、再写入右侧的memory如果芯片形状是竖长条物理上这个数据流就会被拉得特别长时序很难收敛。所以布图规划并不是一个纯数学问题它必须结合你对这个芯片数据流的理解。在Innovus里设置芯片尺寸可以直接用命令createFloorplan也可以通过GUI界面手动修改die area。这里有一点经验值得分享不要一上来就把die区域画得刚好最好留出5%到10%的余量。原因很简单布图规划阶段你对自己的设计还没有完全吃透很多时候要到跑完trial routing才能发现某块区域特别拥挤如果有余量在手里还可以通过调整utilization来消化如果没有余量就只能改尺寸重跑浪费很多时间。3.3 IO规划细节从方向到PAD宽度IO规划在整个布图规划里看起来不复杂但实际踩坑率极高。IO规划包括几个子任务确定每个信号pin放在芯片的哪个方向、确定IO pad的类型和连接方式、确定IO区域和内部逻辑区域之间的路由空间。确定pin在哪个方向最理想的方式是根据数据流来。总线信号从一个方向进、从另一个方向出不走回头路时钟信号尽量靠近芯片中心减少时钟到达各个模块的距离差异高速信号比如DDR接口要放在离对应memory宏单元近的一侧缩短线长电源pad要均匀分布避免某一边电流密度过大。在Innovus里IO pin的摆放位置通常不是在布图规划阶段手动一个个摆的而是通过约束文件IO constraint file读入或者在顶层集成阶段由chip level确定。布图规划阶段我们需要做的是检查这些IO位置是否合理以及给IO区域预留充足的空间。这里有一个常见的坑信号IO和电源IO之间的切换处往往会出现一个绕线资源特别紧张的区域因为信号的出线方向会被电源IO挡住。我的做法是在布图规划阶段就把IO区域附近的density要求提高相当于预留一些缓冲空间。IO pad宽度的问题也值得提一句。不同的IO库pad宽度不同通常是几十微米到上百微米不等。芯片周长的估算不能只看IO数量还要看IO布局时pad的物理宽度以及pad之间的最小间距否则到了装配assembly阶段会出现pad间距违规。这一块在项目初期就要和封装工程师对齐后端工程师千万别想当然。3.4 宏单元摆放原则数据流优先时序驱动宏单元比如SRAM、ROM、模拟IP、PLL的摆放是布图规划里最考验经验的环节。摆放方式直接决定了整个设计的时序、拥塞和电源分布也是布图规划里最难自动化的内容很大程度上依赖工程师对设计的理解。我摆放宏单元时心里有一个优先级列表第一数据流方向。在一起交换数据的宏单元和逻辑之间物理距离要短第二pin位置对齐。宏单元的pin是固定的所以放置宏单元时要让pin朝向它需要驱动的逻辑模块否则信号要从macro内部绕一大圈才能出线第三memory之间的供电和时钟结构。同一时钟域的memory尽量集中方便做时钟平衡和电源共享第四热分布。高功耗模块不能全部堆在一起否则局部温度过高对漏电和时序都有负面影响。这里特别想聊一下macropin facing的问题。很多新手摆放macro时只关心数据流方向不关心pin朝哪个方向。实际上如果memory的pin全部朝外那么它周围需要一圈标准单元来缓冲这些信号的驱动强度同时还占大量绕线资源。如果pin朝向设计得合理信号可以直接接入到附近的逻辑显著减少绕线长度。Innovus在摆放macro时有一个很有用的功能叫pin facing view可以直观地看到每个macro的pin方向和分布建议每次摆完macro之后都检查一遍。宏单元之间以及宏单元和标准单元之间的间距也要预留。间距一方面来自物理规则比如某些工艺对density梯度有要求另一方面来自实际绕线需求。宏单元周围通常要放endcap和tapcell这本身就要占一列空间宏单元的pin出线如果需要很多信号线周围还得留出足够多的绕线track。我的经验值是在65nm及以下工艺中memory密集区域周围至少留出3到5个标准单元row高度的间距具体多少要根据该区域pin密度和拥塞分析来决定而不是拍脑袋。3.5 利用率的理解与计算利用率这个概念很多学习阶段的朋友理解得不够到位我这里多花一点篇幅讲讲。利用率在Innovus的布局阶段会直接影响单元摆放的密度。如果utilization设为0.7意味着布局器最多使用70%的可摆放区域来摆放标准单元剩下30%预留给绕线和时钟树。但这个预留比例不是越多越好利用率太低会导致芯片面积浪费、成本上升——在量产项目中每多一平方毫米的芯片面积都是实实在在的成本。标准单元利用率和含macro利用率的计算方式不同。纯标准单元利用率公式是标准单元总面积 /标准单元摆放区域面积。如果我们把macro占了的地方排除掉了这个值就衡量纯标准单元区域的拥挤程度。而含macro利用率是标准单元总面积 macro总面积/ 芯片总面积。这两种利用率都能在Innovus的报告里查到但含义完全不同。常说的利用率70%到底是指哪种项目中一定要对齐否则不同成员之间沟通会出大问题。实际操作里我通常会在做布图规划预估时设置一个总利用率然后跑完trial placement之后再回头检查各区域的局部利用率。如果某个局部区域利用率超过了85%就要高度警惕了——这片区域大概率会在绕线阶段出现拥塞。这时候要么调整macro位置要么扩大芯片面积要么将该区域的部分逻辑迁移到其他区域。关于估算标准单元面积工艺库里有一个间接的办法从综合后的面积报告直接读数字。这个数字一般比实际物理实现后的面积小因为综合阶段不包含物理信息时序修复后会有面积增量。我一般会乘以一个1.1到1.2的经验系数具体系数大小取决于设计的时序裕量和寄存器密度。寄存器多的设计后面对hold buffer的需求大系数就要往高处取。4. Innovus实操从命令行到GUI的布图规划全流程4.1 布图规划前的数据准备在打开Innovus开始布图规划之前有几样东西必须先准备好否则后面会不断返工。这些数据包括综合后的门级网表.v或.vg、时序约束文件SDC、物理库文件.tf和LEF/DEF、时序库文件.lib、IO约束文件.io或tdf、以及电源约束文件.cdl或UPF如果设计有特殊电源域。这里面有两点要单独提醒。第一SDC文件里的时钟定义一定要仔细检查。布图规划阶段虽然暂时不跑时序优化但Innovus需要根据时钟树信息来估算时序拥塞如果SDC里时钟定义不全extract时光钟网络的估算就会失真。第二LEF文件要和库文件匹配。有时候为了前端仿真方便会用一套timing library、一套physical library但后端工具里这两套必须严格对齐版本否则后面出pin脚定义、macro bounding box等一系列问题。在Innovus里导入数据一般的流程是这样的set init_mmmc_file {mmmc.tcl} set init_lef_file {tech.lef stdcell.lef macro.lef} set init_verilog {./netlist/design.v} set init_top_cell {design_top} set init_pwr_net {VDD} set init_gnd_net {VSS} init_design其中mmmc.tcl里定义了时序库、约束文件的路径和SDC文件。导入完成后第一步我会先用report_io命令检查IO pin的数量和方向同时用report_inst检查宏单元的数量确认数据导入无误之后再开始布图规划。4.2 快速创建初始Floorplan创建初始布图规划Innovus里最常用的命令是createFloorplancreateFloorplan -dieSizeBySite {width height} -site {coreSite} -coreMarginsByDie {top bottom left right} -noIO或者更常见的是只指定core区域和IO边距让工具自动算出die区域createFloorplan -coreRow {left bottom right top} -coreMarginsByDie {50 50 50 50} -noIO这里的-site参数很关键它指定了标准单元的site行高单位必须和库里的prBoundary一致。如果site指定错误后面标准单元的全部放置都会出问题。-coreMarginsByDie指的是die边界到core边界的距离这个距离通常默认等于IO区域的高度如果IO pad比较多要适当加大。创建完floorplan后我一般马上做两件事。第一在GUI里按F键fit view直观检查die和core区域是否合理IO区域是否足够宽。第二运行report_floorplan把当前die尺寸、core尺寸、可用面积和预估利用率打印出来和3.1节里我们自己算的目标面积做个对比。如果差异在10%以内可以继续往下走如果差异太大先分析原因再决定是不是要改尺寸而不是盲目继续。这里有一个非常实用的GUI小技巧Innovus的Floorplan Editor可以以Resource模式显示当前设计的pin density和net density分布这个可视化工具比命令行报告直观得多特别适合快速判断IO区域和边界区域是否太挤。4.3 宏单元摆放与自动布局验证的迭代摆macro是整个布图规划过程中交互性最强的一步。我习惯的做法是先用手动方式摆放关键宏单元再用工具辅助摆放其余宏单元最后跑一版快速布局来验证。手动摆放关键宏单元通常在Innovus GUI里操作鼠标选中macro对象然后拖拽到目标位置。也可以使用命令方式placeInstance {mem_inst} {x_position y_position} -orientation R0 -status FIXED手动摆放时要注意把一个macro从原来位置拖到新位置后它的相对位置关系可能会改变这个过程中要频繁查看数据流关系。我的经验是先把所有memory按数据流方向摆成一个逻辑清晰的结构然后让工具比如place_macro命令配合自动模式把剩下的IP自动摆放最后再微调。摆完macro之后建议立刻用setPlanDensity或GUI里的plan density功能看看各区域的cell density预估也可以跑一个快速trial placementtrialPlace reportCongestion -overflow -verbosetrialPlace做的是一个不优化时序、只考虑合法性的快速布局耗时很短但能给出一个相当可靠的拥塞预估。reportCongestion输出的overflow值如果某个区域超过了2%到3%就说明这个区域绕线资源可能不足了需要调整。我要强调一下trialPlace是布图规划阶段最重要的验证手段没有之一。很多工程师把macro摆好后就直接去做电源规划等到place_opt做完了才看congestion报告那已经晚了改起来伤筋动骨。在布图规划阶段跑一版trialPlace的成本非常低通常几分钟却能在最早的阶段暴露出80%以上的拥塞问题。4.4 电源网络搭建Power Ring、Stripe与Followpin电源规划是布图规划里技术含量很高的一块它决定了整个芯片电压降IR drop和电迁移EM是否在安全范围内。在Innovus里电源网络搭建分为三个层次电源环Power Ring、电源条Power Stripe和标准单元电源轨Followpin/Row Power。电源环在die四周像一个城市的外环快速路电源条横穿芯片内部像城市里的主干道标准单元电源轨是每一行标准单元边上的电源金属线接的是标准单元的VDD/VSS引脚像小区里的街巷。电源条的设计参数主要是金属层、宽度和间距。金属层方面高层金属比如M5、M6电阻小适合走横向长距离低层金属电阻大适合短距连接。宽度和间距的选取要综合IR drop目标、绕线资源消耗和EM可靠性。经验公式是IR drop预算一般是电源电压的3%~5%在这个预算下推导出电源网络的等效电阻再根据每层金属的方块电阻反推宽度。一个典型的Innovus电源规划流程如下# 创建电源环 addRing -nets {VDD VSS} -layer {top M6 bottom M6 left M5 right M5} -width 5 -spacing 1 -offset 2 -around each_die # 创建电源条 addStripe -nets {VDD VSS} -layer M6 -direction horizontal -width 3 -spacing 1 -set_to_set_distance 50 -max_same_layer_jog_length 100 # 连接标准单元电源轨 sroute -nets {VDD VSS} -allowJogging 1 -allowLayerChange 1这里的width单位是微米具体取多大要参考工艺库的设计规则和项目电源需求。set_to_set_distance是stripe间距它直接影响IR drop间距越小IR drop越好但绕线资源消耗越大。在新工艺节点上我一般先用间距50微米左右搭一版跑IR drop分析如果裕量充足再放宽间距节省面积如果IR drop超标则缩紧间距。还有一点要注意电源网络必须与macro的电源引脚正确连接。有些memory有独立的供电pin比如VDDCE如果忘记接或者接错层后面跑IR drop分析时这些macro的电压会异常轻则性能下降重则芯片功能错误。布图规划阶段就要检查每个macro的power pin连接是否符合库里的定义。在Innovus里除了用GUI观察整个power grid的结构外我建议每隔一段时间跑一次verify_pg_netlist命令检查所有电源网的连接完整性这个命令能找出没有接到电源网络的单元引脚在早期发现连接问题会省下很大的返工成本。5. 常见问题与排查技巧实录5.1 拥塞Congestion热点高怎么办跑完trialPlace之后看到某块区域congestion超过3%甚至更高这是布图规划阶段最常遇到的问题。遇到拥塞热点时我会按照下面的顺序排查原因先看这个区域是不是macro pin过密比如多个memory的pin都集中在一个狭窄区域再看是不是有大量的宏单元和标准单元混放导致绕线资源被截断最后看是不是芯片尺寸估算偏小整体利用率偏高。针对不同原因有不同的解决手段。如果是pin过密可以考虑调整宏单元摆放方向让pin分散到不同方向如果是单元混放可以把部分标准单元区域划到另一个位置避免在拥塞区域周围再堆逻辑如果是整体利用率偏高则要认真考虑扩大芯片面积。还有一个比较容易忽略的技巧把拥塞区域上面的金属层绕线资源打开更多。工艺里高层金属的电阻小、绕线能力强如果原来的绕线层分配不合理比如所有长走线都挤在M3/M4上而M5/M6空中通道很少那拥塞区域非常容易出现。检查一下tech LEF里的routing layer定义有时候只要把某个特定层的方向换一下或者允许更高层金属用于绕线就能显著改善拥塞。如果是局部区域拥塞率在5%上下跳动还可以通过局部移动macro来调整。具体做法是选中这个拥塞区域附近的macro沿垂直于其pin排布的方向挪动10~20微米然后重新跑trialPlace对比结果多试几次找到最优位置。这种方法虽然笨但是在后期不想改芯片尺寸的时候常常是性价比最高的解法。5.2 IR drop超标时优先从哪里下手在做完电源规划、跑完初步IR drop分析后发现某块区域IR drop超标比如超过5%的电源电压这个问题在布图规划阶段就要解决拖到后面会越来越严重。我的处理顺序非常固定。第一步检查该区域的电源stripe密度看是不是stripe间距太大导致供电通路太长在路径中段电压降累积过大如果是缩小该区域周边的stripe间距或者在原间距中间增加一条stripe。第二步检查stripe的方向和宽度。如果stripe用了低层金属且宽度较窄电阻偏大IR drop表现会差这种情况下可以考虑把关键区域的部分stripe切换到高层金属并加宽。第三步检查标准单元followpin连接质量。有时候sroute做得不完整某些行的电源轨没接到stripe上这会在局部造成很大的IR drop用verify_connectivity即可定位。这一块有一个独门经验IR drop分析结果不要只看平均值一定要看热点图heat map。平均IR drop可能只有1.5%但某个角落可能已经3.5%了。不同区域的时序余量不同对IR drop的敏感度也不同——时钟树附近的cells对IR drop非常敏感因为时钟树上的buffer级联很长任何一层的电压抖动都会在级联之后被放大。所以布图规划阶段要额外关注时钟区域附近的电源密度宁可在这个区域多放一些stripe也不要省面积。5.3 标准单元摆放密度不均局部利用率过高有时候整个芯片的整体利用率看起来不高比如65%但某个局部区域比如两个macro之间的实际密度已经超过90%甚至出现摆放不下的情况。这种问题的根源通常是宏单元摆放时留下的缝隙太窄——两个macro之间的channel宽度不足标准单元摆进去之后几乎贴满完全没有预留绕线空间。遇到这种情况我的经验是给channel区域设置一个minimum channel width。根据工艺节点的不同channel宽度通常要求能容纳4到8条signal track如果是重要的数据总线区域还要更多。这个值不是一个简单的常数它取决于该区域实际走信号的密度但4条track是我个人能接受的最低线。如果确实是因为macro摆放太密集导致channel不足就需要移动一些macro。这种情况在布图规划里并不少见毕竟macro位置是循环迭代出来的不可能一出就完美。Innovus里可以通过editPlace命令或者GUI手动微调macro位置也可以设置density区域约束让工具在布局时自动限制某些区域的密度。另一个容易忽视的问题是标准单元摆放密度不均可能源于DontUse单元的分布。如果某些高密度单元比如高驱动强度的buffer被设置成DontUse之后布局器为了满足时序会到处插入中等驱动强度的buffer局部密度就上去了。这种情况下可以通过优化库单元选择策略或者插入decap cell来缓冲但这已经超出了布图规划本身的范畴——我们作为布图规划工程师重点是保证物理空间有足够的调整余地。5.4 数据流与逻辑层次不匹配时怎么摆macro有些设计的网表结构是这样的逻辑上属于同一module的单元在网表里并不是连续的而是和其他module的单元交织在一起。这时候按照数据流方向摆放macro的想法就容易失效——你以为A模块在左边、B模块在右边但实际上A模块的一部分单元散布在B模块的区域里。面对这种情况我通常会先把网表里宏单元之间的连接关系通过report_net或GUI中的net highlight功能画出来看看哪些宏单元之间有大量高扇出连接。比如A macro的输出连接到B macro的输入而同时C macro的输出也连接到B macro那么B macro应该摆在A和C的连接路径交汇处或者尽量靠近连接线最短的位置。如果发现module之间的交错很复杂没有清晰的单向数据流我的做法是优先满足关键时序路径critical path上的模块贴近放置。芯片里真正决定性能极限的往往就是那么几十条关键路径把这些路径上的物理距离缩得足够短其他非关键路径的线长拉长一些也没关系。这一点做布图规划时必须清醒你不是在优化所有路径而是在优化瓶颈路径。5.5 经验总结与常见错误避坑清单做布图规划这几年我踩过不少坑有些坑反复出现在不同的项目里这里做个小结也当作给自己的一份备忘。第一个教训是做布图规划前一定要先跑通数据导入流程确认库文件、约束文件和网表版本匹配。很多时候floorplan本身做得没问题结果report出来的数据全是乱的最后发现是LEF文件版本和LVS用的库不一致。这种问题排查起来非常耗时但完全可以避免。第二个教训是不要等到电源规划做完才检查macro的power pin连接。我遇到过memory的VDDCE没有接上电源网络到IR drop分析阶段才发现的悲剧因为这时候几乎整个数据库都已经建立起来了修改成本高得吓人。布图规划阶段花十分钟跑一下pg verification能省下来来回回的十几小时debug时间。第三个教训是重视保存中间版本。floorplan阶段的设计变动非常频繁今天觉得不错的macro摆放明天可能因为一个时序反馈全盘推翻。我习惯在每次重大决策前保存一个新的floorplan版本比如floorplan_v1floorplan_v2这样回溯起来很方便。第四个教训是在Innovus里做操作时尽量留好所有脚本。GUI操作方便直观但不可回溯脚本则可以在几分钟内重建一个版本。纯GUI流后期维护成本高混合流脚本为主、GUI辅助才是一个靠谱后端工程师该有的习惯。6. 实战心得一次完整的布图规划操作流程演示纸上谈兵讲了这么多这一节我模拟一个典型的中等复杂度设计把布图规划从零开始的完整操作流程串一遍这样读起来会更有实感。假设现在手里是一个28nm工艺的设计有一个顶层模块、两组SRAM宏单元每组4个memory、一个PLL和一个模拟IP。IO数量是256个其中模拟信号32个、数字信号200个、电源地24个。综合后标准单元面积约0.6平方毫米宏单元总面积约0.3平方毫米。第一步算面积。目标总利用率设为70%总单元面积为0.9平方毫米除以0.7得到约1.29平方毫米加上IO区域和电源环的预留面积约15%目标die面积约1.48平方毫米。第二步定宽高比。256个IO排布在四边每边约64个IO考虑IO band宽度约为120微米结合面积目标最终把die尺寸定在1.3mm x 1.15mm附近。加上IO band之后的core面积约1.06mm x 0.91mm能满足要求。第三步摆macro。PLL和模拟IP放在芯片左下角远离数字逻辑避免电源噪声干扰。两组SRAM分别放在右侧和上方因为数据流从左边输入、经过中间的逻辑运算、分别写入右侧和上方的memory这样的摆法最短化了关键路径。第四步跑trialPlace查看congestion report。如果右侧memory附近有拥塞热点就把右侧的那组memory八个为一组适当向芯片中心靠近一些给边缘留下绕线空间然后重新跑trialPlace。第五步做电源规划。先在die四周创建5微米宽的VDD/VSS双环然后在core内部以60微米间距创建横向stripe再运行sroute把标准单元的followpin连上电源轨最后通过GUI检查整个PG结构是否有断裂或悬浮。这五步走完一个可用的初始布图规划就完成了。后续就可以进入摆放placement和优化阶段但布图规划这个基础打得坚实与否会在接下来几周的工作中持续产生影响。实际上在真实项目中我经常在place_opt做到一半时又回过头来修改floorplan这是正常的也正说明布图规划不是一个一蹴而就的动作而是陪跑全流程的持续迭代过程。最后再分享一个小技巧在Innovus里布图规划阶段的任何调整都建议把原来的floorplan另存为一个文件比如用saveDesign floorplan_v1.enc这样的方式保存。这样当你发现新方案还不如旧方案时可以快速回退而不必从头再来。我在实际项目里往往是几版floorplan并行验证最后选数据最好的一版继续跑后面的流程。这种做法的背后逻辑是布图规划阶段的时间成本相对较低但你在这里多花的时间能在后面的布局和布线阶段节省数倍的调试时间——这笔账怎么算都是值得的。