IC验证学习笔记(MCDF)UVM实验1-工厂机制

一、工厂的注册、创建和覆盖机制

工厂机制_知识回顾

  • 工厂是为了更方便的替换验证环境中的实例或注册了的类型,带来配置的灵活性
  • 背景:有时候无法直接修改验证平台的代码,比如①别人正在用,修改会影响别人使用;②验证IP你没有办法直接看到,所以也无法修改。
  • 作用:为了更方便地替代验证环境中的实例或者注册类型
  • 核心三要素:注册、创建、覆盖

1、注册:要用 uvm_component_utils()或者uvm_object_utils()注册

  • uvm_component常见的组件有:uvm_driver、uvm_monitor、uvm_sequencer、uvm_agent、uvm_scoreboard、uvm_env、uvm_test,凡是继承他们的组件都需要用 uvm_component_utils()进行注册;

  • 除了上述提到的组件外,几乎所有的类都派生自uvm_object,常见的有uvm_sequence_item、uvm_sequence、config等在这里插入图片描述

首先是`uvm_component_utils()注册;然后是new函数,第二个参数是parent,必须调用super.new();最后是build_phase()函数,也是必须调用super.build_phase(p)函数

class comp1 extends uvm_component;
`uvm_component_utils (comp1)//注册组件;new函数必须只有两个参数
function new (string name=:comp1", uvm_component parent=null);//parent是指上一层,当前实例是谁例化的,谁就是这个实例parent
	super.new(name, parent);//继承父类new函数
	$display($sformatf("%s is created", name));//已例化当前类
endfunction : new
function void build_phase (uvm_phase phase);
	super.build_phase (phase);
endfunction: build_phase
endclass

2、创建:UVM中创建实例的方法有很多,常用xxx::type_id::create来创建;注意,如果用new()来创建则无法使用工厂的覆盖

        例化component用c2 = comp1::type_id::create ("c2",null);也是两个参数

        例化object用o2 = obj1::type_id::create("o2");

comp1 c1, c2;
obj1 o1,o2;
initial begin
c1 = new ("c1");//任何对象的例化最终都是通过new()函数来实现,sv的方法
o1 = new ("o1");
c2 = comp1::type_id::create ("c2",null);//这个也是例化的写法,factory提供的方法
o2 = obj1::type_id::create("o2");
end

3、覆盖
覆盖并不是工厂机制的发明,所有面向对象的语言都支持函数/任务重载。
采用工厂进行覆盖有以下条件:

        原类型和新类型都需要注册到工厂里;
        需要用工厂机制来创建;
        覆盖的类和被覆盖的类有继承关系,并且被覆盖的方法要声明为virtual。不过有例外:component和object之间不能相互覆盖(虽然component是object的子类,但血缘关系太远了)
        若有多层覆盖时,最终覆盖的类必须是最初被覆盖类的子类;多层覆盖,以最后一个覆盖结果为准

set_inst_override ( uvm_object_wrapper override_type, string inst_path);
//uvm_object_wrapper override_type是注册过后的某一个类在工厂中注册时的句柄,用new_type::get_type()找到
module factory_override;
import uvm_pkg::*;//可直接import和include,编译器已经包含了
`inculde "uvm_macros.svh"
 
class comp1 extends uvm_component;//1声明
`uvm_component_utils(comp1)//2注册
 
function new (string name="comp1", uvm_component parent= null);//3new函数
	super.new(name, parent);
	$display ($sformatf("comp1::%s is created", name));
	endfunction
 
virtual function void hello (string name);//virtual是关键
	$display ( $sformatf("comp1:: %s is said hello!", name);
endfunction
endclass
 
class comp2 extends comp1;//要覆盖的类一定要继承于被覆盖的类
`uvm_component_utils(comp2)
 
function new (string name="comp2", uvm_component parent= null);
	super.new(name, parent);
	$display ($sformatf("comp2::%s is created", name));
	endfunction
 
function void hello (string name);
	$display ( $sformatf("comp2:: %s is said hello!", name);
endfunction
endclass
 
comp1 c1, c2;//两个句柄都是comp1的类型
initial begin
comp1::type_id::set_type_override (comp2::get_type());//调用覆盖函数,如上段例码
c1= new("c1");//例化c1(comp1),没有通过工厂。打印comp1::c1 is created,
c2= comp2::type_id::creare("c2",null);//工厂创建的对象,create返回一个comp2句柄给c2
//但是c2是comp1的句柄,却指向了comp2类型的对象。这里就是子类句柄覆盖父类句柄。所以必须是继承关系
//用工厂注册,就一定要用工厂来创建,达到便利的目的
//打印comp1::c2 is created,comp2::c2 is created
c1.hello("c1");//调用comp1的hello,打印 comp1::c1 is said hello
c2.hello("c2");//调用comp2的hello,打印 comp2::c2 is said hello
end
 
endmodule

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值