ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

数字IC后端DRV修不动?先查dont_touch属性再查congestion

数字IC后端DRV修不动?先查dont_touch属性再查congestion 做数字IC后端的人大概率都经历过这种场面跑完route_opt打开report密密麻麻一排DRV违规数量不多不少477条net。你反复跑了三轮optDesign -drc违规数纹丝不动连status都懒得变化。这种时候千万别急着怀疑congestion或者floorplan先停下来想一个问题工具到底是修不动还是它被禁止去修DRV问题在PR阶段太常见了但大面积、持续、无法修复的DRV九成以上不是物理问题而是属性问题。我那次项目中把477条net全部翻出来之后发现它们的共同点是全都挂在几个被打上dont_touch的hierarchy上。正是dont touch hierarchy这个用来锁定网表的属性把工具修复DRV的手脚全绑住了。这篇文章就把这个case拆开聊DRV到底是什么、dont_touch怎么阻止优化、如何快速定位以及怎么安全地解除封锁把违例清掉。1. 先搞清楚DRV到底是哪一种违例1.1 后端工程师口中的DRV通常指哪些指标首先统一一下概念。PR工具里报的DRV全称是Design Rule Violation但在物理实现和STA语境下它跟你做DRCDesign Rule Check查metal spacing、min width是两码事。工具报的DRV一般特指三种约束违例max_transition信号翻转沿的最大允许时间也就是slew不能太慢。max_capacitance驱动pin能带的总负载电容包括线电容和扇出pin电容。max_fanout驱动单元允许连接的扇出数量。这三个值在lib库里一般有默认定义同时SDC里也可以通过set_max_transition、set_max_capacitance、set_max_fanout覆盖。工具在place、CTS、route阶段会不断检查并在优化中修复这些违例。max_transition和max_capacitance是最常见的两类DRV。transition太慢会影响时序计算准确性也增加短路功耗capacitance超过驱动能力极限信号上升时间只会越来越差。修DRV的手段也基本固定加buffer、增大驱动cell尺寸、调整逻辑结构、pin swap等。说白了必须动网表。1.2 477条net这个量级能说明什么先给个直观感觉。一个百万门级SoC顶层几千条net实在太正常。477条net的DRV违规如果均匀散布在整个die上其实是个很小的数字工具大概率几轮就修完了。真正要警惕的是两个特征违规数量在多次优化后完全不变或者只增不减。这些net在hierarchy路径上有明显的集中趋势比如都集中在某几个子模块的边界上。出现这种局面第一反应应该是工具真的想修但它没有权限去碰这些net。换成人话就是你的网表上某些地方被贴了禁止入内的标签工具优化引擎跑到那儿就绕道走只负责记录违规不负责处理。477条这个数字在这种场景下非常典型——它不是几百条net恰好都有物理问题而是几百条net恰好都受了同一个属性开关的管控。2. dont_touch hierarchy是如何把网表焊死的2.1 dont_touch属性从哪里来又是怎么传下去的dont_touch是综合和后端实现工具里一个很常见的属性目的是告诉工具这个对象你不要乱动。它经常出现在这几个地方综合脚本里为了锁定某个单元或者某个模块的网表结构使用set_dont_touch。集成第三方IP时为了保证IP网表和交付版本一致对整个IP instance加dont_touch。时钟约束里对clock net设置dont_touch或dont_touch_network防止CTS和优化工具修改时钟路径。memory、PLL、IO等特殊单元为了保持库提供商的reference netlist不被改动也会加dont_touch。最容易被忽略的是属性传递性。虽然dont_touch可以分别设置在instance、net、design、reference等不同对象上但一旦对一个hierarchy instance设置了dont_touch很多工具会默认它内部的cell和net也全部继承保护。尤其在一些集成流程里脚本喜欢写set_dont_touch [get_cells xxx]一口气把整个IP锁住那这个IP内部就是铁板一块。我曾经排查的时候做过对象级别的对比这里直接列出来属性设置对象工具会被限制的操作典型命令instance/hierarchy禁止改变内部cell尺寸、插buffer、逻辑重组set_dont_touch [get_cells u_ip1]net禁止改变该net的拓扑结构、插入bufferset_dont_touch [get_nets xxx]design/reference禁止对整个设计做跨边界优化set_dont_touch [current_design]2.2 为什么工具对dont_touch的net只报不修要理解修不了的根因得先看工具修DRV到底要做什么。就拿最简单的一条max_capacitance违规来说负载太高工具通常两个选择把驱动cell从低驱动强度换成高驱动强度也就是upsize。在net中间插入一个或几个buffer把大的扇出拆成几段每段负载降下来。这两种操作都必须改网表。upsize要求工具能替换cell type插buffer要求在net上增加新的cell和连线。而dont_touch属性的作用恰恰就是把这类网表改动全部禁止掉。工具在优化阶段看到dont_touch对象会把它放进一个受保护列表内部引擎不会对这些对象做任何sizing或insertion操作。它不会停下来说这里修改不了而是非常安静地把这条net跳过。最后你看到的报告就是DRV数量还在工具显示eco完成一切正常但违例原封不动。如果你手动修比如打开ECO工具在hierarchy边界硬插一个buffer工具会直接报类似instance is inside a dont_touch hierarchy的错根本落不下去。这个场景很像你把一个抽屉彻底封死了机械臂要整理抽屉里的东西它只能看着然后告诉你里面不整齐但你问它为什么不整理它回答不了因为它连把手都碰不到。3. 定位根因不查属性先查congestion会走弯路3.1 第一步从报告里看共性遇到大面积修不动的DRV第一件事不是打开GUI看布局而是先分析报告里的net分布。我当时写的脚本很简单把report出来的违规net做三件事按hierarchy前缀分组统计每一组数量。区分违规类型是max_transition还是max_capacitance。标记这些net是否是某个IP/hierarchy的输出端口或内部节点。477条net做完分组之后规律立刻出来了其中410条集中在同一个hierarchy下面另外几十条分散在这个hierarchy的边界net上。这个信号非常明确——问题大概率出在这个hierarchy本身而不是整颗芯片。同时再看一眼这些net的驱动cell和负载cell。如果驱动cell是IP内部cell负载cell在顶层那就基本可以断定工具的优化引擎被block挡在hierarchy外面只能眼睁睁看着IP输出口的驱动能力不够、顶层负载又拉高。3.2 第二步用工具命令实锤dont_touch定位到具体层次之后下一步就是用工具命令确认dont_touch属性。不同工具命令差异很大我这里讲思路你对应自己环境里找命令。在ICC2里可以先用report_dont_touch看整个设计有哪些dont_touch对象再用类似这样的过滤找到受影响的netget_nets -hier -filter full_name ~ *u_ip1* dont_touch true在Innovus里可以用dbGet体系去查net或者inst的dont_touch状态dbGet top.nets.isDontTouch dbGet top.insts.isDontTouch更直接的做法是在GUI里把477条违规net高亮再叠加dont_touch对象高亮两条高亮如果高度重合实锤基本就落地了。命令名字不重要关键是脑子里要有这个判断路径先查属性再查物理。3.3 第三步把其他常见原因排除掉dont_touch是最常见的修不掉原因但它不是唯一原因。为了不被自己的判断带偏我当时把下面几个因素也一起排掉了约束设得是否不可实现。比如set_max_transition 0.02ns但标准单元库里即使最小尺寸的cell也做不到这么快的slew。此时工具无论怎么修transition都降不到约束值以下。这种情况可以通过放宽约束后重跑一版来验证。buffer/inverter库是否被dont_use禁用。如果link library里buffer本来就不全或者被set_dont_use禁掉工具在修DRV时没有可用的插入cell结果也是修不动。面积利用率过高、局部congestion严重。工具想插buffer但找不到位置DRV也无法修复。这种情况和dont_touch的区别是它会尝试修但修不完一版跑完违例数量会变化而不是完全不变。加密IP或者只读网表。有些IP交付时已经encrypt内部结构不可见也不能改这在物理上就等效于一个超大dont_touch。我那次排查到最后还把违规net临时解除dont_touch跑了局部ecoDRV数量马上往下掉。这一步能直接证明根因就是属性保护而不是物理实现能力不够。4. 修复思路与操作从全局锁死到局部放行4.1 方案一定位到hierarchy精准解除dont_touch明确根因之后最直接的修复方案就是在PR流程里精准解除对应hierarchy的dont_touch。操作上不是简单地把所有dont_touch删掉而是要做范围控制。先向上游确认这个IP能不能动。如果IP是内部团队交付的一般会有一个physical ECO授权的概念——逻辑功能不能改但允许后端工具做cell sizing和插buffer来满足物理实现。拿到授权之后在PR脚本里把目标instance的dont_touch移除# ICC2示例思路 set_dont_touch [get_cells u_ip1] false# Innovus示例思路 set_dont_touch u_ip1 false然后重新跑一轮optDesign -drc或者route_opt。工具会立刻开始对它之前不敢碰的区域做优化该插buffer插buffer该upsize的upsize。我那次解除之后跑了不到半小时477条net清零了380多条剩下的靠再一轮迭代就收干净了。这里有个细节容易踩坑有些脚本是综合阶段生成的网表里带着dont_touchPR读入网表的时候属性已经长在网表上了。你需要在place之前就处理掉或者至少在DRV修复之前处理。如果已经跑完了CTS再解除属性工具对内部cell做size调整可能会引入hold问题后续还得补一轮hold fixing。4.2 方案二只放行net保留内部cell保护有些场景不允许解掉整个hierarchy的dont_touch比如IP内部结构需要严格保持但允许在边界上插buffer。这种情况下可以把保护粒度细化到net层面。思路是instance仍然保持dont_touch但把该hierarchy下面所有net的dont_touch属性移除。工具在看到net没有保护后依然不能改内部cell尺寸但可以在net上插入buffer等于在物理层增加驱动级。这样逻辑网表层面IP内部大体没动相关路径延迟增加不会太夸张。当然这种中间态方案修复能力有限。如果违例是IP内部某个大扇出net本身驱动不足仅靠边界插buffer是解决不了的。如果477条net大部分是IP输出口到顶层负载的边界net那这个方案就非常好用。4.3 方案三上游配合从网表和约束源头解决如果时间允许更好的方式是让上游在交付前就把问题解决掉。我当时通过排查报告发现这批IP在单独跑flow的时候并没有DRV问题是在顶层集成以后才出现的。原因是顶层SDC约束更紧而且顶层布线负载更大IP输出口的驱动能力按standalone场景设计到了顶层就不够用了。正确做法是IP团队交付前处理掉边界net的DRV或者至少在交付时明确告诉后端团队哪些hierarchy加了dont_touch、为什么加、是否可以放开。如果IP确实不能动内部逻辑那就要在顶层约束里合理设置边界net的max_transition/max_capacitance而不是直接套用一个全芯片统一值。另一个上游方案是在综合导出网表时就把dont_touch粒度拆细。比如只锁IP内部逻辑单元但边界上的输出级寄存器/buffer不锁给后端留出优化空间。这些需要前后端流程配合但对收敛效率提升非常明显。4.4 修复后的回归验证不能省DRV不再报违例只是第一步改网表之后的验证才是重点。不管用了哪种修复方案至少要做三件事形式验证确认ECO前后的网表逻辑等价。工具插buffer、交换pin通常不会改变逻辑但万一工具在优化时把一个cell的功能替代错了形式验证能兜住。STA回归DRV修复很可能影响路径延迟特别是upsize会增大cell面积和功耗但也会改变transition从而导致setup/hold变化。跑完修复之后重新看所有path的slack。物理检查插了buffer之后局部congestion可能变化尤其要检查插buffer区域有没有routing short或blockage违例。我当时还额外做了一步把修复前后的netlist diff打出来给前端团队review。确保所有改动都可以解释而不是黑盒里出来的大网表。这一步在流片前的ECO里尤其有用。5. 常见问题与避坑经验5.1 现象与排查方向速查表现象可能原因排查思路大量DRV集中在某个hierarchy多轮修不掉该hierarchy被加dont_touch优先查dont_touch属性而非congestion工具log里有cannot fix / skipped due to dont_touch字样net或cell受保护在log里搜dont_touch关键词追根溯源手动ECO插buffer报hierarchy protectedinstance级dont_touch确认保护范围或改用方案二只放行net时钟网络上DRV高工具无法修clock net被set_dont_touch_network误伤区分dont_touch和dont_touch_networkCTS前处理放宽max_transition限制后DRV立即减少约束不可实现对照库的最小transition能力确定约束合理性工具尝试修但每次违例数量都有变化局部congestion或buffer资源不足看congestion map确认面积利用率5.2 我踩过坑后总结的三条规律第一条先查属性再查物理。这个优先级要刻在脑子里。我见过太多人拿着DRV报告直接盯congestion map和floorplan折腾了一两天才发现罪魁祸首是网表里一个不起眼的dont_touch。查属性最快的方法不是GUI点来点去而是在日志里直接搜dont_touch和cannot fix工具其实早就告诉你了。第二条dont_touch不是只有综合脚本才有。很多物理实现工程师不知道导入第三方IP的网表时IP自带属性也会带进来。你要把report_dont_touch当成前期flow的例行检查项在place之前了解清楚整个设计哪些区域是不能动的。这样一来后期DRV乱飞的时候你心里早有一张受保护区地图。第三条修DRV的ECO改动要留痕。无论你解除了哪个hierarchy的dont_touch插了哪些buffer都建议用一个ECO log文件记录下来。流片前跑ECO freeze的时候这些记录能帮你快速判断当前netlist相对golden netlist改了什么也方便做formal verification的setup。我自己在项目里把这一套流程完整走下来之后最大的感受是后端遇到匪夷所思的DRV数量时最先排除的往往不是物理问题而是那些写在约束文件前几行、看起来人畜无害的dont_touch。它能把工具半个身体锁住而报告只会告诉你结果不会告诉你原因。如果你也遇到类似的场景别急着怀疑floorplan先花半个小时把属性和约束翻清楚很多修不掉的违例其实只是没被允许去修而已。
返回列表