Innovus postRoute冗余hold buffer自动清理与PHC识别实战

发布时间:2026/10/3 15:15:37

Innovus postRoute冗余hold buffer自动清理与PHC识别实战 做数字后端的人八成都在postRoute阶段被hold buffer坑过。Innovus里跑完optDesign -postRoute之后打开layout经常会看到一大片BUF_X占着地方signoff前通常都要花时间清理。我最早遇到过最夸张的一次一个28nm项目在postRoute阶段因为约束反复迭代插进去的hold buffer最后冗余了四百多个手动删到怀疑人生。后来我整理了一套自动清理流程核心思想就是先识别PHCPotential Hold Candidate潜在保持时间修复候选单元再用Tcl脚本批量删除、ecoRoute收尾整个流程跑完不到五分钟。这篇文章就把这套流程、脚本以及几个容易踩的坑都放出来适合正在做Innovus后端ECO、或者刚上手Innovus还不清楚怎么处理冗余buffer的工程师参考。1. 为什么postRoute阶段会残留大量冗余hold buffer1.1 从hold修复机制说起要理解冗余buffer从哪来得先明白hold修复为什么非要插buffer。数据路径比时钟路径短或者时钟到达寄存器的时间差大到一定程度hold就会违例。修hold不是改时钟树最直接的办法就是在数据路径上插入延迟单元让数据晚一点到达。这个延迟单元通常是buffer或者inverter。正常来说工具在postRoute阶段会结合真实绕线寄生参数去修hold但有几种情况会让buffer“修过头”。一种很常见的是约束切换——前端在某次版本迭代里把hold margin从0.05改成0.2工具就会重新插一批buffer之前插的又不会全部自动退掉。另一种是修setup的时候工具挪动了附近cell让本来就刚好的hold路径变得过于乐观于是又多插了缓冲。总之修hold是一个增量过程而不是从零开始重排冗余buffer自然就累积下来了。1.2 冗余buffer的三大来源我自己总结下来postRoute阶段冗余hold buffer主要有三个来源约束迭代造成的“过期buffer”。这类最常见。每次SDC版本更新hold margin、时钟uncertainty一变工具基于新约束再插buffer旧的buffer不会被清理就留在netlist里。一个项目跑五六版约束留下几十个到上百个过期buffer都很正常。ECO移动单元造成的“孤立buffer”。后端做完ECO以后工具为了满足congestion或者其他物理要求会把一些标准单元搬走。原来在数据路径上串得好好的buffer被搬到旁边之后就变成了纯摆设信号根本不再经过它。这种buffer最隐蔽不看layout你很难发现它已经不在关键路径上了。工具自动优化留下的“双buffer”。有些时钟单元或逻辑单元因为max_transition/max_cap违例会被工具加倍buffer但后续路径延时被其他修复手段优化掉这第二个buffer就不再需要了。这三个来源里约束迭代是最要命的因为每次改动都可能留下十几个到几十个冗余buffer累积起来就是上百个。1.3 冗余buffer不清理的代价冗余buffer不清理短期看时序还能过但长期看风险很大。首先面积白白增加尤其是一些high-Vt的buffer漏电功耗还不小对低功耗项目来说就是硬伤。其次buffer占据了place区域会让density分布变差后期IR drop分析和EM检查更容易冒红。还有一个容易被忽略的问题冗余buffer对应net上会多出输入pin的电容这对时序分析来讲是乐观的但实际芯片上这个pin还挂在net上一旦这个buffer因工艺偏差翻转异常反而可能引入毛刺。所以做signoff之前把这些东西清掉不只是好看是真的必要。尤其在先进工艺节点cell area和power都是签核指标的一部分冗余buffer留下的面积和功耗浪费最后都要你来解释。2. PHC识别技巧先找到“该清”的buffer2.1 什么是PHCPHC这个叫法在我们项目组内部很常用全称是Potential Hold Candidate翻译过来就是“潜在保持时间修复候选单元”。说白了就是那些看起来在修hold但实际上已经不再起作用的buffer。PHC最直观的特征是输入pin和输出pin连在同一个逻辑网络上。你想buffer的作用是把一个信号延迟后再送出去如果它输入pin和输出pin接的是同一个net那就等于在一条导线上硬生生串了个缓冲器信号从buffer里穿过去之后还是回到了原来的网络这个buffer对逻辑功能没有任何改变纯粹就是“视觉上在修hold”实际没有任何缓冲意义。这种单元的物理表现就是input net和output net同名或者在layout上可以看到一条信号线穿过buffer。2.2 从时序角度筛PHC识别PHC最快的方式是先看时序报告把hold slack特别大的路径挑出来。我用Innovus的get_timing_paths命令例如set hold_paths [get_timing_paths -hold -nworst 5000 -slack_lesser_than 10.0]当然这个命令是抓所有hold路径接下来遍历每条路径提取上面的实例再过滤出buffer类型。为什么要先筛时序因为如果一条路径的hold slack只有20ps说明这个buffer可能还在“勉强干活”贸然删掉风险极大。但如果hold slack大于300ps甚至500ps那这条路径上的多数buffer都是可以被牺牲的。我一般会把阈值设成300ps低于这个值的路径一律不动。这一步可以得到一个初步的候选实例列表。2.3 从物理角度二次确认时序筛选之后还不能马上删必须再用layout层面的信息做一次确认。原理很朴素用dbGet拿到每个候选buffer的输入pin对应net和输出pin对应net对比两边的net name。如果两个net是同一个名字那这个buffer就是纯冗余可以安全删掉。脚本示意set inNet [dbGet [dbGet -p top.insts.name $inst].instTerms -if {.pin.dir input}].net.name set outNet [dbGet [dbGet -p top.insts.name $inst].instTerms -if {.pin.dir output}].net.name if {$inNet $outNet} { puts REDUNDANT: $inst $inNet }这里有个小细节要注意有些buffer是双pin输入比如带enable的时钟buffer直接用pin.dirinput可能会取到多个net。遇到这种情况我一般会限定取第一个input的net或者先检查单元类型。还有对于inverter来说输入输出天然不在一个net上所以这一类要单独处理不能直接套用“same net”逻辑。好在我清理的对象以buffer为主inverter我一般只做时序判断不强行做物理判断。2.4 顺带小技巧用dbGet选中标准单元的PG term写脚本的时候还有一件事绕不开就是确认待删buffer的PG引脚连接是否正常。有次我准备删一个buffer结果删完发现它还有一个悬浮的VDD pin直接导致下一轮LVS报错。后来学聪明了删除之前先看一眼PG连接。有人会问Innovus里怎么选中一个标准单元比如名字为biasnw的pg term其实很简单dbGet [dbGet -p top.insts.name biasnw].pgInstTerms这条命令会返回该instance下所有PG terminal的名字和连接net。如果只想看VDDdbGet [dbGet -p top.insts.name biasnw].pgInstTerms.name这一招在排查PG悬空、检查power switch cell是否接对电源域时特别实用。放在这个场景里就是在批量删除buffer之前过滤掉那些PG没有正常连接的异常单元避免删完留下一堆dangling pin。3. 5分钟自动清理流程3.1 准备工作确认约束和时序收敛动手清扫之前有几个前提条件必须确认好否则后患无穷。第一确认当前postRoute的时序已经收敛尤其是hold不能还有一大批红色violation就急着清理那是拆东墙补西墙。正常流程是先把hold用optDesign修干净再进入冗余buffer清理。第二记得在清理前存一个干净的database快照。我习惯用saveDesign clean_before_buffer_cleanup.enc存一份万一删完跑完时序发现问题还能快速回滚。第三设置好清理阈值参数。我把这些参数定义在脚本最前面比如hold margin阈值、最大删除数量、buffer cell name关键字等方便根据不同项目调整。3.2 核心Tcl脚本解析整套脚本剥离掉项目定制部分以后大概长这样set holdThreshold 0.3 ;# hold slack 0.3ns 才删 set maxDelete 500 ;# 单次最多删除个数 set bufPattern {BUF*CKBD*CLKBUF*} ;# 需要匹配的buffer单元名 set deleteList {} set phcCount 0 # Step 1: 遍历所有实例按cell名粗筛buffer foreach inst [dbGet top.insts.name] { set cellName [dbGet [dbGet -p top.insts.name $inst].cell.name] if {[regexp -- $bufPattern $cellName]} { # Step 2: 获取input net和output net set inputNets [dbGet [dbGet -p top.insts.name $inst].instTerms -if {.pin.dirinput}].net.name set outputNet [dbGet [dbGet -p top.insts.name $inst].instTerms -if {.pin.diroutput}].net.name set inNet [lindex $inputNets 0] # Step 3: 物理层面验证——输入输出在同一net if {$inNet $outputNet} { # Step 4: 时序层面验证——路径hold slack足够大 # 这里调用查询hold slack映射表判断是否大于阈值 if {$holdSlackMap($inst) $holdThreshold} { lappend deleteList $inst incr phcCount } } } if {$phcCount $maxDelete} { break } } # Step 5: 批量删除 foreach inst $deleteList { deleteInst $inst } puts Totally deleted $phcCount redundant hold buffers我来说明几个关键点。第一步的regexp匹配可以根据你自己lib里buffer的命名来调整比如有些工艺叫BUF_X1/BUF_X2有些叫CKBD0BWP我建议把CLKBUF也加进去因为时钟buffer同样会变成冗余。第二步的小心点在于instTerms返回的可能是一个列表要取第一个input net作为参考。第三步是整个脚本的核心确认输入输出在同一net。第四步的时序验证其实可以用更简单的方式比如在进入循环前先跑一遍所有hold路径生成一个hold slack与buffer实例的映射表再在这个循环里查表而不是每删一个就现场跑一次时序那样会慢很多。第五步删除的时候Innovus会同时移除该实例的PG pin连接只要PG连接正常就不会有残留问题。执行完这五步再用ecoRoute把相关net重新绕一遍整个清理就算完成了。3.3 清理后处理ecoRoute与重新验证删除buffer以后工具会自动把原net断开重建但绕线资源不会立刻优化所以我会顺手跑一次ecoRoute -modifyNet 删除涉及的所有net如果你删的buffer涉及几十个net也可以直接ecoRoute不加参数做全局eco不过时间会稍微长一点。做完ecoRoute后再跑一轮optDesign -postRoute -hold做增量收敛。这一步非常重要因为删除buffer后数据路径的延时变小了哪怕我们只删那些hold slack大于300ps的buffer理论上不会产生新的hold违例但实际项目中时钟树和模块边界相互影响偶尔也会出现个别路径反弹。所以我在流程里一定会安排一次postRoute hold的增量优化。清完之后再做一次面积和功耗对比。这里有个直观的方法清理前后分别跑report_qor对比total cell area和total power。我印象最深的一次清掉两百多个冗余buffer面积直接降了1.2%漏电功耗降了大概3%这是一个很可观的数据尤其对面积敏感的芯片来说。4. 常见问题与排查技巧实录4.1 删了buffer反而报hold违例这个坑我踩过不止一次。最典型的情况是你删掉的buffer虽然输入输出net同名但它本身是某个dont care路径上的单元或者它的物理位置正好支撑了其他net的绕线布局删掉之后旁边的net绕线资源重构导致真正的hold路径变差了。解决办法是第一别贪心把hold阈值往上调只删那些hold slack非常大的buffer第二删除后必须重新跑postRoute hold优化不能删完就直接导网表第三如果违例总是集中出现在某一小片区域大概率是congestion影响建议把这片区域的buffer全部保留不要硬删。4.2 输入输出同名net但物理相隔很远脚本判断冗余的标准是input net等于output net但如果碰到那种同名net分布在两个很远物理位置的场景直接合并会有问题。比如一个buffer的输入pin在坐标(100,100)输出pin在坐标(5000,5000)虽然net name一样但中间经过复杂的绕线直接删除可能导致RC变化很大。我的经验是在脚本里加一道物理距离检查取buffer输入pin和输出pin的坐标计算欧氏距离如果超过某个值比如200um就跳过不删。代码大概是set inPt [dbGet [dbGet -p top.insts.name $inst].instTerms.pin.pt] set outPt [dbGet [dbGet -p top.insts.name $inst].instTerms.pin.pt]然后算距离这个在项目里实测有效能过滤掉大概10%到20%的“假冗余”。4.3 buffer的PG term悬空问题前面提到过删buffer前一定要确认PG连接。正常PR流程里VDD/VSS会通过globalNetConnect连接好删除实例不会造成问题。但如果你用的是某些特殊的power switch cell或者buffer在floorplan边缘有可能出现PG pin连接到dangling net上的情况。查看标准单元PG term的方法我上面讲过用dbGet选中实例的pgInstTerms。如果发现某个待删buffer的PG连接异常那就先手动处理掉或者直接跳过这个cell避免留下隐患。4.4 清理后DRC变差有些项目清理完buffer后ecoRoute跑完却冒出新的DRC violation尤其是最小面积、最小间距之类的。这是因为删除buffer后留下的空间被工具随机填充了一些小碎片metal。解决方法有两种一是单独针对清理涉及的net跑ecoRoute -modifyNet二是删完后在那一小片区域跑一次addFiller把空隙填上再重新布线。大多数情况下局部ecoRoute就能解决只有大面积删除时才需要全局处理。我个人实际操作的体会是这套流程最值钱的地方不是“删buffer”本身而是“识别哪些buffer可以删”。把PHC识别逻辑做扎实后面删得又快又安全。我通常在项目后期每跑完一版ECO就清理一次每次用时控制在五分钟以内效果很稳定。最后再分享一个小技巧清理前可以把hold阈值先设置成500ps跑一次看看删除清单里有没有你预期之外的多余buffer如果有大概率是约束或者时钟树哪里还有问题值得停下来查一查而不是急着执行删除。
延伸阅读

更多相关文章

2026/10/3 15:15:37

智慧食堂取盘机选型指南:RFID与视觉识别技术路线对比

1. 先别急着问“哪家公司”,先搞懂取盘机的技术路线 这几年跑过不少食堂改造项目,从几百人的企业食堂到几千人的高校餐厅都接触过。每次甲方开口第一句往往是“智慧食堂取盘机哪个公司好”,但说实话,这个问题没法直接回答——因为…

2026/10/3 15:15:37

手眼标定实战:用Python从零实现Ax=xB求解与闭环验证

简介:本资源是一套面向高校本科生及自动化方向初学者的机械臂手眼标定实践方案,聚焦工业机器人视觉引导中的核心标定问题,适用于毕业设计、课程设计与中小型项目开发。内容以Python为实现语言,完整覆盖标定原理推导、数据采集流程…

2026/10/3 15:15:37

淘宝API返回JSON怎么解析?五大主流语言实战对比与选型

刚接触电商数据这块的朋友,十有八九都问过同一个问题:淘宝商品详情API返回的JSON数据,除了用Python,还有没有别的语言能解析?我当年入行时也这么问过,后来才发现,这个问题背后其实藏着两件事&am…

2026/10/3 16:10:39

2026企业AI办公工具选型指南:如何评估端到端任务交付能力

数字化转型进程中,不少企业引入AI办公工具时,容易陷入功能清单对比的误区。很多团队在选型阶段只关注模型对话能力、单次文档生成效果,忽略工具能否完成从需求拆解、信息调研、方案撰写到成果交付的完整链路。部分工具仅能作为问答助手&#…

2026/10/3 16:10:39

大牌口红小样代加工,灌装温度差三度整批膏体就废了

小样代工这活儿,最怕听到客户说“跟大牌看着差不多就行”。差不多是差多少?小管径灌装,料温上下浮动三五度,膏体收缩率就变了,出来要么脱壁要么出汗。拿着大牌色卡来问价,问完嫌贵,转头找个低价…

2026/10/3 16:10:39

类—对象结构关系:面向机器认知的世界结构理论

类—对象结构关系:面向机器认知的世界结构理论资料来源:wsaios.cn 摘要本文基于WSaiOS研究框架,系统阐述类—对象结构关系理论。该理论旨在解决机器认知中的一个基础问题:抽象的类结构如何映射到现实世界中的对象结构,…

2026/10/3 16:10:39

LLM 推理内核拆解:KV Cache、Prefill 与 Decode 的优化逻辑

LLM 推理内核拆解:KV Cache、Prefill 与 Decode 的优化逻辑 一、部署大模型,先搞懂推理在发生什么 很多团队部署大模型时,只关心两件事:模型能不能跑起来、响应快不快。至于"推理过程中到底发生了什么",往往…

2026/10/3 16:10:39

Vibe Coding 开发工作流:从个人提效到团队协作的落地路径

Vibe Coding 开发工作流:从个人提效到团队协作的落地路径 一、什么是 Vibe Coding:一场编程范式的转移 Vibe Coding(氛围编程)这个概念由前 OpenAI 联合创始人 Andrej Karpathy 在 2025 年提出,核心定义是:…

2026/10/3 16:05:39

轮速传感器全解析:从原理到故障排查的底盘制动工程指南

轮速传感器这东西,底盘工程师几乎天天跟它打交道,但很多刚入行的朋友对它的理解停留在“ABS用的那个小东西”这个层面。我做了十多年制动系统零部件开发,第一次拆解轮速传感器内部结构、对着示波器看它输出波形的时候,才真正意识到…

2026/10/2 8:16:46

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/10/2 18:20:53

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/3 15:02:19

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/3 0:04:31

国内大学生必备的AI写作辅助软件是哪款?

国内高校学生在论文写作过程中,越来越依赖AI辅助工具提升效率,主流方案以本土化全流程工具为核心,结合通用大模型与专业插件,覆盖选题构思、框架搭建、初稿撰写、查重降重、格式调整等关键环节,本文将深入解析当前主流…

2026/10/3 0:04:31

Codex接入Jev模型完整指南:配置方法、本地部署与踩坑排查

最近不少人在讨论 Codex 搭配 Jev 这套玩法,我一开始没太当回事,直到自己把 Jev 接进 Codex跑了几轮编码任务之后,才明白那些说“直接起飞”的人是怎么想的。Codex 作为工具本身已经够能打了,但模型固定、上下文策略固定&#xff…

2026/10/3 0:04:31

GitHub 热门: NVIDIA/Model-Optimizer

👋 Hi,我擅长 AI 大模型应用落地、意识解码与 AI 开发工具链 。 💡 创业路上,用技术换时间,一起把 AI 变成生产力 🚀 >GitHub 热门: NVIDIA/Model-Optimizer 凌晨两点,你刚把跑通了的 Qwen3.…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑