对UVM平台架构进行自顶向下的说明。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Q:顶层的作用是什么?
A:用于连接验证平台和DUT。验证平台产生激励,通过接口文件传输到RTL。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Q:顶层包含哪些内容?
1)Interface接口。
对DUT输入信号来说,验证平台将驱动接口上的信号,把激励传到RTL。
对DUT输出信号来说,验证平台监测接口上的信号变化,将信号传到平台内和C算法期待值做比较,从而判断RTL功能是否正常。
2)时钟,复位。
DUT,接口,验证平台使用相同的时钟和复位信号,用于产生相关时序逻辑。
3)打印相关配置
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
为了清晰的区分验证和设计,分为两个文件【hdl_top.sv】,【hvl_top.sv】来定义。
hdl_top.sv
`timescale 1ns/1ps
module hdl_top();
import pkg_1::* ;
clock_if CLK(); //通过时钟接口产生时钟clock
reset_if RST(); //通过复位接口产生复位信号rst
wire sys_clk = CLK.clock ;
wire sys_rst = RST.rst ;
`include "fsdb_set.svh" //仿真参数配置
`ifdef test_hdl //在仿真参数中通过定义 test_hdl来选择对应的文件。增强复用性
`include "test_hdl.svh"
`endif
endmodule : hdl_top
test_hdl.sv
initial begin
if(!sys_rst) begin
test_in_if_1.rd = 0;
test_in_if_1.wr = 1;
end
end
test_in_if test_in_if_1 (sys_clk,sys_rst) ;
test_out_if test_out_if_1 (sys_clk,sys_rst) ;
dut i_dut(
.clk (sys_clk),
.rst (sys_rst),
.test_in_if (test_in_if_1),
.test_out_if (test_out_if_1)
);
· test_in_if 实例化得到test_in_if_1,通过test_in_if_1向dut的接口test_if传入激励信号。
· test_out_if 实例化得到test_out_if_1,通过test_out_if_1采集输出信号到验证平台执行比较。
· 可以通过initial 初始化接口信号。
hvl_top.sv
module hvl_top();
import uvm_pkg::*;
import pkg_2::*; //package中定义顶层需要的内容
initial begin
uvm_config_db#(virtual clk_if)::set(null,"uvm_test_top","CLK",hdl_top.CLK)
uvm_config_db#(virtual rst_if)::set(null,"uvm_test_top","RST",hdl_top.RST)
end
`ifdef test_hvl
`include `test_hvl
`endif
endmodule : hvl_top
test_hvl.svh
import pkg_3::* ;
initial begin
//input if
uvm_config_db#(virtual test_in_if)::set(null,"uvm_test_top","test_in_if_1",hdl_top.test_in_if_1);
//out_if
uvm_config_db#(virtual test_out_if)::set(null,"uvm_test_top","test_out_if_1",hdl_top.test_out_if_1);
run_test();
end
· 通过config_db把在hdl_top中定义的时钟,复位,输入,输出接口传输到验证平台使用。在继承自uvm_base_test的base_test类中拿到接口信号。
· run_test是UVM中集成的方法。通过仿真参数UVM_TESTNAME创建uvm_test_top实例,并执行内部的main_phase。
Q:这里的virtual是什么?为什么要用虚接口
A:接口用来连接验证平台和DUT端口的实际物理信号线。而用于验证的SV语言和UVM验证环境是偏向软件世界内容,所以我们无法在UVM中通过Interface来发送激励到DUT。
为了解决这个问题,引入了虚接口概念,虚接口是一个物理接口的句柄,该句柄指向实际的接口,验证平台通过处理虚接口间接的控制接口信号。
关于虚接口是一个句柄,在面向对象的验证平台中,很重要的一点就是类,通过把类声明为一个句柄,再实例化该句柄实现类的调用,和虚接口句柄的处理是类似的。
Q:config_db在什么场景使用?具体参数是什么?
config_db的全称是 configration database 配置数据库。在UVM中提供数据的存储,读取功能。
在其他组件需要用到当前层的某个数据/句柄时,通过config_db这个数据库就可以共享这些内容。config_db是继承自uvm_resource_db的一个带参数的类。
在使用中主要使用到两个功能,set和get。set是把在源侧把目标对象放到数据库中,get在目标侧从数据库中读取目标对象。想要把数据放到数据库中,就要给数据贴上让目标侧能够识别的标签。也就是set的各个参数。
具体的使用方法就参考【UVM实战】中的例子就好。
uvm_config_db#(virtual test_out_if)::set(null,"uvm_test_top","test_out_if_1",hdl_top.test_out_if_1);
在本例中,
1)#(virtual test_out_if)
uvm_config_db传递的数据类型
2)::
类作用域解析符 调用config_db类中的静态函数set
3)null,"uvm_test_top"
前两个参数一起构成一个目标路径,该路径就是数据的有效作用范围scope。uvm_test_top是run_test的实例化名。在uvm_test_top中会通过get函数读取数据
4)test_out_if_1
数据在数据库中的名字,在get读取数据时,就通过这个名字在数据库中查找目标数据。
5)hdl_top.test_out_if_1
数据值,要传递的数据的值,可以是变量,常数,句柄。这个值的类型必须和1)中定义的数据类型一致。
------------------------------------------------------------
之前有个疑问,为什么要数据传递,要用的数据放到一个package中就可以使用了,为啥要config_db勒?
现在的理解有以下两点,不一定对。
· 一方面是要传递虚接口,vif是在top_tb层定义的,而通过run_test实例化得到的uvm_test_top是脱离了top_tb层次结构的实例,需要用config_db才能把vif传到验证平台内使用。
· 另一方面,package范围内是可以使用类中的内容,但是类实例化后,对句柄进行赋值,这个句柄是无法通过package能使用的?所以config_db传递句柄到指定路径,让处理后的句柄能够在该路径下被调用。
------------------------------------------------------------