大芯片后端设计必备:Hierarchical Flow层次化流程核心思路与实战

发布时间:2026/10/5 4:38:22
大芯片后端设计必备:Hierarchical Flow层次化流程核心思路与实战
芯片越做越大这句话放在数字后端设计里从来不是感叹而是实打实的压力。我刚入行那会儿跑一个三百万门的模块晚上下班前提交job第二天早上看结果刚刚好。现在随便一颗SoC都几千万门起步几亿门的芯片也不稀奇要是还按老思路把整个芯片拉平去做flat flow一版floorplan跑完光等结果就能把人熬到没脾气。所以这几年hierarchical flow几乎成了大芯片后端实现绕不开的标配方案。hierarchical flow的核心就四个字分而治之——把一颗大芯片按功能或物理边界切成若干block每个block独立做综合、布局布线、时序收敛最后再到top层做集成和顶层收敛。听起来不复杂但真正从flat flow切到hierarchical flow里面的门道远比想象中多划分怎么切、budget怎么给、数据怎么交、跨block路径怎么收每一环都有讲究。现在很多公司在招数字IC后端工程师时都会把hierarchical flow当成重点考察对象。我之前帮朋友看过一些公司的数字IC笔试题比如芯动科技的数字IC笔试题里就有不少和层次化设计相关的内容。这说明它已经不是大厂专属的进阶技巧而是每个后端工程师迟早要补上的一课。这篇文章先不聊具体工具命令重点把hierarchical flow的整体思路、核心概念和落地节奏讲清楚再分享一些我在实际项目里踩过的坑。内容面向正在从flat flow往层次化流程过渡的工程师也适合刚接触后端的同学建立整体认知。这篇先打个底后面几篇再分头展开block级实现、顶层集成和时序收敛的具体操作。1. 为什么大芯片绕不开hierarchical flow1.1 flat flow的瓶颈到底在哪先说说flat flow为什么在大芯片上行不通。flat flow就是把整个芯片的所有单元放在一起做布局布线它最大的优点是简单整个设计只有一个绣球时序分析全局一致不需要处理block边界和接口约束。但它的瓶颈也很明显。首先是容量问题。工具能处理的单元数量有上限就算现代EDA工具支持几千万实例跑起来的速度和内存消耗也扛不住。想象一下几千万个标准单元加几十个memory全部堆在一张图上做全局优化每跑一次place就需要几十甚至上百G的内存迭代一轮动不动就是几十个小时。项目进度根本等不起。其次是迭代效率问题。flat flow里只要有一个小模块逻辑改动全芯片就要重新跑一遍。改一个bug全芯片重来这在项目后期是灾难性的。而hierarchical flow里只有改到的block需要重跑其他block的成果可以原样保留重跑范围和控制点都清晰很多。第三是并发和团队协作的问题。flat flow天然不适合多人并行——所有人都在同一个流上想分块跟踪进度都难。hierarchical flow把设计拆成block之后每个block可以交给不同的人或团队负责各自独立收敛、独立交付整体进度自然就快了。提示这里说flat flow行不通不是说它一无是处。芯片规模不大、模块耦合紧密、时序极难切分的场景比如某些高速接口核心反而更倾向flat。选哪种流程永远是看具体design的规模和结构没有绝对的好与坏。1.2 hierarchical flow到底改了什么hierarchical flow相比flat flow本质变化在于数据模型变了。flat flow里只有一张网表、一套约束、一组SDC所有分析都在这一份数据上完成。hierarchical flow里设计被拆成多个层次每个block有自己的网表、约束、时序抽象top层看到的是block的代理模型而不是完整内部细节。这个代理模型常见的有ILMInterface Logic Model和abstract view。ILM保留block端口附近一定深度的逻辑配合接口约束用来在top层相对精确地估计穿过block边界的路径abstract view则更像一个带时序信息的黑盒只保留端口和相应的时序模型。两者各有适用场景下面会细说。从流程动作上看hierarchical flow多出了几个关键动作划分partition、接口时序预算budget、抽象视图生成abstract generation、顶层集成top integration、跨block时序收敛。这些动作会贯穿整个实现流程从综合阶段就开始影响决策。为什么要搞清楚这些变化因为很多人第一次切hierarchical flow时最大的问题不是工具不会用而是思维没转过来——总是用flat的思路去理解层次化的数据。为什么我top层的时序和block层不一样为什么block里改了一版top还是旧数据这些问题的根源都在于没理解层次化流程里数据的产生时机和传递关系。这块想通了后面操作基本就顺了。对比项flat flowhierarchical flow数据模型全芯片一张网表各block独立网表顶层代理模型迭代粒度全芯片重跑只重跑受影响的block内存/时间随规模暴涨分摊到各block相对可控协作方式串行为主block级并行收敛难点全芯片拥塞与时序跨block路径与数据一致性2. 动手划分之前必须想清楚的事2.1 怎么切block才合理划分是整个hierarchical flow的地基地基没打好后面全在填坑。我见过不少项目把block切得稀碎结果block间通信路径一塌糊涂顶层收敛比flat还慢。所以第一条经验是划分要尽量减少跨block的路径让绝大多数时序路径落在block内部。怎么判断哪些模块适合切成独立block我一般看几个维度功能是否内聚、物理是否规整、规模是否适中、是否有独立时钟或电压域。功能内聚的模块比如CPU子系统、GPU核、某些IP天然适合做block因为内部交互密集外部接口相对少物理规整的模块规划起来方便容易给top层留出良好的布线通道规模太小的模块不值得切切了反而增加接口开销有独立时钟域的模块更是强烈建议独立因为时钟在层次化里单独处理会简单很多。规模上个人经验是block面积做到总面积的5%到20%比较舒服。太小层次化带来的管理开销吃掉收益太大block内部跑不动退化回flat的老问题。当然这只是参考具体还要看工具能力和团队分工。划分还有一个容易被低估的点划分接口的选择。尽量选在信号较少、时序余量较大的位置切避免把关键路径拦腰切断。这是个经验活通常要结合前期综合和初步floorplan的结果反复调。我自己的做法是先把整芯片的时序拓扑拉出来看一遍找到天然低耦合的位置再决定在哪儿下刀而不是简单地按IP边界切。2.2 接口时序预算budget怎么给block切好之后下一个难题是给每个block的接口路径分配时序预算也就是定义从输入端口进来到哪里、从内部到哪里到输出端口有多少时间可用。这个预算会直接写进各block的SDC决定它内部meet时序的难度。budget给得太紧block内部很难收敛修都修不动给得太松top层跨block路径留的余量不够最后顶层收不拢。所以预算的本质是在block内部和block之间做一次时序资源的再分配。通常的做法是先用理想时钟模型在顶层做初步综合或快速实现把各个端口路径的delay量级摸出来再按比例分配预算关键路径、难修的模块适当放宽之后进入实现迭代根据实际结果不断回调和校准。这个过程不是一锤子买卖而是要伴随整个流程持续更新。这里特别提醒一点budget不只包括时钟周期内的组合逻辑delay还要把时钟偏斜、in-cell delay、线延迟余量这些因素估算进去。很多新手只算launch和capture的clock path结果block内部全部收敛了一进top就全线violation最后查半天发现是预算压根就没给对。所以在正式实现前花一两天把budget做细远比后面返工来得划算。2.3 层次化数据模型ILM、abstract view与FRAM这个点我单独拿出来讲因为很多人第一次上手就被这几个名词绕晕了。ILMInterface Logic Model可以理解成block带着一部分内部逻辑的代理模型。它保留端口附近一定深度通常是两三级的logic因此top层做时序分析时能相对真实地估计穿过block边界的delay。ILM的优点是精度高缺点是数据和文件更大在top层跑起来更重。abstract view则把这个block简化成纯黑盒只保留端口、物理轮廓和时序弧/约束信息。top层跑起来轻快但对跨block路径的估算依赖接口建模质量误差一般比ILM大。FRAMFRAME抽象通常在物理library语境下出现是一个物理层面的抽象视图主要描述block的边界、pin位置、routing blockage等信息供top层布局布线和时序分析使用。可以理解成从物理角度看block的外壳。实际流程里ILM和abstract view通常会并存前期用abstract view快速探索top方案后期用ILM做精细的top时序收敛。我遇到不少团队只迷信ILM任何阶段都开着ILM跑结果top层又慢又重也有人从头到尾只用abstract view最后时序差太多来来回回返工。合适的做法是分阶段切换前期重速度、后期重精度。类型保留内容精度开销适用阶段ILM端口附近多层逻辑时序高大后期精细收敛abstract view端口时序模型中小前期探索与快速迭代FRAM物理边界pinblockage物理级小布局布线与物理验证提示数据模型一旦选错轻则顶层反复返工重则signoff数据被打回。交付前务必检查抽象视图的版本是否与block实际网表一致这个在常见问题部分再展开。3. block级实现先把每个堡垒打下来3.1 综合阶段的边界处理block级逻辑综合是hierarchical flow的起点。综合阶段要做的除了正常的RTL到网表的映射还有两个层次化特有的任务一是处理好接口约束保证综合结果在block边界上是诚实的二是不要把边界逻辑优化得太过分免得top层想修都没得修。接口约束直接来自budget也就是在SDC里把输入端口的input delay、输出端口的output delay写清楚。这里有个容易犯的低级错误input/output delay的参考时钟要定义对否则DRC一跑全是violation。我在一个项目里就吃过亏某个block的输入预算按2ns给的结果SDC里时钟写错成了分频时钟等于预算无形被砍了一截内部塞到冒烟都收不到查了两天才定位到是约束的问题。另外综合阶段一定要合理设置dont_touch和边界优化选项。层次化流程里block间的buffer和跨边界的逻辑经常需要在top层统一处理如果在block内部就把某些边界逻辑吃掉或者优化掉后面top层反而没法修。所以对靠近端口附近的关键逻辑建议保留一定余量别压得太狠。简单说综合阶段要克制不是为了把面积做到最小而是为后端实现留出调整空间。3.2 floorplan与pin assignment的细节block级floorplan其实是整个block实现里最影响结果的一步。比例、pin位置、macro摆放、power plan、routing blockage每一项都值得单独写一篇这里我挑和层次化强相关的两点说。第一是pin assignment端口位置规划。block的pin是它和top层通信的通道位置好不好直接决定了top层的绕线难度和跨block路径的长度。建议pin assignment要和top层floorplan一起看把和它频繁通信的邻居模块的位置考虑进去尽量让pin朝向通信密集的方向减少信号在顶层跑冤枉路。这个工作最好在block和top的floorplan都初步定下来之后同步做两边对齐再动手。第二是macro摆放和blockage规划。block内部的大macromemory等放在哪里不仅影响内部拥塞还影响block的进出线。普通信号要绕开macro所以macro周边要预留走线资源如果macro恰好放在pin密集区附近顶层进出block的线就很容易拥塞。经验是pin和macro之间保留足够的routing margin主流工具都有相应的约束命令建议一开始就设置好别等拥塞了再调。3.3 block级优化与数据交付block级place和route做完之后要先在block内部完成自己的时序收敛和DRC收敛然后才能生成抽象视图交付给top。怎么判断收敛了我的标准是block内部路径要留足余量尤其是跨block接口路径因为top层实现会对这些路径引入额外的偏差。块内要留多少余量一般看delay变化幅度比如目标频率1GHz的项目接口路径我通常会留出150到200ps的余量再交付。交付物一般包括block的最终网表、SPEF/时序库数据、SDC约束、ILM/abstract view、FRAM物理模型、功耗数据等。每一份数据都要锁定版本标注生成时间否则top层一旦用了旧数据后面排查起来极其痛苦。这个版本管理问题我在常见问题里专门讲。另外block级实现里建议把每个阶段的报告归档。place后、CTS后、route后分别的时序报告、拥塞报告、DRC报告都要留档。这样后面top层有问题能快速定位是哪个block在哪个阶段引入的而不是拿着最终版网表从头猜。归档这件事没有技术难度纯粹是习惯问题但在层次化流程里它能让debug效率翻倍。4. top级集成把拼图拼起来4.1 顶层floorplan与模块摆放top级集成是把所有block按物理关系放到一起加上顶层逻辑完成整个芯片的布局布线和时序收敛。这一步里模块摆放是重头戏。摆放block时要考虑的不仅是面积利用更重要的是block间的数据流和时序约束。通信频繁的模块要靠近最好能共用一个走廊来走线高扇出、长距离的全局信号比如时钟、复位要有专门规划别让它们在普通逻辑层里乱窜。我习惯在top floorplan阶段就把数据流图拉出来把每个block之间的连线权重标上然后照着权重去摆放比凭感觉摆靠谱得多。顶层逻辑top pad logic、level shifter、ISO cell这些也要提前规划位置。它们虽然不大但数量多如果摆得分散很容易在稠密区域形成拥塞点。建议在floorplan阶段就把这些cell规划到指定区域或者至少给它们设定合理的spread约束避免后期拥塞爆发再来补救。4.2 跨block路径收敛top层的时序收敛核心难点就是跨block路径。这类路径一端在一个block内部另一端在另一个block内部或顶层逻辑上launch和capture被切在两端中间还要穿过block的抽象视图分析难度比块内路径大不少。跨block路径的收敛依赖两件事一是抽象视图的精度要够二是迭代调整要快。用abstract view时如果发现跨block路径始终收敛不了先检查是不是抽象视图的modeling有问题再看看budget是否合理。如果确认模型没问题就需要迭代要么调整block的budget要么在top层加入buffer要么让相关block重新收敛。这个反复迭代的过程就是hierarchical flow里最磨人的部分。有一个小技巧我觉得很实用在top层做时序分析时把跨block路径单独拎出来建一个group设专门的weight或约束让它有更高的优化优先级。这样工具会优先处理这些难收路径比漫无目的地全局优化效率高得多。我在好几个项目里靠这招省了不少时间。4.3 顶层STA与signofftop级signoff阶段主要工作是完善的STA、功耗分析、DRC/LVS验证以及和block级结果做一致性检查。这里最要留意的是数据一致性——顶层用的抽象视图和block最终交付的网表之间必须严格对应。我会在signoff前做一轮交叉检查拿block最终网表重新生成一版抽象视图和top用的那版做对比重点看端口时序数值是否匹配、有没有missing timing arc、接口约束是否一致。这个检查花不了多少时间但能避免一大批top说收不了、block说没问题的扯皮问题。另外如果时间允许建议对整个芯片做一次golden STA验证用最完整的SPEF和寄生参数重新跑一遍全芯片时序。有些团队嫌麻烦省掉这步结果在最终流片前发现时序错误返工成本反而更高。hierarchical flow省的是迭代时间signoff的严谨性一点都不能省。5. 实战中的坑和排查技巧5.1 抽象视图和网表不同步这是hierarchical flow里最典型的坑。block改了一版逻辑重新跑了实现但top层用的还是旧抽象视图或者抽象视图生成时机不对用了还没有最终收敛的中间网表。结果top层怎么看怎么不对白白消耗大量时间。排查思路很简单先核对版本再看生成时间最后对比端口时序。实际操作里我建议在流程脚本里加一步自动化检查在每次top层启动前自动比对block交付物清单里的文件时间戳一旦发现抽象视图早于网表就报错。花一天搭这个检查后面能省一个月。症状可能原因排查动作top时序与block结果矛盾抽象视图版本过期比对网表与抽象视图时间戳端口missing timing arc抽象视图生成不完整重新生成并跑一致性检查跨block路径普遍violationbudget分配不合理复盘顶层初步实现的delay分布接口DRC全报错参考时钟定义错误核对SDC中的时钟与input/output delay5.2 时钟树和功耗域的层次化处理层次化流程里时钟树综合尤其要注意。block级做CTS时如果top层的时钟还没有确定block内部的时钟树可能和top的时钟树对不上导致跨block路径的clock skew异常。通常的做法是分阶段处理block级先做局部CTStop级统一处理时钟源到各block的路径必要时做balance。功耗域power domain也是层次化流程的常见难点。不同电压域的block之间需要level shifter和ISO cell这些cell放在block内部还是顶层会影响signoff的功耗分析结果。建议在划分阶段就明确power domain的边界把level shifter和ISO cell的归属规划清楚并且在block和top两层都留出相应的corner和constraint。我在一个多电源域项目里就是因为level shifter归属没定清楚导致顶层功耗分析反复报错最后重跑了三轮才把数据对齐。5.3 多iteration下的项目节奏管理最后聊点项目管理上的体会。hierarchical flow的迭代次数比flat flow多好几轮每次top层重新集成都要等各block重新交付节奏一旦没控制好整个项目就会陷入无休止的等待。我经过几轮项目后总结了几条经验。一是建立固定的交付窗口比如每周两次block交付、每周一次top集成避免block随时交付、top随时重跑的混乱状态。二是明确变更影响范围block的小改动要不要触发顶层重跑要有判断标准不能一有改动就全流程刷新。三是保留冻结版本机制在某个节点把block和top的数据同时冻结作为正式signoff的基线后续任何改动都要走变更评审。说实话hierarchical flow最后拼的不只是工具和技术更是团队之间数据管理和协作的默契。一个block改了不通知一个抽象视图没更新就交付这些小问题在扁平流程里几乎没有在层次化流程里全都会被放大。这也是我一直强调入门前先把数据流和协作规则想清楚比学任何工具命令都重要。我个人的体会是hierarchical flow是一套思路而不仅仅是一串流程命令。它的本质是管理复杂度的艺术——当一颗芯片大到一颗脑子装不下的时候就要学会把问题切成小块再优雅地把它们拼回去。这篇先把这个框架和大方向讲透了下一期我打算从block级floorplan和pin assignment讲起把具体操作和参数选择一步步秀给大家看。最后再分享一个小经验吧切到hierarchical flow之后我养成了一个习惯——每个block都准备一份接口手册把这个block的pin定义、时序预算、关键路径、交付物清单和版本历史整理成一份文档随block数据一起交付。刚开始觉得麻烦后来发现这个手册在跨团队协作和后期debug时价值极大很多因为接口理解不一致导致的返工都能靠这份手册提前避免。如果你也要做hierarchical flow建议从第一个block就开始记越早越受益。