ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Innovus cell前缀全解析:从ECO到物理优化的必备指南

Innovus cell前缀全解析:从ECO到物理优化的必备指南 1. 从一次深夜ECO说起为什么你必须看懂cell前缀先讲个真事。前两年做一颗28nm的IoT芯片后端已经跑到signoff前的ECO阶段我需要在一条关键路径上插两级buffer修hold。按习惯我直接调了库里名字最短的BUF跑完innovus的verify_drc屏幕上刷出一片violation——都是min period和extra spacing的问题。当时第一反应是约束写错了抱着log啃了半天最后才发现问题出在我用的那颗cell根本不是普通buffer而是一颗带power switch功能的特殊单元。它的前缀和我平时用的完全不同但因为我只看了名字短短的几位就直接调用了整个ECO网表等于被污染了。那次之后我养成了一个习惯在Innovus里动手之前先把当前库里的cell前缀摸一遍。这个习惯救了我好几次。实际上数字后端工程师每天面对成千上万个cell实例这些名字看起来就是一堆随机字母组合——DFFQXLX4、BUFX12M、CLKAND2X3、ISO_LATCH_1、TIEHI_1……但每一段前缀都在告诉你这个cell的真实身份、电气特性、物理约束和它在flow中的角色。读不懂前缀等于在赌运气。这篇文章我想把Innovus里那些高频出现的cell前缀做个系统梳理并且把这些前缀和物理优化的实际动作串起来。我会按照前缀是什么—每个前缀背后对应什么物理行为—在Innovus里怎么利用前缀信息做决策—实战中踩过的坑这条线来写。适合正在做数字后端实现、跑ECO、或者用Innovus做物理优化的工程师参考也适合刚入行的朋友建立一个系统的查字典思路。先说清楚一点不同工艺库、不同foundry的cell命名差异很大但命名逻辑高度相似。理解了套路换库不慌。2. 高频cell前缀分类速查工具和设计之间的暗号2.1 时序单元DFF/LATCH/SDFF家族这是最常见的一类。标准单元库里以DFF开头的基本都是D触发器但DFF后面跟什么后缀决定了这个触发器的行为完全不同。DFFQ开头带Q输出的普通D触发器。比如DFFQXL、DFFQX1、DFFQX2XL和X1/X2表示驱动强度不同。DFFR或DFFS带异步复位或异步置位的触发器。R一般指resetS一般指set。SDFF扫描D触发器也就是带scan mux的型号。做DFT插入的时候用的就是这类前缀里带S的必须留个心眼——它比普通DFF在D端多了一个scan mux面积和延迟都有代价。LATCH锁存器在MCU和低功耗设计里很常见特别是level-sensitive的模块。LAT、LH、LT这类前缀都要认识。EDFF、SEDFF、REDFF这类带enable的触发器时钟门控和流水线控制里经常出现。Innovus里跑时序分析时如果发现某条路径的起点单元是SDFF而你不认识极易误判它的clock-to-Q延迟。SDFF的CLK端负载比普通DFF更重因为它内部除了主触发器还要驱动scan mux选择逻辑。我第一次做DFT的时候就觉得奇怪为什么同样一段逻辑scan_mode拉起来之后setup变差那么多后来才发现SDFF不同模式下延迟模型完全不同。2.2 组合逻辑BUF/INV/CLK系列Buffer和Inverter是后端工程师玩得最多的单元。但它们的命名远不止BUF和INV两种。BUF普通buffer一般用于信号修复、长互连驱动、树形结构。INV反相器驱动能力强、延迟小是修hold和skew的常用工具。CLKBUF/CLKINV时钟专用buffer和反相器。名字里带CLK的单元不是随便用来搬信号的它们被特别设计用于时钟网络占空比失真更小、对噪声不敏感。我曾经图方便用普通BUF去修复时钟树上的一个duty cycle问题结果CTS做完之后skew倒是好了duty cycle恶化了一大截——CLKBUF和BUF在内部晶体管尺寸设计上差距很大这个不能混用。DELAY延迟单元某些库里直接叫DLY或DL。这类cell内部就是串联的长channel晶体管专门用来提供额外延迟。修hold时如果发现buffer链太长可以考虑用DELAY单元替代减少面积。MUX/AND/OR/NAND/NOR/XOR/XNOR基础逻辑门。重点是MUX有标准MUX、带clock gating的MUX、用于scan的MUX等比如MUX2、MUX4这种数字代表输入数量。组合逻辑单元的后缀强度很重要。一般后缀X后面的数字越大驱动能力越强。X1适合短互连X4、X8适合驱动长线或重负载。在Innovus里做优化时工具会自己做upsize/downsize但如果你手动ECO选错强度往往会导致串扰或者过渡时间问题。2.3 物理与特殊功能单元ISO/LSU/TIE/FILL/CAP/ANT/LEVEL这类单元是物理优化里最容易踩坑的地方。ISO隔离单元一般出现在低功耗设计的power domain边界。isolation cell的作用是当某个domain断电时输出钳制在一个确定电平上。前缀常见ISO_AND、ISO_OR、ISO_LATCH等。记得低功耗design里domain A和domain B之间连信号时如果中间没插ISO cell断电瞬间输出是浮空的整个逻辑都会乱。检查isolate策略对没对最直接的办法就是看net两端挂的cell前缀。LSUlevel shifter unit电平转换单元。多电压域设计里的常客。后缀通常包含输入电压域和输出电压域信息比如LSUP_1V8_3V3。物理上电平转换单元需要接特定的供电轨placement时如果放错电压域power rail会短路或者IR drop剧烈。TIEHI/TIELO高/低电平连接单元。这一类不处理信号专门在芯片空闲区域或者需要固定电平的端口上接高接低。物理上全是金属连接长得很小但千万不能删。我见过一个新手做cleanup时看到TIE单元觉得没用删了结果后面ECO插入逻辑时没地方接固定电平工具直接报unconnected port。FILL填充单元。包括filler cell、decap cell。名字里带FILL的用于填充placement gap以维持N-well continuity带DECAP的用于提供片上电容、抑制IR drop。CAP电容单元。有时跟DECAP类似有时特指片上去耦电容。ANT天线效应防护单元。天线效应在先进工艺里非常常见金属线越长、暴露的面积越大在离子刻蚀工序中收集的电荷越多就可能损伤栅氧化层。带ANT的cell或者二极管单元就用来泄放这些电荷。2.4 时钟门控与电源管理ICG/PD/HEAD/Tail时钟门控单元在数字后端里出场频率极高。前缀ICG或CKLG表示integrated clock gating。这类cell内部是latch加AND门用于在不改变时钟逻辑的前提下控制时钟的开关。使用集成门控单元的一个关键物理参数是clock pulse width控制能力选型时功耗和延迟互相权衡。供电管理单元里常见的还有HEAD和TAIL开关单元用于power gating。名字里带PG、PSW、HEAD、TAIL、SWITCH的基本都是开关管。这些单元面积大、上下电延迟长placement时不能和普通逻辑混在一起需要专门的power switch cell row。3. 前缀信息如何驱动物理优化决策3.1 通过前缀判断单元的物理性格每个cell在物理上都有不同的属性spacing规则、可放区域、走线层偏好、电源引脚位置、是否需要额外间距。Innovus的LEF里定义了每个cell的这些属性而这些属性在命名时往往有迹可循。一个很实用的经验名字里带特殊字符的cell物理约束通常也更特殊。带*的可能是dont-use单元带_1、_2结尾的可能是分块版图单元带ISCin cell标识的可能是倒装或特殊封装单元。在place之前跑一版init_design用verify_db查一下cell的physical classes远比靠记忆靠谱。3.2 修时序时怎么选cell一个延迟匹配问题修hold time的常规手段是插buffer。但不是所有buffer都一样。当你拿到一条hold violation路径通常的做法是加buffer链来增加data path延迟。这时有两个选择插BUF还是插DELAY。BUF的输入电容相对均匀输出阻抗固定级联之后每级延迟趋近一个稳定量。DELAY单元内部是串联晶体管单级延迟可以做得很大面积远小于多级BUF。实测中同样增加500ps延迟用DELAY单元的面积大约是多级BUF的1/3。但DELAY单元有一个很大的短板——它对电压和温度的敏感度更高PVT变化下延迟漂移远大于BUF链。如果这条路径PVT余量本来就很紧建议老老实实用BUF链别贪面积。这就是为什么我后来在ECO时序修复时总是先看一眼库里DELAY单元的lib曲线再决定用不用。修setup的思路刚好相反——你需要减少延迟。常规做法是upsize或者换高速单元。注意不要把普通的逻辑门直接替换成CLK系列高速门CLK系列有专门的负载匹配要求乱换容易在时钟网络上引入反射和过冲。3.3 时钟网络优化的cell选择CLKBUF不是万能的时钟树综合CTS里CLKBUF、CLKINV是最基础的构件。Innovus的CTS引擎会根据时钟树的层次和负载自动选择不同的驱动强度。但如果你手动干预时钟树有几个原则时钟网络里不要随便加普通BUF。普通BUF的延时对输入slew敏感输入slew一变它的输出延迟会自动变化会加剧时钟偏斜。CLKINV有成对使用的要求。有些库的时钟反相器必须两两配对使用以实现差分输出。如果你一边加了CLKINV另一边不加整个时钟树的相位平衡就崩了。时钟树末端的门控单元要用ICG。带ICG前缀的单元内部有锁存器可以在时钟的低电平期间关断输出时钟避免glitch。如果贪便宜用MUXAND来搭门控时钟沿的毛刺问题会让你在仿真阶段吃尽苦头。我在实际项目里见过一个经典问题芯片上电后存在随机性功能错误查来查去最后定位到是某个时钟分支用了普通AND门做门控而AND门本身的毛刺被时钟沿采样进去了。换成ICG后问题彻底消失。这属于典型的省了面积赔了可靠性。3.4 低功耗单元的物理落位ISO和LSU不能乱放隔离单元ISO和电平转换单元LSU在placement时有严格的电压域约束。ISO的输出端必须落在接收domain的供电范围内这样在发送domain断电后输出才能稳定在接收domain可识别的电平上。判断方法很简单看net连接到ISO的哪一端。ISO的输入来自断电domain输出连到常开domain。如果放反了隔离就失效了。Innovus里可以通过get_cells -quiet [all_connected $net]来查cell所在的voltage area。然后在set_voltage_area阶段给ISO和LSU加约束强制它们放在指定的voltage area边缘这样才能在route阶段正常布通电源。电平转换单元则是输入端在低压域、输出端在高压域。物理上它的VDD引脚可能有两个一个接高压一个接低压所以摆放时需要专门保证两套供电轨都能连接到。如果LSU放的位置离power switch太远IR drop一上来电平转换的阈值就不准了直接导致跨域信号误判。3.5 FILL和DECAP别把它们当成可丢弃的边角料fill cell负责维护阱连接的连续性。CMOS工艺里如果同一阱区内距离过远的两个阱接触点之间电阻过大会引发闩锁效应风险。fill cell本质上就是没有逻辑功能的阱接触和一个大电容。用带FILL前缀的cell填补placement空隙是为了让阱电位稳定。DECAP的作用更直接当某一块逻辑在某个瞬间同时翻转局部电源会掉压DECAP里存储的电荷会瞬间补充到电源网络上。名字里带DECAP前缀的单元一般有特殊的spacing规则要求它们靠近高翻转活动率模块。很多工程师physical verification时报了一堆天线效应violation第一反应是插ANT diodes。但ANT diode也是带前缀的专门单元它必须放在信号线的起始端或者靠近驱动端的位置并且它只有一个引脚。如果你插错了方向或者放错了位置天线效应不仅没消除还可能导致新的short。这里还有个细节插完ANT单元之后必须在Innovus里重新跑一遍antenna check因为天线效应和金属层的暴露面积有关你插了diode但没改走线violation可能依然存在。4. 在Innovus里高效应用前缀信息的实用命令流4.1 用通配符查询特定前缀的cell理解前缀就要会查前缀。Innovus的get_cells和get_lib_cells命令支持通配符这是最高频的使用方式。# 查设计里所有以DFFQR开头并包含X2的cell get_cells -hier *DFFQR*X2* # 查当前库所有隔离单元 get_lib_cells */ISO* # 查设计中的所有电平转换单元 get_cells -hier *LSU* # 查某个模块里的所有时钟buffer get_cells -hier tb_top/u_digit/*CLKBUF*在ECO脚本里我几乎每次都会用类似的通配符来筛选目标。比如修hold时想找出所有高扇出的BUF来评估是否冗余set high_fanout_bufs [get_cells -hier *BUF* -quiet] foreach buf $high_fanout_bufs { set fanout [sizeof_collection [get_nets -quiet -of_objects $buf]] if {$fanout 32} { puts High fanout buffer: [get_full_name $buf], fanout $fanout } }4.2 用dbGet一步读取属性和前缀Innovus里更底层、更强大的查询接口是dbGet。dbGet可以直接读数据库里所有object的属性。当你需要批量分析cell属性时dbGet比get_cells更高效。# 查看设计里所有DFF单元的名称和功耗估算值 dbGet [dbGet top.insts.cell.name -p *DFF*] .name # 查看所有带ISO前缀单元的电压域属性和坐标 dbGet [dbGet top.insts.cell.name -p *ISO*] .placeStatus当年修一颗芯片的低功耗模块问题时我需要确认所有跨域信号是否有ISO保护就是用一段dbGet命令完成的。挑选出所有连接在两个voltage area之间net上的cell然后再逐一检查net的source和sink整个过程比手动看原理图快十倍。4.3 利用prefix做批量ECO操作ECO场景中常用bulk操作。比如你要将某个模块里所有驱动能力不足的BUFX1替换成BUFX2set bad_bufs [get_cells -quiet -hier -filter ref_name ~ *BUFX1*] foreach buf $bad_bufs { set mod [get_attribute $buf mod_name] if {[string match *u_dig_top* $mod]} { changeCell -inst $buf -cell BUFX2 } }同样的思路可以用在CLKBUF强度调整、ISO单元类型切换、LSU方向修正上。还有一个比较进阶的用途用前缀来识别并限制某些cell的使用。有些库里有功耗表现差、延迟奇怪的old cell可以通过set_dont_use把它们整体封掉set_dont_use [get_lib_cells */OLD_*] true这里的OLD_就是那个库里老一代单元的公共前缀。一个前缀过滤就把整批低频/高功耗单元全部排除掉了工具选型速度也快很多。4.4 前缀之外读lib和LEF才能看到完整信息前缀只是快速检索引。真正判定一颗cell能不能用、有没有特殊物理约束还得看lib和LEF定义。在Innovus里推荐用report_cell来查看完整信息report_cell [get_lib_cells */ISO_AND2X1]输出里会列出cell的area、power、pin信息、timing model、physical class等。拿这些和LEF里的SITE、WIDTH、HEIGHT、SYMMETRY属性对照才能知道它能不能放进你当前place的区域。比如FILL单元和DECAP单元在LEF里一般都有CLASS CORE SPACER之类的描述Place阶段工具会自动把它们放在空隙中——只是它们没有逻辑功能不能参与时序计算。如果你在用find_or_create_filler这种命令时没把前缀过滤对很可能把DECAP也当成普通filler塞进去了。DECAP做filler用可以但DECAP还有个作用是为动态功耗提供电荷塞满了逻辑区域的空隙之后对IR drop是有正向帮助的。所以具体取舍要看设计目标优先IR/EM还是优先面积。5. 前缀认知盲区导致的典型事故与排查链路5.1 案例一CLK_DIVIDER的历史包袱在某次MPW项目中我接手一个来自老模块的网表里面有一个以CLK_DIV开头的cell。当时项目中其它模块用的都是ICG来做分频和门控只有这块老IP还在用。集成之后CTS阶段每次跑到clock tree building就报错——因为这款CLK_DIV单元根本不在时钟专用cell list里。工具试图把它当普通逻辑单元优化结果输出时钟端没有delay arcCTS直接流产。排查链路先看check_timing和CTS log里的warning定位到CLK_DIV实例——因为其它时钟单元都带ICG前缀就它长得不一样。hook上get_lib_cells *CLK_DIV*发现库里确实有这颗cell但clock tree synthesis的黑名单里没有它。最后是在CTS setup里把它加进set_clock_tree_references的列表并且配好leaf pin属性CTS才跑通。从这个案例学到的是时钟网络上的cell一定要在早期就确认它的身份。在Innovus里用report_clock_tree查看时钟树里每一级用的是什么cell如果看到不认识的单元马上查它的lib定义和CTS reference配置。5.2 案例二ECO时把LSU当普通Buffer用有段时间为了修功耗把芯片两个电压域从1.1V/0.9V改成1.0V/0.8V。改动后很多跨域信号的建立时间窗口变了需要插buffer修setup。当时经验不足在低电压域里直接用了高电压域里常见的BUF单元。结果是这些BUF单元输入端虽然是低电压信号它们本身却是用高电压供电的电平判断阈值完全不对。更麻烦的是我在Liberty里看到信号延迟还算正常但转到SPICE仿真后发现低电压域输出高电平经过这颗BUF之后输出高电平被拉低——因为它的输出级在高电压域里输入到输出有静态电流路径低电压信号根本没法完全关断PMOS。后来复盘时我用report_cell查看这些BUF的电源引脚发现它们只有VDDH没有VDDL才意识到它们其实是一批特殊的buffered level shifter前缀是LSU_BUF而不是BUF。排查链路先看路径上cell的前缀有LSU但它后面有BUF字样被我主观忽略了。检查cell所在voltage area对照lib里VDD pin定义。用derive_pg_connection重新生成power连接跑IR drop分析发现电平转换位置压根不对。把所有LSU_BUF替换成普通LSU后再做仿真功能恢复。警惕一点凡是名字里既有功能前缀又有电压域标识的cell多半有特殊的供电要求。改动跨域路径时别只盯着延时数字先确认单元供电。5.3 案例三天线效应修复单元引发的DRC二次爆炸这个坑比较冷门。某次修完天线效应往net上插了一批ANT单元之后本来clean的DRC冒出几十个M1 spacing violation。原因是这些ANT单元的金属1引脚面积过大在密集的窄线区域里挤在一起间距不够了。如果你只看前缀ANT就往网表里加很容易忽略它在物理上引入的额外金属。正确做法是插完ANT cell之后跑一遍physical verification确认天线问题真的解决再检查这些ANT单元之间、ANT单元与附近cell之间的间距。Innovus里可以先做一次ecoPlace只把这些新加的单元摆好先忽略其它逻辑单独看它们的位置。如果有spacing violation就要调整布局或替换成金属层更少的ant单元。常有工程师说我插了天线二极管为什么还在报天线效应——多半是因为ant单元的泄放路径没有真正接到psub/nwell上。这时需要检查引脚连接ANT cell一般有个额外的D terminal是接衬底的如果netlist里没接好物理上等于没插。5.4 案例四FILL与DECAP的身世之谜做DRC之前跑例行检查发现一堆area不足的报错。起初以为filler没插够后来发现innovus插的是带FILL前缀的普通阱连接单元但报告里要的其实是另一类带FILLCAP前缀的单元。这个前缀差异直接决定了filler是不是自带电容。如果没有电容在电源网络上就起不到去耦作用局部高翻转区域的IR drop就压不住。还有一次发现APadvanced process规则里要所有的filler都有nwell边沿连接但工具默认插的FILL只有一端有well tie。最后是在filler命令里加了-prefix FILLCAP选项强制所有filler都从带电容和双端well tie的单元族里选。这个案例说明每次换个工艺节点都不要想当然地把带FILL的就能用当成铁律——务必看一眼LEF里的spacer cell list是什么前缀。Innovus的addFiller命令一个常见坑位是filler cell的prefix如果不限制死工具可能从库里的很多FILL类型里随机选。如果你的库里有FILL1、FILL2、FILLCAP、NOFILL等多种类型那最好用-prefix参数指定。否则工具倾向于选面积最小的导致最终密度满足但阱和电源连续性不达标。6. 把前缀思维固化成工作习惯的几个建议整理一下我个人在使用Innovus处理cell前缀这件事上的习惯希望对你有帮助。第一拿到一个新的工艺库第一周先把库里的cell name扫一遍分类存档。不需要全部记住但至少知道库里有哪几个家族clock族、logic族、power族、filler族、特殊功能族。可以用下面的脚本快速导出一个Excel清单set all_lib_cells [get_lib_cells */*] set fp [open cell_prefix_tree.txt w] foreach cell $all_lib_cells { set cell_name [get_attribute $cell name] set ref_name [get_attribute $cell ref_name] set base [regsub {^[^_]_} $cell_name ] puts $fp $cell_name\t$ref_name } close $fp导出后按前缀排序一眼就能看出哪些是常用驱动强度哪些是特殊功能单元。我在好几个项目里都是靠这份清单在ECO时快速定位可用cell的。第二写ECO脚本时永远不要用裸的cell name做替换。要么带上前缀匹配要么用完整ref_name。裸名字匹配最大的风险是撞上跨工艺库的同名不同物理单元。比如BUFX1在很多库里都有但驱动电流、引脚位置可能不同替换错了就是灾难。# 比较安全的写法限定library changeCell -inst u_buf3 -cell lib_core/BUFX2A # 更严谨的写法检查cell的lib归属再替换 set target_cell [get_lib_cells -quiet *BUFX2A] if {[sizeof_collection $target_cell] 1} { changeCell -inst u_buf3 -cell [get_object_name $target_cell] }第三定期做前缀审计。特别是从place阶段转到CTS阶段、从CTS到ECO阶段分别用report_cells加前缀过滤看一眼当前设计里所有cell类型的占比。如果某个模块里出现了不该出现的前缀多半是约束或者脚本哪里出了问题。比如ECO之后发现某模块里突然多出大量LSU_BUF那很可能是在时序修复过程中level shifter的位置被破坏了。第四把前缀知识和库文件本身绑定做版本管理。不同版本库可能调整过cell命名。比如某次库从TSMC 28nm换到TSMC 16nm原本的ISOLATEND2变成了ISOLATE_ND2前缀多了下划线。如果项目脚本里还有基于旧前缀的filter功能会悄悄失效。每次换库版本花一个小时跑一边全库前缀比对成本很低但收益极高。第五别忘了standard cell library的doc 。多数库包都会带一个cell_name_mapping或者命名规范说明文档有些甚至直接写在README里。专门抽出半天读一遍里面的命名章节比你自己试错总结快得多。像Cadence的Generic Library、TSMC的CLN28HPC等命名规则基本是公开且稳定的。最后说个判断标准如果你的团队里任何一个人问这个cell是干嘛的你能在10分钟内从前缀推导出大概、再从lib/LEF里确认细节那这套前缀思维基本就建立了。这10分钟里前8分钟其实是花在查库文档上的前缀只是帮你缩小了检索范围——但恰恰是这个缩小范围才是整个排查流程里最值钱的环节。Innovus里的cell前缀本质上是工艺库设计者留给后端工程师的善意引导。越早把它当成自己的语言你在ECO、CTS、物理验证里的效率提升就越明显。别等踩了坑再回头学。
返回列表