共计 2284 个字符,预计需要花费 6 分钟才能阅读完成。
从版图生成失败说起
上周在 Cadence Virtuoso 中遇到一个典型问题:使用脚本批量生成 MOS 管时,部分器件神秘消失。最终定位到是 Skill 变量作用域问题——在循环内误用 global 声明导致变量覆盖。这促使我系统梳理 Skill 语法要点,以下是实战中总结的经验。

Skill vs Tcl/Python 的领域优势
- EDA 原生支持 :Skill 直接调用
geGetEditCellView等 Virtuoso 内部 API,而 Python 需通过 PCI 接口绕行 - 性能敏感操作 :版图数据处理时,Skill 的
foreach比 Python 列表推导快 3 - 5 倍(实测 5000 个 instance 场景) - 语法简洁性 :工艺规则检查这类任务,Skill 的
when条件判断比 Tcl 的if-else链条更紧凑
核心语法三剑客
1. 变量作用域:防污染指南
; 危险示范(全局变量污染)globalVar = 10
procedure(dangerousProc()
println(globalVar) ; 输出 10
globalVar = 20 ; 意外修改全局变量
)
; 推荐做法(局部变量 + 参数传递)procedure(safeProc(@optional (localVar 5))
let((tempVar)
tempVar = localVar * 2 ; 安全使用局部变量
println(tempVar)
)
)
2. 条件语句:cond/case 性能对比
cond适用场景:多条件判断且需执行不同代码块时cond((layer == "METAL1" => println("0.1um width")), (layer == "VIA1" => println("0.05um size")), (t => println("Default rule")) )case优势:纯值匹配时速度提升约 30%case(layer ("POLY" 0.12) ("DIFF" 0.15) (t 0.08) ; 默认值 )
3. 循环结构:大数据量实战
; 避免使用 while 做集合遍历
procedure(slowIterate()
let((i list)
list = list(1 2 3 4 5)
i = 0
while(i < length(list) ; 每次循环都计算 length
println(list[i])
i++
)
)
)
; 推荐 foreach+lambda(实测快 2 倍)procedure(fastIterate()
foreach(item list(1 2 3 4 5)
println(item)
)
)
工业级代码示例:版图元件生成
/*
* 批量创建 MOS 管单元
* @param libName 库名称
* @param cellName 单元名称
* @param width 器件宽度(um)
* @param fingers 指数
*/
procedure(createMosArray(libName cellName width fingers @optional (step 0.5))
let((cv inst bBox)
unless(ddGetObj(libName)
error("Library %s not found" libName))
cv = geGetEditCellView()
when(cv
for(i 0 fingers-1
inst = dbCreateInst(
cv
ddGetObj(libName cellName)
sprintf(nil "M%d" i)
list(i*step 0) ; 自动步进排版
"R0"
)
; 添加参数化属性
dbSetProp(inst "w" width)
dbSetProp(inst "l" 0.05)
)
geRedraw()
; 错误处理示例
t = catchAll(bBox = geGetSelSet()~>bBox
println(sprintf(nil "Total width: %f" bBox->width))
)
when(t
println("WARNING: Bounding box calculation failed")
)
)
)
)
性能优化进阶
内存泄漏检测
- 使用
dbMemReport查看对象分配 - 重点检查未释放的
list和table - 推荐
let作用域自动回收
procedure(checkMemory()
let((before)
before = dbMemReport()
; ... 执行可疑代码...
println(difference(dbMemReport() before))
)
)
大数据分块策略
; 处理 10 万个 instance 的 DRC 检查
procedure(batchDrcCheck()
let((allInsts batchSize)
allInsts = geGetAllInstances()
batchSize = 5000 ; 每批处理量
for(i 0 length(allInsts)-1 batchSize
let((batch)
batch = slice(allInsts i min(i+batchSize length(allInsts)-1))
foreach(inst batch
drcCheckSingleInst(inst)
)
gc() ; 主动触发垃圾回收)
)
)
)
思考与延伸
- 跨工艺移植方案:
- 使用
technology变量封装工艺参数 - 正则表达式替换尺寸单位
-
建立工艺映射表
techMap = '(("TSMC40"0.04) ("SMIC28" 0.028)) -
CI/CD 集成思路:
- 用
skillpp做语法检查 - 通过
skill -n -l script.il运行测试用例 - 结合 Jenkins 的 Violation 插件统计警告
最后建议:在 Virtuoso 中开启skillDevelopmentMode,遇到语法错误时能获得更详细的堆栈信息。Happy scripting!
正文完
发表至: EDA工具
近一天内
