文章目錄
- 覆寫組詳解
-
- 1、在類裡定義覆寫組
- 二、覆寫組的觸發
-
- 1、使用回調函數進行采樣
- 2、使用事件觸發的覆寫組
- 3、使用SV斷言進行觸發
- 三、資料采樣
-
- 1、個體倉和總體覆寫率
- 2、自動建立倉
- 4、對表達式進行采樣
-
- 5、使用使用者自定義的倉發現漏洞
- 6、命名覆寫點的倉
- 7、條件覆寫率
- 8、為枚舉類型建立倉
- 9、翻轉覆寫率
- 10、在狀态和翻轉中使用通配符
- 11、忽略數值
- 12、不合法的倉
- 13、狀态機的覆寫率
覆寫組詳解
覆寫組與類相似,一次定義後便可以進行多次執行個體化。它含有覆寫點、選項、形式參數和可選觸發。一個覆寫組包含了一個或者多個資料點,全都在同一時間采集。
覆寫組可以定義在類裡面,也可以定義在程式或子產品層次上,它可以采樣任何可見的變量或者信号。
在SV中,覆寫組應該定義在适當的抽象層次上,這個層次可以在測試平台和設計的邊界上,在讀寫資料的總線交換單元中,在環境配置類裡或者任何需要的地方。
對任何事務的采樣都必須等到資料被待測設計收到以後,如果在事務中間注入一個錯誤,導緻資料傳輸失敗,那麼就需要改變功能覆寫中對這種情況的處理方式。
一個類裡可以包含多個覆寫組,每個組可以有單獨的觸發,可以從多個源頭收集資料。
一個覆寫組必須執行個體化後才可以用來收集資料。
1、在類裡定義覆寫組
覆寫組可以在程式、子產品、類中定義,但都要進行明确地執行個體化後才可以采樣。
類裡的功能覆寫率
class Transactor;
Transaction tr;
mailbox mbx_in;
covergroup CovPort;
coverpoint tr.port;
endgroup
function new(mailbox mbx_in);
CovPort = new();
this.mbx_in = mbx_in;
endfunction
task main;
forever begin
tr = mbx_in.get(); //擷取下一個事務
ifc.cb.port <= tr.port; //發送到待測設計中
ifc.cb.data <= tr.data;
CovPort.sample(); //收集覆寫率
end
endtask
endclass
二、覆寫組的觸發
功能覆寫率的兩個主要部分是采樣的資料和資料被采樣的時刻。當這些新資料都準備好了以後,測試平台便會觸發覆寫組。可以直接使用sample函數來完成。
如果想在程式代碼中顯式地觸發覆寫組,可以使用sample方法。
如果要借助已有的事件或信号來觸發覆寫組,可以在covergroup聲明中使用阻塞語句。
1、使用回調函數進行采樣
使用回調函數可以在決定資料采集的位置和時間。
使用功能覆寫率回調函數的測試
program automatic test;
Environment env;
initial begin
Driver_cbs_coverage dcc; //把回調基類Driver_cbs擴充成Driver_cbs_coverage
env = new();
env.gen_cfg();
env.build();
//建立并登記覆寫率回調函數
dcc = new();
env.drv.cbs.push_back(dcc); //放進驅動器的隊列中
env.run();
env.wrap_up();
end
endprogram
用于測試功能覆寫率的回調函數
class Driver_cbs_coverage extends Driver_cbs;
covergroup CovPort;
...
endgroup
virtual task post_tx(Transaction tr);
CovPort.sample(); //采樣覆寫率數值
endtask
endclass
2、使用事件觸發的覆寫組
與直接調用sample方法相比,使用事件觸發的好處在于能夠借助已有的事件進行采樣。
帶觸發的覆寫組
event trans_ready; //覆寫組CovPort在測試平台觸發trans_ready事件時進行采樣
covergroup CovPort @(trans_ready);
coverpoint ifc.cb.port; //測量覆寫率
endgroup
3、使用SV斷言進行觸發
帶SV斷言的子產品
module mem(simple_bus sb);
bit[7:0] data, addr;
event write_event;
cover property
(@(postedge sb.clock) sb.write_ena == 1)
-> write_event;
endmodule
使用SVA觸發覆寫組
program automatic test(simple_bus sb);
covergroup Write_cg @($root.top.m1.write_event);
coverpoint $root.top.m1.data;
coverpoint $root.top.m1.addr;
endgroup
Write_cg wcg;
intitle begin
wcg = new();
//在此處添加激勵
sb.write_ena <= 1;
...
# 10000 $finish;
end
endprogram
三、資料采樣
關于覆寫率資訊的收集,在覆寫點上指定一個變量或表達式時,SV便會建立很多的“倉(bin)”來記錄每個數值被捕捉到的次數。這些倉是衡量功能覆寫率的基本機關。采樣一個單比特變量,最多會有兩個倉被建立。每次覆寫組被觸發,SV都會在一個或者多個倉裡留下标記。在每次仿真的末尾,所有帶有标記的倉會被彙聚到一個新建立的資料庫中。最後利用分析工具進行分析并生成覆寫率報告。
1、個體倉和總體覆寫率
為了計算出一個點上的覆寫率,首先必須确定所有可能數值的個數,這也被稱為域。
一個倉中可能有一個或多個值,覆寫率就是采樣值的數目除以域中倉的數目。例如一個3比特變量覆寫點的域是0:7,正常情況下會除以8個倉,仿真過程中如果有7個倉的值被采樣到,那麼覆寫率為7/8或者87.5%,所有這些點組合在一起便構成了一個組的覆寫率,而所有組組合在一起就可以得到整個仿真資料庫的覆寫率。
2、自動建立倉
SV會自動為覆寫點建立倉,它通過被采樣的表達式的域來确定可能值得範圍。對于一個位寬為N的表達式,有2^N個可能值。
3、限制自動建立倉的數目
覆寫組選項auto_bin_max指明了自動建立倉的最大數目,預設值是64。值域超過指定的最大值,SV會把值域範圍平分到auto_bin_max個倉中。
使用auto_bin_max并把倉數設定成2
covergroup CovPort;
coverpoint tr.port
{options.auto_bin_max = 2;}
endgroup
覆寫率報告:
在所有覆寫點中使用auto_bin_max
covergroup CovPort;
options.auto_bin_max = 2; //影響port和data
coverpoint tr.port;
coverpoint tr.data;
endgroup
4、對表達式進行采樣
在覆寫點裡使用表達式
class Transaction;
rand bit[2:0] hdr_len; //範圍0-7
rand bit[3:0] payload_len; //範圍0-15
rand bit[3:0] kind; //範圍0-15
...
endclass
Transaction tr;
covergroup CovLen;
len16 : coverpoint(tr.hdr_len + tr.payload_len);
len32 : coverpoint(tr.hdr_len + tr.payload_len + 5'b0); //帶有額外常量啞元的表達式,可以計算達到5比特精度,進而把自動生成的最大倉數擴大到32。
endgroup
5、使用使用者自定義的倉發現漏洞
自動生成的倉适用于匿名數值,如計數值、位址值或2的幂值,而對于其他數值,應該明确對倉命名。SV會自動為枚舉類型的倉命名。
為事務長度定義倉
covergroup CovLen;
len : coverpoint(tr.hdr_len + tr.payload_len + 5'b0);
{bins len[] = {[0:23]};}
endgroup
覆寫率報告:
從圖中可以看到長度為23,即十六進制17的一項沒有出現過,最長的頭是7,最長的負載是15。0-7一共有八種情況,用3bit來表示,0-15一共有16種情況,用4bit來表示。是以總共是7+15=22,而不是23!,我們應該在倉的聲明中改成{bins len[] = {[0:22]};}才對。
6、命名覆寫點的倉
當自定義倉時,SV不再自動建立倉,而且會忽略掉那些不被事先定義的倉所涵蓋的數值,計算功能覆寫率時隻會使用建立的倉。
指定倉名
//對一個4比特變量kind進行采樣
covergroup CovKind;
coverpoint tr.kind{
bins zero = {0}; //一個倉zero,對kind采樣值為0進行計數
bins lo = {[1:3],5}; //lo倉代表1:3和5的值
bins hi[] = {[8:$]}; //8個獨立的倉8-15,分别儲存
bins misc = default; //一個倉用來儲存沒有被選中的值
}
endgroup
7、條件覆寫率
使用關鍵字iff可以覆寫點添加條件。
條件覆寫——複位期間禁止
covergroup CoverPort;
//當reset=1時不要收集覆寫率資料
coverpoint port iff(!bus_if.reset);
endgroup
也可以使用start和stop函數來控制覆寫組裡各個獨立的執行個體
initial begin
CovPort ck = new(); //執行個體化覆寫組
//複位期間停止收集覆寫率資料
# 1ns ck.stop();
bus_if.reset = 1;
# 100ns bus_if.reset = 0;
ck.start();
...
end
8、為枚舉類型建立倉
對于枚舉類型,SV會為每個可能值建立一個倉。
枚舉類型的功能覆寫率
typedef enum{INIT,DECODE,IDLE} fsmstate_e;
fsmstate_e pstate, nstate;
covergroup cg_fsm;
coverpoint pstate;
endgroup
9、翻轉覆寫率
确定覆寫點的翻轉次數
covergroup CoverPort;
coverpoint port{
bins t1 = (0 => 1), (0 => 2), (0 => 3);
}
endgroup
使用範圍表達式可以快速地确定多個翻轉過程,(1,2 => 3,4)建立了四個翻轉過程,分别是(1 => 3),(1 => 4),(2 => 3),(2 => 4)。
10、在狀态和翻轉中使用通配符
可以使用關鍵字wildcard來建立多個狀态或翻轉。在表達式中,任何X、Z或?都會被當成0或1的通配符。
用在覆寫點倉中的通配符
bit[2:0] port;
covergroup CoverPort;
coverpoint port{
wildcard bins even = {3'b?? 0};
wildcard bins odd = {3'b?? 1};
}
11、忽略數值
使用== ignore_bins == 排除掉不用來計算功能覆寫率的數值
bit[2:0] low_ports_0_5; //隻使用數值0-5
covergroup CoverPort;
coverpoint low_ports_0_5{
ignore_bins hi = {[6,7]}; //忽略掉6,7兩個倉
}
endgroup
12、不合法的倉
使用== illegal_bins ==對倉進行辨別,可以捕捉到那些被錯誤檢查程式遺漏掉的狀态
bit[2:0] low_ports_0_5; //隻使用數值0-5
covergroup CoverPort;
coverpoint low_ports_0_5{
illegal_bins hi = {[6,7]}; //如果出現6,7兩個倉就會報錯
}
endgroup
13、狀态機的覆寫率
如果在狀态機上使用了覆寫組,那麼就可以使用倉來列出特定的狀态和翻轉軌迹,使用代碼覆寫率工具可以自動提取狀态寄存器、狀态以及翻轉軌迹。
版權聲明:本文為部落客原創文章,遵循 CC 4.0 BY-SA 版權協定,轉載請附上原文出處連結和本聲明。
本文連結:https://blog.csdn.net/qq_39794062/article/details/113477197