UVM:UVM的树形结构

        UVM采用树形的组织结构来管理验证平台的各个部分。sequencer、driver、monitor、agent、model、 scoreboard、env等都是树的一个结点。为什么要用树的形式来组织呢?因为作为一个验证平台,它必须能够掌握自己治下的所 有“人口”,只有这样做了,才利于管理大家统一步伐做事情,而不会漏掉谁。树形结构是实现这种管理的一种比较简单的方式。

(1)uvm_component中的parent参数

        UVM通过uvm_component来实现树形结构。所有的UVM树的结点本质上都是一个uvm_component。每个uvm_component都有 一个特点:它们在new的时候,需要指定一个类型为uvm_component、名字是parent的变量

function new(string name, uvm_component parent);

        一般在使用时,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。为什么要指定这么一个parent呢?一种常见的观点 是,b_inst是A的成员变量,自然而然的,A就是b_inst的parent了,无需再在调用new函数的时候指定,即b_inst在实例化时可以这 样写:

b_inst = new("b_inst");

        这种写法看似可行,其实忽略了一点,b_inst是A的成员变量,那么在SystemVerilog仿真器一级,这种关系是确定的、可知 的。假定有下面的类:

class C extends uvm_component;
    A a_inst;
    function void test();
        …
    a_inst.b_inst =
        …;
    a_inst.d_inst =
        …;
        …
    endfunction
endclass

        可以在C类的test函数中使用a_inst.b_inst来得到B的值或者给B赋值,但是不能用a_inst.d_inst来给D赋值。因为D根本就不存在 于A里面。SystemVerilog仿真器会检测这种成员变量的从属关系,但是关键问题是它即使检测到了后也不会告诉A:你有一个成员 变量b_inst,没有一个成员变量d_inst。A是属于用户写出来的代码,仿真器只负责检查这些代码的合理性,它不会主动发消息给代 码,所以A根本就没有办法知道自己有这么一个孩子。
        换个角度来说,如果在test中想得到A中所有孩子的指针,应该怎么办?读者可能会说,因为A是自己写出的,它就只有一个 孩子,并且孩子的名字叫b_inst,所以可以直接使用a_inst.b_inst就可以了。问题是,假设要把整棵UVM树遍历一下,即要找到每个结点及结点的孩子的指针,那如何写呢?似乎根本就没有办法实现。
        解决这个问题的方法是,当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树的根

        UVM是以树的形式组织在一起的,作为一棵树来说,其树根在哪里?其树叶又是哪些呢?从第2章的例子来看,似乎树根应 该就是uvm_test。在测试用例里实例化env,在env里实例化scoreboard、reference model、agent、在agent里面实例化sequencer、 driver和monitor。scoreboard、reference model、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。UVM为什么不以uvm_test派生出来的测试用例(即uvm_test_top)作为树根,而是搞了这么一个奇怪的东西作为树 根呢?
        在之前的例子中,所有的component在实例化时将this指针传递给parent参数,如my_env在base_test中的实例化:

env = my_env::type_id::create("env", this);

但是,假如不按照上面的写法,向parent参数传递一个null会如何呢?

env = my_env::type_id::create("env", null);

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

        uvm_root的存在可以保证整个验证平台中只有一棵树,所有结点都是uvm_top的子结点。
        在验证平台中,有时候需要得到uvm_top,由于uvm_top是一个全局变量,可以直接使用uvm_top。除此之外,还可以使用如 下的方式得到它的指针:

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

(3)层次结构相关函数

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

(3.1)get_parent函数

        get_parent函数,用于得到当前实例的parent,其函数原型为:

extern virtual function uvm_component get_parent ();

(3.2)get_child函数

        与get_parent相对的就是get_child函数:

extern function uvm_component get_child (string name);

        与get_parent不同的是,get_child需要一个string类型的参数name,表示此child实例在实例化时指定的名字。因为一个component 只有一个parent,所以get_parent不需要指定参数;而可能有多个child,所以必须指定name参数

(3.3)get_children函数

        为了得到所有的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]);

(3.4)get_first_child和get_next_child

        除了一次性得到所有的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 (comp.get_next_child(name));

        这两个函数的使用依赖于一个string类型的name。在这两个函数的原型中,name是作为ref类型传递的:

extern function int get_first_child (ref string name);
extern function int get_next_child (ref string name);

        name只是用于get_first_child和get_next_child之间及不同次调用get_next_child时互相之间传递信息。无需为name赋任何初始 值,也没有必要在使用这两个函数过程中对其做任何赋值操作

(3.5)get_num_children函数

        get_num_children函数用于返回当前component所拥有的child的数量

extern function int get_num_children ();


 

  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值