做版图的人,遇到“把两个GDS拼到一起”这种需求太常见了。比如顶层芯片还没集成某个IP的物理实现,要把IP的GDS嵌到顶层指定位置;或者一个项目分成了几个partition分别做完,流片前要合成一个完整GDS;再比如数字模块和模拟模块分开画,最后要合到一个库里统一跑DRC/LVS。我用Calibre处理这类合并操作比较多,每次都会被问到“是不是直接把文件A的内容复制到文件B里就行”。如果只是打开两个文件手动复制图形,那大概率会踩到单元层级、坐标原点、数据库单位、图层映射、重名单元这些坑。这篇我用实际操作的视角,把“Calibre里怎么把两个GDS拼到一起”讲透,包括合并的本质、Calibre DESIGNrev的图形化操作、KLayout辅助对齐的备选路线,以及合并后最容易出问题的地方。
1. 合并的本质:不是把两张图叠在一起
1.1 GDS的层级结构:Cell和Instance
GDSII(通常直接叫GDS)是一种层次化版图数据格式,所有图形都放在Cell(单元)里,Cell之间通过Instance(实例引用)形成树状结构。你可以把Cell理解成“零件图纸”,Instance就是“装配图上某个位置放了一个零件”。顶层Cell是整颗芯片的入口,里面引用下一层Cell,下一层Cell又引用更底层的单元,叶节点里才是实实在在的多边形、路径、边界这些图形。
所以“把两个GDS拼到一起”,本质不是把图形文件合并成一个平面,而是要把两个Cell库合并,并把各自的顶层Cell作为Instance挂到同一个父Cell下,或者把一个库的顶层Cell作为子模块放进另一个库的顶层Cell里。如果只是把两堆多边形硬塞进同一个文件而不处理Cell之间的引用关系,后续Calibre做DRC、LVS时会找不到被引用的Cell,或者引用错版本,整个验证流程都会乱掉。
1.2 为什么必须保留“引用”而不能直接拍平
我见过有人图省事,合并时直接把所有Cell打个勾“Flatten All Cells”,把全部层次拍平成一张图。小模块几十个Cell可能没事,但只要数据量一大,问题立刻冒出来:文件体积暴涨,打开卡顿,DRC跑几个小时都跑不完,LVS更是没法做,因为网表对照时需要靠Cell边界和pin来识别器件,全拍平后这些边界信息虽然还在,但层级信息全丢了。
有一个比较直观的类比:GDS的层次结构就像一本字典,Cell是词条,Instance是词条之间的交叉引用。把两本字典合并,不是把两本书的纸订在一起,而是要把两边词条整理到一个索引体系里。拍平操作等于把几千个词条全部展开成一行行文字,目录、索引全不要了,后面想查内容自然困难。
所以我在实际操作中,除非确认只是做一次快速预览,否则一定保留层次。Calibre DESIGNrev的合并操作默认也会保留Cell层级,这点在对话框里要特别留意,别手滑勾选了Flatten。
1.3 动手前先查三个值:DBU、顶层Cell和图层编号
合并前先做三件事,三个都查清楚了再动手,能避开后面一大半问题。
第一,查数据库单位(DBU,Database Unit)。DBU是GDS里定义的最小坐标单位,常见的有1纳米(0.001um)、0.005um、0.001um等。两个GDS如果DBU不一致,合并时坐标值不换算或者换算错了,模块尺寸和位置就会整体偏移。查看方法很简单,在Calibre DESIGNrev里打开文件时,状态栏或文件属性里能看到“Database Units per Micron”,比如1000代表1um=1000个DBU,也就是DBU=1nm。
第二,确认顶层Cell名字。每个GDS通常有一个顶层Cell,但实际项目里经常出现“top”和“Top”大小写不同、或者两个文件都叫“chip”但内容完全不同的情况。合并前先想清楚:谁当最终顶层,第二个文件是作为子模块放进去还是也要出现在顶层下面的同一级。这决定了在合并对话框里选择“合并到当前Cell”还是“合并到新建Cell”。
第三,确认图层编号(Layer Number)和数据类型(Datatype)。GDS里的图形靠“Layer + Datatype”标识,比如金属1可能是layer 31 datatype 0。不同IP供应商或者不同工具导出的GDS,同一物理层的编号可能完全不一样。如果两个GDS的图层编号对不上,合并后要么层显示一团糟,要么后续DRC deck里的layer map找不到图形。
另外说一句工具获取的话题:有人搜“calibre designrev下载地址”,Calibre是商业EDA套件,正规途径是公司EDA环境或者Siemens EDA官方申请评估license。网上流传的绿色/破解版版本旧、缺模块,我见过有人拿它merge大GDS直接崩掉,最后还得回归正版。如果只是预览和简单拼版,可以先用KLayout开源工具,后面我会详细说。
2. Calibre DESIGNrev图形化合并实操
2.1 打开主GDS文件
正式合并前,先把主GDS文件打开。启动Calibre DESIGNrev后,File菜单下选择Open,在文件过滤器里选GDSII格式,找到主文件(也就是最终要作为基础的那一个GDS)打开。
打开后先看两件事:一是状态栏里的DBU信息,确认它和你预期的一致;二是Cell层级树面板(通常叫Cell Manager或Layout面板)里顶层Cell的名字。如果主文件里有多个Cell都像顶层,就先把真正的顶层Cell设为当前视角,通常双击Cell节点或者右键Set As Current可以做到。
这里有个经验:如果主文件本身很大,比如几个GB,建议打开时不要加载全部显示层,先只打开要用的图层,等合并完再全开。Calibre DESIGNrev打开大文件时可以指定图层过滤,减少内存占用。否则两个大GDS同时加载,很容易出现内存不够的情况。我一般会把两个GDS先各自转成OASIS格式(如果工具支持)再打开,OASIS体积小很多,打开和合并都更快。
2.2 用Merge Data把第二个GDS并入
在主文件打开正常的情况下,在File菜单附近找到Merge Data或者Import Data入口(不同版本叫法略有差异,有的版本是Data菜单下,有的版本在File菜单下,核心功能一样)。点开后指定第二个GDS文件。
这一步里最关键的几个选项要理解清楚:
合并到当前Cell(Merge to Current Cell)还是新建Cell(Merge to New Cell)。如果你希望第二个文件的顶层Cell成为主文件顶层Cell的子模块,选合并到当前Cell。如果想把两个文件都作为平级模块挂到一个新的顶层下,就选新建Cell。我大部分场景是要把IP嵌到顶层里,所以选前者。
单元名称冲突处理。两个GDS里很可能存在同名Cell但内容不同,对话框一般会提供“使用现有”“替换”或者“重命名导入Cell”之类的选项。强烈建议选择为导入单元加前缀或重命名,比如把第二个库的所有Cell统一加上“IP1_”前缀。这样不会覆盖主库里原有的同名单元。
数据库单位转换。默认情况下工具会以当前主库的DBU为准,第二个文件如果DBU不同会自动换算。但别依赖自动换算,最好提前把两个文件统一成相同DBU,可以在打开第二个文件后先看它的属性,确认DBU值。如果不一样,先用KLayout或Calibre的Save As功能把第二个文件转成与主库相同的DBU再合并。
是否复制空Cell(Include Empty Cells)。有些工艺库里会存在大量空Cell,默认可能不复制,但如果后续DRC脚本会引用这些Cell名字,还是建议保留,避免出现“missing cell”这类报错。
确认这些选项后点确定。Calibre DESIGNrev会把第二个GDS的Cell库并入主库,同时在层级树里出现导入的顶层Cell。这时候它还只是一个躺着没摆放的Cell,没有真正挂到目标位置上。
2.3 偏移、旋转、镜像:让尺寸严格对齐
“尺寸对齐”是拼GDS时最容易出问题的地方。这里说的对齐既是物理坐标对齐,也是单位量纲对齐。先算清坐标再输入参数,比在图形窗口里肉眼对齐靠谱得多。
先看目标Cell的边界框(Bounding Box)。在Cell层级树里选中要摆放的Cell,属性面板或菜单里能找到它的bbox坐标范围,比如从(0,0)到(200,300)微米。同时也要看主文件里目标位置的bbox。假设要把一个IO模块放到主芯片右上角外侧,IO模块自己的left-bottom逻辑原点在(0,0),主芯片右上角是(1000,800)微米,希望IO的左边贴合主芯片,留50微米间隔,那么IO模块原点要放在(1050, 800-300)=(1050,500)微米的位置。
这里要注意DBU换算。比如主库的DBU=1nm,那么X方向偏移1050微米换算成DBU就是1050/0.001=1,050,000。如果合并对话框里偏移参数以DBU为单位,就要填1050000;如果对话框里允许直接填物理单位,就填1050。不同版本对话框习惯不一样,填之前先看清楚单位标示。统一DBU的好处就在这里:如果两个文件DBU都是1nm,坐标数字可以直接用物理位置换算,少一层换算风险。
旋转和镜像也在这个界面里设置。有些模块在源库里是正向摆放,但目标位置需要旋转180度或者做一次镜像。旋转中心一般是当前Cell的本地原点,所以如果旋转后位置不对,通常是因为原点和旋转中心没配合好。一个稳妥做法是:先设旋转/镜像参数,再输入偏移量,最后在版图窗口里打开目标Cell的bbox显示,肉眼确认位置关系是否正确。
这里还要多说一句:GDS的坐标系是右手系,镜像操作会把旋转方向反转,所以90度旋转加镜像的组合结果很容易搞反。如果项目里对方向有严格要求,比如pin要和下一层金属对齐,建议先在KLayout里模拟一下变换结果,确认方向正确后再到Calibre DESIGNrev里输入统一的参数。
2.4 保存输出文件并快速复查
合并完不急着保存,先在版图窗口里缩放检查一遍。把目标Cell的bbox和模块的实际位置都打开,看看是否重叠、是否超出边界、间距是否正确。如果模块需要放在芯片外面(比如某些IP的dummy block),还要确认不会和别的单元重叠。
检查没问题后,File菜单下选择Save As,输出格式选GDSII(如果你想兼容性足够),或者选OASIS(如果后续工具支持,文件更小,读写更快)。保存时再确认一次DBU设置,防止保存过程中被改成别的单位。
保存完,我习惯重新打开一遍刚保存的文件,做三个快速复查:第一,顶层Cell是不是预期的那个;第二,导入的Cell是否出现在层级树里并且引用关系完整;第三,数据库单位有没有变化。这三个都没问题,再继续后面的DRC/LVS流程。
3. 备选路线:脚本化批处理与KLayout预处理
3.1 把GUI操作固化成脚本,适合重复合并
如果只是偶尔拼一次GDS,用GUI点几下没问题。但如果一周要拼几十组数据,或者每次merge完还要做同样的图层过滤和单元重命名,那就得考虑把操作脚本化。
Calibre DESIGNrev本身支持把一些操作记录成命令序列或者Preference文件,也可以在工作目录里保存上次的会话配置。实际操作时,先把一次完整的merge操作在GUI里跑通,然后检查工作目录下生成的配置文件或日志,里面通常记录了读取的库、合并选项、输出格式等信息。后续要重复执行时,可以通过命令行参数或者启动脚本加载同样的配置,再替换输入文件名。
不同版本的Calibre对脚本化支持程度不一样,所以我不在这里给一个死命令,只建议先看看自己环境里有没有以下文件:工作目录下的命令日志、启动时的-pref后缀文件、或者.designrev文件。如果公司里有熟悉Calibre流程的工程师,直接问他们拿一份现成的merge脚本模板,比自己从零研究快得多。
没有Calibre DESIGNrev环境也没关系,批量合并可以拆成两块:先用KLayout或脚本统一DBU和加前缀,再回到Calibre做正式merge。把预处理做好,GUI里的操作就会非常机械,点起来不容易错。
3.2 KLayout也能拼GDS,关键是先统一DBU
KLayout是开源工具,用来做GDS/OASIS预览和简单拼版非常方便,很多没有Calibre DESIGNrev授权的人会用它在Windows下看图、转格式、做小规模合并。
在KLayout里合并两个GDS的基本思路是这样的:用File菜单打开主库GDS,然后用Import(或者在Cell树里通过插入Instance的方式加载另一个库文件)把第二个GDS导入。导入后,Import对话框通常会让你确认目标库和源库、数据库单位换算方式、以及图层映射关系。把第二个文件的内容作为一个Cell库加进当前版图后,在Cell树里找到它的顶层Cell,把它作为Instance插到主Cell里,再用左下角坐标输入框输入精确的X/Y位置。如果要旋转镜像,在Instance属性里设置相应的变换参数。
KLayout好用的地方在于预处理能力:比如把第二个库的所有Cell加上统一前缀,可以用KLayout的脚本遍历Cell树重命名;统一DBU可以在Save As时调整数据库单位,或者在导入时手动指定缩放因子;图层编号映射可以在导入时加载一个layer map文件。
但我的建议是,KLayout适合做“合并前准备”和“合并后快速检查”,最终进入signoff流程的合并结果,还是应该用Calibre DESIGNrev跑一遍再保存。因为后续DRC/LVS的环境是Calibre,同一个GDS在不同工具里解析出来的层级和坐标语义可能有细微差别,别再折腾出意外。
3.3 合并前后的“体检”清单
不管用哪条路线,我每次merge前后都会过一遍下面这个清单,标题叫“体检三件套”。
第一件,查DBU。打开源文件和目标文件,记录各自的Database Units per Micron。如果不一样,先转成一致再合并。这一步是尺寸对齐的基础,检查成本最低,收益最大。
第二件,查层次完整性。合并后打开Cell树,确认没有出现“unresolved reference”或者“missing cell”之类的报错。如果有,八成是第二个库里的某个Cell没有被完整复制进来,或者同名Cell被错误替换了。
第三件,查图层映射。打开Layers面板,对照源文件里的图层编号,确认每个关键物理层都在预期位置。如果你发现合并后金属层全跑到别的层号上,就要检查导入时的layer map设置。
这三件套做完,基本可以保证GDS在数据层面是干净、可用的。
4. 常见问题与排查:合并后到底哪里出了问题
4.1 DBU不一致导致的尺寸漂移
这是最常见的问题。症状是:合并后两个模块相对位置对不上,一个模块明显比另一个大了好几倍或者小了好几倍。比如A文件DBU=1nm,B文件DBU=5nm,B文件里画了一个长度10000单位的矩形,实际物理长度是50um,但在A文件看来,这个矩形只有10000纳米也就是10um。如果合并时没换算,整个模块尺寸就缩水了80%。
排查方法很简单:打开B文件属性,看它的Database Units per Micron是多少。然后打开A文件属性,看同样字段。两个值不一样,就统一成同一个再合并。如果用的KLayout做合并,导入时它会弹窗提示单位差异,一定要选择按比例换算,不要选“as is”。
4.2 单元重名和顶层Cell冲突
症状是:合并后某个Cell里的图形内容变成另一个库的版本,或者顶层多了好几个看起来一样的Cell,引用关系一片混乱。我踩过一个很典型的坑:两个模块里都有一个叫“cap_2x”的Cell,但尺寸和图形完全不同,merge时没注意重名,结果整个电容阵列的尺寸全错了,LVS怎么跑都不过。
解决方案就是我在前面反复强调的:在merge前给其中一个库的所有Cell加统一前缀,或者在上游工具里重命名。KLayout里可以通过脚本遍历所有Cell,加上“IP1_”这样的前缀。Calibre DESIGNrev的Merge对话框如果提供“Rename cells on import”选项,也直接勾选。重命名带来的副作用是某些底层的层次化引用关系也会变化,所以改完前缀之后一定要重新跑一遍体检,确认没有丢引用。
4.3 图层编号映射对不上
症状是合并后打开版图,发现图形都变成了一些莫名其妙的层,或者该显示金属的层空空如也。原因是两个GDS的layer/datatype定义不一致。比如主库的金属1是layer 201 datatype 0,而IP库的金属1是layer 31 datatype 0,合并时没有把31映射到201。
这种问题的解法是准备一个layer map文件,里面每行写“源层号 源datatype 目标层号 目标datatype”,在合并对话框或者后续DRC deck里加载。layer map的格式各家略有不同,但核心就是这种一一映射关系。如果公司有标准的LAYER MAP文件,直接拿过来用;如果没有,就对照工艺文件手工建一份,建好后记得让不同成员共享,避免各建各的又对不上。
4.4 数据量太大、内存不足、文件损坏
两个几GB的GDS合并,对内存和磁盘都是考验。症状是Calibre DESIGNrev卡死、报out of memory、或者保存时直接退出。优化手段有这么几个:合并前把两个文件都转成OASIS,体积能砍掉不少;合并时关掉不必要的显示层,别让工具把全层图形都加载进渲染;如果目标是拼版而不是保留详细层次,必要时只保留顶层和几个关键子模块,其他层过滤掉再merge。
另外,如果源GDS本身已经损坏,合并过程中会出现读取cancelled或者单元缺失。这时候回到源文件,用KLayout打开一次,如果能正常打开,再另存一遍;如果KLayout也打不开,那就是源文件有问题,让交付方重新导出。
4.5 合并之后DRC/LVS报错的快速定位
合并后的GDS拿去跑DRC,报了一堆错,不一定是merge本身的问题,也可能是在merge过程中弄丢了某些信息。快速定位方法很简单:把merge前的两个原始GDS分别跑一遍DRC,看看是否也报同样的错。如果原始文件跑出来是干净的,那就一定是merge过程引入的问题,重点查前面说的三类:Cell引用、图层映射、DBU。如果原始文件本身就报错,那是源库问题,与merge无关,先解决源库再说。
LVS出现missing instance或者short/open异常,多数情况是层次化结构被破坏。比如合并时把某个Cell拍平了,而LVS deck里又依赖这个Cell做器件识别,那就会大面积报错。这种时候回到merge对话框,确认没有勾选Flatten,或者重新选择保留层次的选项。
4.6 常见问题速查表
| 问题 | 可能原因 | 快速排查 | 解决方案 |
|---|---|---|---|
| 合并后尺寸不对、位置漂移 | DBU不一致且未换算 | 检查两个文件Database Units per Micron字段 | 统一DBU后再合并 |
| 同名字Cell内容被覆盖 | 两个库存在重名Cell | 对比两个库Cell列表 | 导入时加前缀或重命名 |
| 图层显示乱 | layer/datatype映射不一致 | 检查Layers面板 | 加载layer map文件 |
| 合并后某些Cell找不到 | 空Cell未复制或者引用不完整 | 查看unresolved reference | 勾选保留空Cell,重新merge |
| 文件巨大、卡顿 | 层次被拍平或显示层过多 | 检查文件大小和Cell层级数 | 保留层次、过滤显示层、使用OASIS |
| DRC新增大量报错 | merge破坏了层次或图层映射 | 原始文件单独跑DRC对比 | 定位是哪个环节引入后修复 |
5. 几句实操体会
我自身习惯的流程,已经有固定套路了:拿到两个GDS文件,先用KLayout做一遍预处理——统一DBU、给其中一个库的Cell加前缀、检查图层编号差异,把这些杂事先在免费工具里解决掉,然后回到Calibre DESIGNrev里做正式merge,保存成OASIS,最后再跑一小块区域的DRC做个快速验证。
这个流程听起来步骤多,但其实每一步都很短,加在一起比直接拖进Calibre里重复试错省时间。尤其“加前缀”这件事,我流片前吃过一次亏之后就一直坚持做,宁可多花五分钟处理命名,也不愿后面对着几千个报错挨个查。给准备做lge merge的同行一个建议:先花十分钟把两个文件的“性格”摸清楚(DBU、顶层Cell、层号),再做合并,你会发现Calibre其实很听话,大多数所谓“拼不了”“拼出来乱的”问题,其实都在合并前就埋下了。