☰
用Calibre SVRF脚本合并两个GDS的完整指南
2026/10/3 4:01:29 网站建设 项目流程

1. 为什么要把两个 GDS 拼在一起

先说清楚一个容易混淆的概念:在芯片后端设计里,GDS 文件不是画图软件里的一张图纸,而是一个包含分层、坐标、多边形和引用关系的版图数据库。你拿到的“两个 GDS”,可能是两个模块分别导出的版图,也可能是不同工具流出来的数据源,Calibre 本身不承担绘图功能,它靠的是自己这套 SVRF 规则语言在后台做几何运算和逻辑判断。把两个 GDS 拼到一起,核心就是利用 SVRF 规则文件,将两个 GDS 的几何图形、层次信息和 cell 结构加载到同一个版图空间里,再按需调整位置与层次关系。

我在实际项目里遇到这类需求,通常来自下面几种场景。

第一种是模块级整合。比如模拟前端给你一个 analog 模块的 GDS,数字那边给你一个 digital block 的 GDS,后端要把两个模块对到一个芯片 layout 上,验证整体连接关系。这时候不是简单地在 KLayout 里把两个文件拖进同一个界面,而是要按芯片的 floorplan 坐标系统,把两个模块放到正确的位置、对齐到同一个 assert 网格上。

第二种是 full-chip 合并。多 die、多通道设计,或者是多个 IP 拼接,需要把分属不同团队、不同 PDK 基准甚至不同版图工具产出的 GDS,统一 merge 到一个顶层版图里,做最终的 DRC、LVS 和密度检查。

第三种是改版和 ECO。某个模块被替换过了,或者工艺版本升级导致某些层次被重新映射,你希望把新旧两个版本的关键层次拼在一起,对比差异或者生成 mask 文件。

不管场景是哪一种,拼 GDS 这件事本质上都绕不开几个关键点:cell 结构、层次映射、坐标对齐、合并规则。其中最容易出问题、也最影响验证结果的就是坐标对齐——你必须先搞清楚每个 GDS 自身的坐标系原点在哪,才能保证拼完之后两个模块的相对位置正确。很多人上来就用 Calibre DESIGNrev 手动拖,结果保存出来的版图坐标一塌糊涂,后面 LVS 报出一堆 cell 边界不匹配,排查到怀疑人生。

下面我按实际操作顺序,把完整方案拆开来讲,包括了 SVRF 脚本的写法、坐标对齐的具体操作、以及我在多项目里反复踩过的坑。

2. GDS 结构、坐标系统与合并的核心思路

2.1 GDS 文件到底“长”什么样

在动手之前,你得对 GDS 的底层结构有个基本认知。GDS 里最基本的单位是 BOUNDARY(多边形)和 PATH(连线),再加上 TEXT(文字标注)、SREF(cell 引用)和 AREF(矩阵引用)。一个 top cell 可以引用若干个子 cell,子 cell 也可以引用更底层的 cell,这种嵌套结构跟代码里的函数调用是一个概念——原本模数模块里可能有好几个 levels 的 cell 层级,当你把两个 GDS 合并时,顶层 cell 的名字、层叠关系和引用路径都必须保证不冲突。

如果你打开 GDS 的 ASCII 转换文件(比如用 Calibre 的 gds2ascii 导出),你会看到类似下面的结构:

HDR ENDLIB BGNSTR STRNAME TOPCELL LAYOUT CELL TOPCELL ... BGNSTR STRNAME MODULE_A BOUNDARY LAYER 45 XY 1000 1000 2000 1000 2000 2000 1000 2000 1000 1000 ENDEL ENDSTR ... ENDSTR ENDLIB

我建议你在合并之前,先用工具查一下两个 GDS 的 cell 列表和顶层 cell 名。如果两个文件里都出现了相同的 cell 名字,但又各自定义,就会出现名字冲突。Calibre 加载时会自动做 rename 吗?答案是不会自动做,而是直接报错或者按顺序覆盖,这就会造成几何丢失,务必要先检查。

2.2 坐标系统:拼之前必须搞懂“原点”

拼 GDS 最核心的一个问题是“对齐”,而“对齐”的前提是两个人对“原点”的口径一致。绝大多数情况下,IC 版图工具(如 Virtuoso、ICC2、Innovus)导出 GDS 时,坐标原点是 (0,0),单位通常是微米或纳米,而 GDS 内部的最小单位是数据库单位(database unit),由导出工具决定。

举个例子,A 模块的原点在左上角,它的 geometry 从 (0, 0) 到 (500, 300);B 模块的原点在模块中心,它的 geometry 从 (-250, -150) 到 (250, 150)。如果直接把两个文件都当成“完整版图”去 merge,B 模块就会有一半坐标落在负区间,整个文件加载后看起来就是乱七八糟的。所以正确思路是:先确定顶层版图的原点坐标约定,再决定每个子模块该以什么基准放入。

这里我给一个比较实用的“坐标对齐流程”:

  1. 先找顶层 floorplan 文档,确认每个模块的放置原点坐标,比如 A 模块左上角位于 (0,0),B 模块左上角位于 (5000, 0)。
  2. 检查每个子模块自身 GDS 里的几何包围盒(bounding box)是否已经按照顶层坐标写好。很多后端工具在导出模块 GDS 时,坐标已经是 floorplan 里的绝对坐标了,这时候直接把两个 GDS merge 到一个 top 下就行,不需要额外平移。
  3. 如果子模块 GDS 的坐标是 local origin(比如以模块自己的原点为准),就需要在合并脚本中做 MOVE 或者用 cell origin 转换,把它平移到目标坐标。

2.3 合并方案如何选择

Calibre 体系里合并 GDS 的主要途径分三类,我按推荐顺序排列。

第一类是写 SVRF 规则文件,用 LAYOUT FLATTEN 把两个版图合并到一层 cell 结构里。这类方法是首选,因为可控性最强——你可以在一个规则里同时完成加载、层次映射、平移、合并多个动作,对批量处理也友好。

第二类是使用 Calibre DESIGNrev 的交互式 GUI 版图界面。它有直接的 Import 和 Merge 功能,但我在多项目实践中发现,GUI 操作适合临时看一下版图、做小规模验证,不适合做精确到坐标的批量合并,因为 GUI 里手动拖动的精度和可重复性都比较差。

第三类是用 KLayout 这类第三方工具中转处理。KLayout 支持多个 GDS 的叠加,但当涉及 Calibre 后续验证流程时,你需要重新导出 GDS 并在 Calibre 规则里重新映射层次,这等于是额外增加了一步文件转换环节,而且 KLayout 里处理过的层次名称和坐标导出精度,总归跟原生 Calibre 环境有差异,容易埋坑。

我个人最推荐的做法是:弄清楚两个 GDS 的层次构成之后,直接用 SVRF 脚本做合并,整个过程可追溯、可重复、精度高。接下来我把 SVRF 合并脚本的写法、参数含义和常见坑讲透。

3. 用 SVRF 脚本把两个 GDS 加载到一起

3.1 脚本的基本骨架

SVRF 是 Calibre 验证规则的脚本语言,它看起来像是一种声明式的规则,但执行起来是按拓扑逐层去做的。你可以在一个规则文件里写多种操作,Calibre 会依次解析执行。拼 GDS 最基本的脚本骨架如下。

LAYOUT PATH "/path/to/module_A.gds" LAYOUT PATH "/path/to/module_B.gds" LAYOUT FLATTEN TOPCELL "merged_top" MODIFY LAYOUT HIERARCHY PREFIX "A_" ... LAYOUT HIERARCHY PREFIX "B_" ...

让我分别解释一下每一行的意义。

LAYOUT PATH用于指定要加载的 GDS 文件路径。Calibre 允许指定多个输入文件,后续层叠操作会对所有已加载的数据生效。

LAYOUT FLATTEN是核心命令。它会把指定 cell(或全部 cell)展平,并输出一个新的顶层 cell 名。当你要合并两个 GDS 时,不能简单地把两个文件写成两个LAYOUT PATH,然后指望它们自动合并成一个 cell——必须显式地 FLATTEN 到一个新的顶层 cell 之下。

LAYOUT HIERARCHY PREFIX作用是为来自不同 GDS 的 cell 增加前缀,这样能保证两个库里的 cell 名称不会重叠。比如 module_A.gds 里有 cell "inv_std",module_B.gds 里也有 cell "inv_std",合并后如果不做前缀处理,两个 cell 就会被解析成同一个 cell 对象,导致引用关系错乱。加上前缀后,它们变成 "A_inv_std" 和 "B_inv_std",互不影响。这一点极其容易被忽略,但往往就是它决定你敢不敢放心跑后续的 LVS 和 DRC。

3.2 多文件合并的进阶写法

刚才的骨架只是把两个版图加载进来做展平,但如果只是展平,你不一定能控制它们的具体位置。我通常在项目中用的更完整写法会加上坐标变换、层次过滤等操作,如下所示。

LAYOUT PATH "/home/design/module_A.gds" LAYOUT PATH "/home/design/module_B.gds" // 将 A 所有 cell 加前缀 A_ LAYOUT HIERARCHY PREFIX "A_" 1 0 0 // 将 B 所有 cell 加前缀 B_ LAYOUT HIERARCHY PREFIX "B_" 2 0 0 // 建立顶层 cell,并把 A、B 都展平进来 LAYOUT FLATTEN TOPCELL "merged_top" MODIFY // 对 A 模块做坐标平移 TRANSFORM MASK LAYOUT "merged_top" CELL "A_TOP" MOVE BY 1000 500 TRANSFORM MASK LAYOUT "merged_top" CELL "B_TOP" MOVE BY 5000 0

注意这里TRANSFORM MASK ... MOVE BY的坐标是一个相对平移量。如果你希望把 A_TOP 模块的原点放到 (1000, 500) 处,就用这个相对量。如果 A_TOP 已经采用绝对坐标,则不需要再次 MOVE,直接MOVE BY一个 0 偏移量即可。

还有一种更常见的做法是先把两个 cell 放到正确的绝对坐标,然后统一展平。比如在 Virtuoso 里导出模块 GDS 时直接使用全芯片坐标,这种情况下你甚至不需要TRANSFORM,直接展平,两个模块的 geometry 就会落在它们应该在的顶层相对位置。

我建议你在脚本里额外加上层次过滤,只保留你真正关心的层次。

LAYOUT FILTER LAYERS "45 14 15 18 21"

LAYOUT FILTER LAYERS可以在展平过程中把不需要的层次直接过滤掉,不仅让结果文件更干净,也能减少后续 DRC/LVS 报错时的干扰信息。拼 GDS 之后跑 LVS 时,最烦的事情之一就是看到密密麻麻一千条关于金属密度和 dummy 层次的问题,很多其实是保留了你根本不想参与检查的层次造成的。

3.3 尺寸对齐:处理不同模块的包围盒与原点

热词里提到“且尺寸要对齐”,这往往是两个模块的大小、原点、网格不一致造成的。拼 GDS 时“尺寸对齐”不是指把图形放大缩小到一样大,而是指它们各自在顶层坐标系里的位置和边界正确。

比如 A 模块的坐标跨度是 (0,0) 到 (1000,500),B 模块的坐标跨度是 (2000,0) 到 (3000,700)。你希望 A 模块和 B 模块左右拼在一起,A 的右边界紧贴 B 的左边界。这里要注意 B 模块的几何在导出时是从 (2000,0) 开始的,而不是 (1000,0),所以拼的时候你需要让 B 的左上角落到 (1000,0) 这个坐标上——如果你不管坐标,直接把两个文件展平,A 和 B 的几何之间会有 1000 微米量级的空隙,DRC 报“dup cell area”或者“overlap”时你根本不知道问题出在哪。

其实最稳妥的核对方法,是用 Calibre DESIGNrev 加载原始 GDS,逐个测量包围盒坐标。在设计工具里,你通常能看到每个 cell 的 bbox(比如bbox = (xmin, ymin, xmax, ymax))。你把这些 bbox 整理成一个坐标表,然后在 SVRF 脚本里逐一对 sub-cell 做平移,确保边界坐标对齐。这一步一定要写成文档和脚本,因为一旦下周要换一个模块版本,你需要重新核对坐标表。

如果两个模块的网格(grid)不一致,比如 A 是 0.005 网格,B 是 0.001 网格,合并后顶点会出现很多非均匀坐标。DRC 工具对网格不一致的问题通常不会直接报错,但在后续 mask 数据合并时,EDA 工具链可能会出警告,甚至影响物理验证的清洗。经验做法是:以较细的网格为基准,把所有多边形顶点吸附(snap)到共同网格,一般 snap 到设计规则允许的最小网格即可。这一步可以用 SVRF 的LAYOUT GRID SNAP完成,也可以直接在 KLayout 里预处理,但 KLayout 预处理后要注意层次名映射。

4. 核心实操环节:完整合并流程复现

4.1 从坐标表到平移到展平的完整示例

我拿一个真实项目的简化版来演示。假设我有两个模块:

  • analog_top.gds:顶层 cell 叫ANALOG_TOP,bbox 为 (0, 0) 到 (1000, 800),所有图形坐标已经是绝对坐标。
  • digital_top.gds:顶层 cell 叫DIGITAL_TOP,bbox 为 (0, 0) 到 (2000, 1200),但它导出时用的是模块本地坐标,没有平移到全局坐标。

我计划让DIGITAL_TOP的 (0,0) 对齐到全局坐标的 (1100, 100) 处,即模拟芯片中数字模块放在模拟模块右侧、向上偏移 100 单位的位置。

那么我在 SVRF 脚本里就可以这样写。

LAYOUT PATH "/proj/merged_top/output/analog_top.gds" LAYOUT PATH "/proj/merged_top/output/digital_top.gds" LAYOUT HIERARCHY PREFIX "ANA_" 1 0 0 LAYOUT HIERARCHY PREFIX "DIG_" 2 0 0 LAYOUT FLATTEN TOPCELL "chip_merged" MODIFY // analog 不需要平移,可以加一个空移 TRANSFORM MASK LAYOUT "chip_merged" CELL "ANA_TOP" MOVE BY 0 0 // digital 平移:x 从 0 到 1100,y 从 0 到 100 TRANSFORM MASK LAYOUT "chip_merged" CELL "DIG_TOP" MOVE BY 1100 100 // 展平子 cell,输出最终 GDS LAYOUT FLATTEN TOPCELL "chip_merged" OUTPUT LAYOUT "/proj/merged_top/output/chip_merged.gds"

这里LAYOUT FLATTEN出现了两次,第一次是建立新的顶层 cell 并把两个模块挂进去;第二次是在做完平移变换后,把内部层级真正展平,输出一个简洁的 flat GDS。实际使用中你可能不希望完全展平,因为完全展平后文件体积会急剧膨胀,而且层次信息全丢。我通常会用LAYOUT FLATTEN TOPCELL "chip_merged"加一个可选的RESOLUTION参数来控制展平级别,或者干脆保留子 cell 层级、只展平父层。Calibre 支持这种部分展平的用法,具体参数可以查手册。

4.2 用 DESIGNrev 校验合并结果

合并完成后,务必用 Calibre DESIGNrev 打开输出文件,亲自看一遍拼完的实际效果。这一步我会做三个检查:

第一,跑一个DRC流程,哪怕只是最简单的间距检查,确保两个模块拼接处没有异常 overlap 或者间距冲突。很多人以为合并就是“文件操作”,跟 DRC 没关系,但实际上两个模块边缘可能由于网格或形状误差造成 0.001 级的侵入,DRC 一跑就现原形。

第二,检查 cell 名称和层映射。用LAYOUT LIST CELLS、LAYOUT LIST LAYERS命令查看输出 GDS 的 cell 列表和层次列表,确认没有引入意外的 cell 名或重复层次。

第三,检查坐标。在 DESIGNrev 里,打开 merged cell,用 ruler 量一下模拟模块的右边界和数字模块的左边界之间的间距,对照坐标表确认是否符合预期。

下面这个表格是我在项目里常用的一份“合并前检查清单”,每次拼 GDS 前都会过一遍。

检查项目操作预期结果
Cell 名冲突LAYOUT LIST CELLS两个 GDS 中不出现同名不同定义的 cell
层映射对比 PDK layer map合并后层次号与设计层次一致
坐标基准bbox 对齐检查各模块 bbox 与定义坐标一致
网格统一检查坐标小数位数所有顶点坐标落在允许网格上
顶层 cell确认顶层 cell 名唯一合并后只有一个 topcell,无循环引用

4.3 大量单元拼装时的自动化思路

如果只是两个 GDS,手动写脚本完全够用。但如果你有十几个模块,甚至几十个 GDS 文件要拼成一个 top,手写TRANSFORM会变得异常繁琐,也容易抄错坐标。遇到这种情况我会写一个小脚本来生成 SVRF 文件:用表格维护“模块名、GDS 路径、目标 X、目标 Y、是否翻转、是否加入前缀”,然后脚本直接编译出规则文件。

拿 Python 举个例子,脚本核心逻辑如下。

import csv modules = [] with open("merge_config.csv") as f: for row in csv.DictReader(f): gds_path = row["gds_path"] cell_name = row["cell_name"] target_x = float(row["target_x"]) target_y = float(row["target_y"]) prefix = row["prefix"] modules.append(...) svrf_lines = [] for i, m in enumerate(modules): svrf_lines.append(f'LAYOUT PATH "{m.gds_path}"') svrf_lines.append(f'LAYOUT HIERARCHY PREFIX "{m.prefix}" {i+1} 0 0') svrf_lines.append('LAYOUT FLATTEN TOPCELL "chip_merged" MODIFY') for i, m in enumerate(modules): svrf_lines.append( f'TRANSFORM MASK LAYOUT "chip_merged" ' f'CELL "{m.prefix}{m.cell_name}" ' f'MOVE BY {m.target_x:.3f} {m.target_y:.3f}' ) svrf_lines.append('OUTPUT LAYOUT "/proj/output/chip_merged.gds"')

这里要注意的一个细节:: .3f是格式化成三位小数,但如果你的版图网格更细,别盲目截断坐标。坐标精度丢失是很多人在自动生成脚本时最容易忽略的坑。你应该从原始 floorplan 数据里直接读坐标,或者用设计数据库脚本导出,而不是在表格里手敲到有限位小数。

5. 实测中常见问题与定位技巧

5.1 “合并后 cell 重叠或者丢失”怎么办

这个问题我在早期项目里碰到过很多次。表面上看是两个 GDS 都加载进来了,但最后生成的版图里总有部分图形消失,或者两个模块的图形叠在一起。原因往往出在两处。

第一处是顶层 cell 引用重复。比如两个 GDS 都包含一个叫TOP的顶层 cell,而你在LAYOUT PATH把它们加载进来时,没有加前缀,Calibre 在处理时会认为这是同一个 cell,后加载的会覆盖先加载的,导致其中一个模块整体消失。解决办法就是我前面提到的LAYOUT HIERARCHY PREFIX——对所有输入 cell 都加前缀,确保名称唯一。

第二处是展平层级混乱。如果你在LAYOUT FLATTEN之前没有对子 cell 做重命名,Calibre 会自动生成一些临时 cell 名,有一种情况是 cell 的引用被重复创建,导致看起来像多个 cell 叠放在一起。这种情况你把输出 GDS 再导回 Virtuoso 或 KLayout,会看到 cell tree 里面同一个 cell 出现了很多份。如果你做 DRC,DRC 会报海量 poly overlap。解决办法是增加LAYOUT HIERARCHY PREFIX之后,再显式重设顶层 cell 名,多用几次LAYOUT FLATTEN的MODIFY参数。

5.2 “坐标对不上,差了一个固定值”的排查逻辑

坐标对不上是最让人头疼的问题,因为看起来每一步都对,但最终量出来总是差。我的经验是把排查顺序固定下来,能省很多时间。

第一步,确认双方 GDS 的 database unit。A 工具导出时 DBU=0.005,B 工具导出时 DBU=0.001,它们各自记录的坐标数值可能是同样的数字,但实际物理尺寸差 5 倍。如果直接合并,把两个文件当成同一个坐标空间,你看到的结果会突然“变大变小”。解决方式是转成统一的 DBU,通常在 SVRF 脚本里写LAYOUT UNITS或者工具选项来转换,也可以在导出 GDS 前在来源工具里统一单位。

第二步,确认你的 MOVE 坐标系方向。有些工具里 Y 轴方向是向上,有些图形界面上可能向左下角,但 GDS 内部通常遵循右手坐标系。如果你在脚本里把 X 和 Y 写反了,就会出现对称性的错位。

第三步,确认预制件 unit cell 的 offset。比如你用的 standard cell 库或者 SRAM compiler 生成模块时,cell 的原点可能不在 cell 左下角,而是在它的中心,或者在一个 corner。如果模块导出时没有把这一点修正过来,坐标就会偏移 cell 大小的一半。这类问题靠肉眼很不好找,我一般用脚本一次性量取每个 cell 的 bbox,再和预期坐标表比对,能快速定位。

5.3 合并后 DRC/LVS 结果异常怎么办

合并 GDS 之后跑 DRC/LVS 出现异常,未必是布局有错,也可能是验证环境没适配。最常见的一种情况是:合并后的 GDS 里保留了原始 cell 边界(boundary layer),顶层版图里也出现了新的边界,DRC 把新旧边界都当成图形来查了,于是报出一堆间距错误。解决方法是把不需要的 boundary 层通过LAYOUT FILTER LAYERS过滤掉,或者检查设计规则文件是否允许 boundary 层存在。

还有一种情况是 text 层次被重复引用,LVS 里出现重复 label 会导致器件识别失败。如果你是拼两个不同来源的 GDS,上面可能各自带有 label text,合并后 label 位置重叠,LVS 会认为一个节点上存在多个 label。解决方式是把非顶层 text 层过滤掉,或者在展平后对顶层 cell 重新做一次 text attach 操作。

我整理了一份常见的合并异常速查表,内容和解决思路如下。

问题现象常见原因解决思路
cell 丢失顶层 cell 重名互相覆盖给每个 GDS 加 cell 名前缀
图形整体偏移DBU 单位不一致或 MOVE 坐标错误统一单位,核对 MOVE 方向与数值
局部图形重叠子 cell 引用路径重复使用LAYOUT HIERARCHY PREFIX后展平
DRC 报大量边界错误boundary 层参与检查用LAYOUT FILTER LAYERS过滤
LVS 识别多 labeltext 层跨模块冲突统一 label 和 text 层映射
输出 GDS 过大完全展平导致数据膨胀用部分展平替代,保留合理层级

5.4 一个很容易被忽略的小技巧:输出前使用 SVRF 自动检查

合并脚本写完以后,我建议先用 Calibre 的语法检查模式跑一遍规则文件,不加任何 DRC/LVS 命令,只让 Calibre 解析并定位到输出 GDS 这一步。这种做法能尽早暴露语法错误和层级引用问题,而不是等到全套流程跑完才发现坐标错位。我在命令行下常用的命令格式类似:

calibre -svrf -rules merge_gds.svrf -turbo 4

如果不想一次性处理大量数据,也可以在规则里加上分段输出,先输出一个包含几十个 cell 的中间结果,用 DESIGNrev 快速验证位置,再放开全量合并。分段输出的好处是查错时不用反复读巨大的输入文件,尤其是某些 IP 的 GDS 动辄几个GB,每次重跑一遍很浪费时间。

6. 我的经验总结与实用心得

做了这么多合并 GDS 的活,我最想强调的一点是:不要把“拼 GDS”看成文件操作,要把它看成物理设计验证流程的一部分。哪怕只是临时把两个模块拼到一起跑个 DRC,你也要像跑正式 tapeout 一样去核对坐标、层次、单位和网格。因为只要某一个环节有偏差,后面的结果全都会跟着歪,而且歪得很隐蔽。

我个人的固定习惯是,每个合并任务开工前先建一个简单的文本文件,把以下信息写清楚:

  • 所有输入 GDS 的路径、版本号、和来源工具。
  • 每个 GDS 的 DBU 和单位。
  • 每个模块对应的目标坐标。
  • 合并后的顶层 cell 名称。
  • PDK 层映射表的版本。

这样一份记录每次都能帮我省掉至少半小时的排查时间。尤其是当模块版本更新了,但坐标表没更新的时候,没有记录你根本说不清是哪里变了。

我也建议大家用 SVRF 脚本而非纯 GUI 操作,哪怕最开始觉得写代码门槛高。原因很简单:GIU 拖一次可能就完事了,但你怎么向别人证明你的坐标对?怎么在下一次版本更新时重复执行?脚本可以留痕,可以走版本管理,可以批量跑,一旦标准化之后,合并 GDS 这件事就变成一个可复用的流程动作,而不是每次都得重新摸索一遍的临时操作。如果你担心脚本复杂度,也可以先用 KLayout 或 DESIGNrev 交互式预览一遍,确认两个模块的相对位置关系,然后再把坐标写进 SVRF——这样既保证了直观确认,又保证了流程的规范化和可重复性。

最后再补充一个小技巧:如果你拼接的两个模块在物理上严格相邻,我建议在两个模块之间预留一个小间隙,而不是让边界恰好贴在一起。这样在 DRC 时能够清楚区分模块边界,也不会因为网格精度问题出现莫名的小 overlap。我最初做合并时,喜欢把两个模块的边界精确对齐,结果每次 DRC 都会报出边界处的一些微小间距违规,查来查去发现就是坐标 snap 的零点几个纳米的误差导致的。留出间隙之后,这类问题几乎消失,也让你后续做模块边界检查更轻松。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询