4. 实现矩阵加法模块的覆盖率收集

任务目标

为矩阵加法DUT建立覆盖率收集机制:定义功能覆盖点(矩阵维度、数据范围)与代码覆盖率(行/分支/表达式),在UVM验证环境中完成覆盖率的采样与报告,以量化验证充分性。

环境依赖

本案例基于前序已搭建的UVM验证环境(含driver、monitor、scoreboard),需确保以下组件可用:

  • UVM-1.2或IEEE 1800.2兼容库
  • 支持覆盖率收集的仿真器(VCS/Xcelium/Questa任选)
  • 矩阵加法DUT接口:input [7:0] a[4][4], b[4][4]; input [1:0] dim; output [8:0] sum[4][4]

覆盖率定义与实现

在UVM环境中新建cov_collector.sv,通过covergroup定义功能覆盖点,并通过bind方式采样DUT内部信号实现代码覆盖率统计。核心覆盖策略:

  • 功能覆盖:矩阵维度dim取值(2×2/3×3/4×4)、输入数据边界(0x00/0xFF/随机中间值)
  • 代码覆盖:通过cover property监控加法器进位链分支、饱和溢出路径
// cov_collector.sv - 覆盖率收集器
class cov_collector extends uvm_component;
    `uvm_component_utils(cov_collector)
    
    // 功能覆盖组
    covergroup cg_matrix_add with function sample(int dim, byte a_val, byte b_val);
        // 覆盖点1:矩阵维度
        cp_dim: coverpoint dim {
            bins dim_2x2 = {2};
            bins dim_3x3 = {3};
            bins dim_4x4 = {4};
        }
        // 覆盖点2:输入数据范围
        cp_a_data: coverpoint a_val {
            bins zero = {0};
            bins max = {255};
            bins mid = {[1:254]};
        }
        cp_b_data: coverpoint b_val {
            bins zero = {0};
            bins max = {255};
            bins mid = {[1:254]};
        }
        // 交叉覆盖:维度×数据边界
        cross_dim_data: cross cp_dim, cp_a_data, cp_b_data;
    endgroup
    
    // 代码覆盖率属性(通过bind监控DUT内部)
    cover property (dut.carry_out && dut.dim == 2);
    cover property (dut.sat_overflow);
    
    function new(string name, uvm_component parent);
        super.new(name, parent);
        cg_matrix_add = new();
    endfunction
    
    // 从monitor获取事务并采样
    virtual function void write_to_cov(int dim, byte a[4][4], byte b[4][4]);
        foreach(a[i,j]) begin
            cg_matrix_add.sample(dim, a[i][j], b[i][j]);
        end
    endfunction
    
    // 覆盖率报告
    function void report_phase(uvm_phase phase);
        `uvm_info("COV", $sformatf("功能覆盖率: %.2f%%", cg_matrix_add.get_coverage()), UVM_NONE)
        `uvm_info("COV", $sformatf("代码覆盖率: 行=%0d%% 分支=%0d%%", 
                   $get_coverage_line(), $get_coverage_branch()), UVM_NONE)
    endfunction
endclass

// bind模块:采样DUT内部信号
module cov_bind;
    bind matrix_add_dut dut_cov_probe (
        .carry_out(dut.carry_out),
        .sat_overflow(dut.sat_overflow),
        .dim(dut.dim)
    );
endmodule

集成到UVM环境

在base_test.sv中创建收集器并连接monitor:

class base_test extends uvm_test;
    cov_collector cov;
    
    function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        cov = cov_collector::type_id::create("cov", this);
    endfunction
    
    function void connect_phase(uvm_phase phase);
        // 假设env中已有monitor的analysis_port
        env.monitor.ap.connect(cov.analysis_export);
    endfunction
endclass

运行与验证

  1. 编译:vcs -sverilog -uvm dut.sv cov_collector.sv cov_bind.sv testbench.sv
  2. 运行:./simv +UVM_TESTNAME=base_test
  3. 覆盖率收集:添加-cm line+cond+branch+assert编译选项,运行后生成simv.vdb目录
  4. 查看报告:urg -dir simv.vdb -report coverage_report

通过标准:

  • 功能覆盖率≥95%(需确保测试序列覆盖所有dim取值和边界数据)
  • 代码覆盖率≥90%(行覆盖),分支覆盖≥85%
  • 若未达标,需增加定向测试用例(如全0、全FF、随机边界组合)

常见问题

  • 覆盖率始终为0:检查covergroup是否在build_phase后创建,且sample调用是否在事务到达时触发
  • 代码覆盖率缺失:确认bind模块中信号名与DUT内部层次一致,且编译时添加了-cm选项
  • 交叉覆盖空洞:使用cg_matrix_add.get_coverage()打印各bin详情,定位未覆盖组合