版图设计新手必看:Skill脚本自动化布局实战指南

1次阅读
没有评论

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

image.webp

手动布局的三大痛点

作为 IC 设计新手,手动布局就像用绣花针搭建乐高城堡——我经历过连续 48 小时调整 MOS 管间距却因漏掉一个接触孔导致流片失败的惨痛教训。主要问题集中在:

版图设计新手必看:Skill 脚本自动化布局实战指南

  • 时间黑洞:一个中等规模模块的器件摆放需要反复拖动、对齐、验证,占项目 60% 以上时间
  • 人为错误 :设计规则检查(DRC) 阶段常发现间距 / 包围等基础错误,90% 源自手动操作疏忽
  • 版本灾难:每次工艺更新或模块调整,所有手动布局需推倒重来

自动化方案选型:Python 还是 Skill?

在 Cadence 设计环境中,两种主流自动化方案各有利弊:

  1. Python 方案
  2. 优势:生态丰富,可用 pya 等库处理复杂算法
  3. 劣势:通过 API 调用存在性能损耗,无法直接操作数据库

  4. Skill 方案

  5. 优势:原生支持 Virtuoso 数据库操作,执行效率高
  6. 劣势:学习曲线陡峭,调试工具较少

新手推荐路径:先用 Skill 实现基础布局自动化,再通过 Python 调用处理算法密集型任务

Skill 脚本速成课(含生存必备语法)

基础语法三件套

; 变量定义(注意动态类型)
let((x y)
  x = 5       ; 整数
  y = "cell"  ; 字符串
  list('(1 2 3)) ; 列表
)

; 循环结构
foreach(i '(1 2 3 4 5)
  printf("Value: %d\n" i)
)

; 函数定义
defun(createRect (@optional (layer "M1") (width 0.1))
  geCreateRect(
    ?layer layer
    ?width width
  )
)

版图元素操作实战

这段代码演示如何自动放置标准单元并连线:

procedure(autoPlaceInstance()
  let((lib cell view inst bBox)
    ; 打开目标库
    lib = ddGetObj("analogLib")
    cell = dbOpenCellViewByType(lib "nmos" "symbol" """r")

    ; 在 (100,200) 坐标放置实例
    inst = dbCreateInst(geGetEditCellView()
      cell "I1"
      list(100:200) "R0"
    )

    ; 获取边界框用于连线
    bBox = dbGetInstBBox(inst)

    ; 自动创建 M1 层金属连线
    geCreatePath(
      ?layer "M1"
      ?width 0.2
      ?pts list(list(xCoord(bBox->lowerLeft) yCoord(bBox->upperRight))
        list(xCoord(bBox->upperRight)+5 yCoord(bBox->upperRight))
      )
    )
  )
)

DRC 自动化实现技巧

通过内置 drcQuery 函数实现间距检查自动化:

procedure(checkPolySpace(@optional (minSpace 0.15))
  let((violations)
    violations = drcQuery(
      ?rule "space"
      ?layer1 "poly"
      ?value minSpace
      ?cell geGetEditCellView())

    when(violations
      foreach(viol violations
        printf("Violation at %L\n" viol->coordinates)
      )
    )
  )
)

性能优化双引擎

内存管理黄金法则

  • 对象回收 :用dbRelease 释放不再使用的版图对象
  • 批处理:超过 1000 个实例时,分区块处理并定期调用garbageCollect

多线程加速方案

; 启动多线程任务
defun(parallelPlace(instList)
  let((workers)
    workers = makeThreadPool(4)  ; 创建 4 线程池

    foreach(inst instList
      threadPoolSubmit(workers
        `dbCreateInst(geGetEditCellView() ,inst->master ,inst->name ,inst->origin ,inst->orient)`
      )
    )

    threadPoolJoin(workers)  ; 等待所有任务完成
  )
)

生产环境避坑指南

坐标系统转换陷阱

工艺厂提供的 GDSII 使用微米单位,而 Skill 默认用内部数据库单位(通常为纳米级)。必须严格转换:

; 错误做法(单位混淆)dbCreateRect(?width 0.18)  ; 可能是 0.18nm 或 0.18um?; 正确做法
defvar(*dbUPerUU* 1000)  ; 根据 PDK 设置单位比例
width = 0.18 * *dbUPerUU*  ; 明确单位转换

工艺库版本兼容性

遇到过因 PDK 升级导致脚本失效的案例:

  • 防御性编程:检查层名是否存在

    unless(layerExists("M1") 
      error("Current PDK missing M1 layer!")
    )

  • 版本嗅探

    pdkVersion = cdfGet(cdFindCellView("tsmc18" "device" "symbol") "pdkVersion")
    when(pdkVersion != "2.1"
      warn("Script developed for PDK v2.1, current is %s" pdkVersion)
    )

进阶挑战:MOS 管阵列生成器

现在尝试实现一个可配置的 MOS 管阵列生成器:

  1. 输入参数:行数(N)、列数(M)、器件类型
  2. 自动计算最优 finger 宽度以满足电流要求
  3. 生成符合 DRC 规则的差分对布局

提示代码框架:

defun(genMosArray(n m mosType)
  let((totalWidth fingers)
    ; TODO: 计算总宽度
    ; TODO: 自动 finger 划分
    ; TODO: 生成对称布局
  )
)

调试技巧 :在 CIW 窗口使用step 命令单步执行,配合 print 查看变量值

学习路径推荐

  1. 基础:Cadence 官方《Skill Language User Guide》
  2. 进阶:Eliot 讲的《Practical Skill Programming》视频课
  3. 实战:修改 PDK 中的标准单元生成脚本

最后提醒:所有示例代码需在 Cadence IC6.1.7+ 环境验证,建议先用测试库练习操作。遇到问题欢迎在 Cadence Support 社区提问(提问时请附上 skill getVersion() 输出)

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