从零开始掌握Skill脚本:新手入门指南与实战技巧

4次阅读
没有评论

共计 2555 个字符,预计需要花费 7 分钟才能阅读完成。

image.webp

背景痛点

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

从零开始掌握 Skill 脚本:新手入门指南与实战技巧

环境配置

  1. 打开 Cadence Virtuoso,在 CIW(Command Interpreter Window)窗口输入 skill 进入交互模式
  2. 设置开发环境变量(示例为 Linux 系统):
export CDS_SKILL_PATH=$HOME/skill_scripts
export CDS_LOAD_PATH=$CDS_SKILL_PATH:$CDS_LOAD_PATH
  1. 常用 CIW 命令:

  2. load("script.il") 加载脚本

  3. ?funName 查看函数帮助
  4. Ctrl+C 中断执行

注意:Windows 用户需通过菜单 Tools→Skill Development→Skill IDE 启用集成环境。

核心语法精要

列表处理三剑客

  1. cons vs list:
; 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)
  1. 访问函数:

  2. car 取首元素(O(1))

  3. 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!")
  )
)

避坑指南

  1. 内存泄漏

  2. 未释放的 db 对象会导致内存持续增长

  3. 解决方案:用 dbClose 或包裹在 let 中自动释放

  4. 版本兼容性

  5. Virtuoso 6.x 与 IC617 的 API 差异示例:

; 旧版
leHiConvertRectToPolygon()

; 新版
leConvertRectToPolygon()

建议在脚本开头添加版本检查:

when(version < "IC6.1.7"
  error("Require IC617 or higher")
)

性能优化

  1. 循环优化

  2. 避免在循环内进行 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
    ...
  )
)
  1. 惰性加载

  2. 使用 dbLayerQuery 替代cv~>shapes

  3. 分块处理大规模数据:
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++
      )
    )
  )
)

思考题

如何实现工艺库参数的动态验证?可以考虑:

  1. 通过 libGet 获取工艺库属性
  2. 使用 paramGet 读取当前规则值
  3. 建立规则检查函数:
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)
    )
  )
)

建议结合定时器实现实时监控。如果对具体实现感兴趣,欢迎在评论区讨论!

正文完
 0
评论(没有评论)