UVM - 9 (override - 2)

System Verilog本身就是一种面向对象的语言,即本身就支持重载(override),重载即当父类中定义一个virtual类型的函数或任务时,在子类中可以重载这个函数或任务。所以我们来先看一下System Verilog对重载的支持。

案例2

system verilog重载

  • 本质是使用继承和多态的思想实现方法的重载
class bird extends uvm_object;
    virtual function void hungry();
        $display("I am a bird, I am hungry");
    endfunction

    function void hungry2();
        $display("I am a bird, I am hungry2");
    endfunction
endclass

class parrot extends bird;
    virtual function void hungry();
        $display("I am a parrot, I am hungry");
    endfunction

    function void hungry2();
        $display("I am a parrot, I am hungry2");
    endfunction
endclass

function void my_case0::print_hungry(bird b_ptr);
    b_ptr.hungry();
    b_ptr.hungry2();
endfunction

function void my_case0::build_phase(uvm_phase phase);
    bird bird_inst;
    parrot parrot_inst;

    super.build_phase(phase);
    
    bird_inst = bird::type_id::create("bird_inst");
    parrot_inst = parrot::type_id::create("parrot_inst");
    print_hungry(bird_inst); // 传入的bird_inst,根据多态的思想,调用的是bird的方法
    print_hungry(parrot_inst); // virtual方法调用的是parrot的方法,普通方法调用的是bird中的方法
endfunction
// print_hungry(bird_inst);
"I am a bird, I am hungry"
"I am a bird, I am hungry2"
// print_hungry(parrot_inst);
"I am a parrot, I am hungry"
"I am a bird, I am hungry2" // hungry2()不是virtual方法,所以调用bird中的方法
  • 类通过继承可以重载其中的方法,在使用多态的方式调用方法的时候,virtual方法通过子对象调用,可以表现出子对象新的行为

system verilog约束重载

System Verilog还有一个非常有用的特性是支持约束的重载。像我们已经在transaction里定义了某些变量的约束,如果我们需要修改约束的时候只需要派生一个新的transaction,然后直接重载约束即可。

class new_transaction extends my_transaction;

    `uvm_object_utils(new_transaction)
    function new(string name= "new_transaction");
        super.new(name);
    endfunction
    constraint crc_err_cons{
        crc_err dist {0 := 2, 1 := 1};
    }
endclass

变量crc_err已经在my_transacton里给定了约束,但是我们想更改这个约束,就从my_transaction里派生一个新的transaction,然后直接重载crc_err的约束即可。

uvm factoroy重载

function void my_case0::build_phase(uvm_phase phase);
    
    // 用parrot替代bird类型
    set_type_override_by_type(bird::get_type(), parrot::get_type());
    
    bird_inst = bird::type_id::create("bird_inst");
    parrot_inst = parrot::type_id::create("parrot_inst");
    
    print_hungry(bird_inst);
    print_hungry(parrot_inst);

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"


  • 实例化对象的时侯,实例化语句并不会立马生效,UVM会通过factory机制在自己内部的一张override表格中查看是否有相关的重载记录。 set_type_override_by_type语句相当于在factory机制的override表格中加入了一条记录。当查到有重载记录时,会使用新的类型来替代旧的类型。所以虽然在build_phase中写明创建bird的实例,但是最终却创建了parrot的实例。
  • set_type_override_by_type()函数的作用就是在创建实例之前,将新的类型记录到override的表中
  • 实例化的时候,factory会先查找override表中原类型是不是被override了,然后创建对象,如果没有override,就创建原对象,如过有override就创建新对象

连续重载

连续重载即factory机制查到一条重载记录时不会立马创建重载类的实例,而是全部查完后再创建,假设查到parrot派生自bird后又查到big_parrot派生自parrot,那么所有的bird和parrot的实例化都会被big_parrot重载掉,这就是连续重载。

class big_parrot extends parrot;
    virtual function void hungry();
        $display("I am a big_parrot, I am hungry");
    endfunction

    function void hungry2();
        $display("I am a big_parrot, I am hungry2");
    endfunction

    `uvm_object_utils(big_parrot)
    function new(string name = "big_parrot");
        super.new(name);
    endfunction
endclass
//////////////
function void my_case0::build_phase(uvm_phase phase);
    bird bird_inst;
    parrot parrot_inst;
    super.build_phase(phase);
    set_type_override_by_type(bird::get_type(), parrot::get_type());
    set_type_override_by_type(parrot::get_type(), big_parrot::get_type());
    bird_inst = bird::type_id::create("bird_inst");
    parrot_inst = parrot::type_id::create("parrot_inst");
    print_hungry(bird_inst);
    print_hungry(parrot_inst);
endfunction
# I am a big_parrot, I am hungry
# I am a bird, I am hungry2

替换重载

替换式重载即已经查到了一条重载记录是parrot重载bird,但再继续查找的过程中又找到了sparrow重载bird(sparrow也派生自bird),这样sparrow就会把上一条的parrot的重载替换掉(前提是重载函数的replace参数值为1,即default值)。

// 替换重载
class sparrow extends bird;
    virtual function void hungry();
        $display("I am a sparrow, I am hungry");
    endfunction

    function void hungry2();
        $display("I am a sparrow, I am hungry2");
    endfunction

    `uvm_object_utils(sparrow)

    function new(string name = "sparrow");
        super.new(name);
    endfunction
endclass
//////////////
function void my_case0::build_phase(uvm_phase phase);
    bird bird_inst;
    parrot parrot_inst;
    super.build_phase(phase);
    set_type_override_by_type(bird::get_type(), parrot::get_type());
    set_type_override_by_type(bird::get_type(), sparrow::get_type());
    bird_inst = bird::type_id::create("bird_inst");
    parrot_inst = parrot::type_id::create("parrot_inst");
    print_hungry(bird_inst);
    print_hungry(parrot_inst);
endfunction
# I am a sparrow, I am hungry
# I am a bird, I am hungry2
# I am a parrot, I am hungry
# I am a bird, I am hungry2

uvm factory重载的条件

  1. 无论是重载的类(parrot) 还是被重载的类(bird) , 都要在定义时注册到factory机制中。

  2. 被重载的类(bird) 在实例化时, 要使用factory机制式的实例化方式, 而不能使用传统的new方式。

  3. 最重要的是, 重载的类(parrot) 要与被重载的类(bird) 有派生关系。 重载的类必须派生自被重载的类, 被重载的类必须是重载类的父类。

  4. component与object之间互相不能重载

uvm重载方法

uvm_component中的重载方法

  • 使用set_type_override_by_type函数可以实现两种不同类型之间的重载,
  • set_inst_override_by_type函数(并不是希望把验证平台中的A类型全部替换成B类型,而只是替换其中的某一部分)
extern static function void set_type_override_by_type
				(uvm_object_wrapper original_type,   
//第一个参数是被重载的类型,父类
				uvm_object_wrapper override_type,    
//第二个参数是重载的类型。子类
				bit replace=1);

extern function void set_inst_override_by_type(string relative_inst_path,   
  //其中第一个参数是相对路径,
						uvm_object_wrapper original_type,  
                          //第二个参数是被重载的类型,父类
  						uvm_object_wrapper override_type
                          //第二个参数是被重载的类型,子类
);
  • 无论是set_type_override_by_type还是set_inst_override_by_type,它们的参数都是一个uvm_object_wrapper型的类型参数,这种参数通过xxx::get_type()的形式获得。
    使用类的名称进行替换的方法:set_type_override/set_inst_override
  • 传入参数为字符串
set_type_override("bird","parrot");

set_inst_override("env.o_agt.mon","my_monitor","new_monitor");

tb_top中initial中的也可以用的重载函数

  • 以下四个函数可以用于替换上述函数
  • 这四个函数都是factory的重载函数
  • 在component中也可以使用factory机制的重载函数
initial begin
  factory.set_type_override_by_type(bird::get_type,parrot::get_type());
end

在命令行重载函数

+uvm_set_inst_override="my_monitor,new_monitor,env.o_agent.mon"
+uvm_set_type_override="my_monitor,new_monitor"
posted @ 2024-03-15 09:27  Icer_Newer  阅读(223)  评论(0编辑  收藏  举报