【学习记录丨UVM】2.1uvm_component 与uvm_object
1.uvm_component派生自uvm_object
上图展示了UVM中常用类的继承关系,可以看到:
(一) uvm_conponent是继承自uvm_object的。这说明了uvm_component继承了object的特性,又同时有自己的特别属性:1. 能够在new的时候指定parent参数来形成UVM平台组件间的树形组织结构;2. 有phase的自动执行特点。
(二) 所有UVM树的结点都是由uvm_component组成的。这些在前边也介绍过。只有派生自uvm_component的类才能成为UVM树的节点。
可以回顾一下前边的介绍,看一下各个类都是从哪个派生出来的。【学习记录丨UVM】1.11建造测试用例-CSDN博客
2.常用的派生自uvm_object的类
在验证平台中经常遇到的派生自uvm_object的类有:
uvm_sequence_item :
uvm_sequence_item派生自uvm_transaction,在继承了uvm_transaction的性质基础上多了些实用的成员变量和函数/任务。所以,我们在验证平台中的transaction是派生自uvm_sequence_item。
class my_transaction extends uvm_sequence_item;
...
endclass
uvm_sequence:
所有的sequence都派生自uvm_sequence,sequence就是sequence_item的组合。 sequence直接和sequencer打交道,当driver向sequence索要数据时,sequencer会检查是否有sequence要发送数据。当发现有sequence_item(transaction)待发送时,就会把sequence_item交给driver。可以回顾:【学习记录丨UVM】1.10UVM的终极大作:sequence_uvm function new(string name=-CSDN博客
class my_sequence extends uvm_sequence#(my_transaction);
my_transaction m_trans;
`uvm_object_utils(my_sequence)//factory注册
function new(string name="my_sequence");
super.new(name);
endfunction
virtual task body();//当一个sequence启动后会自动执行body()中的代码
repeat(10)begin
`uvm_do(m_trans)//调用宏产生事务对象,每调用一次产生一个
end
#1000;
endtask
endclass
config:
这个前边还没出场过,可以先简单了解,后边的文章会有介绍。 config一般直接派生自uvm_object。 config的主要功能是规范验证平台的行为方式。
uvm_reg_item:
它派生自uvm_sequence_item,用于register model中。
uvm_reg_map,uvm_mem,uvm_reg_field,uvm_reg,uvm_reg_file,uvm_reg_block等与寄存器相关的众多类都是派生自uvm_object,用于register model中。
uvm_phase:
派生自uvm_object,主要用于控制uvm_component的行为方式,使得uvm_component平滑地在各个不同的phase之间依次运转。
3.常用的派生自uvm_component的类
在验证平台中经常遇到的派生自uvm_component的类有(前文介绍的验证平台组件都是):
uvm_driver :
driver派生自uvm_driver。driver的主要功能是向sequencer索要sequence_item (transaction),并且将sequence_item里的信息驱动到DUT端口上。 与uvm_component相比,uvm_driver多了如下几个成员变量:
uvm_sequence_item_pull_port #(REQ, RSP) seq_item_port;
uvm_sequence_item_pull_port #(REQ, RSP) seq_item_pord_if;
uvm_analysis_port #(RSP) rsp_port;
REQ req;
RSP rsp;
其中seq_item_port用于和sequencer之间信息通道的连接,有介绍过【学习记录丨UVM】1.10UVM的终极大作:sequence_uvm function new(string name=-CSDN博客
uvm_monitor :
monitor派生自uvm_monitor。monitor做的事情与driver相反,driver向DUT的pin上发送数据,而 monitor则是从DUT的pin上接收数据。
uvm_sequencer:
sequencer派生自uvm_sequencer。sequencer的功能是组织管理sequence,当driver要求数据时, 它就把sequence生成的sequence_item转发给driver。与uvm_component相比,uvm_sequencer做了很多扩展,额,咕咕咕🕊一定会在之后的文章中介绍。
uvm_scoreboard:
scoreboard派生自uvm_scoreboard。scoreboard的功能就是比较reference model和monitor分别发送来的数据,根据比较结果判断DUT是否正确工作。与uvm_monitor类似,uvm_scoreboard也几乎没有在uvm_component的基础上做扩展。所以,当定义自己的scoreboard时,可以直接从uvm_component派生。
reference model:
reference model都是直接派生自 uvm_component。reference model的作用就是模仿DUT,完成与DUT相同的功能。DUT是用Verilog写成的时序电路,而reference model则可以直接使用SystemVerilog高级语言的特性,同时还可以通过DPI等接口调用其他语言来完成与DUT相同的功能。
uvm_agent:
所有的agent要派生自uvm_agent。与前面几个比起来,uvm_agent的作用并不是那么明显。它只是把driver和 monitor封装在一起,根据参数值来决定是只实例化monitor还是要同时实例化driver和monitor。agent的使用主要是从可重用性的角 度来考虑的。如果在做验证平台时不考虑可重用性,那么agent其实是可有可无的。与uvm_component相比,uvm_agent的最大改动 在于引入了一个变量is_active:【学习记录丨UVM】1.6代理人agent_uvm agent-CSDN博客
uvm_env :
所有的env都派生自uvm_env。env把验证平台上的component都封装在一起。这样,当要运行不同的测试用例时,只需要在测试用例中实例化此env即可。
uvm_test:
所有的测试用例都要派生自 uvm_test或者其派生类,且都需要在其中实例化env。
class base_test extends uvm_test;//派生自uvm_test
my_env env;
`uvm_component_utils(base_test)//factory注册
function new(string name="base_test",uvm_component parent);
super.new(name,parent);
endfunction
extern virtual function void build_phase(uvm_phase phase);
extern virtual function void report_phase(uvm_phase phase);
endclass
function void base_test::build_phase(uvm_phase phase);
super.build_phase(phase);
env = my_env::type_id::create("env",this);//实例化env
uvm_config_db#(uvm_object_wrapper)::set(this,//设置sequencer的default_sequence
"env.i_agt.sqr.main_phase",
"default_sequence",
my_sequence::type_id::get());
endfunction
function void base_test::report_phase(uvm_phase phase);
uvm_report_server server;
int err_num;
super.report_phase(phase);
server=get_report_server();
err_num = server.get_severity_count(UVM_ERROR);
if(err_num != 0)begin
$display("TEST CASE FAILED");
end
else begin
$display("TEST CASE PASSED");
end
endfunction
4.与uvm_object相关的宏
uvm_object_utils:把派生自uvm_object的类注册到factory中。
uvm_object_param_utils:把派生自uvm_object的参数化的类注册到factory中。参数化的类在代码可重用性中经常用到。所谓参数化的类,是指类似于如下的类:
class A#(int WIDTH=32) extends uvm_object;
uvm_object_utils_begin: 当需要使用field_automation机制时,需要使用此宏。【学习记录丨UVM】1.9field_automation机制_uvm field automation-CSDN博客
uvm_object_param_utils_begin:与 uvm_object_utils_begin一样,只是它用于参数化的类使用field_automation机制时。
uvm_object_utils_end: 它总是和uvm_object_*_begin成对出现,作为factory注册的结束标志。
5.与uvm_component相关的宏
uvm_component_utils:类同不再介绍;
uvm_component_param_utils:类同不再介绍;
uvm_component_utils_begin:使用field_automation机制时,需要使用此宏。field_automation机制对component的最大意义在于可以自动使用config_db来获得某些变量的值。后边的文章会举例。
uvm_component_param_utils_begin;
uvm_component_utils_end;
6.uvm_component的限制
限制一:不能使用uvm_object的clone函数
在uvm_object中有clone函数。它用于分配一块内存空间,并把另一个实例复制到这块新的内存空间中。clone函数的使用方法如下;
class A extends uvm_object;
...
endclass
class my_env extends uvm_env;
virtual function void build_phase(uvm_phase phase);
A a1;
A a2;
a1 = new("a1");
a1.data = 8'h9;
$cast(a2,a1.clone());//为a2分配一块内存空间,并复制a1给它
endfunction
endclass
clone函数可以拆分为两步:1.分配内存空间,即 new 函数;2. 复制,即 copy 函数。没错,copy也是uvm_object中的一个函数,在目标实例已用new分配过内存空间后,才能使用。显然clone = new + copy.
uvm_component中可以使用copy函数,但是无法使用clone函数,因为新clone出来的类其parent参数没经过new函数指定。
限制二:parent相同的component,实例化时不能使用相同的名字
错误示例:
注意这是错误示例,这样写是绝对不行的!
class A extends uvm_component;
...
endclass
class my_env extends uvm_env;
virtual function void build_phase(uvm_phase phase);
A a1;
A a2;
a1 = new("a1",this);
a2 = new("a1",this);//这样写,是会出错的哦~!
endfunction
endclass
ok!祝大家今天也愉快自洽的一天!