一、规则文件基础结构
驱动 Calibre 工具的语句和操作存储在一个文本文件中。可以使用任意文本编辑器编写该文件,该文件被称为规则文件 。加载规则文件时,工具会对其进行语法及其他错误检查 ,并完成编译。由于编译器将规则文件作为单一整体 处理,因此元素的呈现顺序通常无关紧要 。但在某些情况下,元素存在顺序依赖性。
二. SVRF 规则文件格式
适用工具 :Calibre 和 ICverify 工具SVRF 规则文件包含多种元素,例如层分配与定义 、规则检查 、注释 、规范语句 、器件识别语句 、条件语句 和宏。
2.1 格式
规则文件元素的主要类别如下表所述:
- 层分配
- 全局层定义
- 注释
- 包含语句
- 规则检查语句 {
- 局部层定义
- 层操作
- 规则检查注释}
- 规范语句
- 连通性提取操作
- 寄生参数提取语句
- 器件识别操作
- 条件语句
- 宏
- 运行时 TVF 函数
2.2 参数
参见下表
表 2-7. 规则文件元素
| 元素 | 描述 |
|---|---|
| 层分配与定义 | 层分配通过 Layer 规范语句完成。示例: LAYER POLY 1 LAYER OXIDE 2 在这些语句中,层号被分配给层名(通常称为原始层 或绘制层 )。不允许重新分配层名。层集是指被分配了多个层号或层名的层。示例: LAYER MET1 1 2 LAYER ALL_MET MET1 MET2 MET3 层定义用于从原始层派生出新层。层定义命名后,可通过引用其名称在规则文件的其他操作中使用该派生层。层定义的格式为: name = layer operation 规则文件中的层定义可位于规则检查语句内部 或外部 。位于规则检查语句外部的层定义称为全局层定义 ,其定义的层名可在规则文件的任意位置的操作中使用。位于规则检查语句内部的层定义称为该规则检查语句的局部层定义 ,其定义的层名在规则检查语句外部不被识别。在局部作用域中,层名可在不同的规则检查语句中重复使用 。两个全局层定义不能重名 ,同一规则检查语句内的局部层定义也不能重名 。在局部层定义所在的规则检查语句中,局部层定义会覆盖同名的全局层定义。 |
| 隐式层定义 | 隐式层定义由一对匹配的括号包裹单个层操作构成。该层操作的输入也可以是隐式派生的。隐式层操作可用作任意操作的输入。示例: taps = (pdiff AND (bulk NOT nwell)) OR (ndiff AND nwell) 在此例中,有两个隐式层定义用作 OR 操作的输入,第一个 AND 操作的输入也包含一个隐式层定义。隐式层定义也可用于规则检查。示例: rule {EXT < 0.1 (poly NOT oxide) oxide} 注意 :当括号 () 和方括号 [] 用作派生边缘层运算符时,隐式层定义不能 用于 Enclosure、External 和 Internal 操作。 |
| 注释 | 双斜杠 // 用于开启规则文件注释,注释持续至该行末尾。同时支持多行 C 风格注释 /* ... */。在规则检查块内(大括号内)的注释,可使用 @ 符号开头。此类注释可在 Calibre RVE 中显示。规则检查注释中可使用脱字符 ^ 来引用变量的值(数组取第一个值)。例如,若 my_var 是一个数值变量,以下示例会将 my_var 的值显示在规则检查输出中:@ 间距在 ^my_var 范围内脱字符 ^ 可通过以下方式转义(作为文字处理):・在规则检查注释(@)中使用 \^・在 DFM RDB COMMENT 中使用 ^^・在 SVRF Message 语句中使用 \\^ |
| 包含语句 | 在包含语句所在位置,将另一个规则文件插入到当前规则文件中。该语句的效果等同于将指定文件名的规则文件的所有文本直接包含在当前语句所在位置。格式如下:INCLUDE 文件名支持多个包含语句 ,且包含深度不受限制 。不允许递归调用被包含的文件。 |
| 层操作 | 此类命令用于操作层数据,通常用于层派生 和规则检查 。它们常被简称为操作 ,以区别于另一主要命令类别 ------规范语句。 |
| 规则检查语句 | 该语句为 Calibre nmDRC 类应用所特有。当应用程序执行规则检查语句时,其指定的层操作所生成的派生层会被存入结果数据库。规则检查的基本格式如下: name { @ rule check comment layer operation or layer definition ... layer operation or layer definition layer operation } 规则文件中的两个规则检查语句不能重名 。规则检查语句无需 跨越多行,也无需 包含注释。但一个规则检查必须包含至少一个独立的层操作 (即非 x = 层操作 形式的层定义),且该操作需向结果数据库输出内容,否则规则检查将无法编译。除非名称用引号括起,否则规则检查名称不能使用特殊符号。 |
| 规范语句 | 此类语句用于控制输入输出流程 ,并指定各类算法的执行方式。 |
| 连通性提取操作、器件操作和寄生参数提取操作 | 此类语句用于控制连通性提取 、器件定义 和寄生参数提取。 |
| 条件语句 | 条件语句(或称为预处理指令 )用于控制规则文件的编译过程,决定规则文件的哪些部分会被启用。 |
| 宏 | 宏是一种模板结构 ,允许重复使用 SVRF 操作。宏可在规则文件中被多次调用。 |
| 运行时 TVF 函数 | 运行时 TVF 要求规则文件中存在一个名为 TVF FUNCTION 的 SVRF 元素,用于定义 Calibre 运行时需执行的操作。 |
三、预处理指令
预处理指令(也称为条件语句 )包含用于工艺控制 、版本控制 和环境变量的规则文件编译器指令。
预处理指令有以下特殊注意事项:
-
Calibre 和 ICverify 应用所使用的预处理指令,其通用性不如 大多数 C 语言预处理器。它仅测试变量的存在性,而非表达式。
-
不能在同一行放置多个预处理指令。
-
每个预处理指令必须是该行的第一个非空格字符。
-
依赖于包含语句或 C 风格注释(
/* ... */)的条件编译指令,其编译顺序为:在包含语句之后 ,在 C 风格注释之前。
通常,不应 通过注释掉预处理指令来修改逻辑,而应使用正确的预处理指令实现所需逻辑。例如,使用 #UNDEFINE 语句来取消 #DEFINE 语句的定义。
| 主题 | 描述 |
|---|---|
| 用于编译控制的条件指令概述 | 可通过规则文件中的 #DEFINE、#UNDEFINE、#IFDEF、#IFNDEF 指令,控制 Calibre 或 ICverify 编译规则文件的哪些部分。这些指令用于定义和取消定义变量,并基于变量定义提供条件执行。用于编译控制的变量也可在 Shell 中定义为环境变量。本文提供了使用说明和示例。 |
#DEFINE |
#DEFINE 预处理指令用于在 SVRF 规则文件中定义变量。这些变量用于控制规则文件部分内容的条件执行。 |
#UNDEFINE |
#UNDEFINE 预处理指令用于在 SVRF 规则文件中取消定义变量。这些变量用于控制规则文件部分内容的条件执行。 |
#IFDEF/#IFNDEF |
#IFDEF(如果已定义)和 #IFNDEF(如果未定义)预处理指令,基于变量定义为 SVRF 规则文件提供条件编译功能。 |
#IFDEF CALIBRE_VERSION |
#IFDEF CALIBRE_VERSION 预处理指令基于 Calibre 版本提供条件编译,便于将新功能集成到现有 SVRF 文件中。 |
#PRAGMA ENV |
#PRAGMA ENV 预处理指令用于为 SVRF 语句中使用的环境变量定义默认值。 |
3.1 用于编译控制的条件指令概述
可通过规则文件中的 #DEFINE、#UNDEFINE、#IFDEF、#IFNDEF 指令,控制 Calibre 或 ICverify 编译规则文件的哪些部分。这些指令用于定义和取消定义变量,并基于变量定义提供条件执行。用于编译控制的变量也可在 Shell 中定义为环境变量。本文提供了使用说明和示例。
有关基于 Calibre 版本提供条件编译的预处理指令,请参考 #IFDEF CALIBRE_VERSION。
3.1.1 定义用于工艺控制的变量
可通过 #DEFINE 指令或在 Shell 环境中定义用于工艺控制的变量。
#DEFINE 用法
#DEFINE var_name [var_value]
var_name为变量名。若变量名包含空格或非字母数字字符,需用引号括起。var_value为可选的变量值。
也可在 Shell 环境中隐式定义 变量,此时无需使用 #DEFINE 语句。
变量定义的判定条件
满足以下任一条件,变量 var_name 即被视为已定义:
-
显式定义 :变量名(
var_name)在条件块中被引用之前,出现在#DEFINE指令中,且在条件块中被引用之前,未出现在#UNDEFINE语句中。 -
隐式定义 :变量名(
var_name)前带有美元符号($),且var_name被定义为非空的 Shell 环境变量。
示例
-
C Shell 环境中的隐式定义:
setenv process 7lm -
Bourne Shell 环境中的等效定义:
export process=7lm基于上述隐式变量定义,字符串
$process在条件语句(#IFDEF或#IFNDEF,后文详述)中表示变量名,其值为7lm。 -
无值的显式定义:
#DEFINE process此语句定义了变量
process,但未为其分配值。 -
带值的显式定义:
#DEFINE process 7lm此语句定义了变量
process,并为其分配值7lm。这与前面的环境变量赋值示例类似,但process和$process并非同一个变量名。
注意事项
-
在
#DEFINE指令中,变量值(var_value)不能 指定为环境变量。例如,在以下规则文件片段中,$value不会被解释为变量:// 在 Shell 中,$value = 7lm #DEFINE process $value // 此处的 $value 是文字字符串,非变量 -
可在规则文件中覆盖 隐式变量定义。假设在 Shell 中定义了环境变量
myvar(例如setenv myvar xyz),则在条件语句中$myvar的值为xyz。使用以下语句可重新定义$myvar:#DEFINE $myvar newvalue此语句会使
$myvar的值变为newvalue(仅对预处理命令有效),而与 Shell 环境无关。即#DEFINE指令可覆盖来自 Shell 环境的隐式变量定义,但不会影响 Shell 本身。
3.1.2 取消定义变量
#UNDEFINE 指令用于取消定义变量。它可用于取消定义:
- 显式定义的变量(通过
#DEFINE定义) - 隐式定义的变量(在 Shell 中定义)
- 之前未定义的变量(用于将变量初始化为未定义状态)
#UNDEFINE 用法
#UNDEFINE var_name
示例
-
取消定义 Shell 中定义的变量 :
#UNDEFINE $process // 取消隐式定义的变量 -
取消定义规则文件中显式定义的变量 :
#DEFINE process ... #UNDEFINE process // 取消显式定义的变量 ...上述两个示例取消的不是同一个变量名 。
#UNDEFINE语句仅影响 规则文件预处理器,不影响 Shell 环境。
注意事项
修改条件编译预处理指令的状态时,应将其切换为相反的指令,而非注释掉。例如,对于以下条件指令:
#DEFINE name
不应在其前添加注释字符,因为所有预处理指令的井号(#)必须是该行的第一个字符。C 风格注释(/* ... */)也无法隐藏该指令,因为当存在依赖关系时,注释的处理顺序在预处理指令之后。正确的取消定义方式是:
#UNDEFINE name
3.2 条件指令(#IFDEF 和 #IFNDEF)
条件指令为规则文件的部分内容提供条件编译 功能。#IFDEF(如果已定义)和 #IFNDEF(如果未定义)分别测试变量是否已定义或未定义,并可选择与指定值进行比较。#IFDEF 或 #IFNDEF 语句可包含可选的 #ELSE 语句,当前置的 #IFDEF 或 #IFNDEF 条件判断为假时,执行 #ELSE 后的内容。
#IFDEF 和 #IFNDEF 用法
{#IFDEF var_name [var_value] | #IFNDEF var_name [var_value]}
rule_file_text
[ #ELSE
rule_file_text ] ...
#ENDIF
-
var_name:变量名,字符串类型。若包含空格或非字母数字字符,需用引号括起。若变量在 Shell 环境中定义,在规则文件的条件指令中使用时,需在开头添加美元符号($)。 -
var_value:可选的变量值,字符串类型。若存在,会通过不区分大小写的字符串比较 ,将var_name的值与var_value进行对比。 -
rule_file_text:根据条件指令执行的规则文件语句和操作。该字符串中也可包含条件语句,形成嵌套预处理指令 。(SVRFError语句可用于在条件结构中插入编译器错误消息。)
相关值的定义
在以下条件指令的讨论中,"相关值" 指以下情况之一:
-
在
#IFDEF或#IFNDEF条件之前,最近的#DEFINE指令为变量var_name分配的值。 -
Shell 环境中为变量
var_name分配的非空字符串(若有)。
#IFDEF 的条件编译逻辑
#IFDEF var_name [var_value] 按以下规则启用或禁用条件编译:
-
若
var_name未定义 ,则禁用编译。 -
若
var_name已定义且带有值 ,但#IFDEF中未指定var_value,则启用编译。 -
若
var_name已定义但无相关值 ,且#IFDEF中指定 了var_value,则禁用编译。 -
若
var_value等于var_name的分配值(通过不区分大小写的字符串比较),则启用编译。 -
其他情况,禁用编译。
#IFNDEF 的条件编译逻辑
#IFNDEF var_name [var_value] 按以下规则启用或禁用条件编译:
-
若
var_name未定义 ,则启用编译。 -
若
var_name已定义且带有值 ,但#IFNDEF中未指定var_value,则禁用编译。 -
若
var_name已定义但无相关值 ,且#IFNDEF中指定 了var_value,则启用编译。 -
若
var_value等于var_name的分配值(通过不区分大小写的字符串比较),则禁用编译。 -
其他情况,启用编译。
示例
示例 1
工艺 P1 规定 metal6 为顶层金属层,工艺 P2 规定 metal5 为顶层金属层,其他所有工艺均规定 metal4 为顶层金属层。参数 P1 和 P2 会出现在控制文件的 #DEFINE 或 #UNDEFINE 语句中,控制文件包含以下代码:
LAYER metal4 23
LAYER metal5 26
LAYER metal6 29
#ifdef P1
LAYER top_metal metal6
#else
#ifdef P2
LAYER top_metal metal5
#else
LAYER top_metal metal4
#endif
#endif
示例 2
本示例中,参数 P1 最初为条件语句定义,随后被取消定义(顺序至关重要):
#DEFINE P1
... // 规则文件语句
#IFDEF P1
... // 条件语句被编译
#ENDIF
#IFNDEF P1
... // 条件语句不被编译
#ENDIF
#UNDEFINE P1
#IFDEF P1
... // 条件语句不被编译
#ENDIF
#IFNDEF P1
... // 条件语句被编译
#ENDIF
示例 3
本示例展示了在显式定义中使用名称 - 值对。P1 被显式定义:
#DEFINE P1 7lm // P1 的相关值为 "7lm"
#IFDEF P1
... // 条件语句被编译
#ENDIF
#IFDEF P1 7lm
... // 条件语句被编译(P1 = 7lm 来自 #DEFINE 指令)
#ENDIF
#IFDEF P1 P1
... // 条件语句不被编译(P1 = 7lm 来自 #DEFINE 指令)
#ENDIF
#IFNDEF P1
... // 条件语句不被编译
#ENDIF
#IFNDEF P1 7lm
... // 条件语句不被编译(P1 = 7lm 来自 #DEFINE 指令)
#ENDIF
#IFNDEF P1 P1
... // 条件语句被编译
#ENDIF
示例 4
本示例中,名称被隐式定义为 Shell 变量。注意 #UNDEFINE 指令不影响 本示例中声明的环境变量。$P1 是一个非空的 Shell 环境变量:
... // 规则文件语句
#IFDEF $P1
... // 条件语句被编译($P1 在 Shell 中已定义)
#ENDIF
#IFNDEF $P1
... // 条件语句不被编译
#ENDIF
#UNDEFINE P1
#IFDEF $P1
... // 条件语句被编译(之前的 #UNDEFINE 不影响 $P1)
#ENDIF
#IFNDEF P1
... // 条件语句被编译(P1 当前未定义)
#ENDIF
示例 5
本示例使用隐式定义为变量分配值。$P1 是一个非空的 Shell 环境变量,其值为 7lm。
#IFDEF $P1 7lm
... // 条件语句被编译($P1 = 7lm 在 Shell 环境中)
#ENDIF
#IFNDEF $P1 7lm
... // 条件语句不被编译
#ENDIF
#UNDEFINE P1
#IFDEF $P1
// 条件语句被编译(之前的 #UNDEFINE P1 不影响 $P1)
#ENDIF
#DEFINE $P1 P1 // $P1 被重新分配为值 P1
#IFDEF $P1 P1
... // 条件语句被编译
#ENDIF
#DEFINE
#DEFINE 预处理指令用于在 SVRF 规则文件中定义变量。这些变量用于控制规则文件部分内容的条件执行。
用法
#DEFINE var_name [var_value]
参数
var_name:变量名,字符串类型。若包含空格或非字母数字字符,需用引号括起。var_value:可选的变量值,字符串类型。
描述
通过 #DEFINE 语句定义的变量,可在 #IFDEF 或 #IFNDEF 语句中使用,以控制规则文件语句的条件执行。有关使用条件指令的完整信息,包括 Shell 中定义的变量的处理和编译顺序,请参见第 82 页的 **《用于编译控制的条件指令概述》**。
不要 通过注释掉 #DEFINE 语句来更改条件语句的状态,应使用 #UNDEFINE 语句。
示例
-
无值定义 :建立
process为已定义状态,未分配值。plaintext
#DEFINE process -
带值定义 :定义变量
process,并为其分配值7lm。plaintext
#DEFINE process 7lm
#UNDEFINE
#UNDEFINE 预处理指令用于在 SVRF 规则文件中取消定义变量。这些变量用于控制规则文件部分内容的条件执行。
用法
#UNDEFINE var_name
参数
var_name:变量名,字符串类型。若包含空格或非字母数字字符,需用引号括起。- 若使用
#UNDEFINE语句取消定义在 Shell 中定义的变量,var_name开头应带有美元符号($)。
描述
通过 #DEFINE 或 #UNDEFINE 语句指定的变量,可在 #IFDEF 或 #IFNDEF 语句中使用,以控制规则文件语句的条件执行。
#UNDEFINE 语句仅影响 规则文件预处理器,不影响 Shell 环境。不要 通过注释掉 #DEFINE 语句来更改条件语句的状态,应使用 #UNDEFINE 语句。
示例
-
取消定义规则文件中定义的变量 :
#UNDEFINE process // 取消规则文件中定义的变量 -
取消定义 Shell 中定义的变量 (例如通过
setenv process定义):#UNDEFINE $process // 取消 Shell 中定义的变量上述两个示例取消的不是同一个变量名。
#IFDEF/#IFNDEF
#IFDEF(如果已定义)和 #IFNDEF(如果未定义)预处理指令,基于变量定义为 SVRF 规则文件提供条件编译功能。
用法
{#IFDEF var_name [var_value] | #IFNDEF var_name [var_value]}
rule_file_text
[ #ELSE
rule_file_text ] ...
#ENDIF
参数
-
var_name:变量名,字符串类型。若包含空格或非字母数字字符,需用引号括起。 -
var_value:可选的变量值,字符串类型。 -
rule_file_text:根据条件指令执行的规则文件语句和操作。该字符串中也可包含条件语句,形成嵌套预处理指令。
描述
条件指令为规则文件的部分内容提供条件编译 功能。#IFDEF 和 #IFNDEF 分别测试变量是否已定义或未定义,并可选择将变量值与指定值(var_value)进行比较。#IFDEF 或 #IFNDEF 语句可包含可选的 #ELSE 语句,当前置的 #IFDEF 或 #IFNDEF 条件判断为假时,执行 #ELSE 后的内容。
变量(var_name)可在 Shell 环境中定义,或在规则文件中通过 #DEFINE 或 #UNDEFINE 预处理指令定义。有关完整讨论,包括扩展示例和条件编译逻辑的精确定义,请参见第 82 页的 **《用于编译控制的条件指令概述》**。
SVRF Error 语句可用于在条件结构中插入编译器错误消息。
#IFDEF CALIBRE_VERSION
#IFDEF CALIBRE_VERSION 预处理指令基于 Calibre 版本提供条件编译,便于将新功能集成到现有 SVRF 文件中。
用法
#IFDEF CALIBRE_VERSION value
rule_file_text
[ #ELSE
rule_file_text ] ...
#ENDIF
参数
-
value:有效的 Calibre 版本字符串,格式为vYYYY.Q_D*.D*。例如:v2011.2_37.32。 -
rule_file_text:根据条件指令的真假状态执行的规则文件语句和操作。该字符串中也可包含条件语句,形成嵌套预处理指令。
描述
若 Calibre 软件版本(在 Calibre 输出日志的顶部横幅中显示)大于或等于 指定值,则触发编译。"大于或等于" 意味着 Calibre 软件版本必须与指定值相同或更新 。在与指定值进行比较之前,Beta 版本和客户特定版本号会被截断。若未指定 value,则忽略该指令。
示例
在以下示例中,若 Calibre 版本大于或等于 v2011.2_0.0,则执行第一个 OR 操作;否则,执行第二个 OR 操作。
#IFDEF CALIBRE_VERSION v2011.2_0.0
X = OR A B C D
#ELSE
X = (A OR B) OR (C OR D)
#ENDIF
#PRAGMA ENV
#PRAGMA ENV 预处理指令用于为 SVRF 语句中使用的环境变量定义默认值。
用法
#PRAGMA ENV variable_name value
参数
variable_name:变量名,字符串类型。若包含空格或非字母数字字符,需用引号括起。value:变量的默认值,必填 ,字符串类型。不能是变量。
描述
在 #PRAGMA ENV 语句之后指定的、引用环境变量 variable_name 的所有 SVRF 操作或规范语句,若该环境变量已定义,则使用其实际值;否则,使用 #PRAGMA ENV 语句中定义的值。
为使 #PRAGMA ENV 语句生效,必须在环境变量 variable_name 首次使用之前指定该语句。
#PRAGMA ENV 语句仅适用于 SVRF 语句中使用的变量,不影响 TVF 代码中 Tcl 表达式使用的环境变量,包括编译时和运行时 TVF。
示例
示例 1
在正常操作中,若环境变量 INCLUDE_DIR 未定义,以下语句将无法编译:
INCLUDE $INCLUDE_DIR/rules.inc
若通过 #PRAGMA ENV 将环境变量 INCLUDE_DIR 定义为 ./inc,则该语句可编译,且 Include 语句会读取文件 ./inc/rules.inc。
#PRAGMA ENV INCLUDE_DIR "./inc"
INCLUDE $INCLUDE_DIR/rules.inc
示例 2
假设环境变量 INCLUDE_DIR 未定义。
#PRAGMA ENV INCLUDE_DIR "."
INCLUDE $INCLUDE_DIR/rules.inc
该语句可编译,且 Include 语句会读取文件 ./rules.inc。
示例 3
假设环境变量 INCLUDE_DIR 已定义为 ./inc。
#PRAGMA ENV INCLUDE_DIR "."
INCLUDE $INCLUDE_DIR/rules.inc
该语句可编译,且 Include 语句会读取文件 ./inc/rules.inc。
四、宏
宏类似于 C 和 C++ 语言中的宏。宏是一种功能模板 ,可在规则文件中被多次调用。
4.1 DMACRO
宏定义(DMACRO)的语法如下:
DMACRO macro_name [arguments] {
SVRF_code
}
其中,macro_name 是过程名,arguments 是输入参数名,SVRF_code 是有效的 SVRF 语法。
示例
DMACRO WIDTH_CHECK lay val {
S1 = INT lay < val ABUT < 90 SINGULAR REGION
S2 = INT lay < val ANGLED == 2 PARALLEL OPPOSITE REGION
S3 = INT lay < val CORNER TO EDGE REGION
( S1 OR S2 ) OR S3
}
注意事项
-
DMACRO名称必须唯一。 -
每个参数必须是名称 ,且在同一个
DMACRO参数列表中不能重复。 -
DMACRO定义不能嵌套。 -
规则文件中的任意注释字符均可在
DMACRO定义中使用;但用户注释(通过@符号指定)不会出现在 Calibre nmDRC 结果数据库(或 Calibre RVE)中。
4.2 CMACRO
调用宏需使用关键字 CMACRO(调用宏),后跟宏名和零个或多个参数列表,语法如下:
CMACRO macro_name [arguments]
macro_name必须与某个DMACRO定义的名称匹配。- 每个参数可以是名称 (通常是层名或变量名)或数值常量。
CMACRO宏名后必须提供足够数量的参数,以匹配DMACRO中指定的参数。
工作原理
在 CMACRO 调用处,会将 DMACRO 定义内部插入 ,并进行参数替换。
示例
以下 CMACRO 调用引用了前面定义的名为 WIDTH_CHECK 的 DMACRO:
poly_width { CMACRO WIDTH_CHECK poly 0.5 }
metal_width { CMACRO WIDTH_CHECK metal 0.6 }
参数 poly 和 0.5 会被替换到名为 WIDTH_CHECK 的 DMACRO 中,以构建规则检查 poly_width。规则检查 metal_width 会进行类似的替换。
也可按以下方式编写:
width_checks {
CMACRO WIDTH_CHECK poly 0.5
CMACRO WIDTH_CHECK metal 0.6
}
4.3 宏中的层名、派生和变量
层名作用域
当 DMACRO 在 CMACRO 中实例化时,DMACRO 语句中的层定义名默认具有局部作用域 。实现方式为:在 DMACRO 实例化时,为 DMACRO 结构中的每个层定义生成一个规则文件范围内唯一 的名称。DMACRO 中对每个层定义名的引用也会进行相应的替换。
前面的 width_checks 示例就体现了这一点。编译器不会因 width_checks 规则中多个中间派生层(WIDTH_CHECK 宏中的 S1、S2、S3)具有相同名称而产生混淆。
全局层名的指定
若 DMACRO 语句的某个参数与 DMACRO 块定义中的派生层名匹配 ,则对应的 CMACRO 参数将成为全局层名。示例:
DMACRO MAC IN1 IN2 OUTPUT { // OUTPUT 是 DMACRO 的参数
X = IN1 AND IN2
OUTPUT = SIZE X BY 0.01 // OUTPUT 是派生层名
}
CMACRO MAC L1 L2 RES // OUTPUT 被分配为全局层名 RES
在此示例中,OUTPUT 既用作 DMACRO 参数名,又是 DMACRO 中的派生层名;因此,OUTPUT 被视为该派生层的全局名。由于 CMACRO 参数 RES 对应于 OUTPUT,因此全局名 OUTPUT 变为全局层名 RES。
变量作用域
-
DMACRO内部的变量语句具有局部作用域 ,在DMACRO外部不可访问 。这允许在多个DMACRO定义中使用相同的变量名并赋予不同的值。 -
DMACRO外部指定的变量语句具有全局作用域 ,可被规则文件中的任意DMACRO使用。 -
若存在局部作用域变量,它会覆盖同名的全局作用域变量。
4.3 宏中的嵌套
DMACRO 定义本身可以包含嵌套的 CMACRO。例如,以下结构是允许的:
DMACRO skew_edge inlayer {
ANGLE inlayer > 0 < 45
ANGLE inlayer > 45 < 90
}
DMACRO acute_angle inlayer grid_size {
INT inlayer < 4*grid_size ABUT > 0 < 90 INTERSECTING ONLY
EXT inlayer < 4*grid_size ABUT > 0 < 90 INTERSECTING ONLY
}
DMACRO illegal_shape met grid_size { // 嵌套的 CMACRO
CMACRO skew_edge met
CMACRO acute_angle met grid_size
}
test {CMACRO illegal_shape metal1 .001}
注意 :不允许递归 ,即 CMACRO 不能调用包含该 CMACRO 调用的 DMACRO。
4.4 宏在用户定义器件特性计算中的应用
宏可用于 Device 操作中的用户定义特性计算。
对于 DMACRO 定义中位于方括号 [] 内的参数,会执行参数替换 。注意,方括号必须出现在 DMACRO 定义中。
示例
DMACRO mosprop seed {
[
property W, L
weffect = 0 // 在此处指定宽度效应常数(内置默认值为 0)
W = 0.5 * ( perim_co( S, seed ) + perim_in( S, seed )
+ perim_co( D, seed ) + perim_in( D, seed ) )
L = area( seed ) / W
if( weffect != 0 ) {
if( W > L ) W = W - weffect * bends( seed ) * L
else L = L - weffect * bends( seed ) * W
}
]
}
DEVICE MP gate gate psd psd CMACRO mosprop gate
DEVICE MN gate gate nsd nsd CMACRO mosprop gate
每个 Device 语句中 CMACRO 调用的 gate 层,会作为 mosprop 宏的 seed 参数传入。
注意 :方括号内的 CMACRO 调用不会 被展开。例如,以下代码无效:
DEVICE MP gate gate psd psd [ CMACRO MOSPROP2 gate ] // 错误
DEVICE MN gate gate nsd nsd [ CMACRO MOSPROP2 gate ] // 错误
4.5 Calibre LFD 运行中的 LOCAL() 修饰符
运行 Calibre LFD 时,可使用 LOCAL() 修饰符创建仅在每个 CMACRO 调用作用域内有效的局部名称 。该修饰符可用于在 DMACRO 内定义规范语句。
示例
问题代码:
DMACRO COPY_C L1 L2 C {
LAYOUT CELL LIST LIST1 C
L2 = DFM COPY L1 CELL LIST LIST1
}
// 尝试使用该 DMACRO
LAYER A 1
LAYER B 2
CMACRO COPY_C A A1 "A*"
CMACRO COPY_C B B1 "B*"
此用法无效 ,因为 Layout Cell List 规范语句以名称 LIST1 重复定义。
解决方案 :在 DMACRO 中添加 LOCAL() 修饰符。
DMACRO COPY_C L1 L2 C {
LAYOUT CELL LIST "LOCAL(LIST1)" C
L2 = DFM COPY L1 CELL LIST "LOCAL(LIST1)"
}
CMACRO COPY_C A A1 "A*"
CMACRO COPY_C B B1 "B*"
名称 LOCAL(LIST1) 会被替换为每个 CMACRO 调用唯一 的名称。在一个 CMACRO 调用内,LOCAL(name) 的多个实例始终会被替换为相同的局部名称 (如上述示例中的 LOCAL(LIST1))。同一宏中使用 LOCAL() 的不同名称,替换后仍保持不同。注意 ,字符串 LOCAL(LIST1) 两侧的引号是必需的。