在本系列的第一部分中,介紹了SystemVerilog接口的基本概念,并描述了這些接口的參數(shù)化給測(cè)試平臺(tái)代碼帶來的問題。這篇文章將描述此問題的可能解決方法,但需要付出代價(jià)...
特洛伊木馬:偷襲方法
虛擬接口不支持多態(tài)性,因?yàn)樗鼈兣c靜態(tài)設(shè)計(jì)元素相關(guān)聯(lián)。但是,SystemVerilog 類確實(shí)支持多態(tài)性,這一事實(shí)可用于創(chuàng)建接口訪問器類。
創(chuàng)建一個(gè)虛擬類,該類聲明在 SystemVerilog 接口上執(zhí)行特定操作的純虛擬訪問器方法。然后,參數(shù)化類擴(kuò)展此類以執(zhí)行對(duì)強(qiáng)類型接口的實(shí)際訪問。VIP 代碼僅與非參數(shù)化基訪問器類交互,因此無需參數(shù)化 VIP 代碼即可使用強(qiáng)類型接口。測(cè)試平臺(tái)必須設(shè)置強(qiáng)類型訪問器類并將其傳遞給 VIP,但在此之后,無需參數(shù)化 VIP 即可執(zhí)行與 VIP 的所有交互。以下代碼段演示如何進(jìn)行此設(shè)置。
首先,我們定義參數(shù)化虛擬接口,該接口與上周代碼段中使用的接口相同:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
接下來,我們定義非參數(shù)化接口訪問器類和參數(shù)化以使用參數(shù)化接口的擴(kuò)展類:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
//======================================================================= virtual class port_wrapper extends uvm_object;
pure virtual task do_write(logic[31:0] data);
pure virtual task do_read(output logic[31:0] data);
pure virtual task sync_driver_cb(); endclass //======================================================================= class port_wrapper_typed#(type vif_t=param_vif) extends port_wrapper;
vif_t vif;
function new(vif_t vif);
this.vif = vif;
endfunction
virtual task do_write(logic[31:0] data);
vif.active_cb.data <= data;
endtask
virtual task do_read(output logic[31:0] data);
data = vif.active_cb.data;
endtask
virtual task sync_driver_cb();
@(vif.active_cb);
endtask endclass |
在此之后,實(shí)現(xiàn) VIP 代碼以使用此訪問器類,而不是直接訪問虛擬接口。下面的代碼段展示了驅(qū)動(dòng)程序和代理類,并演示了必須使用訪問器方法的各個(gè)位置。關(guān)于此VIP代碼需要注意的一件事是,它通過配置數(shù)據(jù)庫(kù)而不是接口接受非參數(shù)化訪問器類:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
//=======================================================================
class cust_driver extends uvm_driver#(cust_data);
`uvm_component_utils(cust_driver)
port_wrapper port;
task consume_from_seq_item_port();
forever begin
seq_item_port.get_next_item(req);
port.do_write(req.data);
port.sync_driver_cb(); …
task sample_signals();
forever begin
bit[31:0] sampled_data;
port.do_read(sampled_data);
port.sync_driver_cb(); …
function void build_phase(uvm_phase phase);
if (!uvm_config_db#(port_wrapper)::get(this, "", "port", port))
`uvm_fatal("build", "A valid port wrapper was not received."); …
//=======================================================================
class cust_agent extends uvm_agent;
`uvm_component_utils(cust_agent)
cust_driver driver;
function void build_phase(uvm_phase phase);
port_wrapper port;
if (!uvm_config_db#(port_wrapper)::get(this, "", "port", port))
`uvm_fatal("build", "A valid port wrapper was not received.");
uvm_config_db#(port_wrapper)::set(this, "driver", "port", port);
driver = cust_driver::type_id::create("driver", this); … |
最后,給出了測(cè)試平臺(tái)代碼。測(cè)試用例可以在不參數(shù)化的情況下訪問 VIP,但實(shí)例化接口的頂級(jí)模塊確實(shí)必須實(shí)現(xiàn)一些額外的步驟。它不僅必須實(shí)例化參數(shù)化接口,還必須創(chuàng)建參數(shù)化接口訪問器類并將其傳遞給 VIP 實(shí)例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
//======================================================================= class cust_test extends uvm_test;
`uvm_component_utils(cust_test)
cust_agent agent8;
cust_agent agent16;
cust_agent agent32;
virtual function void build_phase(uvm_phase phase);
agent8 = cust_agent::type_id::create("agent8", this);
agent16 = cust_agent::type_id::create("agent16", this);
agent32 = cust_agent::type_id::create("agent32", this);
endfunction endclass //======================================================================= module test_top;
param_if#(8) if8();
param_if#(16) if16();
param_if#(32) if32();
initial begin
port_wrapper_typed#(virtual param_if#(8)) port_wrapper8;
port_wrapper_typed#(virtual param_if#(16)) port_wrapper16;
port_wrapper_typed#(virtual param_if#(32)) port_wrapper32;
port_wrapper8 = new(if8);
port_wrapper16 = new(if16);
port_wrapper32 = new(if32);
uvm_config_db#(port_wrapper)::set(uvm_root::get(), "uvm_test_top.agent8", "port", port_wrapper8);
uvm_config_db#(port_wrapper)::set(uvm_root::get(), "uvm_test_top.agent16", "port", port_wrapper16);
uvm_config_db#(port_wrapper)::set(uvm_root::get(), "uvm_test_top.agent32", "port", port_wrapper32);
run_test("cust_test");
end endmodule |
如您所見,此解決方案確實(shí)解決了參數(shù)化接口的使用模型問題。創(chuàng)建正確類型的端口包裝器需要一些額外的代碼,但是測(cè)試平臺(tái)編寫者可以訪問使用不同專用接口的代理,而無需知道這些接口是如何專用的。
但是,此解決方案對(duì) VIP 如何使用虛擬接口施加了嚴(yán)格的限制。驅(qū)動(dòng)程序和監(jiān)視器類不能直接與接互,而必須將這些訪問推遲到強(qiáng)類型包裝類。通過將驅(qū)動(dòng)程序和監(jiān)視器類的大部分功能移動(dòng)到強(qiáng)類型包裝類,可以抵消這種生產(chǎn)力損失;然而,這種更復(fù)雜的結(jié)構(gòu)可能會(huì)令人困惑且不太靈活。上面的代碼段僅顯示了驅(qū)動(dòng)程序類可能需要的幾個(gè)訪問方法,但在實(shí)際環(huán)境中,此列表可能會(huì)增長(zhǎng)許多倍,并且監(jiān)視器類也需要完整的訪問器方法。
經(jīng)過反思,處理參數(shù)化接口的蠻力方法和特洛伊木馬方法都不是理想的。使用前一種方法,向類添加參數(shù)會(huì)使 VIP 的使用模型復(fù)雜化。在后面的方法中,必須提前規(guī)劃端口包裝類支持的訪問方法,并且對(duì)虛擬接口的 VIP 訪問受到限制。如果 VIP 代碼可以在不實(shí)際使用參數(shù)化接口的情況下啟用類似于參數(shù)化接口的功能,該怎么辦?
審核編輯:郭婷
-
接口
+關(guān)注
關(guān)注
33文章
8459瀏覽量
150748 -
監(jiān)視器
+關(guān)注
關(guān)注
1文章
780瀏覽量
33080 -
Verilog
+關(guān)注
關(guān)注
28文章
1343瀏覽量
109932
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論