[CU]factory机制3-factory机制创建实例(create_object/component_by_type/name)
1.factory机制创建实例的简单分析
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 12 // Group: Type & Instance Overrides 13 14 // Function: set_inst_override_by_type 15 16 extern virtual function 17 void set_inst_override_by_type (uvm_object_wrapper original_type, 18 uvm_object_wrapper override_type, 19 string full_inst_path); 20 21 // Function: set_inst_override_by_name 22 // 23 // Configures the factory to create an object of the override's type whenever 24 // a request is made to create an object of the original type using a context 25 // that matches ~full_inst_path~. 26 extern virtual function 27 void set_inst_override_by_name (string original_type_name, 28 string override_type_name, 29 string full_inst_path); 30 31 32 // Function: set_type_override_by_type 33 34 extern virtual function 35 void set_type_override_by_type (uvm_object_wrapper original_type, 36 uvm_object_wrapper override_type, 37 bit replace=1); 38 39 // Function: set_type_override_by_name 40 // 41 // Configures the factory to create an object of the override's type whenever 42 // a request is made to create an object of the original type, provided no 43 // instance override applies. 44 45 extern virtual function 46 void set_type_override_by_name (string original_type_name, 47 string override_type_name, 48 bit replace=1); 49 50 51 // Group: Creation 52 53 // Function: create_object_by_type 54 55 extern virtual function 56 uvm_object create_object_by_type (uvm_object_wrapper requested_type, 57 string parent_inst_path="", 58 string name=""); 59 60 // Function: create_component_by_type 61 62 extern virtual function 63 uvm_component create_component_by_type (uvm_object_wrapper requested_type, 64 string parent_inst_path="", 65 string name, 66 uvm_component parent); 67 68 // Function: create_object_by_name 69 70 extern virtual function 71 uvm_object create_object_by_name (string requested_type_name, 72 string parent_inst_path="", 73 string name=""); 74 75 // Function: create_component_by_name 76 // 77 // Creates and returns a component or object of the requested type, which may 78 // be specified by type or by name. 79 80 extern virtual function 81 uvm_component create_component_by_name (string requested_type_name, 82 string parent_inst_path="", 83 string name, 84 uvm_component parent); 85 86 // Group: Debug 87 88 // Function: debug_create_by_type 89 90 extern virtual function 91 void debug_create_by_type (uvm_object_wrapper requested_type, 92 string parent_inst_path="", 93 string name=""); 94 95 // Function: debug_create_by_name 96 // 97 // These methods perform the same search algorithm as the ~create_*~ methods, 98 // but they do not create new objects. 99 extern virtual function 100 void debug_create_by_name (string requested_type_name, 101 string parent_inst_path="", 102 string name=""); 103 104 105 // Function: find_override_by_type 106 107 extern virtual function 108 uvm_object_wrapper find_override_by_type (uvm_object_wrapper requested_type, 109 string full_inst_path); 110 111 // Function: find_override_by_name 112 // 113 // These methods return the proxy to the object that would be created given 114 // the arguments. 115 116 extern virtual function 117 uvm_object_wrapper find_override_by_name (string requested_type_name, 118 string full_inst_path); 119 120 extern virtual 121 function uvm_object_wrapper find_wrapper_by_name (string type_name); 122 123 // Function: print 124 // 125 // Prints the state of the uvm_factory, including registered types, instance 126 // overrides, and type overrides. 127 // 128 extern virtual function void print (int all_types=1); 129 130 131 //---------------------------------------------------------------------------- 132 // PRIVATE MEMBERS 133 134 extern protected 135 function void m_debug_create (string requested_type_name, 136 uvm_object_wrapper requested_type, 137 string parent_inst_path, 138 string name); 139 140 extern protected 141 function void m_debug_display(string requested_type_name, 142 uvm_object_wrapper result, 143 string full_inst_path); 144 145 protected bit m_types[uvm_object_wrapper]; 146 protected bit m_lookup_strs[string]; 147 protected uvm_object_wrapper m_type_names[string]; 148 149 protected uvm_factory_override m_type_overrides[$]; 150 151 protected uvm_factory_queue_class m_inst_override_queues[uvm_object_wrapper]; 152 protected uvm_factory_queue_class m_inst_override_name_queues[string]; 153 protected uvm_factory_override m_wildcard_inst_overrides[$]; 154 155 local uvm_factory_override m_override_info[$]; 156 local static bit m_debug_pass; 157 158 extern function bit m_has_wildcard(string nm); 159 160 extern function bit check_inst_override_exists 161 (uvm_object_wrapper original_type, 162 uvm_object_wrapper override_type, 163 string full_inst_path); 164 165 endclass
1.1利用factory机制创建实例的两种方法
(1)通过名字索引得到string-based关联数组m_types_names与名字对应的uvm_object/component_wrapper,并调用uvm_object_wrapper.create_object或者uvm_component_wrapper.create_component进行实例创建(典型的如run_test()中对uvm_test的实例化,run_test使用它的字符串参数或者来源于+UVM_TESTNAME的字符串);
(2)根据type创建,在创建过程中会查看是否存在type_override情况,并获取到uvm_object/component_wrapper,然后调用uvm_object_wrapper.create_object或者uvm_component_wrapper.create_component进行实例创建;
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 function uvm_component uvm_default_factory::create_component_by_name (string requested_type_name, 2 string parent_inst_path="", 3 string name, 4 uvm_component parent); 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 a component 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_component(name, parent); 30 31 endfunction
1 function uvm_object uvm_default_factory::create_object_by_type (uvm_object_wrapper requested_type, 2 string parent_inst_path="", 3 string name=""); 4 5 string full_inst_path; 6 7 if (parent_inst_path == "") 8 full_inst_path = name; 9 else if (name != "") 10 full_inst_path = {parent_inst_path,".",name}; 11 else 12 full_inst_path = parent_inst_path; 13 14 m_override_info.delete(); 15 16 requested_type = find_override_by_type(requested_type, full_inst_path); 17 18 return requested_type.create_object(name); 19 20 endfunction
1 function uvm_component uvm_default_factory::create_component_by_type (uvm_object_wrapper requested_type, 2 string parent_inst_path="", 3 string name, 4 uvm_component parent); 5 string full_inst_path; 6 7 if (parent_inst_path == "") 8 full_inst_path = name; 9 else if (name != "") 10 full_inst_path = {parent_inst_path,".",name}; 11 else 12 full_inst_path = parent_inst_path; 13 14 m_override_info.delete(); 15 16 requested_type = find_override_by_type(requested_type, full_inst_path); 17 18 return requested_type.create_component(name, parent); 19 20 endfunction
1.2`uvm_object/component_param_utils与实例的创建
(1)`uvm_object/component_param_utils仅仅实现了type-based的注册,不能通过名字进行实例的创建(如果需要,需要人工处理);如果需要对参数化类实现string-based registration,需要为typedef uvm_component_registry/uvm_object_registry提供第二个参数;
[CU]factory机制2-factory机制之用于类注册的宏(factory机制-注册) - __见贤思齐 - 博客园 (cnblogs.com)
//结合`uvm_component_param_utils与`uvm_object_param_utils的宏定义查看; function void uvm_default_factory::register (uvm_object_wrapper obj); if (obj == null) begin uvm_report_fatal ("NULLWR", "Attempting to register a null object with the factory", UVM_NONE); end if (obj.get_type_name() != "" && obj.get_type_name() != "<unknown>") begin if (m_type_names.exists(obj.get_type_name())) uvm_report_warning("TPRGED", {"Type name '",obj.get_type_name(), "' already registered with factory. No string-based lookup ", "support for multiple types with the same type name."}, UVM_NONE); else m_type_names[obj.get_type_name()] = obj; end if (m_types.exists(obj)) begin if (obj.get_type_name() != "" && obj.get_type_name() != "<unknown>") uvm_report_warning("TPRGED", {"Object type '",obj.get_type_name(), "' already registered with factory. "}, UVM_NONE); end else begin m_types[obj] = 1; // If a named override happens before the type is registered, need to copy // the override queue. // Note:Registration occurs via static initialization, which occurs ahead of // procedural (e.g. initial) blocks. There should not be any preexisting overrides. if(m_inst_override_name_queues.exists(obj.get_type_name())) begin m_inst_override_queues[obj] = new; m_inst_override_queues[obj].queue = m_inst_override_name_queues[obj.get_type_name()].queue; m_inst_override_name_queues.delete(obj.get_type_name()); end if(m_wildcard_inst_overrides.size()) begin if(! m_inst_override_queues.exists(obj)) m_inst_override_queues[obj] = new; foreach (m_wildcard_inst_overrides[i]) begin if(uvm_is_match( m_wildcard_inst_overrides[i].orig_type_name, obj.get_type_name())) m_inst_override_queues[obj].queue.push_back(m_wildcard_inst_overrides[i]); end end end endfunction
1.3factory机制通过class_name::type_id::create创建实例的全过程
1 class A extends uvm_object; 2 `uvm_object_utils(A) 3 ... 4 endclass 5 6 A a; 7 a=A::type_id::create("a");
(1) 类里面使用`uvm_object/component_utils等宏在uvm_object/uvm_component中引入一系列函数以及变量uvm_object/component_registry(T,`"S"`);
(2) 当调用uvm_object/component_registry(T,`"S"`)的create函数进行实例创建时,uvm_object_registry的create函数将实例化的任务转交给uvm_factory的creat_object_by_type函数,uvm_factory通过find_overrid_by_type函数查到当前类的重载类所对应的uvm_object/component_registry,然后由该uvm_object/component_registry的create_object函数完成类的实例化,并最终返回对象;
注1:实例化任务转交的前提是uvm_object/component_registry(T,`"S"`)的静态函数get()中调用factory.register()进行了信息的注册;
注2:所谓的把一个object或者component注册到factory中,其实注册的不是这个object或者component,而是uvm_object_registry#(T,”S”)或uvm_component_registry#(T,”S”)的一个实例;
注3:typedef uvm_object_registry#(T1,”S1”) type1和typedef uvm_object_registry#(T2,”S2”) type2在编译时,编译器会认为是两个类;
1.3.1 type_id
1 typedef uvm_object_registry#(T,S) type_id; \ 2 typedef uvm_component_registry #(T,S) type_id; \
(1) type_id是一个类型的重命名,type_id通过typedef映射的类型是参数化uvm_object_registry#(T, `"S`")或uvm_component_registry#(T,`"S"`));
(2) uvm_object/component_registry#(T,`"S"`)都是单实例类,全局唯一例化(uvm_object_registry/uvm_cmponent_registry都派生于uvm_object_wrapper),并且只有在第一次被访问的时候(即调用其get函数)才会被实例化,并同时通过调用default_factory的register函数来记录到工厂的类型队列中。
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 class uvm_component_registry #(type T=uvm_component, string Tname="<unknown>") 2 extends uvm_object_wrapper; 3 typedef uvm_component_registry #(T,Tname) this_type; 4 5 6 ... 7 local static this_type me = get(); 8 9 10 // Function: get 11 // 12 // Returns the singleton instance of this type. Type-based factory operation 13 // depends on there being a single proxy instance for each registered type. 14 15 static function this_type get(); 16 if (me == null) begin 17 uvm_coreservice_t cs = uvm_coreservice_t::get(); 18 uvm_factory factory=cs.get_factory(); 19 me = new; 20 factory.register(me); 21 end 22 return me; 23 endfunction 24 ... 25 endclass
(3) 并不是调用了宏(`uvm_object_utils)就完成了注册(uvm_object_registry#(T, `"S`")),只有在当前类(uvm_object_registry#(T, `"S`"))被实例化的时候,该参数化的uvm_object_registry才会被真正的注册到工厂中。
1.3.2 type_id::create
1 class uvm_object_registry #(type T=uvm_object, string Tname="<unknown>") 2 extends uvm_object_wrapper; 3 4 ... 5 const static string type_name = Tname; 6 ... 7 static function T create (string name="", uvm_component parent=null, 8 string contxt=""); 9 uvm_object obj; 10 uvm_coreservice_t cs = uvm_coreservice_t::get(); 11 uvm_factory factory=cs.get_factory(); 12 13 if (contxt == "" && parent != null) 14 contxt = parent.get_full_name(); 15 obj = factory.create_object_by_type(get(),contxt,name); 16 if (!$cast(create, obj)) begin 17 string msg; 18 msg = {"Factory did not return an object of type '",type_name, 19 "'. A component of type '",obj == null ? "null" : obj.get_type_name(), 20 "' was returned instead. Name=",name," Parent=", 21 parent==null?"null":parent.get_type_name()," contxt=",contxt}; 22 uvm_report_fatal("FCTTYP", msg, UVM_NONE); 23 end 24 endfunction 25 ... 26 endclass
1 class uvm_component_registry #(type T=uvm_component, string Tname="<unknown>") 2 extends uvm_object_wrapper; 3 4 ... 5 const static string type_name = Tname; 6 ... 7 static function T create(string name, uvm_component parent, string contxt=""); 8 uvm_object obj; 9 uvm_coreservice_t cs = uvm_coreservice_t::get(); 10 uvm_factory factory=cs.get_factory(); 11 if (contxt == "" && parent != null) 12 contxt = parent.get_full_name(); 13 obj = factory.create_component_by_type(get(),contxt,name,parent); 14 if (!$cast(create, obj)) begin 15 string msg; 16 msg = {"Factory did not return a component of type '",type_name, 17 "'. A component of type '",obj == null ? "null" : obj.get_type_name(), 18 "' was returned instead. Name=",name," Parent=", 19 parent==null?"null":parent.get_type_name()," contxt=",contxt}; 20 uvm_report_fatal("FCTTYP", msg, UVM_NONE); 21 end 22 endfunction 23 ... 24 endclass
(1) create函数(静态函数)的三个参数-第一个参数name是对象的名字,第二个参数parent和第三个参数contxt共同指定了新创建的对象在UVM层次中的关系;
(2) 实际使用中,第三个contxt通常不指定,如果只指定了parent而没有指定contxt,contxt在函数内部会被设置为parent.get_full_name;
1.3.3 uvm_factory::create_object_by_type
1 function uvm_object uvm_default_factory::create_object_by_type (uvm_object_wrapper requested_type, 2 string parent_inst_path="", 3 string name=""); 4 5 string full_inst_path; 6 7 if (parent_inst_path == "") 8 full_inst_path = name; 9 else if (name != "") 10 full_inst_path = {parent_inst_path,".",name}; 11 else 12 full_inst_path = parent_inst_path; 13 14 m_override_info.delete(); 15 16 requested_type = find_override_by_type(requested_type, full_inst_path); 17 18 return requested_type.create_object(name); 19 20 endfunction
(1) create_object_by_type函数内会查找当前要实例化的类是否被重载;
(2) create_object_by_type函数最终会调用uvm_object_registry中的虚函数create_object完成类的实例化;
(3) uvm_object_wrapper request_type参数可以使用待实例化类::get_type()函数得到;
1 `define uvm_object_utils(T) \ 2 `uvm_object_utils_begin(T) \ 3 `uvm_object_utils_end 4 5 6 `define uvm_object_utils_begin(T) \ 7 `m_uvm_object_registry_internal(T,T) \ 8 `m_uvm_object_create_func(T) \ 9 `m_uvm_get_type_name_func(T) \ 10 `uvm_field_utils_begin(T) 11 12 13 `define uvm_component_utils(T) \ 14 `m_uvm_component_registry_internal(T,T) \ 15 `m_uvm_get_type_name_func(T) \
1 `define m_uvm_object_registry_internal(T,S) \ 2 typedef uvm_object_registry#(T,`"S`") type_id; \ 3 static function type_id get_type(); \ 4 return type_id::get(); \ 5 endfunction \ 6 virtual function uvm_object_wrapper get_object_type(); \ 7 return type_id::get(); \ 8 endfunction 9 10 `define m_uvm_component_registry_internal(T,S) \ 11 typedef uvm_component_registry #(T,`"S`") type_id; \ 12 static function type_id get_type(); \ 13 return type_id::get(); \ 14 endfunction \ 15 virtual function uvm_object_wrapper get_object_type(); \ 16 return type_id::get(); \ 17 endfunction
2.factory机制例化的几种方式
2.1uvm_factory::create_object_by_name
(1) requested_type_name可以通过待实例化类::get_type_name()得到;
1 //class uvm_default_factory 2 function uvm_object uvm_default_factory::create_object_by_name (string requested_type_name, 3 string parent_inst_path="", 4 string name=""); 5 6 uvm_object_wrapper wrapper; 7 string inst_path; 8 9 if (parent_inst_path == "") 10 inst_path = name; 11 else if (name != "") 12 inst_path = {parent_inst_path,".",name}; 13 else 14 inst_path = parent_inst_path; 15 16 m_override_info.delete(); 17 18 wrapper = find_override_by_name(requested_type_name, inst_path); 19 20 // if no override exists, try to use requested_type_name directly 21 if (wrapper==null) begin 22 if(!m_type_names.exists(requested_type_name)) begin 23 uvm_report_warning("BDTYP",{"Cannot create an object of type '", 24 requested_type_name,"' because it is not registered with the factory."}, UVM_NONE); 25 return null; 26 end 27 wrapper = m_type_names[requested_type_name]; 28 end 29 30 return wrapper.create_object(name); 31 32 endfunction
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 // Function: create_object 6 // 7 // Creates an object of type ~T~ and returns it as a handle to a 8 // <uvm_object>. This is an override of the method in <uvm_object_wrapper>. 9 // It is called by the factory after determining the type of object to create. 10 // You should not call this method directly. Call <create> instead. 11 12 virtual function uvm_object create_object(string name=""); 13 T obj; 14 `ifdef UVM_OBJECT_DO_NOT_NEED_CONSTRUCTOR 15 obj = new(); 16 if (name!="") 17 obj.set_name(name); 18 `else 19 if (name=="") obj = new(); 20 else obj = new(name); 21 `endif 22 return obj; 23 endfunction 24 ... 25 endclass
1 //示例
2 my_transaction tr;
3 void'($cast(tr,factory.create_object_by_name("my_transaction"))); //void'($cast(tr,factory.create_object_by_name(my_transaction::get_type_name())));
2.2. create_object_by_type
1 function uvm_object uvm_default_factory::create_object_by_type (uvm_object_wrapper requested_type, 2 string parent_inst_path="", 3 string name=""); 4 5 string full_inst_path; 6 7 if (parent_inst_path == "") 8 full_inst_path = name; 9 else if (name != "") 10 full_inst_path = {parent_inst_path,".",name}; 11 else 12 full_inst_path = parent_inst_path; 13 14 m_override_info.delete(); 15 16 requested_type = find_override_by_type(requested_type, full_inst_path); 17 18 return requested_type.create_object(name); 19 20 endfunction
1 //示例
2 my_transaction tr;
3 void'($cast(tr,factory.create_object_by_type(my_transaction::get_type())));
2.3. create_component_by_name
1 function uvm_component uvm_default_factory::create_component_by_name (string requested_type_name, 2 string parent_inst_path="", 3 string name, 4 uvm_component parent); 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 a component 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_component(name, parent); 30 31 endfunction
1 class uvm_component_registry #(type T=uvm_component, string Tname="<unknown>") 2 extends uvm_object_wrapper; 3 typedef uvm_component_registry #(T,Tname) this_type; 4 5 6 // Function: create_component 7 // 8 // Creates a component of type T having the provided ~name~ and ~parent~. 9 // This is an override of the method in <uvm_object_wrapper>. It is 10 // called by the factory after determining the type of object to create. 11 // You should not call this method directly. Call <create> instead. 12 13 virtual function uvm_component create_component (string name, 14 uvm_component parent); 15 T obj; 16 obj = new(name, parent); 17 return obj; 18 endfunction 19 ... 20 endclass
1 //示例
2 my_scoreboard scb;
3 void'($cast(scb,factory.create_component_by_name("my_scoreboard",get_full_name(),"scb",this)));
//void'($cast(scb,factory.create_component_by_name(my_scoreboard::get_type_name(),get_full_name(),"scb",this)));
2.4. create_component_by_type
1 function uvm_component uvm_default_factory::create_component_by_type (uvm_object_wrapper requested_type, 2 string parent_inst_path="", 3 string name, 4 uvm_component parent); 5 string full_inst_path; 6 7 if (parent_inst_path == "") 8 full_inst_path = name; 9 else if (name != "") 10 full_inst_path = {parent_inst_path,".",name}; 11 else 12 full_inst_path = parent_inst_path; 13 14 m_override_info.delete(); 15 16 requested_type = find_override_by_type(requested_type, full_inst_path); 17 18 return requested_type.create_component(name, parent); 19 20 endfunction
1 //示例
2 my_scoreboard scb;
3 void'($cast(scb,factory.create_component_by_type(my_scoreboard::get_type(),get_full_name(),"scb",this)));