1. 定义coverage文件,文件名ut_cov.sv
//文件名可和class名字不一样,以防找不到命名为一致,找不到环境会报错
class ut_cov extends uvm_component;
  `uvm_component_utils(ut_cov)
  cpu_transfer cpu_tr;
  virtual interface cpu_if  cfgif;
  covergroup top_cfg @(cfgif.cpu_cast_sample_cov);
  // cpu_cast_sample_cov 为自定义的触发事件,定义在cup_if 中
    option.per_instance = 1;
    cpu_addr: coverpoint cpu_tr.addr 
    // cpu_addr为cpu_tr.addr的别名,cpu_tr.addr对应cpu_transfer的addr信号
    {
       bins addr0 = {32'h00};
       bins addr1 = {32'h04};
       bins addr2 = {32'h08};
       bins addr3 = {32'h0c};
       ... // 根据验证需求设置bins 个数和取值
    }
     cpu_wd: coverpoint cpu_tr.datain
    {
       bins datain = {[32'h0:32'hffff]};
    }
    .... //根据验证需求添加coverpoint
   endgroup
   function new(string name="ut_cov", uvm_component parent);
     super.new(name, parent);
     top_cfg = new(); //一定要创建covergroup,否则覆盖率收集会失败,并且不显示error
       if(!uvm_config_db#(virtual cpu_if)::get(null, "*", "cfgif", cfgif))begin
          //该uvm_config_db 与top 层相连
          `uvm_fatal(get_type_name(), "no virtual interface specified for cpu_cast")
       end
   endfunction
   function void build_phase(uvm_phase phase);
     super.build_phase(phase);
   endfunction
endclass2. 完善top.sv文件的uvm_config_db
//在top.sv 里,uvm_config_db必须写进initial begin中
initial
   ...// 验证平台所需的其它uvm_config_db
   uvm_config_db#(virtual cpu_if)::set(uvm_root::get(), "*", "cfgif", cfgif);
begin3. 在env.sv中实例化ut_cov.sv文件
class ut_env extends uvm_env;
  ... //给env其它成员创建句柄
  
  ut_cov   ut_fcov;//句柄名字随意定义,后续实例化保持一致即可
  `uvm_component_utils(efuse_env)
  function new(string name = "cov_env", uvm_component parent = null)
    super.new(name, parent);
  endfunction
  virtual function void build_phase(uvm_phase phase);
    super.connect_phase(phase);
    ...//实例化env其它句柄
    ut_fcov = ut_cov ::type_id::create("ut_fcov", this);
    uvm_config_db#(ut_cov)::set(null, "*", "ut_fcov", ut_fcov); 
    //在哪里收覆盖,哪里就设置get()操作,本文在sequnce中收覆盖率
  endfunction
  
  ... //环境所需其它phase
endclass
4. 在cpu_if .sv 中 定义触发事件
interface cpu_if(input clk, input rst_n);
   
   ...//定义Interface 信号
   event cpu_cast_sample_cov; //名字与ut_cov.sv中一致
endinterface5. 在tb1_seq.sv 中触发覆盖率收集事件
class tb1_seq extends base_sequence;
 
   `uvm_object_utils(tb1_seq)
   ut_cov             ut_fcov;
   cpu_transfer       cpu_tr;
   virtual  cpu_if    cfgif;
   function new(string name="tb1");
     super.new(name);
     cpu_tr = cpu_transfer::type_id::create("cpu_tr");
     
     if(!uvm_config_db#(ut_cov)::get(null, "*", "ut_fcov", ut_fcov))begin
          `uvm_fatal(get_type_name(), "no ut_fcov getted for tb1_seq")
     end
     if(!uvm_config_db#(virtual cpu_if)::get(null, "*", "cfgif", cfgif))begin
        // 与env相连
          `uvm_fatal(get_type_name(), "no virtual interface getted for  tb1_seq")
     end
   endfunction
   virtual task usr_body();
     bit  [31:0] rdata;
     assert(cpu_tr.randomize() with {addr==`REG_0;});//`REG_0是宏定义,可直接设置值
     CPU_RD(cpu_tr.addr, rdata); //CPU_RD  为自定义的发激励task
     //发激励一定要用到coverpoint中的cpu_tr信号,否则收不到
     $cast(ut_fcov.cpu_tr, cpu_tr);//类型转换
     -> cfgif.cpu_cast_samplele_cov; //触发覆盖率收集事件
     ...
    endtask
endclass6. 启动环境运行tb1_seq对应的test case,即可收到覆盖率










