3. DRC脚本语言入门:Tcl语言基础、Skill语言基础、Python在DRC中的应用概览
DRC(Design Rule Check)脚本是连接物理设计与验证工具的桥梁。主流EDA工具(如Cadence、Synopsys、Mentor)各自拥有或支持特定的脚本语言。本章将聚焦于三种最核心的语言:Tcl(工具命令语言)、Skill(Cadence原生语言)以及Python(通用脚本语言),并解析它们在DRC流程中的角色与基础语法。
3.1 Tcl语言基础:EDA工具的通用胶水
Tcl是大多数EDA工具(如Synopsys ICV、Mentor Calibre)的嵌入式脚本语言。其核心优势在于易嵌入、字符串处理能力强以及与工具命令的无缝集成。
3.1.1 变量与替换
Tcl中所有变量都是字符串,通过set命令赋值,使用$进行变量替换。
# 变量赋值与替换
set rule_file "drc_rules.tcl"
set min_width 0.18
puts "当前规则文件: $rule_file"
puts "最小线宽: $min_width um"
3.1.2 列表与循环
DRC脚本常需要遍历多个层次或规则集,Tcl的foreach与lappend非常高效。
# 定义层次列表
set layers {M1 M2 M3 V1}
# 遍历并打印
foreach layer $layers {
puts "正在检查层次: $layer"
}
3.1.3 控制流与过程
使用proc定义可复用的DRC检查过程。
proc check_min_width {layer value} {
if {$value < 0.18} {
puts "错误: $layer 线宽 $value 小于最小要求"
} else {
puts "通过: $layer 线宽 $value"
}
}
# 调用过程
check_min_width "M1" 0.15
3.2 Skill语言基础:Cadence环境的原生力量
Skill是Cadence Virtuoso平台的专用脚本语言,用于层次化规则编写、交互式版图检查以及自定义GUI开发。其语法类似Lisp,以括号表达式为核心。
3.2.1 基本语法与函数调用
Skill使用前缀表示法,函数名在前,参数在后,整体用括号包裹。
; 变量赋值
minWidth = 0.18
layerName = "M1"
; 打印输出
printf("当前检查层次: %s, 最小宽度: %.2f\n" layerName minWidth)
; 列表操作
layers = list("M1" "M2" "M3")
foreach(layer layers
printf("处理层次: %s\n" layer)
)
3.2.2 DRC规则函数
Skill通过dbCreateRule、dbCreateConstraint等函数构建DRC规则。
; 创建一个简单的宽度检查规则
ruleId = dbCreateRule("M1_MIN_WIDTH" "M1")
dbCreateConstraint(ruleId "width" ">=" 0.18)
printf("规则 %s 已创建\n" "M1_MIN_WIDTH")
3.2.3 层次化操作
Skill可以轻松遍历版图层次结构,进行几何运算。
; 获取当前cellView中的所有图形
cv = geGetEditCellView()
shapes = cv~>shapes
foreach(shape shapes
when(shape~>layerName == "M1"
printf("找到M1图形,坐标: %L\n" shape~>bBox)
)
)
3.3 Python在DRC中的应用概览
Python凭借其丰富的库生态(如re、pandas、matplotlib),在DRC流程中主要承担结果解析、批量运行和可视化的角色。它不直接编写DRC规则,而是作为“流程调度与数据分析引擎”。
3.3.1 解析DRC结果文件
DRC工具通常输出文本格式的报告(如Calibre的.summary或.ascii文件)。Python可以高效提取关键指标。
import re
def parse_drc_summary(file_path):
"""解析DRC摘要文件,提取违规总数"""
total_errors = 0
with open(file_path, 'r') as f:
for line in f:
match = re.search(r'Total\s+Errors\s*:\s*(\d+)', line)
if match:
total_errors = int(match.group(1))
return total_errors
# 使用示例
errors = parse_drc_summary("drc_run.summary")
print(f"总违规数: {errors}")
3.3.2 批量运行与流程控制
使用subprocess模块可以批量启动DRC工具,并监控运行状态。
import subprocess
import os
def run_drc_batch(rule_file, gds_file):
"""批量运行DRC检查"""
cmd = f"calibre -drc -hier {rule_file} {gds_file}"
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if result.returncode == 0:
print(f"DRC运行成功: {gds_file}")
else:
print(f"DRC运行失败: {result.stderr}")
# 遍历GDS文件
for gds in os.listdir("./gds_input"):
if gds.endswith(".gds"):
run_drc_batch("drc_rules.tcl", f"./gds_input/{gds}")
3.3.3 数据可视化与报告生成
利用matplotlib和pandas,可以将DRC结果转化为图表,辅助设计迭代。
import matplotlib.pyplot as plt
import pandas as pd
# 假设已解析出违规数据
data = {
'Layer': ['M1', 'M2', 'M3', 'V1'],
'Violations': [12, 5, 8, 3]
}
df = pd.DataFrame(data)
df.plot(kind='bar', x='Layer', y='Violations', legend=False)
plt.title('各层次DRC违规分布')
plt.ylabel('违规数量')
plt.savefig('drc_violations_chart.png', dpi=150)
3.4 三种语言在DRC中的角色对比
下表总结了Tcl、Skill、Python在DRC流程中的典型分工与核心差异:
| 特性 | Tcl | Skill | Python |
|---|---|---|---|
| 主要用途 | 规则文件编写、流程控制、变量传递 | 层次化规则定义、交互式版图检查 | 结果解析、批量调度、数据可视化 |
| 运行环境 | 内嵌于EDA工具(Calibre、ICV) | Cadence Virtuoso CIW | 独立Python解释器 |
| 语法风格 | 命令式,$变量替换 | Lisp风格,括号表达式 | 面向对象,缩进块 |
| 字符串处理 | 强(原生支持正则) | 中等(需调用函数) | 极强(re库) |
| 第三方库 | 有限 | 有限(依赖Cadence API) | 丰富(pandas, numpy, matplotlib) |
| 学习曲线 | 平缓 | 中等(括号语法需适应) | 平缓(通用性强) |
3.5 语言协同工作流
下图展示了一个典型的DRC自动化流程中,三种语言如何协同工作:
3.6 入门实践:编写第一个混合语言DRC脚本
以下是一个简单的入门练习,展示如何用Tcl定义规则、用Skill进行交互检查、用Python解析结果:
- Tcl规则文件 (drc_min_width.tcl): 定义M1层最小宽度为0.18um。
- Skill检查脚本 (check_width.il): 在Virtuoso中加载规则并运行交互检查。
- Python解析脚本 (parse_drc.py): 读取DRC运行日志,提取违规坐标并生成散点图。
# 1. Tcl规则文件片段 (drc_min_width.tcl)
set MIN_WIDTH_M1 0.18
DRC CHECK M1 WIDTH < $MIN_WIDTH_M1
DRC RESULT DATABASE "drc_results.db"
; 2. Skill交互检查片段 (check_width.il)
procedure(checkM1Width()
let((cv shapes)
cv = geGetEditCellView()
shapes = cv~>shapes
foreach(shape shapes
when(shape~>layerName == "M1"
width = shape~>width
when(width < 0.18
printf("违规: M1宽度 %.3f 小于0.18\n" width)
)
)
)
)
)
# 3. Python解析片段 (parse_drc.py)
import re
with open("drc_run.log", "r") as f:
for line in f:
if "违规" in line:
print(line.strip())
$变量替换与Skill的变量直接引用。在Tcl中,$var表示取值;在Skill中,直接写变量名即可。跨语言调用时,务必注意变量传递的格式转换。