目录
1 核心基类
UVM中的类最初都是从UVM_void根类继承而来,除了事务接口(transaction interface)类继承于uvm_port_base,其他所有的类都是从uvm_object类一步步继承而来的。
uvm_object的核心方法主要提供与数据操作的相关服务,包括copy、clone、compare、print、pack/unpack。
域的自动化
要想使用UVM_object提供的相关服务和方法,首先应实现域的自动化。
通过域的自动化,用户可以在注册UVM类的同时也可以声明今后会参与到对象拷贝、克隆、打印等操作的成员变量,这样就可以使用uvm_object提供的预定义方法,无需自定义方法
class box extends uvm_object;
int volum = 120;
color_t color = WHITE;
string name = "box";
//域的自动化
`uvm_object_utils_begin(box)
`uvm_field_int(volum,UVM_ALL_ON)
`uvm_field_enum(color_t color, UVM_ALL_ON)
`uvm_field_string(name, UVM_ALL_ON)
`uvm_object_utils_end
...
endclass
box b1 , b2;
initial begin
b1 = new("box1");
b1.volum = 80;
b1.color = BLACK;
b2 = new();
b2.copy(b1); //直接使用copy()函数
b2.name = "box2"
end
经验总结: 1)在注册component或object时,请使用域的自动化将其包裹
2)相关宏`uvm_field_{int,object,string,enum,real...}(ARG,FLAG),其中ARG表示成员 变量,FLAG表示数据操作,初学建议默认操作UVM_ALL_ON或者 UVM_DEFAULT,表示所有数据操作方法都打开
拷贝(copy)
在UVM数据操作中,需要对copy和clone加以区分:
copy默认已经创建好了对象,只需将数据拷贝;clone会自动创建对象并进行数据拷贝。
在调用copy()函数时默认是深拷贝,会执行copy()和回调函数do_copy(),do_copy需要用户定义
比较 (compare)
//方法,一般省略第二项参数
function bit compare(uvm_object rhs, uvm_comparer comparer=null);
//方法调用
b2.compare(b1)
比较方法经常用在两个数据类中进行。例如从generator中产生一个transaction(数据类),和在设计输出捕捉到的transaction进行比较。除了自定义数据比较,还可以直接使用uvm_object::compare()函数实现比较和打印。
注意事项:
1 默认的比较器,即uvm_package::uvm_default_comparer最大输出错误比较信息为1,当错误发现时,不会进行后续比较。
2 uvm_object提供的方法compare()\pack()\print(),如果不指定数据操作配置对象参数,会使用在uvm_package中例化的全局数据操作配置成员。
打印(print)
打印方法是核心基类提供的另一种便于开发和调试的功能,相比于仿真中设置断点,逐步调试,打印是另一种调试方法。打印的好处在于可以让仿真继续执行,从全局回顾整个仿真轨迹和逻辑。
//直接调用
b1.print();
只要在自动化域中声明过的变量,在稍后的print()函数执行时,都将会打印它们的类型、大小、数值。用户若不做修改,将使用默认的uvm_default_printer规定格式打印。
打包和解包(pack&unpack)
pack方法首先将数据打包成比特流,再发生给其他硬件,unpack与其相反,即将数据解包。
该方法主要面向sv与硬件和其他语言接口直接的精确通信,例如在UVM和FPGA emulator之间进行数据交换, SystemC发生大规模数据传递,该方法是首选。(目前了解即可。)
2 phase机制
SV构建验证环境时,软件部分的例化是发生在仿真开始后执行;在调用new()函数例化对象时,是无法保证例化的先后关系,以及各个组件在例化后 的连接,同时SV也无法在底层组件例化之前就完成对底层的配置逻辑。
UVM中引入了phase机制,通过该机制可以很清楚的将UVM仿真阶段层次化。