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屏蔽的cell,Calibre在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_TOP,xcell文件里写成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阶段如果有很多warning,PEX阶段大概率会出问题。
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直接跑失败。通配符是把双刃剑,用好了省事,用不好就是灾难。