共计 2555 个字符,预计需要花费 7 分钟才能阅读完成。
背景痛点
在 IC 设计流程中,手动操作版图和原理图效率极低。比如需要修改上百个金属层的属性时,设计师不得不逐个点击、检查、修改,不仅耗时耗力,还容易出错。这种重复性工作占据了工程师大量时间,严重拖慢项目进度。Skill 脚本正是为了解决这类问题而生,通过自动化操作可以提升效率 3 倍以上。

环境配置
- 打开 Cadence Virtuoso,在 CIW(Command Interpreter Window)窗口输入
skill进入交互模式 - 设置开发环境变量(示例为 Linux 系统):
export CDS_SKILL_PATH=$HOME/skill_scripts
export CDS_LOAD_PATH=$CDS_SKILL_PATH:$CDS_LOAD_PATH
-
常用 CIW 命令:
-
load("script.il")加载脚本 ?funName查看函数帮助Ctrl+C中断执行
注意:Windows 用户需通过菜单 Tools→Skill Development→Skill IDE 启用集成环境。
核心语法精要
列表处理三剑客
consvslist:
; cons 是构造单元,时间复杂度 O(1)
cons(1 nil) => (1)
cons(1 cons(2 nil)) => (1 2)
; list 是语法糖,实际嵌套 cons,时间复杂度 O(n)
list(1 2 3) => (1 2 3)
-
访问函数:
-
car取首元素(O(1)) cdr取剩余列表(O(1))
数据库对象操作
; 获取当前 cellView
cv = geGetEditCellView()
; 遍历所有 instances
foreach(inst cv~>instances
printf("Found instance %s\n" inst~>name)
)
; 修改属性(注意需要 dbSave 才能持久化)dbSetq(inst "w" 1.2e-6)
文件 IO 黑科技
; 带缓冲的写入(比常规 open 快 3 倍)outfile("data.txt" "w")
fprintf(dataFile "%Y-%m-%d %H:%M\n" getCurrentTime())
close(dataFile)
; 安全读取方式
when(infile("config.cfg")
while(gets(line dataFile)
parseString(line)
)
)
实战案例
案例 1:批量修改金属层
procedure(changeMetalProps(@optional (cv geGetEditCellView()))
unless(cv error("No active cellview!"))
let((metalLayers cnt)
metalLayers = list("M1" "M2" "M3" "M4")
cnt = 0
; 使用 dbLayerQuery 避免全量加载
foreach(layer metalLayers
foreach(shape dbLayerQuery(cv layer)
when(shape~>isWire
dbSetq(shape "width" 0.1)
cnt++
)
)
)
printf("Modified %d wires\n" cnt)
dbSave(cv)
)
)
案例 2:DRC 结果导出
procedure(exportDRC(cellName)
axlCmd("drc execute")
axlDRCGetAllViolations(cellName)
let((csvFile)
csvFile = outfile(strcat(cellName "_drc.csv") "w")
fprintf(csvFile "Type,Location,Rule\n")
foreach(viol axlGetViolations()
fprintf(csvFile "%s,%s,%s\n"
viol~>type
axlXYToString(viol~>xy)
viol~>rule
)
)
close(csvFile)
axlUIWPrint("Export completed!")
)
)
避坑指南
-
内存泄漏:
-
未释放的 db 对象会导致内存持续增长
-
解决方案:用
dbClose或包裹在let中自动释放 -
版本兼容性:
-
Virtuoso 6.x 与 IC617 的 API 差异示例:
; 旧版
leHiConvertRectToPolygon()
; 新版
leConvertRectToPolygon()
建议在脚本开头添加版本检查:
when(version < "IC6.1.7"
error("Require IC617 or higher")
)
性能优化
-
循环优化:
-
避免在循环内进行 db 查询:
; 错误示范(时间复杂度 O(n^2))foreach(inst cv~>instances
foreach(term inst~>terminals
...
)
)
; 正确做法(预加载降低到 O(n))instTerms = mapcar('getTerminals cv~>instances)
foreach(termList instTerms
foreach(term termList
...
)
)
-
惰性加载:
-
使用
dbLayerQuery替代cv~>shapes - 分块处理大规模数据:
procedure(processLargeData(cv chunkSize)
let((total cnt)
total = dbGetq(cv "shapes")
cnt = 0
while(cnt < total
foreach(shape dbGetq(cv "shapes" cnt chunkSize)
processShape(shape)
cnt++
)
)
)
)
思考题
如何实现工艺库参数的动态验证?可以考虑:
- 通过
libGet获取工艺库属性 - 使用
paramGet读取当前规则值 - 建立规则检查函数:
procedure(checkLayerRule(libName layerName)
let((ruleValue)
ruleValue = paramGet(libName "minWidth")
unless(floatp(ruleValue)
error("Rule value not number")
)
; 对比设计值与规则值
when(designWidth < ruleValue
axlUIWPrint("Violation on %s!" layerName)
)
)
)
建议结合定时器实现实时监控。如果对具体实现感兴趣,欢迎在评论区讨论!
正文完
