UVM基础

uvm_component与uvm_object

1.

几乎所有的类都派生于uvm_object,包括uvm_component

uvm_component有两大特性是uvm_object所没有的:

  • 一是通过在new的时候指定parent参数来形成一种树形的组织结构;
  • 二是有phase的自动执行特点。

下图是常用的UVM继承关系:

从图中可以看出,从uvm_object派生出了两个分支,所有的UVM树的结点都是由uvm_component组成的,只有基于uvm_component派生的类才可能成为UVM树的结点;最左边分支的类或者直接派生自uvm_object的类,是不可能以结点的形式出现在UVM树上的。
在这里插入图片描述

2.

常用的派生自uvm_object类的有:

  • uvm_sequence_item:读者定义的所有的transaction要从uvm_sequence_item派生。
  • uvm_sequence:所有的sequence要从uvm_sequence派生。
  • config:所有的config一般直接从uvm_object派生。config的主要功能就是规范验证平台的行为方式。之前我们已经见识了使用config_db进行参数配置,这里的config其实指的是把所有的参数放在一个object中。
  • 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之间依次运转。

常用的派生自uvm_component类的有:

  • uvm_driver:所有的driver都要派生自uvm_driver。driver的功能主要就是向sequencer索要sequence_item(transaction),并且将sequence_item里的信息驱动到DUT的端口上,这相当于完成了从transaction级别到DUT能够接受的端口级别信息的转换。
  • uvm_monitor:所有的monitor都要派生自uvm_monitor。monitor做的事情与driver相反,driver向DUT的pin上发送数据,而monitor则是从DUT的pin上接收数据,并且把接收到的数据转换成transaction级别的sequence_item,再把转换后的数据发送给scoreboard,供其做比较。
  • uvm_scoreboard:一般的scoreboard都要派生自uvm_scoreboard。scoreboard的功能就是比较reference model和monitor分别发送来的数据,根据比较结果判断DUT是否正确工作。
  • reference model:UVM中并没有针对reference model定义一个类。所以通常来说,reference model都是直接派生自uvm_component。reference model的作用就是模仿DUT,完成与DUT相同的功能。
  • uvm_agent:所有的agent要派生自uvm_agent。与前面几个比起来,uvm_agent的作用并不是那么明显。它只是把driver和monitor封装在一起,根据参数值来决定是只实例化monitor还是要同时实例化driver和monitor。
  • uvm_env:所有的env(environment的缩写)要派生自uvm_env。env将验证平台上用到的固定不变的component都封装在一起。这样,当要运行不同的测试用例时,只要在测试用例中实例化此env即可。

3.

在UVM中与uvm_object相关的factory宏有如下几个:

  • uvm_object_utils:它用于把一个直接或间接派生自uvm_object的类注册到factory中。
  • uvm_object_param_utils:它用于把一个直接或间接派生自uvm_object的参数化的类注册到factory中。
  • uvm_object_utils_begin:这个宏在第2章介绍my_transaction时出现过,当需要使用field_automation机制时,需要使用此宏。
  • uvm_object_param_utils_begin:与uvm_object_utils_begin宏一样,只是它适用于参数化的且其中某些成员变量要使用field_automation机制实现的类。
  • uvm_object_utils_end:它总是与uvm_object_*_begin成对出现,作为factory注册的结束标志。

在UVM中与uvm_component相关的factory宏有如下几个:

  • uvm_component_utils:它用于把一个直接或间接派生自uvm_component的类注册到factory中。
  • uvm_component_param_utils:它用于把一个直接或间接派生自uvm_component的参数化的类注册到factory中。
  • uvm_component_utils_begin:这个宏与uvm_object_utils_begin相似,它用于同时需要使用factory机制和field_automation机制注册的类。注意主要为了可以自动地使用config_db来得到某些变量的值,而不是在component中使用field_automation机制。
  • uvm_component_param_utils_begin:与uvm_component_utils_begin宏一样,只是它适用于参数化的,且其中某些成员变量要使用field_automation机制实现的类。
  • uvm_component_utils_end:它总是与uvm_component_*_begin成对出现,作为factory注册的结束标志。

4.

虽说uvm_component是从uvm_object派生来的,但作为UVM的结点,这使得其失去了某些uvm_object的特性。

比如在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());
	endfunction
endclass

上述的clone函数无法用于uvm_component中,因为一旦使用后,新clone出来的类,其parent参数无法指定。

虽然uvm_component无法使用clone函数,但是可以使用copy函数。因为在调用copy之前,目标实例已经完成了实例化,其parent参数已经指定了。

UVM的树形结构

1.

一般在使用时,parent通常都是this。假设A和B均派生自uvm_component,在A中实例化一个B:

class B extends uvm_component;
	…
endclass
class A extends uvm_component;
	B b_inst;
	virtual function void build_phase(uvm_phase phase);
		b_inst = new("b_inst", this);
	endfunction
endclass

在b_inst实例化的时候,把this指针传递给了它,代表A是b_inst的parent。一种常见的观点是,b_inst是A的成员变量,自然而然的,A就是b_inst的parent了。

当b_inst实例化的时候,指定一个parent的变量,同时在每一个component的内部维护一个数组
m_children,当b_inst实例化时,就把b_inst的指针加入到A的m_children数组中。只有这样才能让A知道b_inst是自己的孩子,同时也才能让b_inst知道A是自己的父母。当b_inst有了自己的孩子时,即在b_inst的m_children中加入孩子的指针。

2.

树根应该就是uvm_test。在测试用例里实例化env,在env里实例化scoreboard、reference model、agent、在agent里面实例化sequencer、driver和monitor。

UVM中真正的树根是一个称为uvm_top的东西,完整的UVM树如下图所示。
在这里插入图片描述

uvm_top是一个全局变量,它是uvm_root的一个实例。而uvm_root派生自uvm_component,所以uvm_top本质上是一个uvm_component。uvm_test_top的parent是uvm_top,而uvm_top的parent则是null。

如果一个component在实例化时,其parent被设置为null,那么这个component的parent将会被系统设置为系统中唯一的uvm_root的实例uvm_top。如下图所示:
在这里插入图片描述

可见,uvm_root的存在可以保证整个验证平台中只有一棵树,所有结点都是uvm_top的子结点。

而在之前我们的验证平台中这个parent被设置为null的节点为my_casen,因此其被设置为系统中唯一的uvm_root的实例uvm_top,而我们可以在仿真编译时通过UVM_TESTNAME来指定选择哪个case来进行仿真测试。

另外这里my_casen派生自base_test,但并不因此增加UVM的层级,因此其parent为null。

在验证平台中,有时候需要得到uvm_top,由于uvm_top是一个全局变量,可以直接使用uvm_top。除此之外,还可以使用如下的方式得到它的指针:

uvm_root top;
top=uvm_root::get();

3.

UVM提供了一系列的接口函数用于访问UVM树中的结点。这其中最主要的是以下几个:

  • get_parent函数,用于得到当前实例的parent。
extern virtual function uvm_component get_parent ();
  • 与get_parent相对的就是get_child函数。与get_parent不同的是,get_child需要一个string类型的参数name,表示此child实例在实例化时指定的名字。因为一个component只有一个parent,所以get_parent不需要指定参数;而可能有多个child,所以必须指定name参数。
extern function uvm_component get_child (string name);
  • 为了得到所有的child,可以使用get_children函数:
extern function void get_children(ref uvm_component children[$]);

使用方法为:

uvm_component array[$];
my_comp.get_children(array);
foreach(array[i])
    do_something(array[i]);//自定义函数
  • 除了一次性得到所有的child外,还可以使用get_first_child和get_next_child的组合依次得到所有的child:
string name;
uvm_component child;
if (comp.get_first_child(name))
do begin
	child = comp.get_child(name);
	child.print();
end while 
  • 8
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值