[CU]factory机制6-factory机制重载的原理
1.factory机制的重载功能
(1)在实例化时,UVM会通过factory机制在内部的一张表格中查看是否有相关的重载记录. 当查到有重载记录时,会使用新的类型代替旧的类型.
(2)通常会在env或者具体的case中使用override功能;
1 class case_x extends base_test;
2 function void build_phase(uvm_phase phase);
3 ...
4 set_type_override_by_type(my_driver::get_type(),new_driver::get_type());
5 endfunction
6 endclass
2.用于override功能的数据结构
1 class uvm_default_factory extends uvm_factory;
2 ...
3 protected uvm_factory_override m_type_overrides[$];
4
5 protected uvm_factory_queue_class m_inst_override_queues[uvm_object_wrapper];
6 protected uvm_factory_queue_class m_inst_override_name_queues[string];
7 protected uvm_factory_override m_wildcard_inst_overrides[$];
8
9 local uvm_factory_override m_override_info[$];
10 ...
11 endclass
2.1.uvm_factory_override
(1) uvm_factory_override是专门用于组织factory中override信息的一个类;
(2) uvm_factory_override中记录了原始类型的名字, 原始类型, override类型的名字, override类型以及full_inst_path信息; 其中,full_inst_path用于存储被override的uvm_component的路径信息;
1 class uvm_factory_override;
2 string full_inst_path;
3 string orig_type_name;
4 string ovrd_type_name;
5 bit selected;
6 int unsigned used;
7 uvm_object_wrapper orig_type;
8 uvm_object_wrapper ovrd_type;
9 function new (string full_inst_path="",
10 string orig_type_name="",
11 uvm_object_wrapper orig_type=null,
12 uvm_object_wrapper ovrd_type);
13 if (ovrd_type == null) begin
14 uvm_report_fatal ("NULLWR", "Attempting to register a null override object with the factory", UVM_NONE);
15 end
16 this.full_inst_path= full_inst_path;
17 this.orig_type_name = orig_type == null ? orig_type_name : orig_type.get_type_name();
18 this.orig_type = orig_type;
19 this.ovrd_type_name = ovrd_type.get_type_name();
20 this.ovrd_type = ovrd_type;
21 endfunction
22 endclass
3. set_type_overide_by_type(其他override函数类似)
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 function void uvm_default_factory::set_type_override_by_type (uvm_object_wrapper original_type,
2 uvm_object_wrapper override_type,
3 bit replace=1);
4 bit replaced;
5
6 // check that old and new are not the same
7 if (original_type == override_type) begin
8 if (original_type.get_type_name() == "" || original_type.get_type_name() == "<unknown>")
9 uvm_report_warning("TYPDUP", {"Original and override type ",
10 "arguments are identical"}, UVM_NONE);
11 else
12 uvm_report_warning("TYPDUP", {"Original and override type ",
13 "arguments are identical: ",
14 original_type.get_type_name()}, UVM_NONE);
15 end
16
17 // register the types if not already done so, for the benefit of string-based lookup
18 if (!m_types.exists(original_type))
19 register(original_type);
20
21 if (!m_types.exists(override_type))
22 register(override_type);
23
24
25 // check for existing type override
26 foreach (m_type_overrides[index]) begin
27 if (m_type_overrides[index].orig_type == original_type ||
28 (m_type_overrides[index].orig_type_name != "<unknown>" &&
29 m_type_overrides[index].orig_type_name != "" &&
30 m_type_overrides[index].orig_type_name == original_type.get_type_name())) begin
31 string msg;
32 msg = {"Original object type '",original_type.get_type_name(),
33 "' already registered to produce '",
34 m_type_overrides[index].ovrd_type_name,"'"};
35 if (!replace) begin
36 msg = {msg, ". Set 'replace' argument to replace the existing entry."};
37 uvm_report_info("TPREGD", msg, UVM_MEDIUM);
38 return;
39 end
40 msg = {msg, ". Replacing with override to produce type '",
41 override_type.get_type_name(),"'."};
42 uvm_report_info("TPREGR", msg, UVM_MEDIUM);
43 replaced = 1;
44 m_type_overrides[index].orig_type = original_type;
45 m_type_overrides[index].orig_type_name = original_type.get_type_name();
46 m_type_overrides[index].ovrd_type = override_type;
47 m_type_overrides[index].ovrd_type_name = override_type.get_type_name();
48 end
49 end
50
51 // make a new entry
52 if (!replaced) begin
53 uvm_factory_override override;
54 override = new(.orig_type(original_type),
55 .orig_type_name(original_type.get_type_name()),
56 .full_inst_path("*"),
57 .ovrd_type(override_type));
58
59 m_type_overrides.push_back(override);
60 end
61
62 endfunction
(1) foreach语句块用于查看系统中已有的override信息;
(2) if(!replaced)语句块用于向m_type_overrides队列中插入一条记录;
(3)对于下面code而言, original_type是uvm_component_registry#(my_driver, “my_driver”)中的静态成员变量me; override_type是uvm_component_registry#(new_driver, “new_driver”)中的那个静态成员变量me;
1 1 class case_x extends base_test; 2 2 function void build_phase(uvm_phase phase); 3 3 ... 4 4 set_type_override_by_type(my_driver::get_type(),new_driver::get_type()); 5 5 endfunction 6 6 endclass
3. 类型被override时实例的创建
假设在case里调用了override系列函数-set_type_override_by_type (my_driver::get_type(), new_driver::get_type()),当用drv=my_driver::type_id::create(“drv”,this)实例化时,具体过程如下:
3.1. create函数
1 static function T create(string name, uvm_component parent, string contxt=""); 2 uvm_object obj; 3 uvm_coreservice_t cs = uvm_coreservice_t::get(); 4 uvm_factory factory=cs.get_factory(); 5 if (contxt == "" && parent != null) 6 contxt = parent.get_full_name(); 7 obj = factory.create_component_by_type(get(),contxt,name,parent); 8 if (!$cast(create, obj)) begin 9 string msg; 10 msg = {"Factory did not return a component of type '",type_name, 11 "'. A component of type '",obj == null ? "null" : obj.get_type_name(), 12 "' was returned instead. Name=",name," Parent=", 13 parent==null?"null":parent.get_type_name()," contxt=",contxt}; 14 uvm_report_fatal("FCTTYP", msg, UVM_NONE); 15 end 16 endfunction
3.2. 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