尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Innovus ECO实战:setEcoMode配合ecoAddRepeater批量插buffer的5个关键步骤

Innovus ECO实战:setEcoMode配合ecoAddRepeater批量插buffer的5个关键步骤 做数字后端的人都知道ECO不是“会不会”的问题而是“熟不熟”的问题。流片前最后一版netlist改功能、修timing、清DRC全靠ECO这一套操作兜底。而在所有ECO动作里用ecoAddRepeater批量加buffer也就是常说的repeater insertion是我个人用得最频繁、也最容易出状况的一个。很多人以为这命令就是“选个net、插个buffer”这么简单实际跑起来才发现setEcoMode如果没设对ecoAddRepeater要么插不进去要么插进去之后把布线搞成一团乱麻。这篇文章就围绕“Innovus ECO中用setEcoMode配合ecoAddRepeater做批量buffer替换”这个组合把我自己从定位问题、配置ECO环境、批量插入到跑完DRC和timing验证的完整流程整理成5个关键步骤。无论你是刚接触Innovus的后端新人还是已经被ECO折腾过几轮的老手这份操作路径和踩坑记录应该都能直接参考。1. 先搞清楚什么场景下才需要“批量buffer替换”1.1 ecoAddRepeater能干什么不能干什么ecoAddRepeater字面意思很直白在ECO模式下给指定net插入repeater。Repeater通常是buffer或inverter核心作用是把一根长net或者高扇出net分段让每一段的电阻电容负载都落在驱动单元的承受范围内从而修复max transition、max capacitance、max fanout这类DRVDesign Rule Violation或者优化长互连的延时斜率。但要注意它不能干的事也很多它不是用来做gate sizing的。想把BUFX4换成BUFX8应该用ecoChangeCell而不是删掉旧cell再插个新的。它不是用来改逻辑功能的。功能改动要靠ECO的netlist update流程ecoAddRepeater只能加物理buffer不会改变netlist逻辑。它默认不会去动clock tree。时钟树上的net有特殊属性盲目插buffer会破坏CTS结果后面我会单独讲。很多人一上来就批量插buffer结果发现插完以后timing报告里出现一堆新的违例问题往往不是ecoAddRepeater本身而是没有搞清楚这个命令的边界。1.2 实践中最常见的三种触发场景从我经历的项目看批量buffer替换通常来自以下三个场景场景A功能ECO之后的长net修复。前端在流片前改了逻辑后端用eco -read_file读入新netlistECO place和ECO route之后某些新加的net跨越了大半个blockslew和cap直接爆表。这种时候不可能手工一条条去绕批量插buffer是最快的收敛手段。场景BECO route之后的DRV批量回修。ECO route本身为了减少对原有布线的影响往往会牺牲部分绕线质量跑完report_design_rules满屏的max transition和max cap违例。此时用ecoAddRepeater批量插repeater配合ecoRoute重新走线是标准操作。场景Ccell替换引入的负载失衡。有时候为了修timing把drive能力弱的cell换成了强驱动cell但强驱动cell的输出电容规格可能和原来不同导致相邻net出现新的DRV。这种局部问题虽然量不大但积累起来也需要批量处理。1.3 为什么必须和setEcoMode一起用setEcoMode是用来设定当前ECO操作全局行为的命令可以理解成“接下来这段时间工具以什么模式工作”。ecoAddRepeater只是在这个模式下的一个具体动作。两者关系可以类比成setEcoMode是设置相机的手动模式和参数ecoAddRepeater是按快门拍照。你按快门的姿势再标准模式没设对拍出来的照片一样是糊的。具体来说setEcoMode里的-routeEco、-physicalCellOnly、-honorDontTouch、-updateTiming这些选项直接决定了ecoAddRepeater在执行时允不允许工具顺手改走线能不能动那些被标记了dontTouch的cell和net插入buffer后要不要立刻更新timing数据库插入的新cell要不要遵守blockage和region约束。所以“批量buffer替换”从来不是一条命令的事而是一个“环境配置 执行 验证”的完整流程。这也是我接下来要展开的5个关键步骤的核心逻辑。2. setEcoMode参数逐项拆解设错一个后面全白干2.1 -routeEco与-physicalCellOnly的真实含义这两个参数是setEcoMode里最容易被误用的一对。先看官方语义-routeEco true|false是否允许ECO流程在需要时对布线层进行修改。如果设false所有ECO动作都只能在现有布线基础上做加法不能重绕已经存在的金属线。-physicalCellOnly true|false是否只允许物理层面的改动加cell、挪cell而禁止netlist逻辑层面的改动。很多人设完-routeEco true以后以为万事大吉却忽略了-physicalCellOnly可能还是默认的false或者反之导致工具在你不想让它改逻辑的时候改了logic或者在你需要它自动修连接关系的时候它什么都不动。我个人的经验是如果只是单纯的buffer插入不涉及netlist功能变化那应该用setEcoMode -physicalCellOnly true -routeEco true这个组合的含义是“只做物理改动但如果需要允许重新走线”。这样ecoAddRepeater插入的buffer能正常打上PG和连线同时工具不会擅自动netlist逻辑。如果连走线都不希望动得太厉害比如conflict zone里已经有手动绕好的关键线那就保守一点setEcoMode -physicalCellOnly true -routeEco false代价是ecoAddRepeater之后新增buffer的pin可能连不上需要你额外手动ecoRoute或者接受部分net的DRC不干净。2.2 容易被忽略的辅助选项honorDontTouch、updateTiming、fixDrc除了上面两个下面几个选项在批量场景里非常关键-honorDontTouch true默认情况下工具会尊重cell和net上的dontTouch属性。批量选取net的时候如果你用get_nets -hier抓到的net里混了dontTouch标记ecoAddRepeater会全部跳过并报warning。反过来如果你确实想强制插入可以在ecoAddRepeater上加-honorDontTouch false但这非常危险尤其不能用在clock net和dontTouch的保护cell上。-updateTiming true|falseECO过程中是否增量更新timing。批量插几百个buffer的时候如果每次插入都实时更新全量timing速度会非常慢但完全关掉最后你又得额外花时间重新提取RC和跑timing。实际项目里我会在批量阶段关掉最后统一更新前提是net数量可控。-fixDrc true|falseECO结束以后是否自动调用工具内部的DRC修复。这个选项和省心的程度成正比但也会让工具多花不少runtime。如果batch里插buffer的位置比较紧张建议打开让工具在插入阶段就规避一部分short和spacing问题。这些选项没有绝对正确的组合完全取决于你当前design的状态和你希望ECO对现状的扰动程度。但有一点是共通的在批量执行之前先拿两三根net做单条实验把选项组合的预期行为确认好再全量跑。2.3 一套可复用的ECO环境配置参考以我自己用的配置为例不涉及具体工艺只讲套路# 批量buffer插入前的ECO环境 setEcoMode \ -physicalCellOnly true \ -routeEco true \ -honorDontTouch true \ -updateTiming false \ -fixDrc true \ -allowFillerRemoval true \ -maxChanges 10000几个细节说明-allowFillerRemoval trueECO插入新cell需要空间如果filler挡路工具可以把filler挪走。这个在density高的block里几乎是必开的。-maxChanges 10000限制单次ECO最大改动量防止工具发疯全盘重排。具体数值根据block规模调整。如果当前design还在早期place还不太紧张-updateTiming true也可以开这样每次插入后工具会维护增量时序数据最后的验证负担小一些。还有一个容易被忽略的动作跑ECO之前保存一个独立的database副本。很多工程师习惯直接在working database上操作结果ECO出问题想回退只能从一个小时前的floorplan重新来。我的做法是ECO前先saveDesign eco_before_buffer_insert跑完确认无误再删。3. ecoAddRepeater批量替换5个关键步骤实操3.1 第一步锁定目标net清单并分级这一步的核心是搞清楚“到底哪些net需要插buffer”以及“这些net分别属于什么优先级”。通常我这样抓net# 抓所有违反max transition / max capacitance的driver pin set vio_nets [get_nets -of_objects [get_pins -hier -filter max_transition_violation ! 0]] append_to_collection vio_nets [get_nets -of_objects [get_pins -hier -filter max_capacitance_violation ! 0]]如果你已经有timing报告或者report_design_rules输出文件更稳妥的方法是写脚本从report里解析net名因为Innovus的collection接口在不同版本里filter字段名略有差异直接照抄网上老脚本很容易抓空。拿到net清单后不要急着全量插入先分级P0级clock net、dontTouch net、macro pin直连net。这些要么不能动、要么动了要格外小心建议排除或者单独手工处理。P1级长距离跨block的data netslew/cap严重违例优先处理。P2级轻度违例、边界情况的net可以批量处理但需要更保守的buffer尺寸。分级的目的很简单避免批量操作把风险放大。尤其P0级一旦在clock net上误插了bufferCTS全部作废那可不是重跑一次CTS的问题是整轮ECO都要推翻的问题。3.2 第二步组好setEcoMode环境并验证用上一节的配置把ECO模式设定好然后拿第2~3根net做试验setEcoMode -physicalCellOnly true -routeEco true -honorDontTouch true -updateTiming false -fixDrc true ecoAddRepeater -cell {BUFX4 BUFX8} -net $test_net -numRepeaters 1 -prefix ECO_BUF跑完以后不要急着看结果先做三件事ecoPlace看新cell能不能合法放下去ecoRoute -modifyOnly看pin能不能连上report_design_rules -check max_transition,max_capacitance看这个net的DRV有没有改善。这三件事确认没问题再决定全量跑。千万不要跳过这个试验步骤我见过太多人全量跑完才发现buffer尺寸选小了slew一点都没改善白耗几个小时。3.3 第三步构造ecoAddRepeater命令ecoAddRepeater的完整语法在不同版本里略有区别但核心参数基本稳定。我常用的形式是ecoAddRepeater \ -cell {BUFX4 BUFX8 BUFX12} \ -net $net_list \ -numRepeaters 1 \ -prefix ECO_RPT_ \ -skipPinAssignment逐个解释我为什么这么写-cell {BUFX4 BUFX8 BUFX12}候选buffer列表。工具会根据负载情况自动选一个合适的尺寸。列表里最好放2~3个尺寸等级不要只给一个否则工具没有选择空间可能插进去一个过大的buffer造成面积浪费或者过小的buffer根本没效果。-net可以接单个net名也可以接一个collection。批量场景里接collection是常规操作。-numRepeaters 1每个net默认插1个repeater。如果你的net特别长需要插多个可以设成2或3但注意插入数量越多对布局资源的消耗越大后续congestion风险越高。-insertionMode这个参数控制repeater插入位置的计算策略。网上很多老帖子给了具体模式编号但不同版本支持的数值不一样我的建议是先用工具默认值确认有效再考虑微调别照抄旧版本的数字。-prefix ECO_RPT_给新增cell统一加前缀方便之后get_cells ECO_RPT_*快速选中和过滤也能避免和设计中已有cell重名。选cell的时候Innovus支持通配和层级匹配有了统一前缀后面get_cells -hier ECO_RPT_*一下就能把所有ECO buffer抓出来省很多事。-skipPinAssignment跳过插入时的pin分配让工具在place阶段统一处理。批量场景下这个选项能省不少runtime。还有两个经常用到的选项-honorDontTouch false默认true。除非确认net安全否则不要关。-loc {x y}手动指定插入位置。单条net调试时好用批量场景基本不用。3.4 第四步批量化执行的脚本写法批量化的核心不是把net名堆在一条命令里而是做好三件事筛选、循环、留日志。推荐用文件驱动的脚本结构。先把第一步筛好的net清单写成文本文件每行一个net名然后脚本读入并循环执行set fp [open eco_buf_nets.list r] set net_list {} while {[gets $fp line] 0} { if {[string trim $line] eq } { continue } # 按名字精确抓net避免通配符误抓 set n [get_nets -quiet [string trim $line]] if {$n ne } { lappend net_list $n } else { puts WARNING: net $line not found, skipped } } close $fp set num 0 foreach n $net_list { # 排除dontTouch和clock net不同版本接口有差异用dbGet或filter实现 if {[dbGet [dbGet -p top.nets.name $n].isClockNet -quiet]} { continue } if {[get_net_attribute $n dont_touch] true} { continue } ecoAddRepeater -cell {BUFX4 BUFX8} -net $n -numRepeaters 1 -prefix ECO_RPT_ incr num # 每50根net打一次进度 if {[expr {$num % 50}] 0} { puts INFO: processed $num nets } } puts INFO: total processed $num nets这段脚本有几个细节值得注意用文件驱动而不是直接在内存collection上循环好处是可追溯、可重跑。哪根net没插入、哪根net找不到都有log可查。每次循环都检查isClockNet和dont_touch这是第二道保险。即便第一步已经筛过保不齐中间有net属性被改过。每50根net打印一次进度批量几千根net的时候你能知道脚本跑到哪里了不会干等。如果你担心一次性跑完出问题不好回退可以每500根netsaveDesign一次出问题从最近checkpoint重来而不是整个ECO推倒。另外关于并行Innovus的ECO建议在同一个session里串行执行不要自己开多线程同时跑ecoAddRepeater。工具内部的database操作不是为并发设计的多线程同时写database会出各种诡异问题比如cell重复、net断连。真要并行按block或者partition拆分再用merge流程合并那是另一个层面的话题了。3.5 第五步ECO后验证与收尾批量插入buffer以后并不意味着大功告成。以下几步一个都不能少1. 布局合法化。ecoPlace -coarse -noLegalize legalizePlacement如果插入数量不大直接legalizePlacement就能搞定。插得多了建议先ecoPlace -coarse让工具把新增cell放到大致位置再legalize速度和成功率都更好。2. 布线ECO。# 只重绕新插入buffer相关的net避免动到无关走线 ecoRoute -modifyOnly [get_nets ECO_RPT_*]-modifyOnly表示只重绕和新cell相关的net避免动到无关的既有走线。这个参数在ECO里特别重要因为ECO的基本原则就是最小扰动——你没有动到的net不应该因为这次操作被重新绕线否则回归验证的成本会无限放大。3. Filler补齐。ECO插buffer会挪走fillerECO结束后需要重新加filleraddFiller -cell {FILLER1 FILLER2 FILLER4} -prefix ECO_FILLER注意这里和普通physical signoff时的addFiller是一样的但加完以后一定要检查PG connection。尤其如果工艺里有metal filler或者decap filler的区分别加错类型。用dbGet按名字筛选标准单元、查看PG term的时候要养成先确认库单元属性的习惯防止把不带PG的decap cell当成普通filler用。4. DRC检查。check_design -checks all_drc verify_drc -limit 1000批量插buffer最容易在插入点附近产生short和spacing违例特别是density高的区域。如果DRC爆出来一堆错先别慌按区域聚类大概率是某几个buffer插到了pin access不好的位置手工挪一下或者用ecoPlace -modifyOnly微调就能解决。5. Timing和DRV回归。extractRC report_design_rules -check max_transition,max_capacitance,fanout \ -violation_only -format text report_timing -slack_max 0.0 -net -format full重点确认两件事一是原本要修的DRV确实修掉了二是没有产生新的严重timing违例。批量插buffer修了远端slew往往会让近端的load变大、arrival变差所以timing回归是必须的。到这里一轮标准的“setEcoMode ecoAddRepeater批量buffer替换”才算真正落地。4. 实测踩坑批量buffer替换的4个高频问题与排查链路4.1 ecoAddRepeater报了“no location found”却找不到原因现象ecoAddRepeater执行以后log里一堆No legal location found for repeater的warningnet也没修好。排查链路先看是不是blockage挡路。用report_placement_blockages -box ...把目标net附近的placement blockage打出来。ECO插buffer的合法位置必须避开blockage、halo、region约束。高density区域里filler和已有cell把空间占满了自然没有地方放新cell。再看是不是-insertionMode或者net的几何形状导致工具找不到一个好的插点。长net如果走线路径上有大量congestion工具计算出来的插入点全在非法区域也会报这个错。我的处理习惯先打开GUIhighlight -net $net_name眼睛看一下这根net的形状和周围拥挤程度。如果是congestion问题把-cell列表里加一个尺寸更小的buffer比如BUFX1或者用ecoAddRepeater -loc手工指定一个空闲位置往往就通了。4.2 插完buffer以后DRC一片红现象batch跑完verify_drc报出几百个short和min spacing违例集中在ECO buffer附近。排查链路先用dbGet或者GUI定位DRC的具体坐标看是不是所有违例都紧挨着新插入的buffer。如果是十有八九是插入时工具没有考虑routing blockage或者pin accessbuffer的A/Y pin落在了被阻挡的金属层上。解决办法有三条路检查是不是setEcoMode -routeEco false导致的。这种情况下新cell的pin根本没有走线资源必须打开routeEco并重新ecoRoute。检查blockage是否把buffer周围的routing track全挡住了。设计里经常有routing blockage保护关键走线ECO插buffer前要先确认目标区域routing blockage的分布。手动把问题buffer挪一挪再用ecoRoute -modifyOnly重新绕那一小片。DRC问题不能靠硬扛一定要从根上找原因。批量修DRC里的经验是先抓一个点分析清楚再去看分布规律最后才是批量修。一上来就批量ecoRoute大概率把原来的好线也重绕了回归验证会很痛苦。4.3 重复ECO后buffer重叠、cell重复现象同一个block里跑了好几轮ECO每次插的buffer都带不同前缀结果某片区域cell密度爆表、重叠严重。原因上一轮ecoAddRepeater插入的buffer在下一轮ECO里没有被正确识别和复用。很多人直接用新的-prefix插新buffer旧buffer还留在原处越积越多。正确的做法下一轮ECO开始前先确认上一轮的ECO buffer哪些还有用。用get_cells ECO_RPT_*把所有ECO buffer抓出来逐个检查timing和DRC。已经没有用的buffer用ecoDeleteRepeater -cell $unused_eco_buf删掉再重新插。如果只是尺寸不合适BUFX4要换成BUFX8不要删了重插用ecoChangeCell -inst $eco_buf -cell BUFX8这样保留物理位置只换master对周边影响最小。这个坑的本质是ECO操作要像代码提交一样有可追溯性。每次ECO的改动记录、cell列表都要留档否则几轮迭代下来设计中堆满了历史遗留的ECO cell谁都说不清楚哪些该留哪些该删。4.4 插完buffer timing反而更差现象DRV修掉了但setup或者hold的slack比ECO之前更差。原因buffer把net分成两段第一段的负载虽然小了但buffer本身的cell delay加进了路径第二段如果buffer选小了驱不动后面一大片负载slew反而更差。另外插buffer带来的绕线长度变化也会改变RCnet delay不一定变小。排查链路先report_timing -from $driver -to $sink -net -delay看每一段的delay分解。重点看buffer input到output的cell delay以及前后两段net的RC delay。如果是buffer cell delay占了太大比重说明buffer尺寸偏大或偏小。尺寸偏大输入cap大前一段delay变大尺寸偏小输出驱动不够后一段slew差。处理方式把-cell列表换成更合适的尺寸组合重新跑减少-numRepeaters一个buffer能解决的就不要插两个如果某个特定net反复出问题单独用-loc手工指定插入位置放在net的中点附近物理中点不是绕线中点通常delay分配最均衡。还有一个常被忽略的点ECO buffer的VT类型。默认ecoAddRepeater会选库里的标准VT buffer如果是在关键路径上可以考虑用HVT或者LVT的buffer来微调delay。用-useLibCell可以指定具体cell比如ecoAddRepeater -cell BUFX8_LVT -net $n -numRepeaters 1 -useLibCell BUFX8_LVT但这种做法会让ECO buffer列表复杂化建议只在关键路径的局部net上手工用。5. 从单次操作到可复用的ECO流程5.1 一套可以直接落地的脚本框架把前面5个步骤串起来我一般会组织成三个文件文件1eco_buf_config.tcl放setEcoMode和公共变量set ECO_BUF_CELLS {BUFX1 BUFX4 BUFX8} set ECO_BUF_PREFIX ECO_RPT_ set ECO_NET_LIST eco_buf_nets.list set ECO_BEFORE_DB eco_before_buffer_insert setEcoMode -physicalCellOnly true -routeEco true \ -honorDontTouch true -updateTiming false \ -fixDrc true -allowFillerRemoval true文件2eco_buf_insert.tcl放循环插入逻辑就是前面那段脚本略作完善。文件3eco_buf_verify.tcl放验证逻辑ecoPlace -coarse -noLegalize legalizePlacement ecoRoute -modifyOnly [get_nets ${ECO_BUF_PREFIX}*] addFiller -cell {FILLER1 FILLER2 FILLER4} -prefix ECO_FILLER check_design -checks all_drc report_design_rules -check max_transition,max_capacitance -violation_only report_timing -slack_max 0.0执行的时候source eco_buf_config.tcl source eco_buf_insert.tcl source eco_buf_verify.tcl这套框架的好处是第二次、第三次用的时候只需要更新net list和cell列表不用重写脚本。而且每个文件职责清晰出了问题能快速定位是哪一步的锅。5.2 和周边ECO命令的搭配批量buffer替换很少是孤立操作它经常和以下命令一起出现ecoChangeCell替换已有cell尺寸适用于gate sizing场景。ecoDeleteRepeater删除不再需要的repeater配合addRepeater使用。ecoPlace -modifyOnly只挪动指定cell保持其它cell不动。ecoRoute -modifyOnly只重绕指定net。addFiller -ecoECO后的filler补齐。一个常见的工作流是先用ecoChangeCell把关键路径上的cell尺寸调整一遍再用ecoAddRepeater修剩余的长net DRV最后ecoRoute -modifyOnly addFiller收尾。这套组合拳能覆盖后端ECO里绝大部分的timing和DRV修复需求。5.3 我的几点个人体会做ECO这么多年最大的体会是ECO不是炫技而是最小代价解决问题。每次做ECO之前我都会问自己三个问题这次改动真的有必要吗改动范围能不能更小如果出了问题能不能快速回退批量buffer替换看上去是个体力活但真正拉开工程师差距的恰恰是setEcoMode里那几个看似不起眼的选项以及你对net清单的筛选和分级能力。把每一步都留好日志、存好checkpoint比任何高级技巧都管用。还有一个小技巧批量插入完成后记得用setDontTouch把已经确认没问题的ECO buffer保护起来防止后续其它ECO操作把这些buffer又挪走或者替换掉造成二次污染。这一步很多人不做等到下一轮ECO跑完才发现上一轮的buffer全被动了那种返工真的是欲哭无泪。
返回列表