2026/10/7 1:05:01

数字后端Placement阶段Density与Congestion控制实战

数字后端Placement阶段Density与Congestion控制实战 数字后端做到placement这一环density和congestion是绕不开的两个老对手。无论你手上跑的是ICC2还是Innovus只要block规模一大、macro一多、pin一密早期placement要是没把密度和拥塞压住后面route阶段就会给你成片的DRC、timing恶化、甚至绕不通。我带过的项目里返工最狠的几次根因几乎都能追到floorplan和place阶段的density没控住。这篇就把平时项目里控制density、追踪congestion、工具命令对照、参数取舍、以及踩过的坑一次性讲清楚给正在被这两件事折磨的同行一个可复现的参考。1. 为什么density和congestion是PR阶段绕不过去的一关很多人第一次听到density以为就是单元摆得密不密但在后端语境里这个词至少有三层意思混着用很容易把自己也绕进去。理解这三层含义是后面所有控制手段的基础。1.1 density的多重含义从cell density到routing density第一层是cell density也就是单元面积占可布区域的比例标准叫法是place density或者utilization。这个数字反映的是物理上摆了多少东西。第二层是pin density指的是单位面积里的pin数量它跟cell density不成正比——有些cell很小但pin很多比如各种复杂的组合逻辑和时钟单元。第三层是routing density也就是全局布线资源被占用的比例工具报告的congestion map本质上就是它。这三层的关系很微妙。cell density高不一定congestion严重但如果pin density在同一区域也高那基本就跑不掉了。我见过不少block整体utilization才60%出头看着很宽松结果local区域pin堆成山route照样炸。所以光看一个总数是没用的必须落到局部去看分布。从工具角度说ICC2的report_congestion和Innovus的reportCongestion输出的overflow才是真正有诊断价值的东西。cell density只是给你一个宏观轮廓真正决定成败的是routing demand和supply的比值。提示别拿整体utilization当验收标准local density热点才是要命的。养成place之后立刻出congestion map的习惯别等到route才回头看。1.2 congestion的本质布线资源与需求的博弈congestion说白了就是某块区域的布线资源不够用。布线资源受几件事影响可用金属层数、轨道的pitch、macro的摆放、power mesh的走向、以及单元和pin的分布。需求侧则来自net的数量和走向。两者一碰撞供需失衡的地方就出overflow。这里有个容易被忽略的点power mesh对signal routing资源的挤压非常狠。一条宽metal在某一层横穿半个block那一层的横向轨道就被吃掉一大片。很多新人floorplan时把power mesh直接按模板画上去根本没考虑后面signal往哪走结果place一看congestion全红。所以power plan和floorplan必须一起权衡不能先定死再补救。另一个点是macro周围的阴影区。macro的pin通常集中在某几边大量net从这里进进出出但macro本身不提供可布资源于是通道被挤爆。这就是为什么macro channel width、halo、以及pin access方向需要提前规划。1.3 为什么必须在PR阶段解决时序与signoff的连锁反应有人会想congestion大不了多绕几圈route热点加个detour不就完了问题是detour会带来线长增加线长一增加timing就崩尤其是高频路径。更麻烦的是route阶段的detour会让local density进一步升高可能触发metal short、spacing violation甚至DRC fail。等到signoff阶段再修成本成倍上升。从流程上讲place阶段解决的congestion一单位代价能修十单位的问题。到了route阶段再修就是拿十倍代价修一单位。这个投入产出比是后端工程师必须建立的基本认知。所以density和congestion的控制窗口严格来说从floorplan就开始了place是主战场route只是收尾。2. Density控制的实操手段与参数解析理解了density的层次接下来就是怎么在工具里动手。ICC2和Innovus在density控制上的思路是相通的但命令、默认值、参数命名差别不小切换工具时特别容易搞混。2.1 全局density目标的设定逻辑全局density目标不是拍脑袋定的要结合几件事block的面积、macro占比、pin密度、可用层数、以及是不是有clock tree的预期占用。经验上macro占比较大的block标准单元区的初始utilization最好压在65%到75%之间给CTS和route留出余量。纯逻辑block可以放到75%到82%但前提是pin分布均匀。ICC2里控制全局密度的入口主要是application option常见做法是# ICC2 控制 coarse placement 的最大密度 set_app_options -name place.coarse.max_density -value 0.72 # 控制初始place的密度 set_app_options -name place_opt.initial_density -value 0.68Innovus里则通过setPlaceMode来设# Innovus 设置全局最大密度 setPlaceMode -place_global_max_density 0.75 # 让密度分布更均匀 setPlaceMode -place_global_uniform_density true这里要强调一点max_density是上限不是目标工具会尽量不超过这个值但不代表局部不会超。真正有约束力的是blockage和region约束。全局值只是给congestion-driven引擎一个基准。2.2 Placement blockage与soft blockage的取舍blockage是density控制最直接的工具但用错了会帮倒忙。hard blockage是完全禁止摆放soft blockage是降低密度倾向。二者的选择取决于目的。如果某个区域下面有敏感结构、或者要预留通道给power用hard blockage。如果只是想让工具别摆太密、给route留口气用soft blockage更合适因为它保留灵活性。ICC2的写法# ICC2 hard blockage create_placement_blockage -type hard -boundary {{100 100} {300 400}} # ICC2 soft blockage create_placement_blockage -type soft -boundary {{300 100} {500 400}}Innovus的写法# Innovus hard placement blockage createPlaceBlockage -box {100 100 300 400} -type hard # Innovus soft placement blockage createPlaceBlockage -box {300 100 500 400} -type soft注意coordinate的格式两工具不同ICC2用点对{{x1 y1} {x2 y2}}Innovus用{x1 y1 x2 y2}切换时经常因为格式写错导致blockage没生效排查半天。这是个非常典型的低级坑。还有一种partial blockageInnovus支持用density参数做成半透膜比如createPlaceBlockage -box {100 100 300 400} -type partial -density 30意思是该区域最多只允许30%的密度比hard blockage灵活得多适合macro周边这种既不能全空也不能太密的位置。2.3 Cell padding与spacing label的精细调节全局和区域控制之后还有一层单元级的微调。cell padding是在单元四周预留空间用于降低局部pin密度、方便route access。ICC2里可以针对特定cell或cell group设置# ICC2 给某类cell加padding set_placement_spacing_label -name pad_label -side both -lib_cells {CLKINVX1} set_placement_spacing_rule -labels {pad_label pad_label} {2 2}Innovus里的等价做法是设置cell padding# Innovus cell padding setPlaceMode -place_global_module_padding {MEM* 2.0}padding的价值在于缓解pin access congestion尤其是memory和复杂macro的输入pin。但padding不能滥用加太多会让面积白白浪费甚至把单元推出理想区域反而拉长线。我的经验是只对真正拥挤的那几类单元动手别全局加。2.4 ICC2与Innovus密度控制命令对照为了切换工具时不至于抓瞎把常用命令整理成表目的ICC2 命令Innovus 命令全局最大密度place.coarse.max_density-place_global_max_density密度均匀化place_opt.initial_density-place_global_uniform_densityhard blockagecreate_placement_blockage -type hardcreatePlaceBlockage -type hardsoft blockagecreate_placement_blockage -type softcreatePlaceBlockage -type softpartial blockage用density option组合实现createPlaceBlockage -type partial -densitycell paddingset_placement_spacing_labelsetPlaceMode -place_global_module_padding拥塞报告report_congestionreportCongestion这张表是我平时贴在工作区墙上的东西切换项目时看一眼能省下不少翻文档的时间。注意两种工具的坐标格式、命令层级差异很大脚本不能直接互抄。跨工具迁移脚本时先跑一个小模块验证blockage是否真的生效再上大block。3. Congestion控制的核心策略density控好了congestion未必就没了因为pin分布和net走向是另一回事。congestion控制更像是体检加手术得先看报告再动刀。3.1 Congestion map的正确读法拿到congestion map先别急着修先学会读。图上通常用颜色表示overflow的严重程度绿色代表资源充足黄色是接近临界红色是已经over。但光看颜色不够要结合net的走向看。我通常分三步第一步看整体分布找出红色聚集的几个block区域第二步放大到热点看是横向拥挤还是纵向拥挤这决定了要不要调power mesh的层次第三步把这些热点和density、pin density叠加上去判断到底是单元太密、pin太多还是macro通道太窄。Innovus里出congestion map常用# Innovus 生成congestion map reportCongestion -map -overflow # 生成更详细的拥塞报告 reportCongestion -hotspot -overflowICC2里则是# ICC2 重新跑全局布线并报告拥塞 report_congestion -rerun_global_router一个实用的技巧是把congestion map和cell density map放在同一视角对比两者重合度高的地方八成是local density问题congestion红但density不高的地方往往是pin access或者macro通道问题。分清这两类修复方向完全不同。3.2 Congestion-driven placement的开关与力度两大工具都有congestion-driven的placing模式核心是让引擎在摆放时就把布线拥塞纳入代价函数。ICC2里通过effort和congestion相关的option控制# ICC2 提高congestion优化力度 set_app_options -name place_opt.flow.enable_congestion -value true set_app_options -name place_opt.congestion.effort -value highInnovus里的入口是place mode的cong effort# Innovus 提高拥塞优化力度 setPlaceMode -place_global_cong_effort high力度分档一般有low、medium、high甚至某些版本有ultra。力度越高运行时间和内存代价越大但拥塞处理越好。我的建议是初次place用medium跑一遍看结果如果整体拥塞可控就保持如果红区明显再上high甚至ultra别一上来就拉满跑一次几小时太浪费。还有个细节congestion-driven会让工具为了降低拥塞而稍微放松线长优化所以timing可能会有一点牺牲。这个trade-off要心里有数别看到WNS变差就以为工具出错了。3.3 Pin density与macro周边的专项处理pin density是congestion的隐形推手。同样密度的区域pin多的那块拥塞会更严重因为每个pin都要引线。降低pin density的办法有几类一是把高pin密度的cell适当分散别扎堆二是给特定模块加padding三是调整模块的摆放朝向让pin朝向宽松的一侧。macro周边是另一个重灾区。常见的处理包括设置macro halo、调整macro之间的channel宽度、以及控制macro pin的access方向。Innovus里可以给macro加halo# Innovus macro halo设置 setPlaceMode -place_global_module_padding {SRAM* 1.5}ICC2里则用keepout margin# ICC2 macro keepout margin create_keepout_margin -type hard -outer {2 2 2 2} [get_cells SRAM*]这里的{2 2 2 2}是四边外扩的距离单位遵循库单位写脚本时要确认清楚是um还是库单位否则差一个数量级halo要么大得离谱要么等于没加。这个坑我踩过当时halo设成了2000把整个block塞满还以为命令没生效。3.4 常用的congestion缓解组合拳单个手段往往不够实际项目里都是组合用。一套比较稳的组合是先调低全局density给引擎松绑再在热点区域加soft blockage引导工具绕开同时对macro加halo保护通道最后开congestion-driven placement高力度跑一遍。这套组合能覆盖80%的常见拥塞场景。拥塞类型判断依据主要手段local density过高congestion与density图重合降density、加soft blockagepin access困难红区窄且碎cell padding、pin分散macro通道不足红区呈条带贴在macro边macro halo、加宽channelpower mesh挤压某层单向拥挤调mesh层次与线宽数据流集中红区跟着某模块走调整模块摆放与朝向这张表是我排查时的第一张对照卡先归类再动手避免盲目试参数。4. 典型场景实战从congestion报告到修复闭环讲完手段落到一个完整的修复流程。这部分我用一个中等规模block的经历来讲方便你照着复现。4.1 定位congestion热点的标准流程拿到一个place完的block第一步不是直接修而是出报告。我会依次跑# Innovus 环境下的诊断 reportCongestion -map -overflow report_density -map把两张图叠加圈出重叠热点。假设发现block右下角有一块红区同时density也偏高初步判断是local density问题。再放大看如果红区呈细碎状、分布在几个小区域那更可能是pin access。第二步用dbGet查这块区域里的instance看都是哪些单元# 查询某个bounding box内的instance数量 set box {100 100 300 400} set cells [dbGet top.insts.bbox.llx [lindex $box 0] ]更精确的写法是按坐标范围过滤把热点区域的instance列出来看单元类型分布。如果发现全是某种高pin的cell那pin density就是主因。4.2 迭代修复的步骤与力度定位之后进入修复循环我的习惯是小步快跑一次只改一个变量跑完place立刻复查congestion。具体顺序先降整体max_density 3到5个百分点看红区是否缓解。这一步改动小风险低。没效果就在热点加soft blockage给工具明确信号。还是不行就针对热点单元的cell类型加padding或者对macro加halo。最后开congestion-driven placement力度逐级上调。每一步跑完都出一次congestion map对比记录哪一步见效。这个记录习惯很重要因为不同block的主因不同积累几轮后你会有直觉。ICC2下迭代时要注意app option的作用范围很多option必须在place之前设置中途改可能不生效需要重新跑place。Innovus的setPlaceMode同理改完要重新place才会体现。4.3 一次真实的修复记录回到那个block。第一轮降density从0.78到0.73红区面积减少了约三成但右下角仍有一块顽固红区。第二轮在右下角加了一块partial blockagedensity限到35%createPlaceBlockage -box {1100 200 1400 500} -type partial -density 35再跑红区基本消退但出现一条新的窄红带贴着macro。第三轮给该macro加halo外扩1.5个库单位红带消失。最后开cong effort high跑一遍收尾整体overflow降到可接受范围timing只有极小波动。整个过程跑了五轮place每轮大概二十分钟总共不到两小时。如果拖到route阶段修同样的效果至少要多花一天而且timing会更难救。提示修复congestion时务必保留每一轮的congestion map和overflow数字写成小日志。这个日志在项目复盘和下次遇到类似block时非常值钱。5. 常见问题与排查技巧实录实操里最耗时间的往往不是大方向而是一些具体的小问题。这部分挑几个高频场景讲。5.1 density降不下去怎么办有时候你把max_density一降再降工具报的density还是居高不下。常见原因有几个一是blockage没生效命令格式写错或者坐标系搞错二是power domain约束把单元锁死在某个区域三是某些cell被dont_touch或者region约束钉住了位置。排查顺序是先确认blockage是否真的生效可以单独查询blockage对象再检查是否有region约束或者grouping约束限制了摆放自由度最后看power intent是不是把可摆区域压缩了。Innovus里可以用reportPlaceBlockage之类的命令确认blockage列表ICC2里用get_placement_blockages。还有一种情况是面积本身就不够你把density目标定到了物理上做不到的值。这时候要么扩面积要么接受更高的density配合更好的congestion控制。5.2 congestion反复出现的根因congestion修了又出现说明没找到根因。最常见的隐藏根因是floorplan本身不合理——macro摆得太挤通道不够或者数据流方向反了。这种情况下无论怎么调placement参数都是治标。判断方法如果congestion红区始终贴着macro边、或者跟着某条数据流走那基本就是floorplan问题得回去调macro位置。另一类根因是power mesh设计不合理某层被单向占用过多导致signal没有足够层可用。这时候要调mesh的层次分布比如把宽metal挪到更高层给低层signal留资源。5.3 在Innovus里选中特定instance和PG term的小技巧有同行问过在Innovus里怎么快速选中名字带特定前缀的标准单元、甚至定位到它的PG term。GUI手动点太慢用dbGet过滤最靠谱。选中名字以某个前缀开头的instance# 选中所有名字以biasnw开头的instance selectInst [dbGet top.insts.name biasnw* -p]如果要在GUI里高亮可以先deselectAll再执行上面这条。要定位到某个instance的PG term可以这样查# 查看某instance的所有PG term名字 dbGet [dbGetInstByName biasnw1].pgTerms.namePG term在数据库里通常作为特殊的pgTerms存在名字多半是VDD、VSS或者工艺相关的power net名。要批量选中某类instance的PG term可以结合过滤# 列出指定前缀instance的PG term foreach inst [dbGet top.insts.name biasnw* -p] { puts [$inst name]: [dbGet $inst.pgTerms.name] }这类操作在debug power连接、检查特殊器件比如well bias相关单元时特别有用。记住dbGet的-p是返回指针列表不加它返回的是属性值很多新手在这里混淆导致selectInst拿到一堆字符串而不是对象命令直接报错。5.4 常见问题速查表现象可能根因排查与解决blockage不生效坐标格式错误核对工具要求的点对/列表格式density居高不下约束钉死单元检查region、grouping、power domaincongestion修反复floorplan不合理回去调macro位置和通道pin access拥塞高pin单元扎堆加padding、分散单元halo大得离谱单位混淆确认库单位与um换算PG term选不中混淆-p返回类型用-p拿指针再操作timing变差cong effort过高权衡拥塞与线长适度降级这张表基本覆盖了我日常遇到的大部分density和congestion问题遇到新问题时也可以往里面归类。我个人在实际项目里的体会是density和congestion这两件事七分靠floorplan三分靠place参数。很多团队把大量精力花在调工具参数上却忽略了floorplan阶段就该把macro、power、通道、数据流一次性规划好。工具能帮你优化但工具救不了先天不良的布局。所以我会建议每次place跑完出了congestion问题先花十分钟问自己一句这是摆放的锅还是布局的锅想清楚这一点能省掉大量无效的参数尝试。至于工具命令ICC2和Innovus各有各的脾气把对照表和常用脚本沉淀下来切换项目时能少交很多学费。