[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

 

 

posted on 2021-10-31 17:07  知北游。。  阅读(253)  评论(0编辑  收藏  举报

导航