UVM factory机制 override机制详解

本文详细介绍了UVM中的factory机制和override机制。factory机制允许根据类名创建实例,而override机制则提供了复用性和灵活性。文章讲解了如何通过宏注册类到factory,以及factory的内部工作原理。此外,还探讨了override的几种方法,如set_type_override_by_type和set_inst_override_by_type,以及它们在创建对象过程中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. factory机制

顾名思义,factory机制(工厂机制),最大的优点是根据字符串(类名),创建该类的实例,比如下面的一个类:class my_driver extends uvm_driver;当使用factory机制时就可以根据字符串“my_driver”创建属于类my_driver的一个实例。还有另一种解释是factory机制本质上是对new函数的重载,从某种意义上也确实是这么回事。实现factory机制需要将类(严谨一点的话与这个类相关的uvm_object_registry或者uvm_component_registry)注册到factory中,通常会调用UVM自带的宏注册。

宏注册主要是`uvm_object_utiles(T)  `uvm_object_param_utils(T)`uvm_component_utiles(T)  `uvm_component_param_utils(T)四个宏,在使用UVM的过程中原则上对所有的class均需要进行factory注册。

在上面我们有讲到,严格意义上向factory中注册的是与类T相关的uvm_object_registery#()或者uvm_component_registery#()的代理类。这两个类均继承与uvm_object_wrapper,这个类是一个virtual class。这里面有3virtual 方法,create_objectcreate_component,get_type_name。在两个继承类中需要进行重载,同时这两个继承类会新建方法createset_type_overvide, set_inst_override,get。这些方法均为static,我们在使用override的时候除了调用component自身的override方法之外,还可以使用::type_id::*的方法实现,当然这种使用方法很少见,一般不会这么费事的使用,毕竟UVM已经给我们封装好了。下面我们讲解一下其中的一个宏注册,`uvm_object_utiles(T)。

class T extends uvm_object;
`uvm_object_utils(T)
endclass
下面我们将宏所表示的代码全部展开
class T extends uvm_object;

   typedef uvm_object_registry#(T,"T") type_id; 
   static function type_id get_type(); 
     return type_id::get(); 
   endfunction 
   virtual function uvm_object_wrapper get_object_type(); 
     return type_id::get(); 
   endfunction
   
   function uvm_object create (string name=""); 
     T tmp; 
     `ifdef UVM_OBJECT_DO_NOT_NEED_CONSTRUCTOR 
     tmp = new(); 
     if (name!="") 
       tmp.set_name(name); 
     `else 
     if (name=="") tmp = new(); 
     else tmp = new(name); 
     `endif 
     return tmp; 
   endfunction
   
   const static string type_name = "T"; 
   virtual function string get_type_name (); 
     return type_name; 
   endfunction 
   
   function void __m_uvm_field_automation (uvm_object tmp_data__, 
                                     int what__, 
                                     string str__); 
   begin 
     T local_data__; /* Used for copy and compare */ 
     typedef T ___local_type____; 
     string string_aa_key; /* Used for associative array lookups */ 
     uvm_object __current_scopes[$]; 
     if(what__ inside {UVM_SETINT,UVM_SETSTR,UVM_SETOBJ}) begin 
        if(__m_uvm_status_container.m_do_cycle_check(this)) begin 
            return; 
        end 
        else 
            __current_scopes=__m_uvm_status_container.m_uvm_cycle_scopes; 
     end 
     super.__m_uvm_field_automation(tmp_data__, what__, str__); 
     /* Type is verified by uvm_object::compare() */ 
     if(tmp_data__ != null) 
       /* Allow objects in same hierarchy to be copied/compared */ 
       if(!$cast(local_data__, tmp_data__)) return;
	   
	end 
   endfunction 
   
endclass

 

 现在是不是一目了然了,在使用的过程中T::tyepe_id::create::就是来自这里。其中tyep_id是类T的一个成员变量,createuvm_object_regisrty#T”T”)的static方法。

那么是怎么实现向factory注册呢,在uvm_object_registry中有一个静态变量me,利用静态方法getfactory中注册,通过调用factoryregister方法实现注册。最终会在factorym_type_namesm_type两个联合数据中注册记录。注意不要尝试对同一个类进行多次注册,如果出现的话factory会提示已经注册了(以warning的报告出现),当然了一般也没有人会这么干。

  1. override机制

其实我们会发现UVM之所以实现factory机制,本质是为了实现平台代码最大的复用性,最主要的用法都集中在override机制方面,下面将会讲解一下override机制。

Override机制是factory机制优势最大的体现

Set_type_override_by_type(initial_type,override_type bit replease=1):

主要作用,在队列m_type_override[$]中放入override信息。比如base_type->ov1_typebase_type->ov2_type。首次调用的话ov1-type overridebase_type。如果第二次再调用ov2_type  override base,如果参数replease=1(默认参数),那么最终base_typeov2_type 覆盖。如果参数replease=1,则覆盖失败。

set-type_override_by_name(initial_type_name,override_type_name bit replease=1):

主要作用:在队列m_type_override[$]中放入override信息。比如base_type->ov1_typebase_type->ov2_type。首次调用的话ov1-type overridebase_type。如果第二次再调用ov2_type  override base,如果参数replease=1(默认参数),那么最终base_typeov2_type 覆盖。如果参数replease=1,则覆盖失败。注意这个函数传入的参数是类名字符串,不是类型。这个方法会根据传入的类名字符串去m_type_name[$]联合数组中寻找与这个类关联的代理类,然后获得代理类,接着执行与Set_type_override_by_type相同的操作。在这个override操作中海油一个要注意的是如果传入的initial_type_namem_type_name[$]没有找到代理类,那么会在联合数组m_lookup_strs[string]中做出标记

Set_inst_override_by_type(initial_type,override_type full_inst_path):

这个是路径替换,特定UVM路径下类的替换,联合数组uvm_factory_queue_class m_inst_override_queues[uvm_object_wrapper],这种类型inst的特换没有replease的概念,但是又路径的概念,所以出现了uvm_factory_queue_class(就是一个queue,存放的是override信息,不同元素的区别在于不同的路径,同一个路径不会多次override(会先判断))

set_inst_override_by_name(initial_type_name,override_type_name full_inst_path):

也是路径特换,有3个重要的变量   uvm_factory_queue_class m_inst_override_queues[uvm_object_wrapper]    m_wildcard_inst_overrides[$],uvm_factory_queue_class m_inst_override_name_queues[string]

如果传入的参数string完整,则在m_inst_override_queues插入记录

如果传入的参数string不完整,但是又通配符,则在m_wildcard_inst_overrides[$]插入记录,同时通配符还匹配完成字符串,同时在m_inst_override_queues插入记录

如果传入的参数及不完整,有没有通配符,则在m_inst_override_name_queues插入记录

 

所有与override相关的队列或者联合数组均会在使用factory机制创建时被使用(遍历使用)

find_override_by_type(request_type,full_inst_path)

主要作用:在create_object_by_typecreate_component_by_type中被调用,寻找真正要创建的对象的类型。如果是之前type_override的话,直接遍历m_type_override[$](比如base_type->ov1_type,传进来的是base_type的代理类类型,发现m_type_override[$]中存在ov1_type覆盖base_type的情况,那么再次调用Find_override_by_type(request_type,full_inst_path),只是传输的是ov1_type的代理类类型,发现m_type_override[$]不存在ov1_type的覆盖,返回ov1_type的代理类型如果base_type->ov1_type->ov2_type。那么最终返回的是ov2_type。以此类推)

如果是之前inst_override的话,直接遍历m_inst_override_queus联合数组,找到init_type类型的元素,下面对这个元素的queue中的path进行匹配base_type->ov1_type(带path,匹配上的话,载次调用Find_override_by_type(request_type,full_inst_path),只是传输的是ov1_type的代理类类型,发现m_inst_override_queus没有匹配的,最终返回ov1_type。如果base_type->ov1_type->ov2_type。那么最终返回的是ov2_type。以此类推。注意一定要path匹配。

 

find_override_by_name(request_type-name,full_inst_path)

这个方法和上面的方法相似,内部还会调用Find_override_by_type。主要是根据参数request_type-name获取类型。如果是type_override。遍历m_type_override[$]寻找。如果是inst_override,根据参数request_type-name,会在与inst overroide相关的联合数组或者队列中查看是否可以寻找到,寻找到的话(匹配上的话,调用Find_override_by_type)。如果之中找到name匹配的地方,返回null

 

 

 

  1. factory机制对象的创建

下面是怎么使用factory创建对象的:

Create_object_by_type(request_type,parent_inst_path,name)

调用find_override_by_type->create_object

Create_object_by_type(request_type_name,parent_inst_path,name)

调用find_override_by_name->create_object。如果find_override_by_name返回null,没有override或者没有找到override的匹配信息。这个实在在m_type_name中看看是否注册是,没有的话番薯直接返回null(没有注册的话当然不能使用factory机制创建)

Create_object_by_type(request_type,parent_inst_path,nameparent)

调用find_override_by_type->create_object

Create_object_by_type(request_type_name,parent_inst_path,nameparent)

调用find_override_by_name->create_object。如果find_override_by_name返回null,没有override或者没有找到override的匹配信息。这个实在在m_type_name中看看是否注册是,没有的话番薯直接返回null(没有注册的话当然不能使用factory机制创建)

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值