[CU]factory机制5-factory机制创建实例的原理

 资料来源:

(1)公众号-芯片学堂;

注1:与[CU]factory机制3-factory机制创建实例(create_object/component_by_type/name) - __见贤思齐 - 博客园 (cnblogs.com)内容略有重叠,但侧重点不同;

1.factory机制相关宏

[CU]factory机制2-factory机制之用于类注册的宏(factory机制-注册) - __见贤思齐 - 博客园 (cnblogs.com)

注1:factory所有的操作都是通过`uvm_object_utils或`uvm_component_utils或`uvm_object_param_utils或`uvm_component_param_utils来完成;

2.factory机制的注册(以uvm_object_registry#(T,`"S`")为例,uvm_component_registry#(T,`"S`"类似))

(1) factory机制的注册是在typedef uvm_object_registry#(T,`"S`") type_id中实现的;

注1: typedef语句声明了一个参数化的类,类的名字为uvm_object_registry,参数有两个:一个是输入的类型T,一个是字符串S; 对于参数化的类而言,只有一个参数就是输入类型T;

注2: 输入参数类型T与type-based factory相对应,可以用来实现根据类型创建实例; 输入参数字符串S与string-based factory相对应,可以用来实现根据名字创建实例;

(2) uvm_object_registry#(T,`"S`")类内部有一个私有的静态成员变量me,通过调用get函数,创建一个me的实例,然后通过factory的register函数注册到factory中;

 1 class uvm_object_registry #(type T=uvm_object, string Tname="<unknown>")
 2                                         extends uvm_object_wrapper;
 3   typedef uvm_object_registry #(T,Tname) this_type;
 4 
 5   ...
 6   local static this_type me = get();
 7 
 8   // Function: get
 9   //
10   // Returns the singleton instance of this type. Type-based factory operation
11   // depends on there being a single proxy instance for each registered type.
12 
13   static function this_type get();
14     if (me == null) begin
15       uvm_coreservice_t cs = uvm_coreservice_t::get();
16       uvm_factory factory=cs.get_factory();
17       me = new;
18       factory.register(me);
19     end
20     return me;
21   endfunction
22   ...
23 endclass

注1:typedef uvm_object_registry#(T1,"S1") type1和typedef uvm_object_registry#(T2,"S2") type2在编译时,编译器会认为是两个类;

注2:所谓的把一个object或者component注册到factory中,其实注册的不是这个object或者component,而是uvm_object_registry#(T,"S")或uvm_component_registry#(T,"S")的一个实例;

3.单实例类uvm_factory

 1 virtual class uvm_factory;
 2 
 3   // Group: Retrieving the factory    
 4   static function uvm_factory get();
 5           uvm_coreservice_t s;
 6           s = uvm_coreservice_t::get();
 7           return s.get_factory();
 8   endfunction    
 9   ...
10 endclass

3.1uvm_factory函数简介

(1)uvm_factory中定义了一系列纯虚函数,主要包括以下几种功能:重载,创建,查找,调试等;

(2)uvm_factory的函数根据参数可以分为基于名字(name-based)和基于类型(type-based)两类; 每一种相同的功能都有两种不同的实现方式,一种是基于名字实现,一种是基于类型实现;

 1 virtual class uvm_factory;
 2      
 3   static function uvm_factory get();
 4           uvm_coreservice_t s;
 5           s = uvm_coreservice_t::get();
 6           return s.get_factory();
 7   endfunction    
 8 
 9   pure virtual function void register (uvm_object_wrapper obj);
10 
11   pure virtual function
12       void set_inst_override_by_type (uvm_object_wrapper original_type,
13                                       uvm_object_wrapper override_type,
14                                       string full_inst_path);
15 
16   pure virtual function
17       void set_inst_override_by_name (string original_type_name,
18                                       string override_type_name,
19                                       string full_inst_path);
20 
21   pure virtual function
22       void set_type_override_by_type (uvm_object_wrapper original_type,
23                                       uvm_object_wrapper override_type,
24                                       bit replace=1);
25 
26   pure virtual function
27       void set_type_override_by_name (string original_type_name,
28                                       string override_type_name,
29                                       bit replace=1);
30 
31   pure virtual function
32       uvm_object    create_object_by_type    (uvm_object_wrapper requested_type,  
33                                               string parent_inst_path="",
34                                               string name=""); 
35 
36   pure virtual function
37       uvm_component create_component_by_type (uvm_object_wrapper requested_type,  
38                                               string parent_inst_path="",
39                                               string name, 
40                                               uvm_component parent);
41 
42   pure virtual function
43       uvm_object    create_object_by_name    (string requested_type_name,  
44                                               string parent_inst_path="",
45                                               string name=""); 
46 
47   pure virtual function
48       uvm_component create_component_by_name (string requested_type_name,  
49                                               string parent_inst_path="",
50                                               string name, 
51                                               uvm_component parent);
52 
53   pure virtual function
54       void debug_create_by_type (uvm_object_wrapper requested_type,
55                                  string parent_inst_path="",
56                                  string name="");
57 
58   pure virtual function
59       void debug_create_by_name (string requested_type_name,
60                                  string parent_inst_path="",
61                                  string name="");
62 
63   pure virtual function
64       uvm_object_wrapper find_override_by_type (uvm_object_wrapper requested_type,
65                                                 string full_inst_path);
66 
67   pure virtual function
68       uvm_object_wrapper find_override_by_name (string requested_type_name,
69                                                 string full_inst_path);
70 
71   pure virtual 
72     function uvm_object_wrapper find_wrapper_by_name            (string type_name);
73 
74   pure  virtual function void print (int all_types=1);
75 endclass 

4.uvm_default_factory::register();

 1 class uvm_default_factory extends uvm_factory;
 2 
 3   // Group: Registering Types
 4 
 5   // Function: register
 6   //
 7   // Registers the given proxy object, ~obj~, with the factory.
 8    
 9   extern virtual function void register (uvm_object_wrapper obj);
10   ...
11 endclass
 1 function void uvm_default_factory::register (uvm_object_wrapper obj);
 2 
 3   if (obj == null) begin
 4     uvm_report_fatal ("NULLWR", "Attempting to register a null object with the factory", UVM_NONE);
 5   end
 6   if (obj.get_type_name() != "" && obj.get_type_name() != "<unknown>") begin
 7     if (m_type_names.exists(obj.get_type_name()))
 8       uvm_report_warning("TPRGED", {"Type name '",obj.get_type_name(),
 9         "' already registered with factory. No string-based lookup ",
10         "support for multiple types with the same type name."}, UVM_NONE);
11     else 
12       m_type_names[obj.get_type_name()] = obj;
13   end
14 
15   if (m_types.exists(obj)) begin
16     if (obj.get_type_name() != "" && obj.get_type_name() != "<unknown>")
17       uvm_report_warning("TPRGED", {"Object type '",obj.get_type_name(),
18                          "' already registered with factory. "}, UVM_NONE);
19   end
20   else begin
21     m_types[obj] = 1;
22     // If a named override happens before the type is registered, need to copy
23     // the override queue.
24     // Note:Registration occurs via static initialization, which occurs ahead of
25     // procedural (e.g. initial) blocks. There should not be any preexisting overrides.
26     if(m_inst_override_name_queues.exists(obj.get_type_name())) begin
27        m_inst_override_queues[obj] = new;
28        m_inst_override_queues[obj].queue = m_inst_override_name_queues[obj.get_type_name()].queue;
29        m_inst_override_name_queues.delete(obj.get_type_name());
30     end
31     if(m_wildcard_inst_overrides.size()) begin
32        if(! m_inst_override_queues.exists(obj)) 
33             m_inst_override_queues[obj] = new;
34        foreach (m_wildcard_inst_overrides[i]) begin
35          if(uvm_is_match( m_wildcard_inst_overrides[i].orig_type_name, obj.get_type_name()))
36             m_inst_override_queues[obj].queue.push_back(m_wildcard_inst_overrides[i]);
37        end
38     end
39 
40   end
41 
42 endfunction

(1) m_type_names联合数组的索引是string类型,其存储的内容是uvm_object_wrapper类型;

(2) factory.register(me)函数,会将uvm_object_registry#(T1,"S1")的静态成员变量me存储到m_type_names数组中,索引是me.get_type_name()的返回值,即"S1",记录的内容是me所指向的实例;

(3) m_types也是一个联合数组,该联合数组的索引是uvm_object_wrapper,存储的内容是bit类型; 如果m_types中没有找到相关记录,则进入else分支,往m_types中加入一条记录,该条记录的索引是uvm_object_registry#(T1,“S1”)的静态成员变量me所指向的实例;

(4) 总结:注册的实质就是uvm_object_registry#(T1,”S1”)的实例me放入m_type_names中,并把"S1"作为索引;把me作为m_types的索引,其内容为1;

5.uvm_default_factory::create_object_by_name();

 1 function uvm_object uvm_default_factory::create_object_by_name (string requested_type_name,  
 2                                                         string parent_inst_path="",  
 3                                                         string name=""); 
 4 
 5   uvm_object_wrapper wrapper;
 6   string inst_path;
 7 
 8   if (parent_inst_path == "")
 9     inst_path = name;
10   else if (name != "")
11     inst_path = {parent_inst_path,".",name};
12   else
13     inst_path = parent_inst_path;
14 
15   m_override_info.delete();
16 
17   wrapper = find_override_by_name(requested_type_name, inst_path);
18 
19   // if no override exists, try to use requested_type_name directly
20   if (wrapper==null) begin
21     if(!m_type_names.exists(requested_type_name)) begin
22       uvm_report_warning("BDTYP",{"Cannot create an object of type '",
23       requested_type_name,"' because it is not registered with the factory."}, UVM_NONE);
24       return null;
25     end
26     wrapper = m_type_names[requested_type_name];
27   end
28 
29   return wrapper.create_object(name);
30 
31 endfunction

(1) 该函数先是根据传入的字符串(待实例化的类名)从关联数组m_type_names中获取相应的wrapper,即uvm_object_registry#(A,”A”)::me;

(2) wrapper.create_object就是uvm_object_registry#(A,”A”)::me.create_object();

6.uvm_object_registry#(T,`"S"`).create_object();

 1 class uvm_object_registry #(type T=uvm_object, string Tname="<unknown>")
 2                                         extends uvm_object_wrapper;
 3   ...
 4   virtual function uvm_object create_object(string name="");
 5     T obj;
 6 `ifdef UVM_OBJECT_DO_NOT_NEED_CONSTRUCTOR
 7     obj = new();
 8     if (name!="")
 9       obj.set_name(name);
10 `else
11     if (name=="") obj = new();
12     else obj = new(name);
13 `endif
14     return obj;
15   endfunction
16   ...
17 endclass

(1) 之所以能调用uvm_object_registry.create_object创造类的实例,是因为uvm_object_registry是一个参数化的类,类T是作为一个类型参数传递进来的;

(2) factory机制中根据类名来创建类的实例所用到的技术: 参数化的类和静态变量及静态函数;

 

posted on 2021-10-31 16:30  _见贤_思齐  阅读(125)  评论(0编辑  收藏  举报

导航