uvm_objection和uvm_component基础
uvm_objection和uvm_component是uvm中两大基础类,刚开始学习的时候,对两个东西认识不深,以为它们俩差不多,谁知道它两是一个是“爷爷”,一个是孙子的关系,两者贯穿整个 uvm验证方法学。至于为什么要划分uvm_object和uvm_component呢,是因为前任在验证的过程中发现,对事情进行分工能降低复杂度,也能提高维护效率。uvm_object在uvm中的地方比较基础,如果按照OPP的思想,它是一个最基础(base)没有太多的物理含义,而uvm_component是高层次抽象后的,具有物理含义,更像一个“对象”,例如我们前面谈到的driver or montIor它们都有自己的意义和功能。
如下图所示,先来整体看一下,uvm方法学中核心的几个自带类型:
- uvm_void:是是始祖类,人如其名,其中不包含任何函数和类
- uvm_obect: 比较基础的类,包含一些比较基础的常用函数,如Copy函数、Clone函数、Compare函数、Print函数
- uvm_component:uvm组件类,继承于该类的子类,用于构成UVM环境(uvm_tree),如在系列(一)中已经涉及过的uvm_driver、uvm_montior、uvm_env和uvm_scoreboard,其他几个组件在后续讲述过程中将会全部涉及。
为了构建uvm_tree结构,uvm_component的实例化具有它自己的特色,需要采用create创建, 原码如下:
//uvm_object
static function T create(string name , uvm_component parent = null, string context="");
//uvm_component static function T create(string name , uvm_component parent , string context="");
uvm_object在实例化过程中,可以指定 parent组件,也可以不指定;但是uvm_component在实例化过程中必须指定,只有指定了parent组件,该子compoent才能成功的挂载于uvm_tree中。
uvm_object与uvm_component的区别:
- uvm_component继承于uvm_objection,包含一些uvm_objection没有的特性和函数,如phase系列函数
- uvm_component必须通过create创建,uvm_objection可以采用new/create创建
- uvm_component存在于验证的整个过程中,不会任何组件(component)不会被析构(释放内存空间),uvm_obect可以在验证的过程中任何时刻被创建实例和析构
为了使用uvm_object和uvm_component自带的函数和机制,我们需要把我们继承类均注册到一张表格中,这张表格主要用于类的继承和重用,我们把这些称为工厂机制(factory),这个过程称为注册
uvm_object类注册:
- uvm_object_utils: 用于把一个直接或者间接派生自uvm_object的类注册到factory;
- uvm_object_param_utils:用于把一个直接或者间接派生自uvm_object的参数化的类注册到factory
参数化类,形如
class A#(int WIDTF=32) extend uvm_obejct
示例代码如下:
class regfile extends uvm_reg_file; `uvm_object_utils(regfile) function new(input string name="unnamed_regfile"); super.new(name); endfunction endclass
uvm_object类及其成员注册:
- uvm_object_utils_begin: (类) ... uvm_object_utils_end
- uvm_object_param_utils_begin: (类) ... uvm_object_param_utils_end
只有将成员变量注册后,使用Copy函数、Clone函数、Compare函数、Print函数才能有效。
常用的变量的注册有以下几种;
`define uvm_field_int(ARG,FLAG)
`define uvm_field_real(ARG,FLAG)
`define uvm_field_enum(T,ARG,FLAG)
`define uvm_field_object(ARG,FLAG)
`define uvm_field_string(ARG,FLAG)
`define uvm_field_queue_enum(ARG,FLAG)
`define uvm_field_queue_int(ARG,FLAG)
`define uvm_field_queue_object(ARG,FLAG)
注册示例代码如下:
class my_transaction extends uvm_sequence_item;
rand bit[47:0] dmac;
rand bit[47:0] smac;
rand bit[15:0] ether_type;
rand byte pload[];
rand bit[31:0] crc;
rand bit crc_err;
`uvm_object_utils_begin(my_transaction)
`uvm_field_int(dmac, UVM_ALL_ON)
`uvm_field_int(smac, UVM_ALL_ON)
`uvm_field_int(ether_type, UVM_ALL_ON)
`uvm_field_array_int(pload, UVM_ALL_ON)
`uvm_field_int(crc, UVM_ALL_ON)
`uvm_field_int(crc_err, UVM_ALL_ON | UVM_NOPACK)
`uvm_object_utils_end
function new(string name = "my_transaction");
super.new();
endfunction
endclass
uvm_component类注册
- uvm_component_utils: 用于把一个直接或者间接派生自uvm_component的类注册到factory;
- uvm_component_param_utils:用于把一个直接或者间接派生自uvm_component的参数化的类注册到factory
uvm_component类及其成员注册:
- uvm_component_utils_begin: (类) ... uvm_component_utils_end
- uvm_component_param_utils_begin: (类) ... uvm_component_param_utils_end
只有将ucm_component类注册到factory后,才能使用一些component重要的机制,那为什么要将comonpent的成员也注册呢,这是的意义不在于使用copy等函数,因为component组建copy等操作意义不大,比较容易想到的问题,复制的组件的父类是谁(专业一点说就是parent无法指定),两个两同的组件又有什么用呢,啥用也没有,它的最大的意义在于自动使用config_db来获取某些变量的值。置于什么是config_db,可以先理解为一个传递参数的工具,比较形象的比如是 写信者、邮递员和收信者之间传递信件,config_db就是邮递员。
- 还没有人评论,欢迎说说您的想法!