
1. 布图规划到底在做什么一个被低估的起点刚接触数字后端的朋友往往会把大部分注意力放在布局布线Place Route上觉得把标准单元放下去、把线绕通就是核心工作。但真正做过几个项目之后你会发现整个芯片的成败很大程度在布图规划Floorplan这一步就已经定下来了。Floorplan 做得顺手后面的布局布线、时钟树综合、时序收敛都会轻松很多Floorplan 做得潦草后面所有环节都在替这一步的错误买单。布图规划简单来说就是把芯片的物理空间先“分好地盘”。芯片有多大、核心区域放在哪里、IO 怎么排、大的宏单元Memory、IP摆在什么位置、电源网络怎么铺这些都是 Floorplan 阶段要定下来的事。它做的是“宏观布局”而不是标准单元级别的“微观布局”。你可以把它理解成装修之前先确定哪里是客厅、哪里是厨房、哪里是卧室水管电线的走向也提前规划好后面再往每个房间里摆家具、走线路——家具和线路可以调整但墙的位置和主水管走向如果一开始就定错了返工代价极大。在 Innovus、ICC2 这类主流数字后端工具里Floorplan 是进入后端流程时遇到的第一道正式关卡。输入是一堆约束文件和设计数据输出则是一个把逻辑设计映射到物理空间上的版图雏形。这个雏形可能看起来只有几个框框和线条一点都不“芯片”但它决定了整个后续流程的可实施性。这篇文章我就从实际项目操作的角度把布图规划中那些容易忽略、但非常关键的知识点和踩坑经验梳理一遍既适合刚入门数字 IC 后端的新手也适合已经跑过流程但想回头补一补底层逻辑的工程师。2. 开工之前先捋清楚布图规划需要哪些输入输出又是什么2.1 输入数据不是拿到 Netlist 就能直接动手很多新手第一次做 Floorplan 的时候会比较困惑工具里明明只有一个空空的版图界面怎么才能把设计“放进去”其实在打开工具之前需要准备的材料远比你想象的多。标准的一套输入大概包括下面几类门级网表Gate-level Netlist综合后的网表记录着所有标准单元和宏单元的逻辑连接关系。这是 Floorplan 的“内容物”你规划的空间最终都是要装下这些东西的。工艺库文件Liberty / .lib包含标准单元、宏单元的时序、功耗、面积等信息。工具需要靠它来了解每个单元的形状、引脚位置、时序特性。物理库文件LEF / .lefLEF 文件记录的是单元的物理信息比如单元的高度、宽度、金属层形状、pin 的位置等。抽象版的 LEF 只有边界和 pin详细版则带有布线阻挡等信息。Innovus 在导入设计时就把这些物理库加载进来了。技术文件Techfile / .tf定义工艺的金属层数、线宽、间距、通孔规则、布线网格等。这个文件决定了你后面布线时的物理规则。约束文件SDC时序约束虽然 Floorplan 阶段不像布线阶段那样严格跑时序但 SDC 中的时钟定义会影响时钟树规划、IO 时序预算分配。IO 信息文件可选如果芯片有封装约束如 IO 位置、焊盘排列、供电 IO 的种类通常需要单独提供可能是.io文件或由封装团队给出的 pin 位置定义。如果你用的是 Innovus还需要关注初始化阶段的命令比如init_design或init_floorplan。在比较新的版本里Innovus 支持通过读入 LEF、DEF、netlist、SDC 等数据来初始化设计然后再开始做 Floorplan。这里我补充一个常见误区很多人以为只要有了 netlist 就能开始布图规划其实没有物理库LEF和技术文件Techfile工具里看到的只是抽象的逻辑连接根本无法判断单元摆下去会不会冲突、布线资源够不够。所以拿到一个项目后我习惯先把所有输入文件整理成一个清单逐一确认。2.2 输出物Floorplan 到底“产出了什么”布图规划阶段的输出通常包括下面几项芯片尺寸与核心区域Die size Core area确定了整个芯片的边界、核心区域core boundary的位置和大小、IO 区域的宽度。IO pin 或 IO pad 的摆放如果设计带 pad需要把数十乃至数百个 pad 一一摆好如果是纯 core-limited 设计则确定 pin 的位置。宏单元的初步/最终摆放根据设计要求和数据流把 memory、模拟 IP、特殊功能模块放到合适位置并设置好 keepout、halo 等约束。电源网络规划包括 power ring、power stripe、电源 IO 的连接方式等这部分有时会单独划分为电源规划Power Planning但通常和 Floorplan 一起做。标准单元区域划分比如划分出数字逻辑区、模拟区、高速接口区等也可能用 region 约束固定某些模块的摆放范围。各种约束文件最终输出 DEF 文件、floorplan 配置文件等供后端流程下一步使用。很多后端项目里Floorplan 会和电源规划一起做因为电源网络要在宏单元摆放定下来之后才能合理铺设。实际操作中我会在 Innovus 里把 Floorplan 和 Power Plan 一块调这样少开一次工具、少导入导出一次数据对项目节奏紧凑的场景非常重要。3. 芯片尺寸估算与 Core 利用率别小看这一步的数学题3.1 面积估算照着网表和库动手算布图规划的第一步一般是从估算芯片尺寸开始的。芯片不能想定多大就定多大——做大了浪费晶圆成本做小了放不下或者布线拥塞严重。Core 区域的大小主要由标准单元总面积 宏单元面积 布线资源预留 电源网络占用这几个部分组成。标准单元总面积的估算方法是标准单元总面积 ≈ 标准单元数量 × 平均单元面积实际项目中更严谨一点的方法是直接读网表把每个实例instance的面积加起来。Innovus 的report_design或者读入设计后的报告里会给出总的 cell area。但这里要注意这个面积是所有单元面积之和Layout 里各个单元之间是会留缝隙和布线通道的所以真正需要的面积要比这个值大得多。这时候就需要引入一个概念利用率Utilization。它的定义大致是Utilization 单元总面积 / Core 区域面积如果 utilization 是 70%意味着核心区域里有 70% 被单元占据剩下 30% 用于布线、电源网络、单元之间的空隙。这个值没有绝对标准通常在 60%75% 之间比较常见。如果设计里有很多比例很大的宏单元或者高速接口很多、布线资源消耗大利用率就要适当调低如果是一个很规整的数字逻辑设计利用率可以稍微高一点。我见过不少刚入行的同事拿到网表后直接把report_utilization里的数字当成最终结果完全不考虑宏单元和布线资源。实际上工具在还没有 Floorplan 的时候给你报的 utilization 一般只是标准单元面积与某个默认区域的比值参考意义有限。真正靠谱的做法是先用宏单元面积 预估标准单元面积算出总需求再根据经验留出 20%40% 的余量然后反推 core 尺寸。这样做出来的 Floorplan 才不会在布线阶段处处碰壁。3.2 从 Core 到 DieIO 和外围空间也要算进去Core 区域确定之后还要加上 IO 区域、电源环、ESD、密封环seal ring等外围空间才能得到最终的 die size。IO 区域到底留多宽取决于用的 IO cell 类型和数量。如果是普通数字 IO每个 IO cell 的宽度是工艺库里写好的如果设计里还有模拟 IO、电源 IO它们的宽度往往和普通数字 IO 不一样需要单独核算。这里分享一个我用过很多次的经验不要只看 IO cell 本身的宽度还要看你的封装方式。如果是 Flip-chip 设计IO 可能不是围着四周排一圈而是分布在芯片表面的凸点bump阵列上这时候 die size 会受到 bump 间距和 IO 数量的影响计算方式完全不同。如果是 Wire-bond 封装四边 pad 排布方式的面积计算就相对直接。所以在估算尺寸之前先搞清楚封装方案是我一直坚持的做法。3.3 行高、Site、Track 与金属层方向底层规则决定布局效率在 Innovus 里做 Floorplan 的时候你会发现工具要求你指定 core 边界时会提示“snap to track”或者“snap to site”。这些底层的网格概念如果不理解做出来的 core 边界可能和标准单元的 row 对不齐轻则浪费面积重则导致单元摆不进去。简单来说标准单元库里每个单元的高度都是固定值一般是某个 base height 的整数倍这个高度单位叫site。单元按行row排列行与行之间的距离就是 row height。Core 区域的边界最好落在整数倍的行高上不然行排不满边缘就浪费了。同样核心区域的宽度最好和布线网格track对齐这样后续电源网络和布线才能顺畅。金属层方向也是一个关键设计决策。CMOS 工艺里一般奇数金属层走水平方向Horizontal偶数金属层走垂直方向Vertical比如 M1 横、M2 纵、M3 横、M4 纵。标准单元内部的 pin 基本都从 M1 引出所以 M1 方向是横的时候单元的行方向往往也是横向排列。这些都是 Floorplan 阶段就要确认的规则如果一开始 core 边界没有对准 site 和 track后面布线阶段会不断冒出 DRC 违例或者绕线困难。还有一个容易被忽略的点row height 与双倍高单元double-height cell。现在工艺节点越来越先进很多库里有各种高度的单元比如 high-performance 单元或者带多个 pin 的特殊单元。这些单元摆放时对 row 的对齐要求更严格。做 Floorplan 时如果 core 高度没有按行高的整数倍设计后期加 high-density 单元时很可能出现区域放不下的尴尬局面。4. IO 规划与 Pin 布置先看封装再看信号4.1 封装决定 IO 位置别把顺序搞反了IO 规划这件事很多设计初学者会从“电路功能”的角度去考虑把相关的信号放在相邻的位置这样逻辑上顺一些。这个想法不能说全错但在真实项目里IO 位置的第一决定因素是封装。封装团队会根据 PCB 布局、引脚间距、电源完整性等要求给出芯片 IO 的初步排布建议这份建议通常就是硬约束——后端设计需要照着它来做。我之前做过一个带 DDR 接口的设计DDR 的信号要求等长、分组摆放且每组信号有自己对应的电源地 pin这些要求全部来自封装方案。如果 Floorplan 阶段没有和封装团队对清楚随意摆放 DDR 的 IO之后绕线阶段会发现这些信号无论如何都绕不到合理的长度和层数——不是绕不通而是物理上离各自对应的 IO pin 太远了。等到项目后期再调 IO往往是牵一发而动全身得不偿失。4.2 IO 排布的细节Power IO、Signal IO 和位置约束在 Innovus 里编辑 IO 位置可以使用editFPlan界面手动拖动也可以直接编辑 io 文件然后加载。对于大型设计手动拖动不现实一般会先让工具根据某个策略自动排一遍再手动微调。这里有几个细节值得关注电源地 IO 要均匀分布电源地 IO 不能全部挤在一个角落否则芯片内部的电源网络离电源 IO 太远的地方会有严重的 IR Drop。所以你可以看到很多设计里VDD/VSS IO 是呈间隔分布的比如每 8 个信号 IO 配一对电源地 IO。高速信号优先高速接口如 SerDes、DDR的 IO 尽量靠近芯片边缘且位置对称减少信号路径长度差异。某些信号对还有差分约束IO 位置需要成对出现。时钟信号 IO 要特别关注时钟信号通常需要经过专用的时钟树网络IO 位置离内部时钟源不能太远否则时钟树综合的难度会直线上升。可测性设计DFT引脚扫描链、测试时钟等引脚的位置一般也有要求尤其是与测试模式相关的时序约束需要提前和后端负责人、DFT 工程师核对。IO 规划完成后建议在工具里把 IO 的位置、名称、对应的 net 都逐一过一遍。我吃过一次亏某个信号 IO 被自动工具排到了对角位置和内部模块距离极远布线阶段那根线绕了整整三层金属还超长时序修了很久。后来再做 Floorplan我一定会在 start point 阶段就把关键 net 的 IO 位置手动约束好不让工具自由发挥。5. 宏单元摆放布图规划真正的核心难点5.1 摆宏单元之前先问三个问题宏单元Macro主要是 Memory 和大 IP摆放是整个 Floorplan 中最考验经验的部分。很多初学者跑到 Innovus 里把宏单元扔进去然后点自动放置发现工具给了个看起来挺整齐的布局就以为大功告成——结果后面布线阶段全是坑。摆宏单元之前我建议先问自己三个问题一数据流是什么方向如果设计中 A 模块的数据经过这块 Memory 再传给 B 模块Memory 放在 A 和 B 之间就是最自然的选择。如果多个 Memory 之间有数据交互它们应该形成一个簇让连线尽量短。二宏单元和标准单元区之间需要多大间距宏单元附近通常需要留出一圈 halo也叫 keepout margin用来避免标准单元和宏单元贴得太近导致布线困难。Halo 的大小没有固定值一般取决于宏单元的 pin 密度和金属层使用情况常用的值在 520 微米不等。注意halo 如果太小宏单元周围的绕线资源会很紧张halo 如果太大又浪费面积。三宏单元的朝向orientation怎么选宏单元内部有大量 pin 和内部走线朝向不同会导致 pin 方向和相邻区域的布线资源分布不同。一条经验是宏单元 pin 密集的一侧应该朝向信号到来的方向pin 相对稀疏的一侧可以和别的宏单元背靠背相邻摆放。5.2 数据流向与宏单元分组照着数据流摆比盲自动省心我之前做过一个 SoC 项目里面有一块大内存阵列和 CPU、DMA、外设控制器都有数据交互。如果单纯依赖工具的自动放置它可能会把这块 Memory 放在一个“看起来面积利用率高”的位置但那一侧的 IO 方向、时钟资源、布线压力全都不是最优的。当时我的做法是先从架构图出发把每个宏模块的数据流向画出来标注出和哪个模块通信最频繁。把这些高频通信的模块尽量放到同一侧或相邻区域。对于通信量较小的连接哪怕远一点也能接受这样能给核心数据流让出更短的路径。这样人工初版摆放完成后再交给工具做自动布局微调placeDesign前处理阶段效率会高很多。工具自动摆放并不是没用而是它没有架构层面的全局观。我的习惯是先人工定大框架再用工具优化细节两边结合才是稳妥路径。5.3 宏单元与标准单元区域的间距Halo、Keepout 与 Fence在 Innovus 里摆好宏单元之后一般要给它设置约束避免标准单元“侵入”宏单元周围的空间。常见的设置方式有Halo在宏单元外圈留出的空白区域标准单元不能进入。Keepout Margin一种更灵活的禁止区域定义可以按距离或按层来设置。Fence/Region强制指定某个模块的单元只能放在某个区域内fence或者只允许放在某个区域内region。实际项目中宏单元多的时候我会对每个宏单元设置 halo同时给某些关键的模块设置 region比如把 CPU 核心放在一起不允许它扩散到 Memory 堆里去。还要注意halo 并不是设得越大越好。我有一次为了图省心把 Memory 的 halo 设得特别大结果是标准单元能用的区域变得碎片化利用率下降后续布局时单元只能分散在小块区域里反而增加了绕线长度。平衡面积和可布线性永远是 Floorplan 阶段不断权衡的主线之一。6. 电源规划与布图规划两件事经常一起干6.1 电源网络的骨架Power Ring 与 Power Stripe布线阶段真正绕信号线之前得先把电源网络搭好。电源网络其实和城市供电系统很像CORE 区域是一个城市电源 IO 是发电厂power ring 是城市外环线power stripe 是主干道标准单元的 VDD/VSS pin 是每户人家的电表。这些“电力主干道”如果不提前规划好等所有信号线都绕完了再补电源线几乎不可能。Power Ring电源环包围在 core 周围通常由 VDD 和 VSS 两条金属环组成有时候还有多层金属叠加的环。环的宽度和层数取决于整个芯片的电流大小和 IR Drop 预算。Power Stripe电源条带则是在 core 内部横向或纵向铺设的长条形电源线它们把电源从 ring 引入到内部让每个标准单元都能就近取电。6.2 电源规划参数怎么定从电流需求反推确定 Power Stripe 的宽度和间距核心依据是电流负载和IR Drop 要求。假设某段电源线要承载 500mA 电流工艺库给了每微米宽度金属的电流密度上限比如 1mA/um那么这一段线至少需要 500um 宽。当然实际不会这么死板因为还有多层并联、通孔via的额外电阻、温度影响等因素。大多数项目会先按经验设定一个初始值——比如 M4/M5 每隔几百微米铺一条宽度为 core 宽度百分之几的 stripe——然后跑 IR Drop 分析根据结果再迭代。Innovus 里做电源规划的常用命令是addRing和addStripe。比如常见的命令形式大致是addRing -nets {VDD VSS} -layer {top M5 bottom M5 left M6 right M6} \ -width 10 -spacing 1 -offset 5 addStripe -nets {VDD VSS} -layer M5 -direction horizontal \ -width 8 -spacing 10 -set_to_set_distance 100需要注意命令参数在不同版本和不同工艺库里差异挺大最重要是确认三件事用哪些金属层、方向和间距是多少、stripe 是否要避开宏单元区域或者特定区域。比如 Memory 上面有 MT 层过孔遮挡的时候stripe 直接穿过去可能导致后续打孔冲突这就要用-skip_via或绕开区域的设置来处理。6.3 电源规划常见问题Macro 下面的电源怎么接宏单元自己的电源连接是电源规划里非常容易踩坑的地方。很多 Memory 或模拟 IP 会在自己的边界上留出一圈 power pin需要通过addRing或connectPower的方式连接到全局电源网络上。如果一个宏单元的电源连接方式不对轻则 IR Drop 超约束重则 LVS 都跑不过。还有一种常见情况是宏单元的某些电源 pin 在顶层金属比如 AP 层普通电源 stripe 在 M5/M6这时候需要通过特定通孔阵列连接。做 Floorplan 时就要把这些通孔的位置和占用面积考虑进去不然等你要在它上方走线的时候才发现没有足够空间打孔返工成本极大。我之前负责一个带多个模拟 IP 的设计有些 IP 要求特定的电源环宽度和 spacing和数字区域的电源网络风格完全不一样。后来踩了坑才明白宏单元的电源连接方式必须逐块确认不能天真地认为统一铺一层 stripe 就万事大吉。7. 布图规划阶段常见问题与排查方法我在实际项目里把 Floorplan 阶段出过的问题大致列了一张速查表分享出来供参考现象可能原因排查思路与调整建议布局布线阶段标准单元利用率突然升高Core 区域过小或宏单元摆放不合理检查宏单元总面积占比、halo 是否过大适当扩大核心区域某个区域内布线严重拥塞宏单元 pin 过于集中、stripe 阻挡、region 设置不合理查看 congestion map调整宏单元朝向或为宏单元留出更多绕线通道IR Drop 在某个角落超标电源 stripe 布设不均、宏单元下方电源连接不足增加该区域 stripe 密度检查宏单元 power via 数量时序收敛困难关键路径绕线过长关键模块之间距离太远、数据流方向不合理回看 Floorplan 数据流方向将高频通信模块拉近电源/地噪声导致功能异常去耦电容缺失或分布不均在 Floorplan 阶段预留 decap 填充区域后补密集 decap标准单元无法铺满角落Core 边界没有对齐 site/track重新调整 core 坐标使其对齐 row 和 trackIO 绕线特别长IO 位置远离相关模块调整 IO 位置或通过 pin swap 优化关键信号这些问题的共同点是它们的根子往往不在出现问题的阶段而在 Floorplan 阶段。这也是为什么我一直建议把更多时间花在布图规划上。后面步骤里你拼命调优化器参数、加约束修时序可能效果远不如在最开始把几个宏单元的位置挪对来得好。这里再提一个我常用的经验Floorplan 做完之后不要急着往后跑先在工具里出一张 congestion map。Innovus 里有全局布线预估的功能能在详细布线之前告诉你哪些地方大概率会拥塞。如果这时候发现热点区域调整宏单元位置或 core 边界还来得及一旦进入详细布线再改 Floorplan时间成本至少翻倍。8. 我做布图规划时的几个习惯性动作最后分享一点我个人积累的小习惯不一定适用于所有项目但对大多数场景都有帮助。第一开始做 Floorplan 前先把整个设计“看一遍”。我用 Innovus 比较多导入设计后会把所有 net、instance、macro 按层次结构列出来看看有没有模块面积特别大、pin 数量特别多、时序约束特别紧的地方心里有个底。盲目直接画框子摆宏单元等于闭着眼睛装修。第二宏单元摆完之后用几行命令快速检查 pin 分布。如果某个宏单元一侧的 pin 特别密集而这侧朝向了一片空旷区域多半是合理的如果 pin 密集侧紧贴着另一个同样 pin 密集的宏单元大概率后面会绕线困难。这时候我一般会手动旋转宏单元或调整间距。第三不要舍不得调整。很多工程师做完了 Floorplan 就想着赶紧进入下一阶段不敢动已经摆好的宏单元。但实际上只要后面还没开始详细布线改 Floorplan 的成本都不算高。我做过一个项目在布局阶段发现一个宏单元的位置造成了严重的拥塞虽然重新摆它花了一天时间但后续绕线省了差不多一周的迭代。该改的时候果断改比硬撑到最后再返工强得多。第四把 Floorplan 版本记录做好。Floorplan 的参数和约束修改非常频繁每次改动都涉及宏单元位置、IO 顺序、电源网络等。如果没有版本管理几天后你根本不知道当前版本和上个版本差在哪里。我的习惯是每完成一个稳定版本就导出 DEF 并备注改动摘要和前端、封装团队同步时也能拿着版本号对需求。数字后端是一条流程很长的链路布图规划只是第一步但它是决定整条链路走向的关键一步。把这一步做扎实了后面每一步都能更顺这一步偷懒后面就会用更惨烈的方式还回来。希望这篇笔记对刚开始接触数字后端的朋友有帮助也欢迎有经验的朋友分享你们在布图规划阶段的心得和踩坑记录相互交流才能进步得更快。