在 IC 设计中,常常需要对已有的 Cell 库进行版本管理或重命名操作。传统的手工重命名不仅效率低下,更容易导致引用关系混乱。本文介绍一个强大的 SKILL 工具,它能够自动完成 Cell 批量重命名并智能修复所有引用关系。

工具功能

这个 SKILL 工具主要解决以下问题:

  1. 批量为 Cell 添加后缀 - 给指定库中的 Cell 统一添加版本后缀(如 _v2
  2. 跨库引用修复 - 自动扫描并修复其他库中对已重命名 Cell 的引用
  3. 前缀匹配过滤 - 支持只重命名特定前缀的 Cell
  4. 防重复保护 - 自动检测并跳过已添加后缀的 Cell

核心设计

两阶段处理流程

工具采用清晰的两阶段设计:

阶段 1:源库重命名

  • 仅在指定的源库列表(libsToRename)中执行重命名
  • 使用 ccpRename API 在文件系统层面移动 Cell
  • 支持前缀匹配和重复后缀检测

阶段 2:跨库引用修复

  • 扫描指定的库列表(libsToScan
  • 识别所有引用源库 Cell 的实例
  • 使用 dbSetInstHeaderMasterName 更新实例指针

关键技术点

1. 使用 ccpRename 重命名

ccpRename(
  srcSpec
  destSpec
  t                           ;; 允许覆盖
  'CCP_EXPAND_ALL            ;; 展开所有层次
  'CCP_UPDATE_COPIED_DATA    ;; 更新拷贝数据
  dummySpecList
)

这种方式比简单的 dbCopyCellView 更可靠,因为它处理文件系统层面的移动。

2. 智能引用判断

工具的核心逻辑在于三层判断:

;; 1. 实例来自被重命名的库?
when( member(instLibName libsToRename)
  ;; 2. Cell 名匹配指定前缀?
  when( rexMatchp(strcat("^" matchPrefix) oldMasterName)
    ;; 3. 尚未更新(名字里没有后缀)?
    unless( rexMatchp(strcat(suffix "$") oldMasterName)
      ;; 执行更新
      dbSetInstHeaderMasterName(instHeader instLibName newMasterName nil)
    )
  )
)

3. 全视图支持

工具处理三种关键视图:

  • layout - 版图实例
  • symbol - 符号实例
  • schematic - 原理图实例

使用方法

基本用法

;; 1. 加载脚本
load("CCSRenameSuffix.il")

;; 2. 定义库列表
renameList = list("IP_ANA_LIB" "IP_DIG_LIB")  ;; 要重命名的源库
scanList   = list("IP_ANA_LIB" "IP_DIG_LIB" "PROJECT_TOP" "TB_LIB") ;; 要扫描的库

;; 3. 执行重命名
CCSRenameAndFixRefs(renameList scanList "" "_v2")

参数说明

参数 类型 说明
libsToRename list 需要重命名 Cell 的库列表
libsToScan list 需要扫描和修复引用的库列表
matchPrefix string Cell 名前缀匹配(空字符串表示全部)
suffix string 要添加的后缀(如 “_v2”, “_bak”)

注意:源库通常也应包含在扫描列表中,以处理库内部的自引用。

典型应用场景

场景 1:IP 库版本管理

;; 为 IP 库创建 v2 版本
ipLibs = list("STD_CELL_LIB" "MEM_LIB" "IO_LIB")
allLibs = cons("TOP_DESIGN" cons("TESTBENCH" ipLibs))

CCSRenameAndFixRefs(ipLibs allLibs "" "_v2")

结果

  • IP 库中所有 Cell 添加 _v2 后缀
  • Top 设计和测试平台中的引用自动更新

场景 2:仅重命名特定前缀的 Cell

;; 只重命名以 "INV_" 开头的 Cell
CCSRenameAndFixRefs(
  list("ANALOG_LIB")
  list("ANALOG_LIB" "MIXED_SIGNAL")
  "INV_"
  "_new"
)

场景 3:项目归档

;; 项目完成后添加日期后缀
projectLibs = list("PROJ_A_ANALOG" "PROJ_A_DIGITAL" "PROJ_A_TOP")
CCSRenameAndFixRefs(projectLibs projectLibs "" "_2026Q1")

工作原理图解

1
2
3
4
5
6
7
8
9
10
11
12
13
原始状态:
├── IP_LIB
│   ├── inv        ← 要重命名
│   └── nand2      ← 要重命名
└── TOP_LIB
    └── chip (包含 inv 和 nand2 的实例)

执行后:
├── IP_LIB
│   ├── inv_v2     ← 已重命名
│   └── nand2_v2   ← 已重命名
└── TOP_LIB
    └── chip (实例指针已更新到 inv_v2 和 nand2_v2)

注意事项

[!WARNING] 重要提醒

  • 重命名操作不可逆,务必先备份
  • 建议在测试库中先验证
  • 确保所有相关库都有写权限

[!TIP] 最佳实践

  • 使用语义化的后缀(如 _v2, _20260115)
  • 将源库包含在扫描列表中
  • 重命名前关闭所有相关 cellview

完整代码

;;--------------------------------------------------------------------
;; File     : CCSRenameSuffix.il
;; Purpose  : 给指定库的 Cell 加后缀,并扫描指定库修复实例引用
;; Author   : wanlin.wang
;; Updated  : 2026/01/15
;;--------------------------------------------------------------------
 
;; === Step 1: 仅在 libsToRename 中重命名 Cell ===
procedure(renameCellAddSuffixSrcOnly(libsToRename matchPrefix suffix)
  let( (oldName newName srcSpec destSpec)
    foreach(libName libsToRename
      printf(">>> [Step 1: Rename] Processing Library: %s\n" libName)
      when(ddGetObj(libName)
        foreach(cell ddGetObj(libName)->cells
          oldName = cell~>name
          when(rexMatchp(strcat("^" matchPrefix) oldName)
            unless(rexMatchp(strcat(suffix "$") oldName)
              newName = strcat(oldName suffix)
              printf("    Action: Renaming %s -> %s\n" oldName newName)
     
              srcSpec  = gdmCreateSpec(libName oldName "" "" "CDBA")
              destSpec = gdmCreateSpec(libName newName "" "" "CDBA")
     
              let((dummySpecList)
                dummySpecList = gdmCreateSpecList()
                ccpRename(
                  srcSpec
                  destSpec
                  t
                  'CCP_EXPAND_ALL
                  'CCP_UPDATE_COPIED_DATA
                  dummySpecList
                )
              )
            )
          )
        )
      )
    )
  )
)
 
;; === Step 2: 在 libsToScan 中遍历,修复指向 libsToRename 的引用 ===
procedure(updateInstanceReferenceInScope(libsToRename libsToScan matchPrefix suffix)
  let( (cv inst oldMasterName newMasterName instLibName)
    foreach(lib libsToScan
      printf(">>> [Step 2: Fix Refs] Scanning Library: %s\n" lib)
      when(ddGetObj(lib)
        foreach(cell ddGetObj(lib)->cells
          foreach(cellView cell~>views
            when(member(cellView~>name '("layout" "symbol" "schematic"))
              cv = dbOpenCellViewByType(lib cell~>name cellView~>name "" "a")
              when(cv
                foreach(instHeader cv~>instHeaders
                  instLibName = instHeader~>libName
                  oldMasterName = instHeader~>cellName
 
                  when( member(instLibName libsToRename)
                    when( stringp(oldMasterName) && rexMatchp(strcat("^" matchPrefix) oldMasterName)
                      if(rexMatchp(strcat(suffix "$") oldMasterName) then
                          nil
                      else
                          newMasterName = strcat(oldMasterName suffix)
                          printf("    Fixing Instance in %s/%s/%s: %s/%s -> %s\n"
                                  lib cell~>name cellView~>name
                                  instLibName oldMasterName
                                  newMasterName)
                          dbSetInstHeaderMasterName(instHeader instLibName newMasterName nil)
                      )
                    )
                  )
                )
                dbSave(cv)
                dbClose(cv)
              )
            )
          )
        )
      )
    )
  )
)
 
;; === 顶层主函数 ===
procedure(CCSRenameAndFixRefs(libsToRename libsToScan matchPrefix suffix)
  printf("\n======================================================\n")
  printf("Job: Rename Cells and Fix References\n")
  printf("Target 1 (Modify): %L will have cells renamed.\n" libsToRename)
  printf("Target 2 (Scan):   %L will be scanned for updates.\n" libsToScan)
  printf("Suffix to append:  '%s'\n" suffix)
  printf("======================================================\n\n")
 
  renameCellAddSuffixSrcOnly(libsToRename matchPrefix suffix)
  updateInstanceReferenceInScope(libsToRename libsToScan matchPrefix suffix)
 
  printf("\n>>> All Done.\n")
)

总结

这个 SKILL 工具提供了一套完整的 Cell 批量重命名解决方案,具有以下特点:

  • ✅ 清晰的两阶段设计(重命名 + 修复)
  • ✅ 智能的引用判断逻辑
  • ✅ 全面的视图支持(layout/symbol/schematic)
  • ✅ 防重复后缀保护
  • ✅ 详细的日志输出

通过合理使用该工具,可以大大提高 IC 设计中库管理和版本控制的效率。