Jump to content


  • Content Count

  • Joined

  • Last visited

  1. Hi Justin, As promised, I'd like to release the modified uvm_factory.svh file in attachment for your reference. Please search keyword '//CHANGE' for all the changes made. I tested it with some simple test cases for type and instance overrides and it works as the old implementation. May need to be verified more. New data structure of uvm_object_wrapper is as below: uvm_object_wrapper ovrd_type : ultimate overriding type. Initialized to this type. Used to create the object of this type (after no instance override matches). uvm_factory_queue_class inst_override : queue of instance overrides (each override consists of a pair of ovrd_type and full_inst_path). The ovrd_type at which full_inst_path matches with get_full_name() of the object to be created will be used to create that object. uvm_object_wrapper direct_ovrd_type : direct override type, i.e, the overriding type that was set by set_type_override_by_type() or set_type_override_by_name(). Used with affected_types (below) for traversing across type override hierachy (e.g, C overrides B, B overrides A). bit affected_types [uvm_object_wrapper] : types that was overriden by this type. Used with direct_ovrd_type (above) for traversing across type override hierachy (e.g, C overrides B, B overrides A). As explained in previous comment, set_type_override_by_type/name() and set_inst_override_by_type/name() will set the ovrd_type of the requested_type argument. When create_object_by_type/name() is called, the ovrd_type in the object wrapper will be used to create the object handily and least lookup operations needed, as opposed to the old implementation. Since set_type_override_by_name() and set_inst_override_by_name() allow arbitrary (including wildcards) type names (a.k.a, lookup names) which may not have been registered with the factory, a new class is introduced and the 2 new data members below are added into the uvm_default_factory for this purpose. class uvm_factory_lookup_type extends uvm_object_wrapper; function new (); inst_override = new; endfunction virtual function string get_type_name(); return ""; endfunction endclass class uvm_default_factory extends uvm_factory; ... protected uvm_factory_lookup_type m_lookup_type_names[string]; protected uvm_factory_lookup_type m_lookup_type_wildcards[string]; ... endclass Because uvm_factory_lookup_type inherits all the aforementioned data members of uvm_object_wrapper, type and instance overrides which set to a lookup type name is treated just like a normal override setting to a registered type. This makes the implementation cleaner as opposed to the old one where lookup type names and registered type names are mixed together into m_type_names associative array. Finally, there're some notes with the attached uvm_factory.svh file. debug_create_by_type/name() methods are not implemented yet. In old factory implementation, the "override loop" error is checked at run_phase, when the create_object. In new implementation, it is checked when set_type_override_by_type/name() is called, so it may happen in build_phase() and the simulation would be stopped due to "build error" reason. Best Regards, Thien uvm_factory.svh
  2. Hi Justin, Thanks for your reply. I don't have the modified code yet. But I'd like to make my proposal clearer as below. The problems with the factory are: An associative array lookup step needs to be done to retrieve instance override info of requested_type: uvm_factory_queue_class qc; qc = m_inst_override_queues.exists(requested_type) ? m_inst_override_queues[requested_type] : null; Iterate through m_override_info queue to check for override loop. Iterate through m_type_overrides queue to check for type override. Recursive calls of find_override_by_type() for the case of "B overrides A, C overrides B, etc": (in function find_override_by_type) // inst override; return first match; takes precedence over type overrides if (full_inst_path != "" && qc != null) for (int index = 0; index < qc.queue.size(); ++index) begin ... return find_override_by_type(qc.queue[index].ovrd_type,full_inst_path); // type override - exact match foreach (m_type_overrides[index]) begin if (m_type_overrides[index].orig_type == requested_type || ... return find_override_by_type(m_type_overrides[index].ovrd_type,full_inst_path); All above things happen for every creation of a UVM object which uses the factory. So I propose to put type override and instance override information in the type proxy itself (i.e, uvm_object_wrapper), so that we can get the override info directly from requested_type and no more lookup needed. It's responsibility of set_type_override_by_type() to do all the awful stuffs, because this method is called only once for each override setting. The override info inside uvm_object_wrapper should be: ovrd_insts [$]: a queue of {<instance-path>, <override-type>} pairs for instance override. ovrd_type: for type override. Set to this type when the type specialization is created or registered to the factory. affected_types [$]: a queue of types that are overriden by this type. Used like a linked-list pointer for set_type_override_by_type() to traverse in the mentioned case "B overrides A, C overrides B, etc". Pseudo code of set_type_override_by_type (original_type, override_type) is as below: function set_type_override_by_type (original_type, override_type) { __set_type_override_by_type (original_type, override_type); // add original_type into 'affected_types' of override_type override_type.affected_types.push_back(original_type); } function __set_type_override_by_type (original_type, override_type) { original_type.ovrd_type = override_type.ovrd_type; // note: ovrd_type defaults to the container type // until it is overriden. // set override for each affected_type of original_type. // may be recursive for each affected_type child of that affected_type, ... foreach original_type.affected_types[i] { if original_type.affected_types[i] == override_type.ovrd_type error("Override loop detected"); else __set_type_override_by_type(original_type.affected_types[i], override_type.ovrd_type) } } Pseudo code of create_object_by_type (): no more lookup or recursive calls to find the override type. function uvm_object create_object_by_type (uvm_object_wrapper requested_type, string parent_inst_path="", string name); // ... code to make full_inst_path from parent_inst_path, etc as in current uvm-1.2 code // instance override. takes precedence over type override. foreach requested_type.ovrd_insts[i] begin if(uvm_is_match(requested_type.ovrd_insts[i].full_inst_path, full_inst_path)) return requested_type.ovrd_insts[i].ovrd_type.create_object(name); end // type override return requested_type.ovrd_type.create_object(name); endfunction The modification for this point is rather simple, but it may impact other functionalities such as factory.print() and name-based override. So please give me some time to do the modification thoroughly. I'll get back when it's done. Best regards, Thien
  3. Hi, As I read the code in uvm-1.2 package, the type override lookup (by uvm_default_factory::find_override_by_type()) seems to be done every time a new UVM object is created. This really hurts performance because object creation happens most frequently in a UVM environment. My idea is: The implementation needs to be changed so that the type override info is put inside each object proxy, instead of a factory's queue (m_type_overrides). When set_type_override_by_type() is called, it sets the override info for every affected object proxy. So when a new object is created, we just use the override info already available inside its proxy to do creation and no more type override lookup needed. The call of set_type_override_by_type() should happen much much less frequently than object creation, I believe. The override info for each object proxy should have 2 element as below: override: the type that overrides this type override_to[$]: a list containing all types that are overriden by this type. so that when set_type_override_by_type() is called, we can traverse all the affected types regardless of the calling order of multiple calls of set_type_override_by_type(). For example: set_type_override_by_type(): B overrides A set_type_override_by_type(): C overrides B then finally C must override A regardless of 1. or 2. being executed first. Best regards, Thien
  • Create New...