Virtuoso中使用leafValue提取Sweep结果
在 Virtuoso ADE Assembler 中,当同一个 Test 对设计变量进行参数扫描时,可以使用 leafValue() 从 Sweep 结果族中提取指定扫描点的数据。
典型应用包括:
- 计算两个参数扫描点的差值;
- 计算扫描起点和终点的变化量;
- 提取固定参数值对应的波形;
- 在每个 Corner 内分别对 Sweep 结果进行运算。
例如,设计变量 N 扫描:
N = 1 16
同时温度由 Corner 设置:
temp = -40:10:120
希望在每个温度 Corner 下分别计算:
DeltaV1(temp) = Vdio1(N=16, temp) - Vdio1(N=1, temp)
此时可以使用 leafValue() 配合:
EvalType = sweeps
leafValue基本语法
基本形式为:
leafValue(
expression
"sweepVariable"
sweepValue
)
各参数含义如下:
| 参数 | 含义 |
|---|---|
expression |
Sweep 产生的波形族或输出结果 |
"sweepVariable" |
Sweep 变量名称 |
sweepValue |
需要提取的变量值 |
例如,从 N Sweep 中提取 N=16 的结果:
leafValue(Vdio1 "N" 16)
提取 N=1 的结果:
leafValue(Vdio1 "N" 1)
Cadence Calculator 中可以使用 leafValue() 从参数扫描结果中选择指定的 Sweep 点;选择两个不同点后,可以直接进行加减、比值等运算。(Cadence Community)
计算两个Sweep点的差值
假设基础输出名称为:
Vdio1
N 的扫描值为:
1 16
则差值表达式为:
leafValue(Vdio1 "N" 16)
-
leafValue(Vdio1 "N" 1)
对应关系为:
DeltaV1 = Vdio1(N=16) - Vdio1(N=1)
这个计算发生在同一个 Test 的同一组 Sweep 结果中,不需要使用 calcVal()。
ADE输出配置
建议建立两个输出。
基础输出Vdio1
输出名称:
Vdio1
表达式为原始测量公式。例如,在瞬态仿真中读取 10 us 时的节点电压:
value(VT("/vdio1") 10u)
其 EvalType 设置为:
point
point 表示表达式在每个仿真点上独立计算。因此,每个温度和每个 N 都会得到一个 Vdio1 结果。
结果结构类似:
temp=-40, N=1 → Vdio1
temp=-40, N=16 → Vdio1
temp=-30, N=1 → Vdio1
temp=-30, N=16 → Vdio1
...
temp=120, N=1 → Vdio1
temp=120, N=16 → Vdio1
差值输出DeltaV1
输出名称:
DeltaV1
表达式:
leafValue(Vdio1 "N" 16)
-
leafValue(Vdio1 "N" 1)
其 EvalType 设置为:
sweeps
EvalType=sweeps 使表达式在相关 Sweep 点完成之后,基于整个 Sweep 数据族进行计算,而不是在每个单独仿真点立即计算。(Cadence Community)
最终配置为:
| 输出名称 | 表达式 | EvalType |
|---|---|---|
Vdio1 |
原始测量表达式 | point |
DeltaV1 |
leafValue(Vdio1 "N" 16)-leafValue(Vdio1 "N" 1) |
sweeps |
与Corner配合使用
当前仿真结构为:
每个温度 Corner
└── Sweep N = 1、16
由于 N 是 Sweep 维度,而温度是 Corner 维度,因此:
leafValue(Vdio1 "N" 16)
-
leafValue(Vdio1 "N" 1)
会在每个温度 Corner 内分别计算。
结果关系为:
temp=-40:
Vdio1(N=16, temp=-40)
-
Vdio1(N=1, temp=-40)
temp=-30:
Vdio1(N=16, temp=-30)
-
Vdio1(N=1, temp=-30)
...
temp=120:
Vdio1(N=16, temp=120)
-
Vdio1(N=1, temp=120)
当计算目标是“跨 Sweep 运算,但每个 Corner 保留一个独立结果”时,应选择 EvalType=sweeps,而不是 EvalType=all。Cadence 对该行为的说明是:sweeps 跨 Sweep 数据计算,并保留每个 Corner 的独立结果。(Cadence Community)
EvalType的区别
| EvalType | 表达式可访问的数据范围 | 典型用途 |
|---|---|---|
point |
当前单个仿真点 | 普通电压、电流、延迟等测量 |
sweeps |
当前 Corner 下的 Sweep 结果族 | 比较不同 Sweep 参数值 |
corners |
对应 Sweep 点下的多个 Corner | 求所有 Corner 的最大值或最小值 |
all |
Sweep 和 Corner 的全部结果 | 对所有结果统一统计 |
对于本例:
温度 = Corner
N = Sweep
因此使用:
DeltaV1 EvalType = sweeps
这样不会把不同温度的数据混合在一起。
EvalType=all 会让表达式看到 Sweep 和 Corner 两个维度的全部结果,通常不适合“每个温度单独计算一次差值”的需求。(Cadence Community)
标量输出和波形输出
leafValue() 返回的数据类型取决于第一个参数。
提取标量
如果 Vdio1 已经是标量:
value(VT("/vdio1") 10u)
则:
leafValue(Vdio1 "N" 16)
-
leafValue(Vdio1 "N" 1)
返回标量差值。
这种方式适合:
- 指定时刻的电压差;
- 延迟差;
- 平均电流差;
- 功耗差;
- 频率差。
提取波形
如果直接使用:
VT("/vdio1")
则:
leafValue(VT("/vdio1") "N" 16)
-
leafValue(VT("/vdio1") "N" 1)
返回两条瞬态波形之差。
对应关系为:
DeltaV1(t)
=
Vdio1(t, N=16)
-
Vdio1(t, N=1)
leafValue() 既可以用于波形族,也可以用于由各 Sweep 点标量结果构成的数据族。(Cadence Community)
常用运算
两个扫描点的绝对差值
leafValue(Vdio1 "N" 16)
-
leafValue(Vdio1 "N" 1)
平均到每个单位N的变化量
(
leafValue(Vdio1 "N" 16)
-
leafValue(Vdio1 "N" 1)
) / (16 - 1)
相对变化率
(
leafValue(Vdio1 "N" 16)
-
leafValue(Vdio1 "N" 1)
)
/
leafValue(Vdio1 "N" 1)
百分比变化率
100 *
(
leafValue(Vdio1 "N" 16)
-
leafValue(Vdio1 "N" 1)
)
/
leafValue(Vdio1 "N" 1)
两个扫描点的平均值
(
leafValue(Vdio1 "N" 16)
+
leafValue(Vdio1 "N" 1)
) / 2
两个扫描点的比值
leafValue(Vdio1 "N" 16)
/
leafValue(Vdio1 "N" 1)
使用除法时,需要检查分母是否可能为零。
直接对原始表达式使用leafValue
除了引用已有输出 Vdio1,也可以直接对原始波形表达式使用 leafValue()。
例如:
leafValue(VT("/vdio1") "N" 16)
-
leafValue(VT("/vdio1") "N" 1)
读取两条波形在 10 us 时的差值:
value(
leafValue(VT("/vdio1") "N" 16)
10u
)
-
value(
leafValue(VT("/vdio1") "N" 1)
10u
)
不过在 ADE Assembler 中,通常更推荐先建立基础输出:
Vdio1
再建立二次运算输出:
DeltaV1
这样能够清楚区分原始测量和跨 Sweep 运算,也便于定位 eval err。
多个Sweep变量
leafValue() 可以依次指定多个 Sweep 变量:
leafValue(
expression
"variable1" value1
"variable2" value2
)
例如同时扫描:
N = 1 16
VDD = 1.6 1.8 2.0
提取 N=16、VDD=1.8 的结果:
leafValue(
Vdio1
"N" 16
"VDD" 1.8
)
leafValue() 支持通过多个“变量名称—变量值”参数对,从多维 Sweep 数据族中定位具体叶节点。(Cadence Community)
如果只指定:
leafValue(Vdio1 "N" 16)
那么 N 维度会被固定为 16,未指定的 VDD 维度仍会保留,返回结果可能仍然是一个 Family,而不是单个标量。
leafValue和calcVal的区别
leafValue
leafValue() 用于从一个 Sweep 数据族中提取指定参数点:
leafValue(Vdio1 "N" 16)
适合:
- 同一个 Test;
- 同一次 Sweep;
- 比较不同扫描点;
- 提取多维 Sweep 中的指定叶节点。
calcVal
calcVal() 主要用于建立 ADE 输出之间或不同 Test 之间的结果依赖,例如:
calcVal(
"Vdio1"
"reference_test"
)
不应在当前 Test 中使用下面的方式选择当前 Test 自己的另一个 Sweep 点:
calcVal(
"Vdio1"
"current_test"
?matchParams list(list("N" "16"))
?ignoreParams "rest"
)
这种写法会触发类似错误:
?matchParams cannot be used to retrieve output values
from the same test as where the expression is defined
对于同一个 Test 内的 N=1 和 N=16 比较,应改用:
leafValue(Vdio1 "N" 16)
-
leafValue(Vdio1 "N" 1)
常见错误
EvalType仍为point
错误配置:
DeltaV1 EvalType = point
此时表达式只能看到当前单个仿真点,无法同时访问 N=1 和 N=16。
正确配置:
DeltaV1 EvalType = sweeps
Sweep变量名称不一致
表达式中的变量名称必须与 ADE 中完全一致:
leafValue(Vdio1 "N" 16)
如果实际变量名为 N,不要写成:
leafValue(Vdio1 "n" 16)
Sweep值不存在
如果实际 Sweep 为:
N = 1 8
则下面的表达式无法找到对应数据:
leafValue(Vdio1 "N" 16)
将数值写成字符串
对于数值型设计变量,通常使用:
leafValue(Vdio1 "N" 16)
而不是:
leafValue(Vdio1 "N" "16")
扫描值的数据类型应与结果族中的 Sweep 参数类型一致。
基础输出没有生成完整结果
Vdio1 应在每个 Sweep 点上正常求值:
Vdio1 EvalType = point
如果某个 N 或某个温度下基础输出为:
eval err
nil
那么后续的 leafValue() 差值表达式也无法得到有效结果。
使用了all导致Corner混合
对于:
温度 = Corner
N = Sweep
应使用:
EvalType = sweeps
如果使用:
EvalType = all
表达式可能同时跨越温度 Corner 和 N Sweep 进行运算,结果维度会与预期不同。
本例最终设置
基础输出:
Name: Vdio1
EvalType: point
Expr: 原始Vdio1测量表达式
差值输出:
Name: DeltaV1
EvalType: sweeps
Expr:
leafValue(Vdio1 "N" 16)
-
leafValue(Vdio1 "N" 1)
仿真结构:
Corner:
temp = -40:10:120
Sweep:
N = 1 16
最终效果:
对于每个温度Corner:
DeltaV1(temp)
=
Vdio1(N=16, temp)
-
Vdio1(N=1, temp)
总结
当需要在同一个 Test 内比较不同参数扫描点时,使用:
leafValue(output "sweepVariable" sweepValue)
本例的核心表达式为:
leafValue(Vdio1 "N" 16)
-
leafValue(Vdio1 "N" 1)
输出设置为:
Vdio1 → EvalType = point
DeltaV1 → EvalType = sweeps
这样可以在每个温度 Corner 内,分别取得 N=1 和 N=16 的结果并完成差值运算。