4. 覆盖率模型构建

覆盖率模型不是验证工程师凭经验“拍脑袋”写出来的,而是从设计规格和验证计划中系统化提取、分层映射、逐步收敛出来的。一个高质量的覆盖率模型,应当做到三件事:覆盖点可追溯到规格条目、覆盖组结构清晰可维护、交叉覆盖能暴露真实场景组合。本节将围绕“提取—定义—交叉—评审”四个环节,说明如何构建一个可签核的覆盖率模型。

一、核心原理:覆盖率模型是规格到激励的映射桥梁

覆盖率模型的本质,是把自然语言描述的设计规格和验证计划,翻译成可被仿真器自动统计的“事件集合”。每个覆盖点(coverpoint)代表一个需要被激励命中的条件,每个覆盖组(covergroup)代表一组相关条件的集合,而交叉覆盖(cross)则代表多个条件同时成立的组合场景。

从信息流角度看,覆盖率模型构建遵循一条清晰的映射链:

  • 规格条目:设计文档中的功能描述、寄存器定义、状态机、接口协议。
  • 验证计划项:验证工程师拆解出的测试意图、场景、边界条件。
  • 覆盖点:将测试意图转化为可采样的变量、表达式或事件。
  • 覆盖组:按功能域或接口边界组织覆盖点,形成可复用、可开关的单元。
  • 交叉覆盖:对存在组合关系的覆盖点进行交叉,捕捉多条件同时命中的场景。

这条映射链的关键在于可追溯性:每个覆盖点都应能反向指向某条规格或验证计划项,否则就是冗余覆盖;每条规格也都应有至少一个覆盖点对应,否则就是覆盖漏洞。

覆盖率模型构建映射链 设计规格 功能/寄存器/协议 验证计划 测试意图/场景/边界 覆盖点 变量/表达式/事件 覆盖组 功能域/接口边界 交叉覆盖 多条件组合场景 可追溯性:每个覆盖点反向映射到规格/计划

二、方法流程:从规格条目到覆盖组定义

覆盖率模型构建通常按以下步骤推进:

  1. 规格条目编号:为设计规格中每一条功能描述分配唯一编号,例如 SPEC-REG-001、SPEC-FSM-003,便于后续追溯。
  2. 验证计划拆解:将每条规格拆解为若干测试意图,明确“要验证什么条件成立”。
  3. 识别采样对象:确定每个测试意图对应的采样变量、表达式或事件。例如寄存器写入值、状态机当前状态、接口握手信号。
  4. 定义覆盖点:为采样对象定义 bin,包括正常值、边界值、非法值、跳转关系等。
  5. 组织覆盖组:按功能域或接口边界将相关覆盖点归入同一 covergroup,并设置采样时钟和使能条件。
  6. 定义交叉覆盖:对存在组合关系的覆盖点进行 cross,并设置合理的 binsof 过滤,避免组合爆炸。
  7. 评审与签核:与设计、验证、系统人员共同评审覆盖率模型,确认无遗漏、无冗余。

关键原则:覆盖点不是越多越好。每个覆盖点都应有明确的验证意图和签核价值。无法追溯到规格或验证计划的覆盖点,应删除或重新评估。

三、案例场景:一个寄存器配置模块的覆盖率模型

假设某 SoC 中有一个寄存器配置模块,规格要求:支持 4 个通道,每个通道可配置使能位、模式选择(2 种模式)、阈值(0~255)。验证计划要求覆盖所有通道的使能组合、模式切换、阈值边界。

对应的 SystemVerilog 覆盖率模型可以这样定义:

covergroup reg_cfg_cg @(posedge clk);
  // 通道使能覆盖点
  ch_en: coverpoint cfg_en[3:0] {
    bins all_off = {4'b0000};
    bins one_on  = {4'b0001, 4'b0010, 4'b0100, 4'b1000};
    bins all_on  = {4'b1111};
    bins others  = default;
  }

  // 模式选择覆盖点
  mode: coverpoint cfg_mode[1:0] {
    bins mode_a = {2'b00};
    bins mode_b = {2'b01};
    bins illegal = {2'b10, 2'b11};
  }

  // 阈值边界覆盖点
  threshold: coverpoint cfg_thresh {
    bins low  = {[0:15]};
    bins mid  = {[16:239]};
    bins high = {[240:255]};
  }

  // 交叉覆盖:通道使能 × 模式选择
  ch_mode_cross: cross ch_en, mode {
    ignore_bins illegal_combo = binsof(mode.illegal);
  }

  // 交叉覆盖:模式选择 × 阈值边界
  mode_thresh_cross: cross mode, threshold {
    ignore_bins illegal_mode = binsof(mode.illegal);
  }
endgroup

这个模型体现了几个要点:覆盖点按功能维度拆分,交叉覆盖只保留有意义的组合,非法值单独建 bin 用于检查,使用 ignore_bins 过滤无效组合。这样既保证了覆盖完整性,又避免了组合爆炸。

四、覆盖组与交叉覆盖的定义要点

要素 定义要点 常见问题
覆盖点 采样对象明确,bin 划分覆盖正常、边界、非法值 bin 划分过粗导致漏测,或过细导致冗余
覆盖组 按功能域组织,设置采样时钟和使能条件 采样时钟错误导致覆盖点永远不命中
交叉覆盖 只交叉有实际组合意义的功能点 无差别全交叉导致 bin 数量爆炸
过滤条件 使用 ignore_bins / illegal_bins 排除无效组合 忽略合法组合导致覆盖漏洞
可追溯性 每个覆盖点关联规格编号或验证计划项 覆盖点无法追溯,签核时无法证明完整性

五、误区与复盘

误区一:把覆盖率模型当成“代码行覆盖”的替代品。代码行覆盖只说明代码被执行过,不说明功能场景被验证过。覆盖率模型必须从规格和验证计划出发,而不是从 RTL 代码反推。

误区二:交叉覆盖越多越好。无差别交叉会产生大量无意义 bin,既增加仿真开销,又让覆盖率收敛变得困难。交叉覆盖应聚焦于“多个条件同时成立才可能暴露缺陷”的场景。

误区三:覆盖点定义后不再评审。覆盖率模型需要与设计、验证、系统人员共同评审,确认覆盖点无遗漏、无冗余、可追溯。评审应在验证早期进行,避免后期返工。

复盘建议:在覆盖率收敛后期,定期检查“未命中 bin”列表。如果某个 bin 长期无法命中,应判断是激励不足、覆盖点定义错误,还是该场景本身不可达。对于不可达场景,应使用 illegal_bins 或 ignore_bins 明确排除,并在验证计划中记录原因。

覆盖率模型构建是覆盖率收敛与签核的起点。只有从设计规格和验证计划中系统化提取覆盖点、合理定义覆盖组、精准设计交叉覆盖,才能保证后续的覆盖率分析、收敛和签核有据可依、有迹可循。