☰
模拟版图0.005um格点DRC报错:从定位到修复的完整实操指南
2026/10/7 3:43:53 网站建设 项目流程

做模拟版图的人,估计十有八九都撞过这个坑:DRC跑下来,Rule Deck里的GRID检查永远报出一堆坐标不对;你放大看看,顶点明明就在网格线上,可DRC就是揪着不放。我自己在0.18um、0.13um到65nm几个工艺节点都被这个家伙折腾过,后来总结出一套从定位到修复再到验证的标准化流程,最快确实能控制在5分钟左右。这篇不是教科书,是我在实际项目中反复试过、能直接抄作业的实操笔记,核心是Cadence Virtuoso里0.005um格点DRC报错的三种修法,以及配套的GDS导出导入全流程。

1. 0.005um格点报错到底是怎么回事

1.1 先分清“显示格点”和“吸附格点”

很多新手一开始就被格点这个概念绕晕。在Virtuoso Layout Editor里至少有两种“格点”:一种是视觉上画在屏幕上的网格线,叫Display Grid,纯粹是给你看的;另一种是鼠标移动和坐标输入时最低能分辨的步进值,叫Snap Grid,这才是真正决定你画出来的边能不能落在指定坐标上的东西。你如果把Display Grid设成了0.005um,但Snap Grid是0.01um,那么你画的每一条边都只会落在0.01的倍数上,想要把一条线压到0.005的边上,鼠标根本“吸”不过去。

更麻烦的情况是,Snap Grid虽然设成了0.005um,但整个数据库的Database Unit不是0.001um。Virtuoso内部存坐标时一律按数据库单位存,常见的是0.001um也就是1nm。如果加工厂要求制造格点是0.005um,那么合法坐标就必须是5的整数倍,比如0.015、0.020、0.025。你手滑输入一个0.017,顶点就会落在“5的整数倍”之外,DRC的GRID检查一看到这种坐标就直接报错。

这个问题的隐蔽之处在于:很多边是Pcell参数化单元生成的,或者是多次复制、旋转、镜像后得到的。哪怕你画的时候很小心,只要中间某一步坐标没有对齐,最终版图里就会混入非格点坐标。你可以理解为,一个桌子的四条腿长度本身都是精确的,但只要有一条腿的尺寸差了半个螺丝位,整张桌子放到平台上就是不稳的。DRC里的grid check查的就是这条“腿”到底差了多少。

1.2 DRC的GRID检查到底查了什么

大多数PDK在规则文件里会写一条类似LAYOUT GRID 0.005的约束,有的写MANUFACTURING GRID,意思就是版图中所有多边形顶点的X和Y坐标,除以0.005之后的余数必须为0。注意它查的是“所有多边形顶点”,不是只查路径的起点终点,也不是只查版图边框。Virtuoso的DRC引擎会把每个多边形拆出来,逐个顶点做模运算。只要有一个顶点不满足条件,这个图形就被认为是非法图形。

这里我走过一个弯路:一开始以为DRC的GRID报错只和金属层有关,后来发现器件层、通孔层、甚至标签文本都可能导致非格点。尤其是文本,如果你在版图里放了带特殊坐标的label,它本身也是带坐标的对象,某些DRC会把它一起查进去。所以修复的时候不要只盯着金属线条,所有图层对象都要覆盖到。

另外要区分“格点报错”和“线宽/间距报错”。格点报错通常是DRC结果里类似GRID或者off grid的规则名,它不会告诉你具体哪个顶点有问题,只会告诉你哪个多边形。这时候你就得自己放大去看,或者用后面讲到的脚本把顶点坐标打出来。很多刚上手的人始终找不到问题点,就是这个原因——DRC只说“多边形离格了”,没说“离格的是哪一个顶点”。

1.3 为什么你的版图会“离格”

离格的原因我归纳下来也就这么几类。第一类是自己画的,输入坐标时手滑或用了公式计算出小数,最常见的是0.0153这种“看起来差不多”的数字。第二类是复制和旋转操作,Virtuoso在rotate 90度的场景下一般能保持整数坐标,但如果旋转角度不是90的整数倍,生成的坐标一定带更多小数。第三类是Pcell参数变化,比如你用某个工艺库的电阻,长度参数设成了0.432um,Pcell内部生成的多边形顶点可能就会落在0.001甚至0.0005的粒度上。第四类是外部数据导入,最典型的就是GDS从别的工具或者别家标准单元库导入后,由于数据库单位不一致,坐标被缩放,导致原本合法的坐标变成了非格点坐标。

知道自己“为什么离格”很重要,因为修复手段不一样。如果是自己画的,改Snap Grid后重新吸附就行;如果是Pcell产生的,你去手动吸附可能破坏参数化单元,下次改参数又变回原样;如果是GDS导入产生的,那就要从导出设置上解决。我通常在项目一开始就统一Snap Grid,并在导出GDS时设好00格点,这样能避免大部分问题在后端集成时才突然爆发。

2. 动手前的准备:先搞清楚你的工艺格点要求

2.1 从工艺文件里查真实格点

很多人默认0.005um就是格点,其实不一定。老工艺用0.01um,先进工艺可能是0.005um或者0.001um,甚至0.0005um。拿到一个新PDK,第一件事不是急着修DRC,而是确认制造端允许的最小格点是多少。我一般直接在CIW(Command Interpreter Window)里执行techGetGrid(),返回的就是当前techfile里的格点值。不同版本的Virtuoso函数可能有差异,但基本都能用。

另一个办法是打开工艺库对应的techfile文件,搜索grid关键字,通常能看到类似manufacturingGrid 0.005的定义。如果PDK已经拿到SMIC、TSMC这类厂家的标准安装包,里面一般还会附带DRC rule deck,你可以直接去runset里搜GRID。搞清楚规则文件里写的是0.005还是0.001,这决定了你后面所有修复操作的目标值。我见过一个项目,规则里同时存在两组格点约束,一组给poly和metal,一组给via,数值还不一样,这种就要分开处理。

2.2 统一Snap Grid和Display Grid

查清楚工艺格点后,打开Layout Editor,进入Options -> Layout Editor Options,把右侧的Snap Grid和Display Grid都设成目标格点。这里有个小细节:Snap Grid可以直接填0.005,Display Grid为了看得清楚通常设成0.005或0.01,二者最好是倍数关系,比如Display Grid设0.01,Snap Grid设0.005,这样屏幕上每一格都包含两条吸附刻度,视觉和实际操作能对上。如果Display Grid设0.003,Snap Grid设0.005,鼠标移动会感觉“一卡一卡”,而且很容易画歪。

还有一个全局参数在CIW里:envSetVal("layout" "snapSpacing" 'float 0.005),不同版本写法略有不同。如果想让整个项目的人都用同一套格点设置,可以在.cdsinit里统一写死。这么做的好处是避免“我的版图看着是对的,别人一编辑就全是格点错误”这种协作灾难。现实中很多格点问题不是画图那个人造成的,而是后一个维护者没有改Snap Grid就顺手拖了一下图形。

2.3 快速定位哪些Cell离格

手动一个个打开cell查效率太低。我的做法分两步:第一步,跑一次DRC,把所有GRID报错的坐标从结果里导出。DRC结果显示窗里一般有坐标信息,可以直接复制;如果没有,可以加载“Highlight”或“Zoom To Error”逐个定位。第二步,如果报错数量多到上百个,直接写一个简短的SKILL脚本遍历当前library下所有layout,把所有多边形的顶点坐标都打出来,判断是不是0.005的整数倍。

脚本思路并不复杂:遍历library下的每个cellview,拿到所有shape对象,如果是polygon或path,就读取它的points,对每个坐标点做mod(x, 0.005)判断。我通常只把非零的打印出来,这样能快速得到一张“离格清单”。SKILL的语法在不同版本有点差异,但核心逻辑就是这样。如果你不熟SKILL,也可以用KLayout打开同一个GDS文件,通过菜单里的“Report”功能做一次off-grid检查,KLayout能直接告诉你哪些多边形在哪个层偏离了规则,而且它会把具体的坐标偏差值列出来,比Virtuoso自带的DRC报告更好定位。

3. 5分钟搞定0.005um格点DRC报错的完整路径

3.1 方案一:全选加Snap All,最快但要想清楚后果

整个流程最快的一招就是:在Layout Editor里按Ctrl+A全选所有对象,然后点菜单Edit -> Advanced -> Snap All,在弹出的对话框里把Snap Grid改成0.005,选择“Selected Objects”或“All Objects”。确认之后,所有被选中的顶点都会被吸附到最近的0.005整数倍坐标上。整个过程基本在几秒内完成,熟练的话一分钟都用不了,所以“5分钟搞定”不是夸张,是真的能在这段时间内完成定位和修复。

但这里有个大坑:Snap All是“就近吸附”,不是“标记偏差让你确认”。如果你的图形本身错得离谱,比如某个顶点本来应该在0.017,Snap All会把它吸附到0.015,这改变了图形的尺寸,也必然影响相邻图形的间距和覆盖关系。所以操作之前要评估:离格的距离是否远小于当前工艺允许的最小变化量。一般来说,drift量在0.002um以内,吸附后对电路性能影响很小;但如果偏差到了0.01um以上,就不能无脑全选吸附,得回到底层去看是不是数据来源出了问题。

另外,如果你在顶层cell执行Snap All,并且选择了hierarchy模式,它会递归处理所有子cell的图形。这相当于把子cell里的内容也改了。问题是你可能只想修某一个有问题的leaf cell,结果把别的leaf cell也动了,导致未预期的影响范围扩大。我一般建议先只对当前cell做snap,先跑一遍DRC,如果还有上层报错,再逐级往上处理。还有一点:Snap All处理Pcell时,可能会把Pcell炸成普通多边形,因为它是直接修改底层几何。Pcell一旦被炸开,参数化能力就没了,这一点在后面“复用”场景里非常致命。

3.2 方案二:用SKILL脚本精准修正离格顶点

Snap All最大的问题是“一刀切”。如果你只需要修特定的layer,或者你不想动Pcell,那就得用脚本。我这里说一个我长期在用的思路:

  1. 获取当前edit cellview对象,命名为cv。
  2. 获取当前规则的格点值,比如0.005,在数据库单位是1nm的前提下,换算成5。
  3. 遍历cv里的所有shape,只处理polygon和path,其它不管。
  4. 对每个shape的points做round:新坐标 = round(原坐标 / 格点) * 格点。
  5. 写回shape的points,保存cellview。

代码逻辑不复杂,但Virtuoso的database对象写法在不同版本之间略有差异。我通常先在CIW里手动执行几行验证,确认当前库的shape对象类型名称,再整段跑。这里不贴完整代码是因为版本差异确实大,直接抄网上老代码经常报错,我更希望你理解原理后自己改。关键是“round到格点整数倍”这个动作,它和Snap All是一样的,只是精准度更高,你可以筛出某层或者某类对象。

脚本方式更适合修那些“很规矩”的数字版图,比如从APR工具导出的标准单元阵列。因为这种图里图形多、层数多、单个图形又不大,Snap All可能会因为鼠标选择范围或hierarchy递归效率不高,而脚本可以限定范围,跑完后DRC一步到位。

3.3 方案三:GDS导出再导入,用“洗版”解决顽固离格

有些版图里的离格问题已经嵌套进了Pcell、子cell,甚至在Virtuoso内部都找不到非格点的来源。这时候我的终极大招是:利用GDS导出时的“Snap to Grid”功能,把整个设计强制清洗一遍。操作路径是File -> Export -> Stream(或GDS),在Stream Out Options里找到Snap to Grid选项,勾选它,并填入0.005。导出完成后,再新建一个空cellview,用File -> Import -> Stream(或GDS)把这个GDS导回来。

这个流程之所以有效,是因为GDSII文件本身是按坐标存储的,导出工具在做Snap to Grid时,会对所有坐标做一次类似SQL里的round操作。导入回来之后,原来那些非格点坐标彻底变成了合法的0.005倍数,相当于版图被重新“洗”了一遍。我接手的很多第三方IP,就是靠这一招把几千个off-grid报错一次性清零的。

但代价也很直观:第一,所有Pcell都会被展平,子cell变成普通多边形,丢失参数化信息。第二,部分property、net名、device信息可能丢失,尤其是那些靠“层次化电路识别”的工具,导回来之后你可能要重新跑一遍LVS再恢复电学标注。第三,如果你有多层文本或者自定义标记图层,导出导入时要确认map文件覆盖了这些层,否则就丢了。所以“洗版”适合做mask流片前的一次性清理,不适合还在频繁改参数的设计阶段。

3.4 修复后立刻复验DRC

不管用哪种方案,修完之后都要立刻重跑DRC。具体操作是Verify -> DRC,或者用你PDK配套的DRC runset跑一遍。这里注意,不要只跑GRID rule,要跑全套,因为Snap All和“洗版”可能会在吸附过程中破坏线宽、间距、甚至连接关系。我遇到过一种情况:Snap All把一条本来间距为0.006um的相邻线吸成了0.005um,刚好压线,GRID不报了,但SPACE规则变成了新的违例。所以完整DRC是必须的。

如果DRC结果里GRID报错数量变为0,同时其它规则也没新增损伤,那就可以放心。如果还残留少量GRID,多半是子cell没处理到,或者你设的格点值和rule deck里的不一致。我建议先核对rule deck里的GRID值,再检查你的Snap设置。在两者一致的前提下还报错,那就用前面提到的脚本把坐标打出来,看具体是哪一个顶点,大概率你会发现某个图形是“不可吸附”类型,比如instance内部的definite图形。

4. GDS导出导入全流程

4.1 导出前准备:map文件与基础选项

GDS导出不只是点一个“Export”按钮那么简单,最容易出问题的就是图层映射。你要先确认工艺库的map文件是不是正确。在Virtuoso里,可以通过Tools -> Technology File Manager -> Layer Map来查看和编辑图层映射关系。map文件的作用是把版图里的layer number和purpose pair映射到GDS的layer number和datatype,例如M1的layer number可能是31,datatype 0。如果map文件选错,导出后所有金属层会错乱,导入到其它工具时即便格点是对的,层次却是错的,DRC跑出来一堆莫名其妙的结果。

导出时还要注意“Output File”名称,不要用中文和空格,建议全部用英文小写加下划线。文件路径也不要有非法字符,有些服务器文件系统对带括号或特殊符号的路径处理不好。Pins、properties、instances这些选项,一般选默认或者全选。如果你只是给下游做物理验证,可以把“Pins”和“Properties”都包含进来,这样后续LVS能少很多工作。另外GDS版本建议选6,现在的主流工具都兼容。

4.2 导出参数的推荐配置表

下面是我个人在项目里常用的导出参数组合,你拿到手上改一下路径和map文件就能用。

参数项推荐值理由
GDS Version6支持更完整的数据类型和层次结构
Output File项目名_版本.gds方便追溯,避免覆盖
Map FilePDK自带的.map文件确保图层映射正确
Snap to Grid勾选,值填0.005强制坐标落在格点,解决离格问题
ModeAll导出全部层次和对象
Units0.001一般与数据库单位一致
PinsONLVS阶段能省去恢复netname的步骤
PropertiesON保留基本属性,方便查来源

勾选Snap to Grid之后,Virtuoso会在导出时对所有坐标执行吸附,但要注意,如果你同时保留Pcell层次,导出工具是在原Pcell结构上做吸附,可能会和导入工具再解析Pcell时的计算产生冲突。所以我们前面说的“洗版”,更推荐的顺序是:先执行一次export,设置Snap to Grid,再新建空cell,导入这个GDS,让它成为普通多边形层次,这样最彻底。

4.3 导入的关键参数与常见误区

导入GDS相对简单,File -> Import -> Stream,或者用File -> Import -> GDS,选择你刚导出的文件,然后选目标库和目标cellview名称。这里最大的坑是Scale。GDSII文件内部有自己的单位定义,通常1 user unit等于1um,数据库单位在文件头部写了是多少,比如1000表示1um等于1000个数据库单位。Virtuoso导入时如果识别出来的比例和你工艺库的数据库单位不一致,版图会被整体放大或缩小,那才是真正的灾难。

大部分情况下,Virtuoso能自动从GDS文件读取单位信息,你只需要保持Scale=1.0即可。但也有一些三方工具导出的GDS单位写得不规范,导致Virtuoso把它当成了别的单位。碰到这种情况,我的排查方法是:先导入一个已知尺寸的矩形,然后量一下它的宽度,看是不是和原始尺寸一模一样。做完这个验证再继续。如果尺寸不对,那就手动调整Scale,比如把1改成0.1或10,直到量测结果与源设计一致。这步要是错,后面所有格点讨论都失去意义,因为整个版图都被变形了。

导入时还要确认目标库的tf文件是否已经加载,否则图层映射关系不完整。如果你没有先创建好一个cellview,建议先创建空layout,再Stream In。直接导入到库根目录可能会生成奇怪的结构。图层映射在导入时同样重要,PDK的map文件必须和工艺库匹配,否则图形进来后图层名全是数字,完全无法编辑。

4.4 从导出到导入的完整测试案例

说一个我亲自跑过的流程,给大家一个直观参考。有一个同事设计的模拟模块,DRC里报了100多个GRID错误,位置散布在三个子cell里。我先把这三个子cell复制到一个临时库,避免搞坏原设计。然后在临时库里打开顶层cellview,执行File -> Export -> Stream,设置Snap to Grid为0.005,勾选Pins和Properties,导出成tmp_top.gds。接着在同一个库里新建tmp_top_clean,File -> Import -> Stream,导入这个GDS。

导入成功后,我打开tmp_top_clean,量了几个关键金属线宽,确认没有尺寸漂移,然后直接在clean版本上跑完整DRC。结果GRID报错全部消失,其它规则也没有新增违例。整个过程包括文件命名和DRC运行,加起来不到十分钟。这里有个细节:导出前我先把临时库里那些Pcell都保存了一遍,确保没有未保存的编辑,否则导出的内容可能和当前编辑状态不一致,容易遗漏最新修改。

5. 常见问题与排查技巧实录

5.1 修完DRC还是报off-grid怎么办

这种“修复无效”的情况一般有三种原因。第一是你处理了当前cellview但没处理hierarchy下的子cell,DRC在顶层运行时又下钻到子cell里报错。解决方法是确认你的Snap All勾选了hierarchy,或使用GDS洗版方式一次性解决全层次。第二是rule deck里的GRID值和你使用的0.005不是同一个数,可能规则里写的是0.001,你的顶点吸附到了0.005的整数倍,但0.005不是0.001的整数倍吗?当然是,但如果规则要求0.001,那0.015和0.020都是合法的,问题不大;反过来如果规则要求0.005,你吸附到0.001的倍数上,就会有一堆顶点落在比如0.003、0.007这种“非0.005倍数”的位置。所以一定要先核对规则。

第三是修完之后又有人碰过版图,比如在未正确设置Snap Grid的session里进行了拖动或拉伸,导致新的离格出现。这也是团队协作里最常见的情况。所以我养成了一个习惯:每次跑DRC之前,先检查Options -> Layout Editor Options里的Snap Grid,确保它是0.005,并且不允许别人用其它值打开这个cell。如果团队里有多人编辑同一块版图,用SKILL脚本把默认Snap Grid锁死,能减少一大半这种问题。

5.2 “partial route conflicts”这类报错要不要管

相关热词里有一条很有代表性:[DRC RTSTAT-6] partial route conflicts: 1184 net(s) have a partial conflict.这其实是自动布线工具或Virtuoso XL相关流程里常见的一类报错,它说的是某些net在布线时只完成了一部分连接,存在“断头路”或“悬空线段”。这个和0.005um格点没有直接关系,但很多人在追GRID报错时会同时看到它,容易混淆。

处理partial conflict,我的建议是先看是不是Router工具遗留的布线废线。最简单的方法是用Virtuoso XL的Highlight功能,选中所有conflict net,然后一个net一个net地查。很多情况下,那些net是不需要连接的多余route,删掉就干净了。如果是关键的电源地net,那就要重新Route,确保每个pin都有完整连接。注意,GDS导出导入不会消除这类冲突,它只处理几何坐标,不处理电学连接逻辑。所以不要寄希望于“洗版”能一并解决partial route conflicts,必须单独去整理布线。

5.3 用KLayout辅助检查时的格点坑

不少人喜欢用KLayout做快速DRC或看GDS,因为启动快、视图流畅。KLayout里做off-grid检查也有对应的函数,直接在DRC脚本里写offgrid(0.005)就能对当前层执行格点检查。但有个坑:KLayout在导入GDS时,会对数据库单位做一次换算。如果你的GDS写入单位是0.001um,而KLayout里的Technology设置成了0.0005um,它显示的坐标虽然看起来正确,实际内部单位换算会让offgrid判断的结果和源文件不一致,甚至产生一堆假阳性报错。

所以我建议使用KLayout辅助检查时,先核对Technology里的dbu设置,确保和GDS原生单位一致。另外,KLayout的DRC脚本语法很容易因为没指定图层而漏检,我通常会在脚本里明确地写layers = input(1, 0)这种语句,而不是依赖全局layer定义。否则你跑出来的DRC可能根本没有检查到金属层,自然也就没有GRID报错,让你误以为版图很干净。

5.4 格点问题处理速查表

典型场景推荐做法注意事项
少量图形离格Edit -> Advanced -> Snap All先备份或临时库操作,防止误改
大量子cell离格GDS导出时Snap to Grid后重新导入会炸Pcell,丢失参数化信息
不想炸PcellSKILL脚本遍历shape顶点吸附需要熟悉数据库对象语法,先小范围试
Pcell参数变化导致离格修改Pcell参数或联系PDK厂商别用Snap All,改了也会被参数更新还原
外部GDS导入后离格检查导入Scale和dbu量测关键尺寸验证缩放是否正常
人为编辑导致离格锁定Snap Grid并加强DRC前自检团队协作时用统一初始化脚本

尾声:一点个人经验

做完这么多项目,我的体会是,格点DRC报错本身不可怕,可怕的是你在一堆里分不清哪些是“坐标脏数据”、哪些是“电气连接问题”。每次看到GRID报错,我现在的第一反应不是急着修,而是先查rule deck里的GRID值,再查当前cellview的Snap Grid,最后去翻Pcell参数和数据来源。三步定位下来,90%的情况都能找到根源。真正让我觉得值得分享的,是“GDS导出导入洗版”这种思路,它不一定适合每个阶段,但当你被几千个off-grid错误逼到墙角时,它真的是救命稻草。最后提醒一句:所有大规模修改前,复制一个临时库再操作,这个习惯能让你少走无数弯路。

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

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

立即咨询