Calibre PEX提参实战:hcell与xcell精准屏蔽模块避坑指南
1. 从一次真实的PEX翻车说起做模拟版图或者混合信号后仿的兄弟大概率都经历过这种场景花了大半天跑完Calibre PEX兴冲冲打开网表一看傻眼了——本该被屏蔽的SRAM、PLL、ADC这类大模块寄生参数全被提了出来网表膨胀到几十万行后仿跑得比乌龟还慢波形还跟预仿对不上。更气人的是明明在规则文件里写了屏蔽语句Calibre却像没看见一样一声不吭地全给你提了。这个问题的根源十有八九出在hcell和xcell文件上。Calibre PEX的模块屏蔽机制本质上是一套“层级匹配”逻辑工具需要知道哪些cell是“黑盒”哪些cell需要保留层级哪些cell要彻底展开。hcell和xcell就是告诉Calibre这些信息的两个关键文件。但这两个文件的语法、优先级、匹配规则官方文档写得极其晦涩很多细节只有踩过坑才知道。这篇博文就围绕Calibre PEX提参实战展开重点讲清楚hcell和xcell文件如何精准屏蔽模块以及我在实际项目中反复踩过的那些坑。内容适合已经能跑通基础PEX流程、但对层级控制和模块屏蔽还不太有把握的版图工程师、CAD工程师和模拟设计者。如果你正在被后仿网表爆炸、模块重复提取、LVS与PEX结果不一致等问题困扰这篇应该能帮你省下不少调试时间。2. hcell与xcell到底在PEX里扮演什么角色2.1 先搞清楚PEX的层级处理逻辑Calibre PEX在提取寄生参数时面对的是一个层次化的版图。工具需要决定哪些cell要保留层级结构哪些cell要打平flatten哪些cell要当作黑盒直接跳过。这个决策过程不是随机的而是由几个输入共同决定的LVS规则文件里的相关语句、hcell文件、xcell文件以及PEX规则文件里的提取选项。很多人误以为只要在PEX规则里写一句“不提取某个cell”就行了实际上Calibre的层级处理发生在LVS阶段就已经开始了。PEX是基于LVS已经建立好的层级映射关系来工作的。如果LVS阶段没有正确识别模块边界PEX阶段再怎么配置都是白搭。这就是为什么我总跟新人说PEX的问题一半要回到LVS去找原因。hcell和xcell的核心作用是在LVS阶段就告诉Calibre版图里的某个cell和原理图里的某个cell是对应的或者某个cell应该被当作黑盒处理。PEX阶段则继承这些信息决定是否对某个cell内部进行寄生提取。2.2 hcell文件层级匹配的“白名单”hcell的全称是hierarchical cell它的作用是建立版图cell和原理图cell之间的层级对应关系。在LVS过程中Calibre默认会尝试自动匹配版图和原理图的层级但自动匹配有时候会出错尤其是当版图里存在多个功能相同但名字不同的cell或者原理图层次和版图层次不一致时。hcell文件的基本语法是# hcell文件示例 layout_cell_name schematic_cell_name比如SRAM_TOP SRAM_TOP PLL_CORE PLL_CORE这告诉Calibre版图里的SRAM_TOP对应原理图里的SRAM_TOP请把它们当作同一个层级单元来处理。在PEX阶段如果这个cell被标记为需要保留层级Calibre就不会把它内部打平而是作为一个整体提取外部寄生。但这里有个关键点hcell只是建立对应关系并不直接屏蔽提取。很多人以为写了hcell就不会提取内部寄生了这是误解。hcell的作用是让Calibre知道“这两个cell是一回事”至于要不要提取内部寄生还要看PEX规则里的设置和xcell的配合。2.3 xcell文件模块屏蔽的“黑名单”xcell的全称是exclude cell它的作用才是真正意义上的“屏蔽”。xcell文件告诉Calibre某些cell不需要进行LVS内部比对也不需要提取内部寄生参数直接当作黑盒处理。xcell文件的语法通常是# xcell文件示例 CELL_NAME或者带选项的形式CELL_NAME 1这里的“1”通常表示该cell被完全排除不进行任何内部处理。在PEX阶段被xcell标记的cell会被当作一个不可分割的单元只提取其外部端口的寄生内部结构完全不看。xcell的典型应用场景包括标准单元库、IP硬核、SRAM、PLL、ADC、DAC等不需要后仿内部细节的模块。把这些模块屏蔽掉可以大幅减少PEX网表规模加快后仿速度。2.4 两者的优先级与配合关系hcell和xcell同时存在时优先级是这样的xcell的屏蔽优先级高于hcell的匹配。也就是说如果一个cell同时出现在hcell和xcell里Calibre会优先按照xcell的规则把它当作黑盒处理。这个优先级逻辑很重要。在实际项目中我通常这样配置对于需要保留层级但不需要提取内部寄生的模块只写hcell对于完全不需要关心的模块写xcell。两者配合使用才能既保证LVS的正确性又控制PEX的网表规模。还有一个容易忽略的点hcell和xcell文件里的cell名字必须与版图或原理图中的cell名字完全一致包括大小写。Calibre对大小写是敏感的写错一个字母整个屏蔽就失效了。我见过不止一个项目因为把“SRAM_TOP”写成“sram_top”导致屏蔽失败白白多跑了好几个小时的PEX。3. 实操从零配置一套可用的屏蔽方案3.1 环境准备与文件放置在开始配置之前先确认你的Calibre版本。不同版本的Calibre在hcell和xcell的处理上有些细微差异尤其是Calibre 3.48和更早的版本对xcell文件里的选项支持不完全一样。建议用calibre -v确认版本然后查阅对应版本的官方手册。文件放置位置没有强制要求但建议放在项目目录下的pex或lvs子目录里和规则文件放在一起方便管理。通常的目录结构是这样的project/ lvs/ lvs_rule.lvs hcell.txt xcell.txt pex/ pex_rule.pex hcell.txt xcell.txt注意LVS和PEX可以共用同一套hcell和xcell文件也可以分开。如果LVS阶段需要更精细的层级匹配PEX阶段需要更激进的屏蔽那就分开写。我个人的习惯是共用一套减少维护成本。3.2 hcell文件的编写要点hcell文件的每一行是一个映射关系格式为layout_cell schematic_cell如果版图和原理图的cell名字相同可以简写为CELL_NAME但我不建议简写因为简写时Calibre会默认版图和原理图名字相同一旦有一边改了名字就会匹配失败。显式写两遍更安全。编写hcell时要注意以下几点只写需要保留层级的cell。不要把顶层cell也写进去顶层cell本来就是保留的。不要写标准单元。标准单元通常由xcell处理写进hcell反而会干扰。注意cell的层次关系。如果A cell里例化了B cell而B cell需要保留层级那么A cell也必须保留层级否则B cell的层级无处依附。避免重复。同一个cell写多次不会报错但会让文件混乱建议用脚本去重。一个实际的hcell文件示例# hcell.txt SRAM_512X32 SRAM_512X32 PLL_DIG PLL_DIG ADC_12BIT ADC_12BIT BANDGAP BANDGAP3.3 xcell文件的编写要点xcell文件的编写更简单每行一个cell名字# xcell.txt SRAM_512X32 PLL_DIG ADC_12BIT BANDGAP但有几个细节需要注意xcell文件里的cell名字必须是版图里的名字不是原理图的名字。这一点和hcell不同hcell是成对出现xcell是单个出现。如果cell有多个版本比如不同驱动强度的标准单元可以用通配符。Calibre支持*和?比如BUF_*可以匹配所有BUF开头的cell。xcell文件里可以加选项。比如在某些版本里CELL_NAME 1表示完全排除CELL_NAME 0表示只排除LVS比对但保留PEX提取。具体选项含义要查对应版本的手册。不要屏蔽顶层cell。顶层cell被屏蔽了整个PEX就没法跑了。3.4 在规则文件中引用这两个文件hcell和xcell文件写好后需要在LVS和PEX规则文件中引用。在LVS规则文件里通常这样写# LVS规则文件中的引用 LVS HCELL FILE hcell.txt LVS XCELL FILE xcell.txt在PEX规则文件里引用方式类似# PEX规则文件中的引用 PEX HCELL FILE hcell.txt PEX XCELL FILE xcell.txt有些流程里PEX规则文件会直接继承LVS的hcell和xcell设置不需要重复写。但为了明确我建议在PEX规则里也显式写一遍避免因为流程脚本的差异导致设置丢失。3.5 验证屏蔽是否生效配置完成后怎么确认屏蔽真的生效了最直接的方法是看PEX生成的网表。如果屏蔽成功网表里应该看不到被屏蔽cell的内部节点只能看到它的端口和外部连接。具体检查步骤跑完PEX后打开生成的.pex.netlist文件。搜索被屏蔽cell的名字比如SRAM_512X32。如果只看到类似XSRAM_512X32 port1 port2 ... SRAM_512X32的实例化语句没有内部节点说明屏蔽成功。如果看到了SRAM_512X32内部的大量节点和器件说明屏蔽失败。另一个验证方法是看PEX的日志文件。Calibre会在日志里报告hcell和xcell的匹配情况包括匹配了多少个cell、哪些cell没有匹配上。日志里如果有“XCELL cell not found”之类的警告就要检查cell名字是否写错了。4. 避坑指南那些年我踩过的hcell和xcell的坑4.1 坑一hcell写了但PEX还是提取了内部寄生这是最常见的问题。原因通常有两个一是PEX规则文件里没有正确引用hcell文件二是PEX规则里的提取选项覆盖了hcell的设置。排查方法先看PEX日志里有没有“HCELL FILE”的加载记录。如果没有说明规则文件里没写对。如果有再看日志里hcell匹配了多少个cell。如果匹配数为0说明cell名字写错了。还有一个隐藏原因PEX规则里的PEX EXTRACT选项可能设置了强制打平。比如有些规则文件里写了PEX EXTRACT FLATTEN这会让所有cell都被打平hcell的设置就失效了。检查规则文件里有没有类似的全局打平选项。4.2 坑二xcell屏蔽了但LVS报错xcell屏蔽的cellCalibre在LVS阶段会跳过内部比对。但如果这个cell的端口连接有问题LVS还是会报错。比如xcell屏蔽了一个SRAM但SRAM的电源端口在版图里没有正确连接LVS会报“open circuit”或“floating node”。解决方法xcell屏蔽不等于不管。被屏蔽cell的端口连接必须正确否则LVS过不了。我通常会在屏蔽之前先确认这些cell的端口连接没有问题。4.3 坑三hcell和xcell同时写导致冲突前面说过xcell的优先级高于hcell。但如果一个cell同时出现在两个文件里Calibre的行为可能因版本而异。有些版本会直接按xcell处理有些版本会报warning。我的建议是不要同时写。如果一个cell需要屏蔽就只写xcell如果需要保留层级但不屏蔽就只写hcell。两者选其一避免歧义。4.4 坑四cell名字大小写不一致Calibre对cell名字大小写敏感。版图里是SRAM_TOPxcell文件里写成sram_top屏蔽就会失效。更麻烦的是Calibre不会报错只会默默地把cell当作没匹配上然后正常提取。等你发现网表爆炸时已经浪费了好几个小时。避免方法用脚本从版图网表里提取cell名字直接生成xcell文件不要手写。手写迟早会出错。4.5 坑五通配符用得太宽泛xcell文件支持通配符比如BUF_*可以匹配所有BUF开头的cell。但如果用得太宽泛比如*就会把所有cell都屏蔽掉包括顶层cell导致PEX直接失败。使用通配符时一定要先确认匹配范围。可以用grep在版图网表里测试一下看看BUF_*到底会匹配到哪些cell。确认无误后再写进xcell文件。4.6 坑六PEX网表里出现了被屏蔽cell的内部节点有时候明明xcell写了PEX网表里还是出现了被屏蔽cell的内部节点。这通常是因为PEX规则文件里的提取选项和xcell设置冲突。比如规则文件里写了PEX EXTRACT ALL这会强制提取所有cell的内部寄生xcell的设置就被覆盖了。解决方法检查PEX规则文件里的提取选项确保没有全局强制提取的设置。如果有改成PEX EXTRACT SELECTED或类似选项让xcell的设置生效。4.7 常见问题速查表问题现象可能原因排查方法解决方案PEX网表膨胀模块内部寄生被提取hcell/xcell未生效检查PEX日志中HCELL/XCELL加载记录确认规则文件引用正确cell名字匹配LVS报错被屏蔽cell端口连接问题xcell屏蔽但端口未连接查看LVS错误报告中的节点名修正被屏蔽cell的端口连接hcell和xcell同时写导致行为异常优先级冲突查看Calibre版本手册只写其中一个避免同时出现屏蔽失效但无报错cell名字大小写不一致对比版图网表和xcell文件用脚本生成xcell文件避免手写通配符匹配范围过大通配符太宽泛用grep测试匹配结果缩小通配符范围确认后再写入PEX网表出现被屏蔽cell内部节点PEX提取选项覆盖xcell检查PEX规则文件提取选项改为SELECTED提取模式5. 进阶技巧让屏蔽方案更稳健5.1 用脚本自动生成hcell和xcell文件手写hcell和xcell文件容易出错尤其是项目大了以后cell数量多名字复杂。我通常用脚本从版图网表和原理图网表里自动提取cell名字生成这两个文件。一个简单的Python脚本示例import re # 从版图网表中提取所有cell名字 def extract_cells(netlist_file): cells set() with open(netlist_file, r) as f: for line in f: # 匹配 .SUBCKT 行 match re.match(r\.SUBCKT\s(\S), line, re.IGNORECASE) if match: cells.add(match.group(1)) return cells # 生成xcell文件 def generate_xcell(cells, output_file): with open(output_file, w) as f: for cell in sorted(cells): f.write(f{cell}\n) # 主流程 layout_cells extract_cells(layout.spi) generate_xcell(layout_cells, xcell.txt)这个脚本会从版图网表里提取所有.SUBCKT定义的cell名字生成xcell文件。实际使用时可以根据需要过滤掉顶层cell和不需要屏蔽的cell。5.2 分层屏蔽策略对于大型项目我通常采用分层屏蔽策略第一层标准单元。全部用xcell屏蔽不提取内部寄生。第二层IP硬核。用xcell屏蔽只保留端口。第三层模拟模块。用hcell保留层级但根据后仿需求决定是否提取内部寄生。第四层关键路径。不屏蔽完整提取寄生保证后仿精度。这种分层策略可以在保证后仿精度的前提下最大限度地控制网表规模。5.3 与LVS流程的协同hcell和xcell文件不仅影响PEX也影响LVS。在LVS阶段hcell用于建立层级对应xcell用于跳过内部比对。如果LVS阶段hcell和xcell配置不当PEX阶段再怎么调也是徒劳。我的经验是先在LVS阶段把hcell和xcell调好确保LVS干净通过然后再跑PEX。LVS阶段如果有很多warningPEX阶段大概率会出问题。5.4 版本差异与兼容性不同版本的Calibre对hcell和xcell的支持有差异。比如Calibre 3.48对xcell文件里的选项支持就比较有限而更新版本支持更多选项。如果项目需要跨版本使用建议用最基础的语法避免使用版本特有的选项。另外有些Foundry提供的PEX规则文件里已经内置了hcell和xcell的设置这时候如果再在外面写一套可能会冲突。遇到这种情况先看Foundry的文档确认是否需要额外配置。6. 个人实操体会我在实际项目中最大的体会是hcell和xcell的配置三分靠技术七分靠细心。技术原理并不复杂但细节特别多一个字母写错、一个选项漏掉就可能导致整个屏蔽失效。而且Calibre往往不会给出明确的错误提示只会默默地按默认行为处理等你发现时已经浪费了大量时间。我现在养成的习惯是每次配置完hcell和xcell先跑一个小规模的测试case确认屏蔽生效后再跑全芯片。测试case里故意放几个需要屏蔽的cell跑完后检查网表里有没有这些cell的内部节点。这个习惯帮我省下了很多返工时间。另外日志文件一定要仔细看。Calibre的PEX日志里会记录hcell和xcell的匹配情况包括匹配了多少个cell、哪些没有匹配上。这些信息是排查问题的第一手资料比盲目猜测高效得多。最后再分享一个小技巧如果项目里用了大量标准单元可以在xcell文件里用通配符批量屏蔽但一定要先用grep在版图网表里确认匹配范围。我见过有人写了*_CELL结果把顶层cell也匹配进去了PEX直接跑失败。通配符是把双刃剑用好了省事用不好就是灾难。