背景
基于SystemVerilog的验证引入了接口的概念来表示设计模块之间的通信。在其最基本的形式中,SystemVerilog 接口只是一个命名的信号束,可以通过模块端口作为单个项目进行通信。然后,接收此接口的设计模块可以通过此接口参考访问信号。但是,接口的更高级别函数也可以提供更强类型的通信,以更好地表示设计意图。以下是系统Verilog接口中可用的高阶函数的子集:
可以通过使用时钟块和模块端口在信号列表上执行访问规则
函数和任务可用于封装高阶排序或访问控制
初始块和始终块等进程可以添加功能
连续赋值语句还可以添加功能
断言可以确保正确的集成
SystemVerilog 接口的一个非常重要的用途是将静态设计元素连接到动态测试平台元素。动态测试平台元素需要访问静态设计元素才能采样和驱动信号,但可重用的测试平台元素无法访问静态设计元素,除非通过称为虚拟接口的特殊构造。虚拟接口是测试平台代码中的接口句柄,可以与接口实例一起分配。虚拟接口是动态属性,可以分配给不同测试平台中的不同接口实例,从而提高可重用性。
设计可重用设计块的常用技术是使用参数使设计块的不同实例具有独特的特征。例如,可以对模块进行参数化,以允许在声明模块并提供参数值时定义数据总线宽度。SystemVerilog 接口也支持参数化,但参数化接口的使用在测试平台端带来了不可预见的复杂性。为了与赋值兼容,参数化虚拟接口必须专用于接口实例专用的相同值。除非采取预防措施,否则这可能会使一些非常丑陋的测试平台代码具有更丑陋的使用模型。
参数扩散:蛮力法
参数化虚拟接口引入的问题是,访问它的测试平台元素必须知道强类型接口。因此,当接口专用化尚未知时,无法编写泛型类以使用参数化虚拟接口。此问题的一个解决方案是参数化访问参数化虚拟接口的类。例如,可以使用 UVM 驱动程序必须使用的虚拟接口类型进行参数化。然而,这只是将问题向上移动了一层,因为现在实例化该参数化驱动程序的代理也必须参数化,以便它可以创建驱动程序的正确专用实例。这会不断向上移动,直到您到达“知道”正在测试的特定专业化存在的顶层测试平台组件。以下代码段演示了此问题。
首先,我们定义参数化的虚拟接口:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
interface param_if#(int width = 8); logic clk; logic[width-1:0] data; clocking active_cb @(posedge clk); default input #1 output #1; output data; endclocking modport active_mp (clocking active_cb); endinterface typedef virtual param_if param_vif |
接下来,我们定义可重复使用的 VIP 代码。此测试平台代码必须设计为可在参数化接口可以使用的任何环境中重用,因此还必须参数化VIP代码本身,以便可以访问正确的接口。以下代码段演示必须如何参数化 UVM 驱动程序类和包含该驱动程序的代理:
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
|
//======================================================================= class param_driver#(type vif_t=param_vif) extends uvm_driver#(cust_data); `uvm_component_param_utils(param_driver#(vif_t)) vif_t vif; function void build_phase(uvm_phase phase); if (!uvm_config_db#(vif_t)::get(this, "", "vif", vif)) `uvm_fatal("build", "A valid interface was not received."); endfunction endclass //======================================================================= class cust_agent#(type vif_t=param_vif) extends uvm_agent; `uvm_component_param_utils(param_agent#(vif_t)) vif_t vif; param_driver#(vif_t) param_driver; function void build_phase(uvm_phase phase); if (!uvm_config_db#(vif_t)::get(this, "", "vif", vif)) `uvm_fatal("build", "A valid interface was not received."); uvm_config_db#(vif_t)::set(this, "param_driver", "vif", vif); param_driver = param_driver#(vif_t)::type_id::create("param_driver", this); endfunction endclass |
到目前为止,这看起来还不错!它给类定义增加了一点复杂性,但不会太多。然而,在你检查测试平台必须如何访问这些参数化类之前,这些问题不会变得明显。以下段显示了测试如何根据接口的参数化方式唯一地访问 VIP 的每个实例:
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
|
//======================================================================= class cust_test extends uvm_test; `uvm_component_utils(cust_test) param_agent#(virtual param_if#(8)) param_agent8; param_agent#(virtual param_if#(16)) param_agent16; param_agent#(virtual param_if#(32)) param_agent32; virtual function void build_phase(uvm_phase phase); param_agent8 = param_agent#(virtual param_if#(8))::type_id::create("param_agent8", this); param_agent16 = param_agent#(virtual param_if#(16))::type_id::create("param_agent16", this); param_agent32 = param_agent#(virtual param_if#(32))::type_id::create("param_agent32", this); endfunction endclass //======================================================================= module test_top; param_if#(8) if8(); param_if#(16) if16(); param_if#(32) if32(); initial begin uvm_config_db#(virtual param_if#(8))::set(uvm_root::get(), "uvm_test_top.param_agent8", "vif", if8); uvm_config_db#(virtual param_if#(16))::set(uvm_root::get(), "uvm_test_top.param_agent16", "vif", if16); uvm_config_db#(virtual param_if#(32))::set(uvm_root::get(), "uvm_test_top.param_agent32", "vif", if32); run_test("cust_test"); end endmodule |
如您所见,对 VIP 的每个引用都必须使用要使用的正确接口类型进行参数化。这不仅会影响VIP建设,还会影响回调注册、工厂覆盖等。这给测试平台开发人员带来了很大的负担,并限制了这些环境的可重用性。
向验证组件添加参数是可重用VIP的有效技术解决方案,但它使使用模型大大复杂化,并限制了测试平台的可重用性。
审核编辑:郭婷
全部0条评论
快来发表一下你的评论吧 !