UVM factory 的理解

通常情况下我们会使用factory机制如下:(这里我们以object为例,component的原理是类似的)

class my_seq extends uvm_seqeuence_item;
  `uvm_object_utils(my_seq)
...
endclass:my_seq

然后我们就可以create:

class my_test extends uvm_test;
  ...
  task main_phase(uvm_phase phase);
  my_seq seq0;
  seq0 = my_seq::type_id::create("seq0");
  endtask:main_phase
endclass:my_test

为什么create就可以直接生成seq0这个object呢? sv中只有new的方式可以生成新的object

其背后的操作如下:

`define uvm_object_utils(T) \
  `uvm_object_utils_begin(T) \
  `uvm_object_utils_end
===================================================
`define uvm_object_utils_begin(T) \
   `m_uvm_object_registry_internal(T,T)  \
   `m_uvm_object_create_func(T) \
   `m_uvm_get_type_name_func(T) \
   `uvm_field_utils_begin(T) 
===================================================
`define m_uvm_object_registry_internal(T,S) \
   typedef uvm_object_registry#(T,`"S`") type_id; \
   static function type_id get_type(); \
     return type_id::get(); \
   endfunction \
   virtual function uvm_object_wrapper get_object_type(); \
     return type_id::get(); \
   endfunction 

line1-> lines2->line6->line12,注意line12中的type_id, 其实际上是一个参数类:

uvm_object_registry#(T, `"S`")

那么我们定义的`uvm_object_utils(my_seq),在背后的代码中体现为(这里只说明uvm如何认识我们定义的新的class: my_seq)

type_def uvm_object_regsitery#(my_seq,"my_seq") type_id

同时声明了一个以my_seq作为class 和class-name作为为参数的类成员:type_id

而uvm_object_register这个参数类的定义如下,其中定义了static 函数成员create,get:

class uvm_object_registry #(type T=uvm_object, string Tname="<unknown>")
                                        extends uvm_object_wrapper;
  typedef uvm_object_registry #(T,Tname) this_type;
。。。
  static function this_type get();
    if (me == null) begin
      uvm_coreservice_t cs = uvm_coreservice_t::get();                                                     
      uvm_factory factory=cs.get_factory();
      me = new;
      factory.register(me);
    end
    return me;
  endfunction
...
  static function T create (string name="", uvm_component parent=null,
                            string contxt="");
    uvm_object obj;
    uvm_coreservice_t cs = uvm_coreservice_t::get();                                                     
    uvm_factory factory=cs.get_factory();
  
    if (contxt == "" && parent != null)
      contxt = parent.get_full_name();
    obj = factory.create_object_by_type(get(),contxt,name);
    if (!$cast(create, obj)) begin
      string msg;
      msg = {"Factory did not return an object of type '",type_name,
        "'. A component of type '",obj == null ? "null" : obj.get_type_name(),
        "' was returned instead. Name=",name," Parent=",
        parent==null?"null":parent.get_type_name()," contxt=",contxt};
      uvm_report_fatal("FCTTYP", msg, UVM_NONE);
    end
  endfunction

注意其中的第23行,

obj = factory.create_object_by_type(get(),contxt,name);(方便引用,记为--1--)

其中,

  1. get()中包含两个操作:

1.1. new me(即为object);

1.2. factory.register(me);

factory的register操作的定义如下:

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

注意其中的第12行,会把obj和get_type_name()作为key-value存入关联数组m_type_names中。

而--1--的create_object_by_type的定义如下

function uvm_object uvm_default_factory::create_object_by_type (uvm_object_wrapper requested_type,  
                                                        string parent_inst_path="",  
                                                        string name=""); 

  string full_inst_path;

  if (parent_inst_path == "")
    full_inst_path = name;
  else if (name != "")
    full_inst_path = {parent_inst_path,".",name};
  else
    full_inst_path = parent_inst_path;

  m_override_info.delete();

  requested_type = find_override_by_type(requested_type, full_inst_path);

  return requested_type.create_object(name);

endfunction

这里第18行,还是调用create_object,不过这个函数应该是隶属于requested_type的成员,requested_type即为我们所指定的type_id,(即uvm_object_registry),故其最终调用的是

class uvm_object_registry #(type T=uvm_object, string Tname="<unknown>")
                                        extends uvm_object_wrapper;
  typedef uvm_object_registry #(T,Tname) this_type;

  // Function: create_object
  //
  // Creates an object of type ~T~ and returns it as a handle to a
  // <uvm_object>. This is an override of the method in <uvm_object_wrapper>.
  // It is called by the factory after determining the type of object to create.
  // You should not call this method directly. Call <create> instead.

  virtual function uvm_object create_object(string name="");
    T obj;
`ifdef UVM_OBJECT_DO_NOT_NEED_CONSTRUCTOR
    obj = new();
    if (name!="")
      obj.set_name(name);
`else
    if (name=="") obj = new();
    else obj = new(name);
`endif
    return obj;
  endfunction

  const static string type_name = Tname;
。。。
endclass

其中地15行 最终new 产生了所需要的seq0.

其完整的调用逻辑如下

完毕

此处提出一个疑问, 如上图所示,uvm好像调用了两次new,是否多余了呢?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UVM (Universal Verification Methodology) is a widely used methodology for verifying integrated circuit designs. The UVM factory is a key component of the UVM framework, responsible for creating and managing objects dynamically. To create an object using the UVM factory, you need to follow these steps: 1. Define a base class for your object. This class should inherit from `uvm_object` or any of its derived classes, such as `uvm_component`, `uvm_sequence`, etc. 2. Register your class with the UVM factory. This step ensures that the factory is aware of your class and can create objects of that type. You can register your class using the `uvm_component_utils` macro or the `uvm_object_utils` macro, depending on the base class you are inheriting from. 3. Use the `create()` method of the UVM factory to create an instance of your object. Pass the class type as an argument to the `create()` method, and it will return a pointer to a newly created object. Here's an example of how you can create an object using the UVM factory: ```systemverilog class MyObject extends uvm_object; // ... endclass // Register MyObject with the UVM factory `uvm_object_utils(MyObject) // Create an instance of MyObject MyObject myObj = MyObject::type_id::create("myObj"); ``` In this example, the `MyObject` class is registered with the UVM factory using the `uvm_object_utils` macro. Then, the `create()` method is used to create an instance of `MyObject` and assign it to the `myObj` variable. I hope this helps! Let me know if you have any further questions.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值