概述
在進行芯片驗證時,最重要的一個環節就是完成對dut的覆蓋率收集工作,覆蓋率主要分為下面三類:
1.代碼覆蓋率
2.功能覆蓋率
3.斷言覆蓋率
如何完成覆蓋率收集?
代碼覆蓋率:是衡量驗證進展的最簡易的方式。它的作用是檢查代碼是否冗余,設計要點是否遍歷,被檢測的對象是RTL代碼,而代碼覆蓋率的檢測一般由工具自動生成的。行覆蓋率(Line coverage)、分支覆蓋率(Branch coverage)、路徑覆蓋率(Path Coverage)、翻轉覆蓋率(Toggle coverage)、條件覆蓋率(Conditional coverage)、有限狀態機覆蓋率(FSM coverage)。
在makefile中添加-cm line+fsm+tgl+cond可完成相對應的代碼覆蓋率的收集。
功能覆蓋率:功能覆蓋率是一個用戶定義的度量標准,它測量了設計規范的多少部分,通過測試計划中的特性枚舉,已經被執行。它可以用來衡量是否有興趣的場景、角落用例、規格不變量,或者其他適用的設計條件(作為測試計划的特性捕獲)已經被觀察、驗證和測試。
這里簡單介紹下如果你收集的代碼覆蓋率很高但是功能覆蓋率缺很低,這個可能是:
- design沒有完全按照功能spec文檔規格實現所有功能,設計不完善;
 - 驗證平台monitor監視器存在漏洞,設計代碼實現了功能但沒有覆蓋到他們;
 - 功能正確,但是發送的激勵不對,對應功能的覆蓋率無法收集。
 
如果你收集的功能覆蓋率很高但是代碼覆蓋率缺很低,這可能是:
- 設計代碼沒有按照spec實現功能,在design中是無效代碼,
 - 用戶定義的功能覆蓋率收集存在錯誤,沒有完全定比覆蓋率收集的邊界,測試計划未捕獲所有設計功能/場景/邊界,或者缺少功能覆蓋率監視器。代碼覆蓋率中未覆蓋的設計代碼可能會映射到這些功能上。
 - 在實現功能覆蓋率監視器時可能存在潛在的錯誤,導致它們收集了錯誤的覆蓋率。因此,在驗證項目中,對用戶定義的功能覆蓋率指標及其實現進行適當的檢查很重要。
 
定義一個coverage class,在類中指定你要收集的coveragegroup和coveragepoint,也可指定你要收集的倉bins。
`ifndef GUARD_COVERAGE
`define GUARD_COVERAGE
class coverage;
packet pkt;
covergroup switch_coverage;
  length : coverpoint pkt.length;
  da     : coverpoint pkt.da {
              bins p0 = { `P0 }; 
              bins p1 = { `P1 }; 
              bins p2 = { `P2 }; 
              bins p3 = { `P3 }; } 
  length_kind : coverpoint pkt.length_kind;
  fcs_kind : coverpoint pkt.fcs_kind;
  
  all_cross:  cross length,da,length_kind,fcs_kind;
endgroup
function new();
  switch_coverage = new();
endfunction : new
task sample(packet pkt);
 this.pkt = pkt;
 switch_coverage.sample();
endtask:sample
endclass
`endif 
         
         
        在scoreboard完成coverage模塊的調用,coverage cov = new() 新建所要使用的類,cov.sample(pkt_exp)采樣pkt_exp數據包。
`ifndef GUARD_SCOREBOARD
`define GUARD_SCOREBOARD
class Scoreboard;
mailbox drvr2sb;
mailbox rcvr2sb;
coverage cov = new();
function new(mailbox drvr2sb,mailbox rcvr2sb);
  this.drvr2sb = drvr2sb;
  this.rcvr2sb = rcvr2sb;
endfunction:new
task start();
  packet pkt_rcv,pkt_exp;
  forever
  begin
    rcvr2sb.get(pkt_rcv);
    $display(" %0d : Scorebooard : Scoreboard received a packet from receiver ",$time);
    drvr2sb.get(pkt_exp);
    if(pkt_rcv.compare(pkt_exp)) 
    begin
       $display(" %0d : Scoreboardd :Packet Matched ",$time);
    cov.sample(pkt_exp);
    end
    else
      error++;
  end
endtask : start
endclass
`endif 
        
斷言覆蓋率:通過設定斷言,一般完成接口時序相關的覆蓋率收集。如AHB總線時序在對同一個地址先做寫操作再不間隔做讀操作,可使用property指定兩次操作的地址是相同的,在cover該property。
  property p_write_read_burst_trans;
    logic[31:0] addr;
    @(posedge clk) ($rose(penable) && pwrite, addr=paddr) |-> (##2 ($rose(penable) && !pwrite && addr==paddr)); 
  endproperty: p_write_read_burst_trans
  cover property(p_write_read_burst_trans); 
        如何查看收集后的覆蓋率?
收集后的覆蓋率保存在simv.vdb文件夾中,可使用urg工具轉成可視化的html文件或直接使用dve工具查看simv.vdb
直接查看指令:dve -full64 -cov -dir simv.vdb&
urg轉成html文件:urg -dir simv.vdb -report urgReport
轉成后的html文件可通過 firefox urgReport/dashboard.html查看
