UVM的factory机制,field_automation机制

  1. 使用factory机制注册的component类,可以通过类名(字符串)进行实例化,并自动调用其main_phase。其功能的实现是因为UVM内部定义了一个参数化的类来实现此功能。本质上看factory机制是对sv中new函数的重载。new函数太简单,factory经过改良提供了更多的功能。
  2. 使用factory机制注册的component类,在接收外部set的变量时,如果要传递的变量使用`uvm_field宏注册后,可以在此component类中省略get语句。用`uvm_field宏注册后可以使用诸如copy、print、compare、pack、unpack等方法,无需自己定义实现。
  3.  经注册的类在用creat实例化后,set_type_override_by_type进行重载时会用子类代替父类。

       1) 定义my_driver类派生自uvm_driver类,并声明变量pre_num。

class my_driver extends uvm_driver;
    
    int pre_num;
    
    `uvm_component_utils(my_driver)
    `uvm_field_int(pre_num)

    function new(string name = "my_driver", uvm_component parent=null);
        super.new(name,parent);
    endfunction
    
    extern virtual task biuld_phase(uvm_phase phase);
    extern virtual task main_phase(uvm_phase phase);
endclass

task my_driver::build_phase(uvm_phase phase);

    super.build_phase(phase);

endtask

task my_driver::main_phase(uvm_phase phase);
    
endtask

        uvm_component类使用uvm_component_utils等宏注册,如test,env,agent,drv,mon,seqr。uvm_object类使用uvm_object_utils等宏注册,如seq,item。

声明component类时使用`uvm_component_utils注册,其参数为要注册的。此宏将这个类注册登记到uvm的一张表里,之后可以通过类名创建一个实例。所有派生自uvm_component的类及其派生类的类都应该使用此宏注册。(在执行用例启动仿真时候的build_phase自动创建各自节点?

在创建节点实例化此类时,此类里的main_phase也会被自动调用

与`uvm_component_utils相关的宏有:`uvm_component_param_utils,用于注册参数化的类。`uvm_component_utils_begin,uvm_component_utils_end,用于同时需要factory机制和field_automation机制的类的注册。

        2)field_automation机制对于uvm_component类最大的作用在于自动使用config_db获取某些变量的值。在env或case中使用config_db传递pre_num的值给driver,在执行uvm的super.build_phase时,会自动执行config_db的get语句,因此可以省略。这种用法的前提是:1. 收信的类需使用`uvm_component_utils宏注册,2. 要传递的变量需在收信的类里使用`uvm_field_xx宏注册,3. set语句和get语句的变量名称应该一致,即在收信类里声明和注册的变量名称。set语句无法省略。这种函数/任务重载的功能在UVM中得到了大量的应用。其实最典型的莫过于各个phase。在一个验证平台中,UVM树上的结点是各个类型的,UVM不必理会它们具体是什么类型,统一将它们当作uvm_component来对待,这极大方便了管理。

         3)如果在build_phase阶段添加set_type_override_by_type,其中括号里的第一个参数为父类,第二个为子类。

1 class bird extends uvm_object;
2    virtual function void hungry();
3        $display("I am a bird, I am hungry");
4    endfunction
5    function void hungry2();
6        $display("I am a bird, I am hungry2");
7    endfunction

8 endclass

9 class parrot extends bird;

10   virtual function void hungry();
11         $display("I am a parrot, I am hungry");

12     endfunction
13    function void hungry2();
14        $display("I am a parrot, I am hungry2");
15     endfunction

16 endclass

17 function void my_case0::print_hungry(bird b_ptr);
18    b_ptr.hungry();
19    b_ptr.hungry2();
20 endfunction

21 function void my_case0::build_phase(uvm_phase phase);
22    bird bird_inst;
23    parrot parrot_inst;
 
24    super.build_phase(phase);

25    bird_inst = bird::type_id::create("bird_inst");
26    parrot_inst = parrot::type_id::create("parrot_inst");
27    print_hungry(bird_inst);
28    print_hungry(parrot_inst);
29 endfunction
    function void my_case0::build_phase(uvm_phase phase);

72     set_type_override_by_type(bird::get_type(), parrot::get_type());
73
74     bird_inst = bird::type_id::create("bird_inst");
75     parrot_inst = parrot::type_id::create("parrot_inst");
76     print_hungry(bird_inst);
77     print_hungry(parrot_inst);

78 endfunction

 打印结果为:

I am a parrot, I am hungry
I am a bird, I am hungry2
I am a parrot, I am hungry
I am a bird, I am hungry2

其原因为:经注册的类使用factory机制实例化(class::type_id::creat)时,如果类之间存在派生关系用set_type_override_by_type进行重载时,set_type_override_by_type语句相当于在factory机制的表格中加入了一条记录,当查到有重载纪录时,用新的类型代替旧的类型。因此74行创建的类的实例实际上是parrot类。对于定义的virtual类型的function则执行子类的行为,非virtual不能重载。

可以使用set_inst_override_by_type函数重载部分类,函数源代码如下。

extern function void set_inst_override_by_type(string relative_inst_path,
    uvm_object_wrapper original_type,
    uvm_object_wrapper override_type);

如要将monitor重载,将env.o_agt.mon替换成new_monitor,第一个参数为相对路径。

class new_monitor extends my_monitor;
    `uvm_component_utils(new_monitor)
     virtual task main_phase(uvm_phase phase);
     fork
         super.main_phase(phase);
     join_none
     `uvm_info("new_monitor", "I am new monitor", UVM_MEDIUM)
     endtask
endclass

set_inst_override_by_type("env.o_agt.mon", my_monitor::get_type(), new_monitor::get_type())

另外还有set_type_override,其源代码是

extern static function void set_type_override(string original_type_name,
    string override_type_name,
    bit replace=1);

 parrot类重载bird,用下述语句即可。还有其它函数,不再详述。

set_type_override("bird", "parrot")

上述讲了部分重载,还有连续重载、替换重载等。连续重载好理解,创建实例时,爷爷实例化的是孙子的类型。替换重载:在使用set_type_override_by_type添加记录时,factory并不会在看完第一条记录后即直接创建一个parrot的实例,而是看完最后记录后才会创建最后类型的实例。

在UVM中,item,seq以及uvm_component都可以重载。对完成特定用例提供了极大的方便和自由。

本文章参考《UVM实战》、《芯片验证漫游指南》等资料整理而成,仅作学习心得交流,如果涉及侵权烦请请告知,我将第一时间处理。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值