在 IC 设计部门承接新 fab 工艺节点时,往往需要从零搭建 Virtuoso 设计环境。本文梳理配置流程中涉及的关键文件与操作步骤。
一、PDK 是什么
PDK(Process Design Kit) 是 fab 交付给设计团队的工艺库包,通常包含:
| 内容 | 说明 |
|---|---|
| Technology Library(技术库) | 层定义、via 规则、连接规则等工艺参数 |
| 器件 SPICE/Spectre 模型文件 | 用于仿真 NMOS/PMOS 及 IP 器件特性 |
| 原语符号库 / 布局库 | Virtuoso 中可直接调用的 cell |
| DRC / LVS 规则文件 | 供 Pegasus / Calibre 等工具使用 |
display.drf |
每一层的颜色与填充样式 |
cds.lib / libInit.il |
库定义与初始化脚本(PDK 标准交付件) |
Cadence 另提供通用 PDK(如 gpdk045、ADVGPDK)供学习与开发使用,可在 Process Design Kits (PDK) Downloads 页面获取。
二、Cadence 的文件搜索机制(CSF)
Virtuoso 启动时通过 CSF(Cadence Setup Search File)机制 依序搜索所有配置文件,入口是 setup.loc。
setup.loc 的默认搜索顺序(从高到低优先级):
1
2
3
4
5
6
7
8
. # 当前工作目录
@LIBRARY # cds.lib 中定义的各库目录
$CDS_WORKAREA # 工作区(若已定义)
$CDS_SEARCHDIR # 工具启动时设置
$HOME # 用户主目录
$CDS_PROJECT # 项目目录(若已定义)
$CDS_SITE # 站点公共目录(默认 install_dir/share/local)
$TOOL_INST_ROOT/share # Cadence 安装目录
对于每一个路径,CSF 会依次在 <path>/.cadence/、<path>/ 和 <path>/cdssetup/ 三个子目录下查找目标文件,找到即停止。
可用以下命令调试搜索结果:
1
cdswhich -debug setup.loc
配置建议:公司/fab 级公共配置放
$CDS_SITE;项目级配置放$CDS_PROJECT;个人偏好放$HOME;当前工程放工作目录。不要修改 Cadence 安装目录下的默认setup.loc,应新建自己的副本。
三、关键配置文件
3.1 cds.lib — 库定义文件
cds.lib 是 Library Manager 的核心,定义 Virtuoso 可访问的所有库路径。
1
2
3
4
5
6
7
8
# 包含 Cadence 内建 analogLib
INCLUDE $CDS_INST_DIR/tools/dfII/etc/cdslib/artist/cds.lib
# 包含 fab PDK 提供的库定义(PDK 通常自带 cds.lib)
INCLUDE $PDK_HOME/cds.lib
# 直接定义用户设计库
DEFINE myProject /home/user/designs/myProject
启动 Virtuoso 时可通过 -cdslib 参数指定非默认路径的 cds.lib:
1
virtuoso -cdslib /path/to/project/cds.lib
注意:
-cdslib是启动时的一次性读取。后续在 Library Manager 中新增或删除库,仍会写入当前工作目录下的cds.lib。
3.2 .cdsinit — 启动初始化脚本
.cdsinit 是 SKILL 脚本,Virtuoso 启动时自动执行一次。
默认搜索顺序:
$CDS_INST_DIR/tools/dfII/local/- 当前工作目录
./ $HOME/
也可通过 csfLookupConfig 文件将其纳入 CSF 搜索路径。
典型内容示例(lab 或公共 $CDS_SITE 级别):
; 加载 fab PDK 的初始化脚本(PDK 通常提供此文件)
load("/pdk/myFabPDK/cdssetup/cdsinit.il")
; 自动打开 Library Manager
ddsOpenLibManager()
3.3 .cdsenv — 环境变量设置文件
.cdsenv 控制各工具窗口的默认行为,格式为:
1
tool[.section] setting type value
其搜索顺序受环境变量 CDS_LOAD_ENV 控制,常用值:
| 值 | 行为 |
|---|---|
CSF(推荐) |
按 setup.loc 搜索所有 .cdsenv |
CWDElseHome |
先找当前目录,再找 $HOME |
addCWD |
先加载 $HOME/.cdsenv,再叠加当前目录 |
3.4 display.drf — 层显示资源
fab PDK 通常提供专属的 display.drf,定义每一工艺层的颜色与填充样式。可通过 .cdsinit 加载:
hiLoadColorMap("/pdk/display/display.drf")
四、工艺库(Technology Library)的挂载
每个用户设计库需要 attach 到 fab 提供的 Technology Library,否则无法获取层定义和设计规则。
界面操作:Library Manager → 右键设计库 → Technology File for Library
SKILL 操作(可写入 libInit.il):
techBindTechFile(ddGetObj("myDesignLib") "/pdk/tech/fabTech.tf")
Technology Library 包含:层次定义(layer purpose pairs)、via / contact 规则、工艺参数等,是 DRC、LVS 以及参数提取的基础。
五、器件模型(Device Model)的接入
PDK 中的器件模型通常是 Spectre 格式(.scs) 文件,内部按工艺角(corner)分成多个 section:
1
2
3
4
5
6
7
8
9
10
11
// 典型模型文件结构
simulator lang=spectre
section tt
model nmos_lvt nmos ...
model pmos_lvt pmos ...
endsection tt
section ff
...
endsection ff
5.1 推荐方式:libInit.il(PDK 级,对所有用户透明)
libInit.il 放在 PDK 库目录中,Virtuoso 打开该 PDK 库时自动执行,是 Cadence 官方推荐的模型注册位置。
; 文件:/pdk/myFabPDK/libInit.il
; 使用 ADE 会话回调,确保在 ADE 完全初始化后再添加模型
ddRegPostOpenLib("myFabPDKLib"
lambda(nil
asiSetEnvOptionVal(asiGetTool('spectre) "modelFiles"
list(
list("/pdk/models/spectre/tt_27c.scs" "tt")
list("/pdk/models/spectre/ff_27c.scs" "ff")
list("/pdk/models/spectre/ss_27c.scs" "ss")
list("/pdk/models/spectre/sf_27c.scs" "sf")
list("/pdk/models/spectre/fs_27c.scs" "fs")
)
)
)
)
5.2 .cdsenv 方式(项目/用户级)
多个模型文件用空格分隔,section 跟在文件路径后以分号连接:
1
spectre.envOpts modelFiles string "/pdk/models/tt.scs;tt /pdk/models/res.scs"
5.3 .cdsinit SKILL 方式(用户级,不推荐用于 PDK 模型)
; 单文件单 section
asiSetEnvOptionVal(asiGetTool('spectre) "modelFiles"
'(("/pdk/models/models.scs" "tt")))
; 多文件多 section
asiSetEnvOptionVal(asiGetTool('spectre) "modelFiles"
list(
list("/pdk/models/models.scs" "tt_bip")
list("/pdk/models/models.scs" "tt_mos")
))
; "#" 开头表示该条目为未勾选状态(inactive)
asiSetEnvOptionVal(asiGetTool('spectre) "modelFiles"
'(("#" "/pdk/models/ff.scs" "ff")
("/pdk/models/tt.scs" "tt")))
不推荐在
.cdsinit中配置 PDK 模型,而是推荐libInit.il。原因:.cdsinit是用户专属文件,不可移植;PDK 升级后容易残留旧路径,导致 ADE 仍引用旧版本模型(参见 ADE still refers to old PDK model files)。此外,如果 PDK 不更新而模型需要更新,此时需要单独处理初始化脚本里的模型文件路径。
5.4 ADE 界面操作(手动,适合临时测试)
1
2
3
4
ADE Explorer / Assembler → Setup → Model Library Setup
→ Add File → 选择 .scs 文件
→ 在 Section 列填写 corner 名称(如 tt)
→ 勾选需要激活的 corner
设置会随 maestro view 保存到设计库中持久化。
六、推荐工程目录结构
1
2
3
4
5
6
project/
├── cds.lib # 项目库定义(INCLUDE PDK + DEFINE 用户库)
├── .cdsinit # 项目级初始化(仅 load fab 提供的 cdsinit.il)
├── .cdsenv # 项目级工具默认值
├── setup.loc # 自定义 CSF 搜索路径(可选)
└── myDesignLib/ # 用户设计库(attach 到 fab Technology Library)
fab PDK 解压后通常包含以下目录,不需要用户单独维护:
1
2
3
4
5
6
7
/pdk/myFabPDK/
├── cds.lib # PDK 库路径定义,项目 cds.lib 中 INCLUDE 此文件
├── libInit.il # 模型注册、工具初始化(打开 PDK 库时自动执行)
├── tech/ # Technology File / Technology Library
├── models/ # Spectre 器件模型文件(含各工艺角)
├── display/ # display.drf 层颜色定义
└── cdssetup/ # cdsinit.il、.cdsenv 模板(供项目引用)
七、各配置层级汇总
| 配置文件 | 推荐放置层级 | 作用 |
|---|---|---|
cds.lib |
项目工作目录 | 声明所有可见库(INCLUDE PDK + DEFINE 用户库) |
setup.loc |
$CDS_SITE 或项目目录 |
自定义 CSF 搜索路径 |
libInit.il |
PDK 库目录(PDK 提供) | 库打开时自动注册模型、加载工具 |
.cdsinit |
$CDS_SITE / 项目目录 |
Virtuoso 启动时执行,load PDK 的 cdsinit.il |
.cdsenv |
$CDS_SITE / $HOME |
工具默认参数,不用于模型路径配置 |
display.drf |
PDK 提供,.cdsinit 中 load |
层颜色与填充 |
附录:libInit.il 的自动加载机制详解
参考:Cadence ASK 官方文档 loading sequence 与 SKILL to reload libInit.il
一、自动加载机制
不需要在 .cdsinit 中手动 load("libInit.il")。只要库在 cds.lib / lib.defs 中被 DEFINE,DFII 框架在首次访问该库时会自动加载其 libInit.il。
触发”首次访问”的典型场景:
- Library Manager 启动时扫描到该库
- 打开该库下的任意 cell(layout、schematic 等任意视图)
- 在 CIW 的 File → recent history 中涉及该库的 cell view
二、多库时的加载顺序
当打开一个设计库中的 cell,该 cell 引用了工艺库和标准单元库时,三个库的 libInit.il 按以下顺序依次加载:
- Design Library(用户设计库)的
libInit.il - Standard Library(标准单元库)的
libInit.il - Technology Library(工艺库 / PDK 库)的
libInit.il
即 PDK 工艺库的 libInit.il 最后加载。各库之间的加载由”首次访问”时序决定。
三、重要限制
每个库的 libInit.il 在一个 Virtuoso session 中只加载一次。此后:
- 在 Library Manager 执行 View → Refresh 并不会重新触发
libInit.il的加载; - 若
libInit.il文件内容有更新,只能通过手动loadi()或重启 Virtuoso 使其生效。
如果需要在 Refresh 时自动重新加载,可在 .cdsinit 中注册如下 trigger:
procedure(abRefreshLibInit()
let((fileName)
foreach(libId ddGetLibList()
foreach(fileName '("libInit.il" "libInit.ils")
fileId = ddGetObj(libId~>name nil nil fileName)
when(fileId && (fileName = ddGetObjReadPath(fileId)) &&
isReadable(fileName)
loadi(fileName)
)
)
)
t
)
)
procedure(abRegRefreshLibInit()
ddRegTrigger("PostUpdateLibList" 'abRefreshLibInit)
)
abRegRefreshLibInit()
四、小结
| 问题 | 结论 |
|---|---|
是否需要在 .cdsinit 中手动 load PDK 的 libInit.il? |
不需要,DEFINE 库后 DFII 自动处理 |
attach 到工艺库是 libInit.il 被加载的前提吗? |
不是,任何 DEFINE 的库首次访问即触发 |
每次打开 Virtuoso 都会重新加载 libInit.il 吗? |
是,但每次 session 内只加载一次 |
Refresh 能重新加载 libInit.il 吗? |
不能,需手动 loadi() 或重启 |
参考资料
本文内容均参考自以下 Cadence ASK 官方文档(需登录访问):