4. 测试用例管理与标签体系
当验证环境从几十个用例扩展到几千个用例时,回归平台面临的核心问题不再是“能不能跑”,而是“该跑哪些、先跑哪些、跑完怎么判断”。vPlan 作为 Cadence 验证管理平台中的规划与用例组织载体,把测试意图、用例实体、覆盖目标与执行结果串成一条可追溯的链路。本节围绕这条链路,讲清用例如何组织、标签如何分类、优先级如何划分,以及回归子集如何被选择出来。
一、vPlan 中的用例组织模型
vPlan 的基本组织单元是 vPlan 节点,它既可以是一个功能点(feature),也可以是一个测试场景(test scenario),还可以是一个具体的测试用例(test case)。节点之间通过父子关系形成树状结构,典型层次为:验证计划 → 功能域 → 功能点 → 测试场景 → 具体用例。每个用例节点通常绑定以下关键属性:
- 用例 ID:全局唯一标识,例如
vplan.dma.ch0.burst_len_max,便于脚本与报告引用。 - 关联覆盖点:指向 vCover 中的 coverpoint 或 cross,用于判断该用例是否真正命中目标。
- 执行入口:指向仿真命令、UVM test 名称或脚本路径,例如
+UVM_TESTNAME=dma_burst_max_test。 - 标签集合:用于分类、筛选和回归子集选择。
- 优先级:决定在有限机时下谁先跑。
这种树状结构的关键价值在于可追溯性:当某个覆盖点未命中时,可以沿树向上找到对应的功能点,再向下定位到具体用例;当某个用例失败时,也能快速判断它影响的是哪个功能域。实际项目中,建议把“功能点”和“用例”分开建模,功能点描述“要验证什么”,用例描述“怎么验证”,避免一个节点既当需求又当实现。
二、标签分类体系的设计
标签是回归子集选择的“索引”。如果标签设计得随意,后续筛选就会变成字符串匹配的泥潭。推荐按以下维度建立标签分类,每个维度使用统一前缀,避免语义重叠:
| 维度 | 前缀示例 | 取值示例 | 用途 |
|---|---|---|---|
| 功能域 | feat_ | feat_dma、feat_pcie、feat_ddr | 按模块筛选回归范围 |
| 测试类型 | type_ | type_smoke、type_func、type_stress、type_error | 区分冒烟、功能、压力、异常 |
| 覆盖目标 | cov_ | cov_basic、cov_corner、cov_cross | 关联覆盖收敛阶段 |
| 接口/协议 | if_ | if_axi、if_apb、if_uart | 按总线或协议筛选 |
| 运行特征 | run_ | run_fast、run_long、run_seed_dep | 控制机时与随机种子 |
| 状态 | state_ | state_new、state_stable、state_known_fail | 标记用例成熟度 |
标签命名应遵循“前缀_小写_下划线”的约定,例如 feat_dma、type_stress。一个用例可以同时拥有多个标签,例如 feat_dma + type_stress + run_long + state_stable。这样在回归脚本中就可以用集合运算表达筛选条件,例如“所有 DMA 功能域中,类型为 stress 且运行特征为 long 的稳定用例”。
三、优先级划分策略
优先级决定回归顺序。常见的做法是把优先级与“失败影响面”和“执行成本”挂钩,而不是凭感觉标 P0/P1/P2。推荐使用如下判定逻辑:
- P0(冒烟级):覆盖基本通路、复位、时钟、寄存器读写。失败意味着环境不可用,必须最先跑,通常控制在 20~50 条以内。
- P1(核心功能):覆盖主要功能点和关键交叉覆盖。每个功能域至少有一条 P1,用于日常回归。
- P2(边界与异常):覆盖 corner case、错误注入、协议违例。通常在 P0/P1 通过后执行。
- P3(长尾与压力):长时间压力、随机种子敏感、性能相关。用于 nightly 或 weekly 回归。
优先级划分后,还需要与标签联动。例如 type_smoke 通常对应 P0,type_stress 通常对应 P3。但两者不是硬绑定:一个 DMA 的 smoke 用例可能是 P0,而一个 PCIe 的 smoke 用例如果依赖外部模型,可能只能算 P1。因此建议在 vPlan 中同时维护 priority 字段和 type_ 标签,用脚本做一致性检查。
四、回归子集选择策略
回归子集选择的目标是:在给定机时预算内,最大化覆盖收益。实际工程中常用以下四种策略,可以组合使用:
- 基于标签的静态筛选:用标签表达式直接圈定范围,例如
feat_dma AND type_func AND NOT state_known_fail。适合日常回归和定向验证。 - 基于覆盖缺口的动态补充:从 vCover 中读取未命中覆盖点,反向查找关联用例,把这些用例加入本次回归。适合覆盖收敛阶段。
- 基于变更影响面的增量选择:根据 RTL 或验证环境的变更文件,映射到受影响的功能域,只跑相关标签的用例。适合每日增量回归。
- 基于历史失败率的加权排序:统计最近 N 次回归中各用例的失败次数,失败率高的优先跑。适合在机时紧张时快速暴露问题。
下面这张图展示了从 vPlan 用例库到回归子集的选择链路,以及标签、优先级、覆盖缺口和历史失败率四个输入如何共同作用:
图中四个输入并非每次都要全部启用。冒烟回归通常只用“标签筛选 + 优先级排序”;日常回归在此基础上加入“变更影响面”;夜间回归才把“覆盖缺口”和“历史失败率”纳入。选择引擎的本质是集合运算加排序,最终输出一个有序的用例列表,交给回归平台调度执行。
五、一个可落地的筛选表达式示例
假设当前处于 DMA 模块的覆盖收敛阶段,机时预算为 4 小时,已知单条用例平均耗时 3 分钟,则最多可跑约 80 条。可以按以下顺序构造回归集:
# 第一步:圈定 DMA 功能域中所有稳定用例
base = vplan.filter("feat_dma AND NOT state_known_fail")
# 第二步:优先取 P0 和 P1
high = base.filter("priority in [P0, P1]")
# 第三步:从 vCover 中找出 DMA 相关未命中覆盖点,反查用例
gap = vcover.uncovered("dma.*").map_to_cases()
# 第四步:合并去重,按优先级和历史失败率排序
regression = (high ∪ gap).unique().sort_by(
priority_asc,
fail_rate_desc
)
# 第五步:按 4 小时预算截断
final = regression.take_within_budget(minutes=240, avg_case_min=3)
执行后,回归平台会输出一份用例清单和预计机时。如果 final 的数量远小于 80,说明筛选条件过严,可以放宽 state_ 标签或加入 P2;如果远超 80,则需要提高优先级门槛或缩短覆盖缺口反查的范围。这个“预算—筛选—截断”的闭环,就是回归子集选择从策略落到执行的关键。
最后需要强调的是,标签体系和优先级不是一次设计完就固定不变的。随着验证阶段推进,state_new 的用例会逐步转为 state_stable,覆盖缺口会从 basic 转向 corner 和 cross,回归子集的构成也应随之调整。把 vPlan 用例库、标签、优先级和覆盖数据放在同一套可查询的模型里,回归平台才能真正做到“按需选、按序跑、按结果判”。