ARTICLE DETAIL

资讯详情

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

PrimeTime生成.lib时PG引脚丢失与pg_type错误排查实战

PrimeTime生成.lib时PG引脚丢失与pg_type错误排查实战 上周接到一个“小活”用PrimeTime给顶层交付一个SRAM宏单元的.lib模型。原以为只是跑一遍write_lib的简单工序结果生成的.lib文件里PG引脚部分出了问题——这里的PG是Power/Ground也就是电源和地引脚。下游Voltus功耗分析直接报错MVRC检查也弹出一堆“missing power pin”。排查到最后才发现问题既不在reference库也不在网表里恰恰藏在PrimeTime自己“生成.lib时往文件里添加PG引脚定义”的逻辑中。这篇把完整过程记录下来给同样在用PrimeTime产出.lib的兄弟团队一个参考。不管你是做库特征化、IP集成还是给顶层提供时序模型只要你的单元带多电源域、backup电源、内部电源尤其是要输出Liberty文件供其他工具解析的建议把这篇看完。这个坑的触发概率远比我原来以为的高得多。1. 交付一个SRAM宏单元.lib活不大坑不小1.1 什么场景会用PrimeTime直接输出.lib按教科书流程.lib应该是库特征化工具的产物SiliconSmart、Liberate、NCX这些工具才负责把SPICE网表变成包含时序、功耗、约束信息的库文件。但实际后端流程里有几种情况会贪图方便直接用PrimeTime来生成.lib宏单元快速建模SRAM、PLL、DDR PHY这类大宏在PR完成后为了给顶层提供足够的时序精度又不想暴露内部结构常用extract_model提取接口时序再通过write_lib输出成标准.lib。库格式互转手上只有编译过的.db下游某个工具却非要文本.lib不可很多人会直接用PT读回.db再写出去图个省事。时序签核附带的模型交付PT做STA签核的同时顺手给顶层或封装/硅后验证导出一份库参考模型。这些场景的共同点是我们并不期望PT去做特征化只是让PT把它已经“知道”的东西按Liberty语法转述出来。麻烦就出在这里——PT是一个时序引擎它最擅长的是延迟计算PG信息对它是“附属品”是转述的、代理的而这条转述链路里恰恰藏着Bug。1.2 任务背景一个带三组电源引脚的SRAM宏单元我这次的SRAM宏单元电压域设计如下引脚名电压域预期pg_type说明VDD0.9V 核心primary_power逻辑供电VDDM0.72V 阵列internal_power存储阵列/位线供电VDDPST1.8V IObackup_power快速唤醒备份域VSS0Vprimary_ground地宏单元在reference lib里的PG定义是完整的netlist也通过UPF做了供电端口映射。我当时操作路径很简单读入网表和SRAM宏单元的reference .db库用extract_model提取接口时序模型最后用write_lib -format lib导出供顶层的Voltus和MVRC使用。三步操作看起来十分钟能交差。结果恰恰就在第三步出了幺蛾子。2. 生成的.lib有两个“典型病例”PG引脚消失和电源类型认亲错误2.1 病例一backup电源引脚在文本里直接蒸发第一版.lib交给验证组很快就收到MVRC的一堆“missing power pin”报错。我打开生成的.lib文件去核发现了一个诡异现象文件里VDD、VSS都好好写着但VDDPST的PG定义整个不见了。更离谱的是它不是被简单地漏掉而是被写到了一个完全错误的层级——挂到了某个leaf cell底下而不是宏单元顶层端口上。我立刻反查reference lib里的db信息SRAM宏单元的端口列表里VDDPST明明存在。也就是说PT在write_lib的“PG添加”阶段把宏单元顶层这组PG端口漏掉了或者错放到了子模块下。当时第一反应是怀疑自己命令写错了反复检查extract_model的边界设置和write_lib的选项都没问题。2.2 病例二pg_type张冠李戴Voltus把VDDM当主电源修完引脚“蒸发”的问题后复查又发现更隐蔽的第二问题VDDM的pg_type被写成了primary_power而不是它应有的internal_powerVDDPST则被标成了primary_power而不是backup_power。这个错误的危害比引脚丢失还大。Voltus识别电源域靠的就是pg_type和voltage_name。当.lib里出现两个primary_power时IR drop分析会认为VDD和VDDPST属于同一电压域导致把1.8V的IO电源和0.9V核心电源的网络合并计算对power mesh做错误的电流密度分配Multi-domain检查时报“multiple primary power”错误。用户层面看到的结果就是功耗分析数据要么离谱地好漏报真正的压降瓶颈要么离谱地差把backup电源压降全算到核心域上。这种东西一旦流片前才被发现那就不是加两天班能解决的事。2.3 下游工具的连锁反应清单把这两类问题的实际影响完整列一下方便各位对照自己的场景下游工具症状根因MVRC / LQA“Missing PG pin” / “Duplicate pg_type”PG引脚丢失 / pg_type写错Voltus电源域映射错误 / IR drop异常primary_power重复顶层UPF连接connect_supply_net无法绑定引脚lib端口缺失或名称不匹配布局布线工具读入电源引脚连接自动悬空PG端口缺失自家脚本解析Liberty解析器报错PG语法/层级异常只要是带多电源域的宏单元上面任何一项都足以让交付延期。而且这类错误往往不在第一时间暴露——时序仿真是能过的逻辑功能也是对的一直到功耗分析或者顶层UPF连接阶段才会爆出来定位成本和修改成本都翻倍。3. 根因排查从质疑reference库开始最后锤到PT自己的write_lib逻辑3.1 先排掉reference库和db编译的嫌疑按照标准排查流程先做排除法。第一步是确认reference .db本身没有丢信息。我在PT里直接检查SRAM宏单元的PG引脚# 检查reference库里SRAM宏单元的PG引脚定义 foreach_in_collection cell [get_lib_cells sram_lib/SRAM_CORE] { set pg_pins [get_lib_pins $cell/* -quiet -filter pg_type!\\] if {[sizeof_collection $pg_pins] 0} { puts cell: [get_object_name $cell] foreach_in_collection pin $pg_pins { puts pin: [get_object_name $pin] pg_type: [get_attribute $pin pg_type] } } }输出结果让人放心VDD、VDDM、VDDPST、VSS四个端口的pg_type、voltage_name、related_power_pin、related_ground_pin全部正确连is_pad、leakage_power这类边角属性都在。说明reference库不是犯人。接着我用Library Compiler把原始.lib文本重新编译成db再反解回来PG信息依然完整。这一步证明db编译环节也没有丢数据。3.2 最小化实验复现一个Inverter就能触发到这里我已经基本排除“我的宏单元特殊”这个假设。于是构造了最小测试环境一个只含inverter单元的网表inverter端口带VDD和VSS两个PG pinreference库里的定义完全标准。跑同样的 read_netlist → link → write_lib 流程问题居然复现了。inverter的VSS在生成库中直接“消失”或者pg_type整体错乱。这非常关键——说明这不是SRAM宏单元特殊结构造成的偶发而是PT在基础单元上就能触发的通用路径Bug。我把这个案例丢给搭环境时用的临时脚本反复改了几次UPF写法、网表连接顺序问题依旧。到这一步我的怀疑对象已经从“我的流程配置”彻底转向“工具本身的write_lib行为”。3.3 write_lib的PG添加逻辑理解工具在做什么、错在哪里在进一步调参数之前值得花点时间把PT生成.lib时的PG信息来源讲清楚。这个理解很重要因为很多人踩坑后第一反应是去改网表、改UPF改几版都没用就是因为对工具的“转述”机制没有概念。PT在write_lib时PG信息的来源主要有三条直接继承reference .db里已有的pg_type、voltage_name等定义。理论上PT应该原样透传网表推断当reference库里PG定义不完整有些时序库确实不写PGPT会根据网表的supply net连接关系、UPF供电端口定义去“补”PG信息内部默认兜底对完全无PG信息的设计PT用内部默认规则生成一套PG引脚。我的案例里PG信息属于第1条来源理论上应该无损透传。但实际输出却错了说明PT在write_lib内部还有一个“PG信息规整”阶段它把各种来源的PG信息统一成内部表再按照目标Liberty版本规则生成文本。这个规整逻辑对单电源引脚单元没问题但对多电源引脚数量超过两个、且引脚命名不符合VDD/VSS惯例的单元会在排序和去重阶段把引脚错误合并或错误标记。VDDM、VDDPST这类名字一旦被内部规则按“VDD开头就归入主电源域”来处理pg_type就被强行改写成了primary_power某些引脚则会因为命名空间的冲突在这个阶段被直接丢弃于是出现我看到的“蒸发”现象。p.s. 由于PT不允许用户在write_lib时手动指定每个引脚的pg_type这个规整阶段一旦出错你几乎没有干预的余地。这也是我最后选择脚本兜底的直接原因。3.4 关底在release note里找到了对应的known issue完成最小复现后我查了手头PT版本2022.06的release note果然在Known Issues部分找到了对应记录大意是当write_lib输出包含多电源域单元的库文件时PG引脚定义可能丢失或被错误标记受影响的是Liberty 2018语法输出路径。另外发现一个关键细节这个问题只在较新的Liberty语法路径下触发。当我们把输出语法强制回退到2009.12版本时PG信息一切正常。这个线索直接奠定了后面的应急方案。4. 画一下雷区哪些lib生成流程最容易踩中4.1 多电源域/backup域的宏单元模型导出最容易踩中的就是本文场景宏单元带着多套电压域PG引脚数量超过两组且命名不是标准的VDD/VSS。SRAM、寄存器堆、带IO PAD的接口宏、含有DVFS单元的block都属于高危对象。这些单元几乎绕不开PT因为顶层集成通常只信任PT生成的时序模型。而且越是大宏PG引脚越多命名越花哨比如VDD_CORE、VDDIO_MEM、VDDM_A、VSS_IO越容易触发内部规整逻辑的误判。4.2 用write_lib把.db“转回”文本.lib的运维操作第二个高危流程是库格式互转。很多团队会习惯性地把PT当成“免费的lib转文本工具”拿到一个.dbread_db然后write_lib -format lib以为拿到了等价文本库。在单电源域库上这个操作问题不大。但一旦库里出现backup电源、内部电源、nwell_power这类非主域PG转出来的文本就有很大概率在PG段出现上述Bug。最麻烦的是转完没人抽查等下游流片前用MVRC审查时才发现波及面已经铺开。4.3 ETM模型导出和UPF感知的lib生成第三个雷区是extract_model提ETM再导出.lib的场景。ETM本身关心的是接口时序但导出文本.lib时PT会把PG信息一并生成。如果原设计有UPF定义的多域供电而ETM提取的边界又恰好切在某个电源域中间PG添加逻辑更容易“想当然”地帮你补一组错误的域定义。ETM交付给顶层后顶层做UPF连接时会报找不到引脚或电压域不匹配。这个场景比前两种更隐蔽因为ETM的时序验证可能全绿问题只会在顶层功耗分析阶段炸出来。5. 绕坑实战三套能落地的规避方案5.1 应急强制Liberty语法版本回退绕开新语法路径既然是Liberty新语法路径上的Bug最快的应急方案就是让PT输出旧版Liberty语法。对PT来说write_lib对语法版本的控制选项一般是-version# 输出Liberty 2009.12语法PG引脚使用传统pin pg_type块 write_lib -format lib -version 2009.12 -output ./sram_model_old.lib输出后检查一下PG段应该能看到传统的pin (VDDM) { direction : inout; pg_type : internal_power; voltage_name : VDDM; related_power_pin : VDD; related_ground_pin : VSS; }而不是出问题的pg_pin块写法。注意不同PT版本对-version的选项名称和支持范围有差异执行前先write_lib -help确认一下。这个方案成本最低但不要过于乐观。如果你的下游工具强制要求Liberty 2018语法这条应急路径就不够用得走脚本修复方案。5.2 兜底脚本自动修复pg_type与related_pin映射如果格式版本不能妥协那就上脚本。核心思路是以reference lib的PG定义作为黄金标准用脚本对比并修正生成lib的PG部分。我用的Python脚本骨架如下import re # 黄金标准pin_name - (pg_type, related_power, related_ground) GOLDEN { VDD: (primary_power, VDD, VSS), VDDM: (internal_power, VDD, VSS), VDDPST: (backup_power, VDDPST, VSS), VSS: (primary_ground, VDD, VSS), } def fix_pg_section(lib_text: str) - str: # 按cell块切分对每个块内的PG引脚覆写pg_type和related_*字段 # 省略逐块解析细节核心逻辑是按名字匹配GOLDEN表后覆写 for pin_name, (pg_type, related_power, related_ground) in GOLDEN.items(): # 在lib文本中找到对应pin块并替换pg_type等属性 pass return lib_text if __name__ __main__: with open(sram_bug.lib, r) as f: fixed fix_pg_section(f.read()) with open(sram_fixed.lib, w) as f: f.write(fixed)实际实现时不要真用这个精简版建议对文本做块级正则替换替换前先定位每个cell块的边界避免误伤同名字的信号引脚。替换后做一轮二次校验解析每个cell块的PG引脚数量和GOLDEN表数量比对即使顺序错乱也没关系按名字匹配后覆写字段即可。我自己的习惯是修正后不着急交付先用reference lib对PG部分做一次结构化diff确认没有多写、漏写再往下游送。这一步五分钟能完成但能挡住绝大多数二次事故。5.3 彻底该走特征化工具的流程不要省最后说点劝退的话。如果你发现“用PT生成.lib”不是偶发一次的应急动作而是反复出现的需求那我强烈建议把正规特征化工具SiliconSmart / Liberate / NCX纳入流程。PT生成.lib只是附带能力用户没法精细控制PG语法细节出了问题只能绕。而特征化工具生来就是管这事儿的PG引脚定义、电压域映射、QA报告都是围绕.lib交付设计的。受控、可回归、可批量。省下的那点license时间远不够填一次PG漏配导致的IR drop重跑成本。6. 这次踩坑换来的几条后端经验6.1 lib交付前PG冒烟检查必须做这次事故以后我给自己组的lib交付流程强制加了PG冒烟检查。检查内容不多就三件事单元端口数 lib中PG引脚数 信号引脚数每组PG引脚的pg_type与UPF里的供电域定义一一对应voltage_name和库文档里的工作电压一致。三件事用脚本自动化耗时不超过五分钟但能在第一时间把这类工具Bug挡在交付线外。上次踩坑时我还抱着“PT转写不会错”的侥幸心理省了这一步结果赔了整整两个工作日。6.2 EDA工具版本行为会漂移升级后要回归这条经验可能比PG Bug本身更重要。我这次用的PT是从老版本升上来的升级前同样一条命令产出的.lib没有任何问题升级后就突然翻车。EDA工具在小版本升级里改行为、改默认值、改语法兼容策略是常有的事。凡是交付物高度依赖工具“默认行为”的环节工具升级后必须做一轮回归不能只看时序结果没变就放行。我现在的习惯是每次工具版本变更后抽一个代表单元重新走一遍.lib生成流程和旧版本输出做diffPG信息有没有变化一眼就能看清。6.3 库文本里的PG信息是全流程的“电源宪法”最后说一个认知层面的收获.lib文本里的PG信息在数字后端全流程里是“电源宪法”级别的存在。综合工具靠它识别电源引脚布局布线靠它连接pg net功耗分析靠它划分电压域MVRC靠它做一致性审查。而恰恰是这个关键字段在PT这类时序工具的“转述”链路上最容易出问题。它错得越晚暴露修复成本越高。凡是经过PT、LC等工具二次转述出来的.libPG部分一定要拿reference库做对照别默认“工具转写不会错”。最后再分享一个小技巧检查PG信息时别只看lib文件里PG引脚的名称在不在还要用get_lib_pins -filter pg_type! \\把每个引脚的pg_type、related_power_pin、related_ground_pin三个字段全部打出来和对一遍。名称和类型有一项对不上后面的功耗分析都是在给定时炸弹倒计时。
返回列表