第二章:DRC规则文件解析

各位同学,今天我们来聊聊DRC规则文件。说实话,我刚入行那会儿,看到动辄几千行的规则文件就头大。但干这行十几年下来,我慢慢发现——规则文件其实就是芯片设计的「交通法规」。你遵守它,芯片就能跑;你违反它,流片回来就是一堆废片。

2.1 规则文件的两种主流格式

目前业界主流的DRC规则文件格式有两种:SVRF和TCL。我个人的习惯是,用Calibre工具时主要接触SVRF,用ICV或Assura时则更多用TCL。但不管哪种格式,核心逻辑是一样的。

SVRF格式

SVRF是Standard Verification Rule Format的缩写,说白了就是Calibre的「母语」。它的语法结构非常清晰,像写文章一样有段落感。我最早接触的就是这种格式,至今仍觉得它最直观。

// SVRF示例:检查金属线宽
WIDTH M1 < 0.18 {
    @ Minimum M1 width is 0.18um
    M1.WIDTH < 0.18 = ERROR "M1 width violation"
}

TCL格式

TCL格式则更灵活,因为它本身就是一种脚本语言。你可以用变量、循环、条件判断来写规则。嗯,这里要注意——TCL格式的规则文件,本质上是用TCL脚本「生成」出来的。

# TCL示例:同样的金属线宽检查
set min_width 0.18
rule check_m1_width {
    condition: M1.width < $min_width
    message: "M1 width violation, minimum is $min_width um"
    severity: error
}
我的经验:如果你刚开始学,我建议先从SVRF入手。它更「死板」,但死板意味着不容易出错。等你把SVRF玩熟了,再转TCL会轻松很多。

2.2 常见规则语句详解

规则文件里最常见的语句就那么几条,我一个个说。

WIDTH(宽度检查)

宽度检查是最基础的DRC规则。它检查你的金属线、多晶硅、有源区等图形是否满足最小宽度要求。为什么要有这个?你想想看,工艺厂的光刻机分辨率是有限的,线太细了,光刻出来可能就断了。

// 金属1最小宽度0.18um
WIDTH M1 < 0.18 {
    @ Minimum M1 width = 0.18um
    ERROR M1 "M1 width < 0.18um"
}

// 通孔最小宽度0.24um
WIDTH V1 < 0.24 {
    @ Minimum V1 width = 0.24um
    ERROR V1 "V1 width < 0.24um"
}
我曾经踩过的坑:有一次我写规则时,把WIDTH和SPACING搞混了。结果检查出来的错误全是假的,浪费了整整两天去debug。记住:WIDTH是检查图形本身的尺寸,SPACING是检查图形之间的距离。

SPACING(间距检查)

间距检查同样重要。两条金属线靠得太近,可能会发生短路或者串扰。工艺厂会根据金属层的厚度、介质层的介电常数等因素,给出最小间距要求。

// 金属1之间最小间距0.2um
SPACING M1 < 0.2 {
    @ Minimum M1 spacing = 0.2um
    ERROR M1 "M1 spacing < 0.2um"
}

// 不同网络之间的间距更严格
SPACING M1 < 0.3 && NET != SAME_NET {
    @ Minimum M1 spacing between different nets = 0.3um
    ERROR M1 "M1 spacing between different nets < 0.3um"
}

AREA(面积检查)

面积检查很多人会忽略,但它其实很关键。比如有源区面积太小,会导致晶体管无法正常工作。我记得有个项目,就是因为在SRAM单元里有个有源区面积不达标,导致整个芯片的漏电超标。

// 有源区最小面积0.5um²
AREA OD < 0.5 {
    @ Minimum OD area = 0.5um²
    ERROR OD "OD area < 0.5um²"
}

// 金属填充块面积检查
AREA M1 > 100 {
    @ Maximum M1 fill block area = 100um²
    WARNING M1 "M1 fill block area > 100um², consider splitting"
}

2.3 层次化规则定义

真正的芯片设计,规则文件动辄上万行。如果每条规则都从头写到尾,那维护起来就是噩梦。所以,我们需要层次化规则定义。

说白了,就是把通用的规则抽象出来,定义成「模板」或者「函数」,然后在具体层上调用。这样改起来也方便——改一处,所有地方都跟着变。

规则继承

// 定义基础规则模板
DEFINE basic_metal_rules(min_width, min_spacing) {
    WIDTH @ < min_width {
        ERROR @ "@ layer width < min_width"
    }
    SPACING @ < min_spacing {
        ERROR @ "@ layer spacing < min_spacing"
    }
}

// 为金属1调用模板
M1: basic_metal_rules(0.18, 0.2)

// 为金属2调用模板,参数不同
M2: basic_metal_rules(0.2, 0.25)

规则分组

我习惯把规则按功能分组:

  • 基础规则组:WIDTH、SPACING、AREA等通用规则
  • 工艺特定规则组:比如天线效应规则、密度规则
  • 设计规则组:比如ESD规则、IO规则
// 规则分组示例
GROUP metal_rules {
    WIDTH M1 < 0.18 { ... }
    SPACING M1 < 0.2 { ... }
    WIDTH M2 < 0.2 { ... }
    SPACING M2 < 0.25 { ... }
}

GROUP via_rules {
    WIDTH V1 < 0.24 { ... }
    SPACING V1 < 0.26 { ... }
    ENCLOSURE M1 V1 < 0.1 { ... }
}

// 在顶层调用
RUN metal_rules
RUN via_rules
核心要点:层次化规则定义的好处有三点——
1. 代码复用,减少重复劳动
2. 维护方便,改一处全局生效
3. 可读性强,新人也能快速理解

2.4 本章知识体系

下面这张图是我自己画的,把本章的核心逻辑串起来了。你看一遍,应该就能明白规则文件的全貌。

DRC规则文件知识体系 DRC规则文件 SVRF格式(Calibre) TCL格式(ICV/Assura) 常见规则语句 WIDTH(宽度检查) SPACING(间距检查) AREA(面积检查) 层次化规则定义(继承/分组)

从这张图你能看到,规则文件从顶层格式到底层具体规则,是一层一层展开的。我个人觉得,理解这个层次结构比死记硬背语法更重要。因为语法可以查手册,但架构思维需要慢慢培养。

一个小技巧:拿到一个陌生的规则文件,先别急着看细节。先看它的目录结构,看它分了几层、用了哪些模板。这样你就能快速把握全局,不至于迷失在几千行代码里。

好了,关于DRC规则文件解析,今天就聊到这儿。下一章我们会讲如何编写高效的DRC规则,到时候我会分享一些我这些年总结的「独门秘籍」。

可可精品资料库