在 Cadence Virtuoso 中进行自底向上的层级化设计时,我们经常需要将底层模块的引脚(Pins)“提升”(Promote)到顶层。在 Layout 视图中,Virtuoso 原生提供了非常完善的 “Promote Pins” 功能;但许多工程师发现在 Schematic 原理图环境中,并没有与之完全对应的现成菜单。
本文将结合 Cadence Support 的官方资源,详细介绍如何在原理图中通过 SKILL 脚本实现 Promote Pins 功能,并简要回顾 Layout 中的标准流程。
1. 原理图中的挑战与解决方案:SKILL 脚本
在标准的 Virtuoso Schematic Editor 中,如果要把一个 Instance 的未连接端口(Instance Terminals)变成顶层的 Pins,手动操作(记下名字、方向,再逐个 Create Pin)既费时又容易出错。
Cadence 官方为此提供了一个自动化 SKILL 脚本:CCSCreatePinsForInstpins。
功能亮点
- 自动识别:能自动找出选中 Instance 上所有尚未建立外部连接的 terminals(
instPins)。 - 属性匹配:创建的 Pin 会自动继承下层端口的名称和方向(Input, Output, inputOutput)。
- 灵活放置:允许将生成的 Pin 直接放置在 Instance 端口上,或设置一定的偏移量(Offset)并自动连线。
使用步骤
- 下载脚本:在 Cadence Support 搜索并下载 Article 11158496 提供的 SKILL 文件。
由于脚本没有正确适配Label的方向,没有做重复检测,下面我提供一个修改后的脚本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/*************************************************************************
* DISCLAIMER: The following code is provided for Cadence customers *
* to use at their own risk. The code may require modification to *
* satisfy the requirements of any user. The code and any modifications *
* to the code may not be compatible with current or future versions of *
* Cadence products. THE CODE IS PROVIDED "AS IS" AND WITH NO WARRANTIES, *
* INCLUDING WITHOUT LIMITATION ANY EXPRESS WARRANTIES OR IMPLIED *
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. *
*************************************************************************/
;;------------ From Here ------------------
procedure(CCSCreatePinsForInstpins(libName cellName viewName offset)
let((cv ip op iop instTermbBox x1 y1 xf yf dir mypin instTermList openres
pinName instList actualList rotation labelAngle labelJustify selBox ibox left_E right_E
top_E bot_E)
;; Will create a schematic view
cv = dbOpenCellViewByType(libName cellName viewName "schematic" "a")
ip = dbOpenCellViewByType("basic" "ipin" "symbol" "" "r")
op = dbOpenCellViewByType("basic" "opin" "symbol" "" "r")
iop = dbOpenCellViewByType("basic" "iopin" "symbol" "" "r")
openres = dbOpenCellViewByType("analogLib" "res" "symbol" nil "r")
unless(cv~>instances
dbCreateInst(cv openres "I1" list(0 0) "R0" 1)
) ;unless
dbSave(cv)
schCheck(cv)
;; Work on the instance selected / just created
if(windowp(geGetCellViewWindow(cv)) && geGetSelSet() then
instList = geGetSelSet()
else
instList = cv~>instances
) ;if
foreach(inst instList
;; Filter out instTerms with external connections
instTermList = inst~>instTerms
actualList = nil
foreach(term instTermList
if(term~>net~>instTermCount == 1 then
actualList = reverse(append(list(term) actualList))
) ;if
) ;foreach term
foreach(ter actualList
;; Get the origin for the instPins
instTermbBox = dbTransformBBox(car(ter~>term~>pins~>fig~>bBox) inst~>transform)
x1 = xCoord(centerBox(instTermbBox))
y1 = yCoord(centerBox(instTermbBox))
dir = nil
rotation = nil
;; Find the edge of the instTerms in the symbol
selBox = setof(x inst~>master~>shapes x~>lpp == '("instance" "drawing"))
ibox = geTransformUserBBox(car(selBox)~>bBox inst~>transform)
left_E = leftEdge(ibox)
right_E = rightEdge(ibox)
top_E = topEdge(ibox)
bot_E = bottomEdge(ibox)
;; rotation : points the connection stub toward the instance
;; labelAngle : text orientation (0=horizontal, 90=vertical)
;; labelJustify: anchor so the text extends AWAY from the pin origin
;; (i.e., beyond the arrowhead, not toward the instance)
cond(
((x1 - 0.1) < left_E
xf = x1 - offset
yf = y1
rotation = "R0"
labelAngle = 0.0
labelJustify = "centerRight" ; text extends leftward, past arrowhead
) ;left_Edge
((x1 + 0.1) > right_E
xf = x1 + offset
yf = y1
rotation = "R0"
labelAngle = 0.0
labelJustify = "centerLeft" ; text extends rightward, past arrowhead
) ;right_Edge
((y1 - 0.1) < bot_E
xf = x1
yf = y1 - offset
rotation = "R90"
labelAngle = 90.0
labelJustify = "centerRight" ; anchor at top → text extends downward past arrowhead
) ;bottom_Edge
((y1 + 0.1) > top_E
xf = x1
yf = y1 + offset
rotation = "R90"
labelAngle = 90.0
labelJustify = "centerLeft" ; anchor at bottom → text extends upward past arrowhead
) ;top_Edge
) ;cond
;; Determine pin symbol (ipin / opin / iopin) from terminal direction
case(ter~>direction
("input"
dir = ip
) ;input
("output"
dir = op
) ;output
("inputOutput"
dir = iop
) ;inputOutput
) ;case
pinName = ter~>name
;; Check if the pin already exists at the target location.
;; A terminal might exist from other pins with the same name, so we check if
;; any physical pin connected to this terminal is located near our target (xf:yf).
let((pinExists)
pinExists = nil
foreach(term cv~>terminals
if(term~>name == pinName then
foreach(p term~>pins
;; Check if the pin's figure coordinates are close to xf:yf
if(p~>fig && p~>fig~>xy &&
abs(xCoord(p~>fig~>xy) - xf) < 0.1 &&
abs(yCoord(p~>fig~>xy) - yf) < 0.1 then
pinExists = t
)
)
)
)
if(pinExists then
printf("Pin %s already exists at target location, skipping creation.\n" pinName)
else
mypin = schCreatePin(cv dir pinName ter~>direction nil xf:yf rotation)
;; Move the label to the outer tip of the pin (beyond the arrowhead).
;; schCreatePin defaults the label to the origin/stub side (toward instance);
;; we override justification and orient so text extends away from the instance.
if(mypin~>children then
let((labelId labelX labelY labelOffset)
labelId = car(mypin~>children)
;; Add an extra offset for the label so it doesn't overlap with the pin wire/shape.
;; We push the label further out in the direction the pin is facing.
labelOffset = 0.1
cond(
(rotation == "R0" && labelJustify == "centerRight"
labelX = xf - labelOffset
labelY = yf
)
(rotation == "R0" && labelJustify == "centerLeft"
labelX = xf + labelOffset
labelY = yf
)
(rotation == "R90" && labelJustify == "centerRight"
labelX = xf
labelY = yf - labelOffset
)
(rotation == "R90" && labelJustify == "centerLeft"
labelX = xf
labelY = yf + labelOffset
)
(t
labelX = xf
labelY = yf
)
)
printf("Pin %s created at (%g, %g). Moving label to (%g, %g) with justify=%s orient=%s\n"
pinName xf yf labelX labelY labelJustify rotation || "nil")
labelId~>xy = list(labelX labelY)
labelId~>justify = labelJustify
labelId~>orient = rotation
)
else
printf("Warning: No children found for pin %s\n" pinName)
)
schCreateWire(cv "draw" "full" list(car(mypin~>xy):cadr(mypin~>xy) x1:y1) 0.0625 0.0625 0.0)
) ; if pinExists
) ; let pinExists
) ;foreach ter
) ;foreach inst
dbSave(cv)
schCheck(cv)
dbClose(cv)
) ;let
) ;procedure CCSCreatePinsForInstpins
- 加载脚本:在 CIW 窗口或
.cdsinit中加载该文件:load("CCSCreatePinsForInstpins.il") - 执行命令:在原理图里选中目标 Instance,然后在 CIW 输入命令(例如设置水平偏移量):
CCSCreatePinsForInstpins("YourLibName" "YourCellName" "schematic" 0.2)(注:具体参数请参考脚本内的注释说明。)
2. Layout 中的原生 “Promote Pins” 工具
与原理图不同,Virtuoso Layout Suite(特别是 XL 及以后引入的 Virtuoso Studio)将 Pin 的管理做成了一个强大的集成平台。
操作路径
最新的 Virtuoso Studio / IC6.1.8 中,该功能集成在统一的 Pin Tool 内:
通过菜单栏:Floorplan -> Pin Tool...(或根据环境配置为 VLS Floorplan -> Pin Tool)。
打开 Pin Tool 面板后,在其中选择 Create -> Promote Pins 即可调出设置表单。
注:Pin Tool 依赖 Virtuoso Layout Suite XL 及以上级别 License。而高级的 “Promote Pins Form” 通常需要 EXL (Design Planning) 或更高级别(如 GXL/MXL)。若当前处于 Layout L 级别的会话中,可能无法找到该菜单。
核心特性
- 多维度提升:支持基于 Pin, Net 或 Instance 进行 Promote。
- 原理图一致性 (Schematic Awareness):可强制只 Promote 那些在顶层原理图中确实存在的 Pin,保证 LVS 的一致性。
- 层级穿透:可以设定深入底层 hierarchy 的层数,把极底层的 Pin 直接“拉”到顶层。
- 自动打标签 (Labeling):在 Promote 的同时自动生成对应的 Text Label。
3. 常见问题与排错 (Troubleshooting)
- 原理图 SKILL 报错 “Unbound variable”:
通常是因为脚本尚未加载或者函数名拼写错误。确认
load命令返回t。 - Layout 中 Promote Pins 灰色不可用: 检查当前 Virtuoso 的 License tier(通常需要 Layout Suite XL 及以上级别),或者确认当前的设计流程是否绑定了完整的 Connectivity(例如有正确的原理图驱动)。
- 权限与环境隔离: IT / CAD 团队如果将此 SKILL 脚本集成到全公司的菜单中,建议封装成带 GUI 的表单(Form),并放在统一的公共库脚本路径下集中维护。
4. CAD/IT 团队的最佳实践建议
- 标准化菜单:强烈建议 CAD 工程师将
CCSCreatePinsForInstpins包装进 Schematic 的右键菜单或自定义 Toolbar 中,避免普通用户频繁在 CIW 中手敲 SKILL 代码。 - 知识库沉淀:很多设计师不知道原理图可以自动 Promote Pins。建议将本文档链接补充进内部 Wiki 的《Virtuoso 快捷操作指南》中。
- 联合 Pin Tool 使用:在进入 Virtuoso Studio 时代后,跨原理图和版图的 Pin 管理愈发重要,推荐让设计团队统一熟悉 Unified Pin Management 流程。
5. 参考资料 (References)
- SKILL to create and place pins on insterms in a schematic (Article 11158496):核心 SKILL 脚本来源。
- Virtuoso Design Planning and Analysis User Guide - Promoting Pins:Layout 原生 Promote 功能的详细使用手册。
Suggested screenshots (建议配图)
- 原理图自动化效果对比:一张展示带有十几个 unconnected instPins 的 Instance,另一张展示运行 SKILL 脚本后自动连线并生成 Pin 的结果。
- Layout Pin Tool 面板:截取
Plan -> Pin Planning -> Pin Tool窗口中Promote Pins对话框,重点圈出 “Schematic Awareness” 选项。