[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机制中根据类名来创建类的实例所用到的技术: 参数化的类和静态变量及静态函数;