做数字后端这些年,我最大的感触是:Floorplan这个阶段看似只占整个项目周期的很小一部分,但它决定了后面Place、CTS、Route每一步是顺风顺水还是步步惊心。尤其是那种几十个Macro、十几万条关键数据通路的芯片,如果Floorplan阶段没把Data Flow摸清楚,没把走线资源预估到位,等Route阶段满屏congestion爆红的时候,你只能眼睁睁看着日子一天天过去,Timing一条条变红,然后开始拆了重摆、摆了再拆的死循环。
这篇文章我就把从Data Flow入手做Macro摆放、走线资源预估与优化这套完整思路拆开讲清楚。内容以Innovus数字后端流程为主,但方法论本身是通用的。无论你是刚入行的后端工程师,还是正在准备数字后端面试,又或是被congestion折磨到怀疑人生的老战友,这篇文章应该都能给你一些可落地的参考。
1. 为什么Floorplan阶段就要盯着走线资源不放
很多新人刚接触数字后端时,对Floorplan的理解就是“把Macro找个地方放一放,把利用率控制在合理范围”。这个理解不能算错,但远远不够。Floorplan的本质其实是给整个芯片的物理实现画好骨架,而这个骨架最核心的约束,不是面积利用率,而是走线资源的合理分配。
1.1 走线资源为什么会成为瓶颈
芯片的每一层金属都有固定的track和pitch,也就是说,每一层金属在一毫米宽度内能走的线数是有限的。后端实现做的事情,说直白点,就是把几千万个标准单元的pin,用一层层金属连起来。当某个区域的逻辑密度过高,或者大量走线被迫绕行时,该区域的局部走线需求就会超过实际可用的track资源,表现出来的就是congestion。
我经常用快递分拣中心来类比:每个Macro就像一个大仓库,标准单元是散货,数据通路是货运通道。Floorplan做好了,货物从进来到出去路径顺畅;做不好,大家都挤在一个通道上,后面怎么调度都是堵。而且芯片这地方没有“多修一条路”选项,金属层是固定的,绕线只能往上走,但布线层数也是固定的。所以在Floorplan阶段就要把路规划好。
1.2 Macro摆放对congestion的影响权重
在真实项目中,congestion的来源大概可以拆成三块:逻辑本身太挤、时钟网络占用资源、Macro摆放不合理。前两块的优化空间相对有限,逻辑密度是综合之后就基本定型的,时钟树资源可以通过CTS策略和时钟shielding来缓解,但很多congestion其实是Macro摆放不当造成的。
一个典型的反面案例是:DDR controller的Macro放在芯片左上角,与之频繁交互的CPU cluster在右下角,数据要横穿整个芯片,中间哪怕有再多的绕线资源都会被吃干榨净。更有意思的是,很多congestion并不是直接发生在Macro周围,而是发生在数据通路的中间地带,因为所有信号都要绕路穿过这片区域。这就是为什么你只盯着congestion热区去修,怎么修都修不掉,因为根子在Macro摆放时的Data Flow方向没理清。
2. 读懂Data Flow:Macro摆放的第一性原理
既然Macro摆放对congestion影响这么大,那正确的做法是什么?答案就三个字:看数据流。Data Flow分析是整个Floorplan流程的起手式,也是我认为最值得花时间的前置工作。
2.1 什么是Data Flow,怎么看
Data Flow就是数据在芯片内部流动的方向和路径。后端工程师拿到手的通常是一份门级网表和RTL代码,很多人一上来就急着看面积、看Pin位置,这是不对的。我自己的习惯是,拿到网表先不看具体单元,最高优先级的事是先把模块级别的数据通路捋清楚。
具体看什么?三个维度:
- 顶层例化关系:看Top下面挂了哪些子模块,谁和谁之间有大量连接。一般通过hierarchy browser或者简单的脚本就能扫出来,重点关注交互信号位宽超过64bit、连接数量在几百根以上的模块对。
- 数据的走向:一个模块的数据是从哪里来的,经过什么样的处理,最终送到哪里去。这个要结合RTL代码和架构文档来看,尤其注意AXI/AHB总线、DDR控制器、高速接口这类关键数据通路。
- 带宽和频率:同样的连接数量,跑到2GHz和跑到500MHz,对物理实现造成的压力完全不同。高频模块之间的物理距离必须尽可能短。
工具方面,Innovus里本身就有connectivity分析相关的功能,能够把Macro之间的高连接关系图形化展示出来。但在跑工具之前,我建议你先自己用Datapath(也可以用普通的文本画图工具)把模块级别的数据流图先画出来,哪怕画得丑一点,这个过程能逼着你去理解架构,而不是机械地等着工具给你答案。
2.2 Data Flow分析的实用流程
我一般会按下面这套sequence走一遍:
- 把RTL的顶层例化树导出来,标注出每个模块的面积、宏单元数量和时钟域。
- 用连接性分析工具统计模块之间的信号连接数量和总线位宽,排出一个Top10的交互关系清单。
- 画数据流图,确认主数据通路是从哪个方向进来、流向哪个方向、中间经过哪些大模块。
- 根据数据流图确定Macro摆放的宏观布局——是横着排还是竖着排、哪几个Macro必须挨着放。
这套流程做下来通常需要半天到一天,看项目复杂度。但我要说的是,这半天时间花得绝对值得。我见过太多项目,Floorplan大家随便摆一摆,觉得可以在后面迭代中慢慢优化,结果到Route阶段发现congestion无解,回头重做Floorplan,反而浪费了好几周。
2.3 一个具体的Data Flow分析示例
拿一个典型的SoC来说:外部数据从DDR进来,经过DDR controller和PHY,进到内部总线上,然后分发给CPU cluster、GPU cluster和视频编解码模块,处理完的数据再经过总线回到DDR。
那么从Data Flow角度,DDR controller和PHY应该摆在芯片边缘靠近DDR接口的位置;CPU、GPU这些高带宽模块应该围绕总线仲裁器形成一个环状布局;视频编解码模块如果和Display接口有大量交互,那它们俩之间应该有一条通畅的走廊。这些结论不是靠猜的,是数据流方向推出来的。这也是面试官问Data Flow相关问题时最想听到的分析思路:不是简单的“A模块挨着B模块”,而是把数据方向、带宽需求和物理约束结合起来综合判断。
3. Macro摆放实战:位宽、间距与通道的取舍
Data Flow分析做完之后,就到了动真格的时候。Macro摆放看起来简单,不就是把大模块拖到指定位置吗?但里面细节多得很。我总结下来,核心就三件事:方向对不对、间距够不够、通道顺不顺。
3.1 方向:Data Flow方向上的线性排布
Surface mount的Macro在摆放时,最重要的一个原则是让数据流方向上的高交互Macro呈线性排列,避免出现“U型”或“Z型”绕路。比如数据从A进、经过B、从C出,那么AB C三个Macro最好在数据流方向上依次排开,让信号能从A的出口直着走到B的入口,再从B出口直着走到C的入口。
实际操作中,我在Innovus里摆放多个Macro时,会先在GUI里用Data Flow视图(Analyze -> Data Flow,或者通过命令打开macro connectivity视图)确认高连接关系,然后手动把高交互的Macro摆成一条链。这里有个容易被忽略的点:Macro的pin方向。很多Macro的pin是集中在一侧或者两侧的,摆放时要考虑pin face的方向,让Macro的pin朝向数据流入的方向,避免信号从Macro背后绕一圈才能接到pin上。
比如一个SRAM的pin面朝北,但它的数据通路在南方,那所有信号都要绕过SRAM本体,绕路本身就在消耗走线资源。摆放时养成一个习惯:记住每个Macro哪些pin是地址、哪些是数据,它们的朝向该朝着谁。
3.2 间距:别把Macro挤到没有呼吸空间
Macro间距是Floorplan阶段最直观、也最容易出问题的地方。间距留小了,会出现两类问题:一是Macro周围没有足够的routing resource,pin access本身都困难;二是标准单元的摆放区域被挤压成很窄的长条,利用率失衡,局部congestion直接爆表。
我的经验值是在先进工艺节点(比如7nm/5nm)下,大尺寸Macro之间的channel宽度一般不要小于3到4个routing track。放到具体数值上,要看工艺的track pitch,但我一般会至少留到6到8微米以上,而且这个还不包括halo。更准确的判断方法是通过工具做一次快速global route的预分析,如果Macro周边的congestion在80%以下,说明间距基本合理;如果超过90%,甚至出现红色,就要考虑拉开间距或者调整Macro摆放。
在Innovus里给Macro加halo的操作很简单:
add_placement_halo -left 8 -right 8 -top 8 -bottom 8 [get_cells {macro1 macro2}]halo的作用不仅仅是留物理空间,更重要的是给工具划清楚区域,避免标准单元贴到Macro边上导致后续pin access困难和局部拥塞。
3.3 通道:给数据流留出高速公路
第三个关键词是通道。如果Data Flow分析告诉你A和B之间会有大量数据交互,那这两个Macro之间一定要预留出一条“直通走廊”。这条走廊上尽量少放标准单元,甚至可以用routing guide或者blockage来显式保护。
我有一次做一个多媒体芯片,ISP模块和DDR controller之间的数据的位宽很大,频率也不低。最开始我把它们摆在斜对角方向,数据要绕过一个大的SRAM阵列才能到达DDR,结果那个SRAM周围congestion直接红了三片区域。后来调整布局,把ISP和DDR controller之间留出一条横行通道,同时在通道上设置了routing guide,congestion立刻从85%降到了60%以下,后续CTS和Route都顺利很多。
在Innovus中创建routing guide可以用下面的命令:
create_routing_guide -box {x1 y1 x2 y2} -layer {M3 M4 M5 M6}Routing guide的作用是告诉绕线工具:这片区域主要用来走线,不要大量在上面放标准单元。如果你的数据通道非常重要,甚至可以考虑创建placement blockage,把标准单元完全挡在外面。
4. 走线资源预估:算清楚再动手
走线资源预估是Floorplan阶段比较硬核的环节,也是最容易被新人忽略的。很多人摆完Macro就开始跑Place,QoR一塌糊涂。其实在Macro摆放差不多的时候,就应该花时间去预估整个芯片的走线资源分配情况,做一些必要的优化,再进入正式流程。
4.1 横纵资源比:数字后端经典的H/V Ratio
芯片的每层金属都有方向,奇数层走水平线、偶数层走垂直线,这是标准做法。不同方向上的走线资源能不能匹配上实际需求,直接影响congestion。H/V Ratio问题在Block级设计里尤其明显:如果这个模块本身是数据横着流的,那水平方向的走线需求天然大于垂直方向,但如果你给水平方向分配的金属层和track不够,那问题就来了。
在Floorplan阶段,我习惯做一个简单的手算:先把所有宏单元和标准单元的Row数估算出来,再估算关键数据通路的走线需求集中在哪个方向,然后反推每一层金属的走线资源。这个算出来的结果不要求很精确,但能帮你建立“这个设计到底缺不缺某个方向的资源”的直觉。
如果工具里有DRC-clean routing resource的报告,可以直接参考。比如Innovus的report_routing_resource可以输出每层金属的利用率预估,我通常在Floorplan搭好之后、Place之前就跑一遍,如果发现某一层的利用率超过80%,就会考虑调整pin方向、调整memory的orientation,或者通过改变Macro摆放方向来改善横纵资源分配。
4.2 Pin Access预判:从Pin Density看congestion苗头
走线资源预估还有一个非常关键但总被忽视的角度:pin access。Macro的pin密度如果过高,哪怕Macro周围的track资源看起来充足,实际绕线也会很吃力。因为每个pin至少要有一个access point,而macro pin通常集中在边缘的几层金属上,pin一多,access point之间会互相打架。
我在实际工作中判断一个Macro区域是否会有pin access问题,会先看两个指标:一是pin density,就是单位长度内的pin数量;二是连接该Macro的net数量。把这两个指标和金属层资源放一起看,基本能预判出这块区域会不会红。如果pin density很高,我会考虑给Macro的pin附近增加额外的halo,或者调整Macro的朝向,让高密度pin集中在更充裕的一侧。
这里多说一句:pin access问题在Macro摆完的当下是看不出来的,因为Place还没跑,一切看起来都风平浪静。所以一定要养成在Place之后马上看一眼pin access和局部congestion的习惯,越早发现越容易改,等Route做到一半再发现就晚了。
4.3 快速预估:用一次临时global route验证
与其纸上谈兵,我现在更推荐大家在实际流程里加一步:Macro摆好、Power Ring和Stripe打好之后,先不急着做正式的Place,而是快速跑一次global route来验证走线资源。
在Innovus里可以这样操作:
set_db congestion_global_enable true route_global report_congestion -global通过report_congestion的输出,可以直接看到各个区域的congestion百分比。然后结合GUI里显示的congestion map,把红色区域和你的Macro摆放、Data Flow分析结果对照起来看。这一步的花费时间不多,但能帮你提前发现很多问题。
我自己在项目里甚至把这个过程迭代跑两三轮:第一轮在Macro摆好后,看大体格局;第二轮在Place完成后,看细节。跑完这两轮,对芯片的走线资源心里基本就有底了。
5. 常见问题与排查技巧实录
上面讲的都是方法论和操作流程,但在实际项目中,你总会遇到各种出乎意料的情况。我把这些年踩过的一些坑和排查思路整理一下,给各位做个参考。
5.1 问题一:Macro周围不红,中间区域却爆红
这个现象在面试题里也很常见:Macro周边看着很干净,congestion却集中在两个Macro之间的空白区域。原因大概率是Data Flow方向没理清,大量的net需要跨Macro走线,中间的空白区域成了必经之地。尤其是当两个Macro的pin面朝相反方向时,所有连接必须先绕到Macro的同一侧,再穿过去,中间区域自然吃满。
排查思路:把congestion热区和Macro连接关系图叠在一起看,确认热区是不是正好在两个高交互Macro的连线上。如果是,要么调整Macro朝向让pin相对,要么通过routing guide把这条路径打通,要么把中间挡路的标准单元挪走。
5.2 问题二:利用率明明不高,为什么还是拥塞
有时候core utilization只有60%左右,看起来相当宽松,但place之后还是有很多congestion热点。这种情况多半是局部资源分配不均导致的。比如某个大Macro把一块区域占掉了,剩下的标准单元被挤在一个很窄的L形区域里,这个区域的局部利用率可能已经超过90%了,当然会红。
排查思路:看局部cell density,而不是看整体core utilization。在Innovus里可以通过GUI的cell density map来检查,凡是深色的高密度小区域,就要考虑是不是Macro摆放时把标准单元的位置挤得太狠了。解决办法通常是调整Macro的位置,留出更规则的std cell区域,或者降低整体利用率。
5.3 问题三:Power Plan做完之后又多出一片红区
这是一个让我记忆非常深刻的教训。有一次Floorplan和Macro摆放都没问题,跑了一轮global route也很干净,结果Power Plan(Ring加Stripe)做完之后再查congestion,突然冒出一片红区。原因很简单:Power Stripe走线本身吃掉了大量M4到M6的track资源,尤其是横跨数据通道上方的Stripe,等于在上面盖了一座桥。
排查思路:在做Power Plan之前,先用第4.3节的方法跑一次global route,然后再做Power Plan,做完之后对比一下两者之间的congestion差异。如果差异集中在Stripe密集区域,可以适当调整Power Stripe的间距和宽度,或者把高频率数据通道上的Stripe用更少的层来走,释放一些走线资源。这也是为什么走线资源预估一定要做在Power Plan之前的原因。
5.4 问题四:CTS之后congestion不降反升
如果Place阶段congestion看着还可以,CTS做完反而变严重了,那大概率是时钟网络的buffer插入挤占了走线资源。时钟树综合会插入大量clock buffer/inverter,这些单元必须有地方放,而且时钟网络本身还会产生大量的长线。如果时钟域的分布和Macro摆放位置不匹配,CTS后的congestion就会失控。
排查思路:时钟树吃资源的问题,根治办法还是在Floorplan阶段就考虑时钟域的物理分布。比如同一时钟域的寄存器尽量集中在一个区域,不让时钟信号跨越大半个芯片。另一个有效的手段是给时钟树预留一些专用的摆放区域,或者在关键位置提前放好clock buffer的endpoint约束,让工具别乱插。
6. 我的几点实操心得
最后聊点不常写进文档里的个人经验吧。
第一,Data Flow分析这件事,真的不要偷懒依赖工具。工具能帮你统计连接数量和位宽,但“为什么数据要走这条路”这个问题,只有理解了架构才能回答。我自己的习惯是在项目初期约上架构工程师聊半小时,把数据流的骨架问清楚,这半小时的作用比后面自己瞎猜三天都大。
第二,Floorplan阶段的走线资源预估,宁可多算一步,不要少算一步。尤其是先进工艺下,走线资源越来越紧张,等到Route阶段再发现资源不够,代价是几何级增长的。把global route作为Floorplan迭代的一个常规检查项,每次调整完Macro都跑一下,二十分钟的代价,能规避掉后面几天甚至几周的重工。
第三,很多做后端的朋友有个误区,觉得Floorplan就是把Macro摆完就结束了。实际上,Floorplan阶段做得好不好,要等到Place之后的congestion报告出来才能验证。所以我的流程里,Macro摆完不算完,至少要看到place之后前几个热点都在预期范围内,才敢说这个Floorplan靠谱。
要说的基本就这些。如果你也正在被某个congestion热点折磨,不妨回头看看是不是Data Flow或者Macro摆放的某个细节没做到位。有时候答案不在你盯着的那片红色区域里,而在离它很远的那个Macro朝向上。