[CU]factory机制1-factory机制的功能,本质,使用与调试,原理的反思
1.factory机制的功能
(1) factory机制的典型功能是创建类的实例和重载.
2.factory机制的本质
(1) factory的本质:重载new函数;
(2) uvm_object/uvm_component的派生类在采用factory机制实例化时,会通过factory机制在内部表格中查找是否有相关的重载记录;如果查到有重载记录,会使用新的类型代替旧的类型;
3.factory机制的使用
(1) 在定义一个类时,需要使用uvm_component_utils/uvm_object_utils等宏进行类的注册,才能使用factory机制的功能;
(2) factory机制仅适用于uvm_object及其派生类和uvm_component及其派生类;
[CU]factory机制2-factory机制之用于类注册的宏(factory机制-注册) - __见贤思齐 - 博客园 (cnblogs.com)
[CU]factory机制4-factory机制重载的前提,方式,复杂重载,常用重载(factory机制重载) - __见贤思齐 - 博客园 (cnblogs.com)
4.factory机制的调试
(1) uvm_component.print_override_info
1 function void uvm_component::print_override_info (string requested_type_name, 2 string name=""); 3 uvm_coreservice_t cs = uvm_coreservice_t::get(); 4 uvm_factory factory=cs.get_factory(); 5 factory.debug_create_by_name(requested_type_name, get_full_name(), name); 6 endfunction
注1:print_override_info实质上调用的是uvm_factory的debug_create_by_name;
注2:print_override_info的参数对应的应该是原始的类型,而不是新的类型;
注3:在connect_phase,使用被重载类的句柄调用该函数,如:
1 //my_case0.sv 2 function void my_case0::build_phase(uvm_phase phase); 3 *** 4 set_inst_override_by_type("evn.o_agt.mon",my_monitor::get_type(),new_monitor::get_type()); 5 *** 6 endfunction 7 8 function void my_case0::connect_phase(uvm_phase phase); 9 super.connect_phase(phase); 10 env.o_agt.mon.print_override_info("my_monitor"); 11 *** 12 endfunction
(2) uvm_factory.print()
注1:该函数只有一个参数,其取值可能为0,1或2;
注2:当其参数为0时,仅仅打印被重载的实例和类型;
注3:当其参数为1时,打印参数为0时的信息,以及用户创建的并注册到factory的所有类的名称;
注4:当其参数为2时,打印参数为1时的信息,以及系统创建的并注册到factory的所有类的名称;
注5:uvm_factory::print()应该放置在override语句后面;
(3) uvm_top.print_topology();
注1:该函数没有参数;
注2:该函数显示整颗UVM树的拓扑结构,而UVM树在build_phase执行完成后才完全建立完成,因此该函数需要置于build_phase后的其他phase调用;
注3:该函数通常会置于所有测试用例的基类base_test中;
5.factory机制原理的反思
为什么在factory机制中引入uvm_object_registry #(type T=uvm_object, string Tname=”<unknown>”)以及uvm_component_registry #(type T=uvm_component, string Tname=”<unknown>”)?
(1) factory机制的核心是联合数组-m_type_names,其索引是string类型的,其存储的内容是uvm_object_wrapper类型的;
(2) 在system verilog中,往任何数组或queue中存放内容,存放的通常是值,而不是一个类型;类是一个抽象的概念,不可能存放在一个数组里面;
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 const static string type_name = Tname; 26 27 // Function: get_type_name 28 // 29 // Returns the value given by the string parameter, ~Tname~. This method 30 // overrides the method in <uvm_object_wrapper>. 31 32 virtual function string get_type_name(); 33 return type_name; 34 endfunction 35 36 local static this_type me = get(); 37 38 // Function: get 39 // 40 // Returns the singleton instance of this type. Type-based factory operation 41 // depends on there being a single proxy instance for each registered type. 42 43 static function this_type get(); 44 if (me == null) begin 45 uvm_coreservice_t cs = uvm_coreservice_t::get(); 46 uvm_factory factory=cs.get_factory(); 47 me = new; 48 factory.register(me); 49 end 50 return me; 51 endfunction 52 53 54 // Function: create 55 // 56 // Returns an instance of the object type, ~T~, represented by this proxy, 57 // subject to any factory overrides based on the context provided by the 58 // ~parent~'s full name. The ~contxt~ argument, if supplied, supersedes the 59 // ~parent~'s context. The new instance will have the given leaf ~name~, 60 // if provided. 61 62 static function T create (string name="", uvm_component parent=null, 63 string contxt=""); 64 uvm_object obj; 65 uvm_coreservice_t cs = uvm_coreservice_t::get(); 66 uvm_factory factory=cs.get_factory(); 67 68 if (contxt == "" && parent != null) 69 contxt = parent.get_full_name(); 70 obj = factory.create_object_by_type(get(),contxt,name); 71 if (!$cast(create, obj)) begin 72 string msg; 73 msg = {"Factory did not return an object of type '",type_name, 74 "'. A component of type '",obj == null ? "null" : obj.get_type_name(), 75 "' was returned instead. Name=",name," Parent=", 76 parent==null?"null":parent.get_type_name()," contxt=",contxt}; 77 uvm_report_fatal("FCTTYP", msg, UVM_NONE); 78 end 79 endfunction 80 81 82 // Function: set_type_override 83 // 84 // Configures the factory to create an object of the type represented by 85 // ~override_type~ whenever a request is made to create an object of the type 86 // represented by this proxy, provided no instance override applies. The 87 // original type, ~T~, is typically a super class of the override type. 88 89 static function void set_type_override (uvm_object_wrapper override_type, 90 bit replace=1); 91 uvm_coreservice_t cs = uvm_coreservice_t::get(); 92 uvm_factory factory=cs.get_factory(); 93 factory.set_type_override_by_type(get(),override_type,replace); 94 endfunction 95 96 97 // Function: set_inst_override 98 // 99 // Configures the factory to create an object of the type represented by 100 // ~override_type~ whenever a request is made to create an object of the type 101 // represented by this proxy, with matching instance paths. The original 102 // type, ~T~, is typically a super class of the override type. 103 // 104 // If ~parent~ is not specified, ~inst_path~ is interpreted as an absolute 105 // instance path, which enables instance overrides to be set from outside 106 // component classes. If ~parent~ is specified, ~inst_path~ is interpreted 107 // as being relative to the ~parent~'s hierarchical instance path, i.e. 108 // ~{parent.get_full_name(),".",inst_path}~ is the instance path that is 109 // registered with the override. The ~inst_path~ may contain wildcards for 110 // matching against multiple contexts. 111 112 static function void set_inst_override(uvm_object_wrapper override_type, 113 string inst_path, 114 uvm_component parent=null); 115 string full_inst_path; 116 uvm_coreservice_t cs = uvm_coreservice_t::get(); 117 uvm_factory factory=cs.get_factory(); 118 119 if (parent != null) begin 120 if (inst_path == "") 121 inst_path = parent.get_full_name(); 122 else 123 inst_path = {parent.get_full_name(),".",inst_path}; 124 end 125 factory.set_inst_override_by_type(get(),override_type,inst_path); 126 endfunction 127 128 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 // 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 21 const static string type_name = Tname; 22 23 // Function: get_type_name 24 // 25 // Returns the value given by the string parameter, ~Tname~. This method 26 // overrides the method in <uvm_object_wrapper>. 27 28 virtual function string get_type_name(); 29 return type_name; 30 endfunction 31 32 local static this_type me = get(); 33 34 35 // Function: get 36 // 37 // Returns the singleton instance of this type. Type-based factory operation 38 // depends on there being a single proxy instance for each registered type. 39 40 static function this_type get(); 41 if (me == null) begin 42 uvm_coreservice_t cs = uvm_coreservice_t::get(); 43 uvm_factory factory=cs.get_factory(); 44 me = new; 45 factory.register(me); 46 end 47 return me; 48 endfunction 49 50 51 // Function: create 52 // 53 // Returns an instance of the component type, ~T~, represented by this proxy, 54 // subject to any factory overrides based on the context provided by the 55 // ~parent~'s full name. The ~contxt~ argument, if supplied, supersedes the 56 // ~parent~'s context. The new instance will have the given leaf ~name~ 57 // and ~parent~. 58 59 static function T create(string name, uvm_component parent, string contxt=""); 60 uvm_object obj; 61 uvm_coreservice_t cs = uvm_coreservice_t::get(); 62 uvm_factory factory=cs.get_factory(); 63 if (contxt == "" && parent != null) 64 contxt = parent.get_full_name(); 65 obj = factory.create_component_by_type(get(),contxt,name,parent); 66 if (!$cast(create, obj)) begin 67 string msg; 68 msg = {"Factory did not return a component of type '",type_name, 69 "'. A component of type '",obj == null ? "null" : obj.get_type_name(), 70 "' was returned instead. Name=",name," Parent=", 71 parent==null?"null":parent.get_type_name()," contxt=",contxt}; 72 uvm_report_fatal("FCTTYP", msg, UVM_NONE); 73 end 74 endfunction 75 76 77 // Function: set_type_override 78 // 79 // Configures the factory to create an object of the type represented by 80 // ~override_type~ whenever a request is made to create an object of the type, 81 // ~T~, represented by this proxy, provided no instance override applies. The 82 // original type, ~T~, is typically a super class of the override type. 83 84 static function void set_type_override (uvm_object_wrapper override_type, 85 bit replace=1); 86 uvm_coreservice_t cs = uvm_coreservice_t::get(); 87 uvm_factory factory=cs.get_factory(); 88 factory.set_type_override_by_type(get(),override_type,replace); 89 endfunction 90 91 92 // Function: set_inst_override 93 // 94 // Configures the factory to create a component of the type represented by 95 // ~override_type~ whenever a request is made to create an object of the type, 96 // ~T~, represented by this proxy, with matching instance paths. The original 97 // type, ~T~, is typically a super class of the override type. 98 // 99 // If ~parent~ is not specified, ~inst_path~ is interpreted as an absolute 100 // instance path, which enables instance overrides to be set from outside 101 // component classes. If ~parent~ is specified, ~inst_path~ is interpreted 102 // as being relative to the ~parent~'s hierarchical instance path, i.e. 103 // ~{parent.get_full_name(),".",inst_path}~ is the instance path that is 104 // registered with the override. The ~inst_path~ may contain wildcards for 105 // matching against multiple contexts. 106 107 static function void set_inst_override(uvm_object_wrapper override_type, 108 string inst_path, 109 uvm_component parent=null); 110 string full_inst_path; 111 uvm_coreservice_t cs = uvm_coreservice_t::get(); 112 uvm_factory factory=cs.get_factory(); 113 114 if (parent != null) begin 115 if (inst_path == "") 116 inst_path = parent.get_full_name(); 117 else 118 inst_path = {parent.get_full_name(),".",inst_path}; 119 end 120 factory.set_inst_override_by_type(get(),override_type,inst_path); 121 endfunction 122 123 endclass