• uvm_factory——我们的工厂(二)


    上节我们说到uvm_object_registry #(T),uvm_object_reistry 又继承自uvm_object_wrapper,所以首先,让我们先看看它爹是啥样子的:

    //------------------------------------------------------------------------------
    //
    // CLASS: uvm_object_wrapper
    //
    // The uvm_object_wrapper provides an abstract interface for creating object and
    // component proxies. Instances of these lightweight proxies, representing every
    // <uvm_object>-based and <uvm_component>-based object available in the test
    // environment, are registered with the <uvm_factory>. When the factory is
    // called upon to create an object or component, it finds and delegates the
    // request to the appropriate proxy.
    //
    //------------------------------------------------------------------------------
    
    virtual class uvm_object_wrapper;
    
      // Function: create_object
      //
      // Creates a new object with the optional ~name~.
      // An object proxy (e.g., <uvm_object_registry #(T,Tname)>) implements this
      // method to create an object of a specific type, T.
    
      virtual function uvm_object create_object (string name="");
        return null;
      endfunction
    
    
      // Function: create_component
      //
      // Creates a new component, passing to its constructor the given ~name~ and
      // ~parent~. A component proxy (e.g. <uvm_component_registry #(T,Tname)>)
      // implements this method to create a component of a specific type, T.
    
      virtual function uvm_component create_component (string name, 
                                                       uvm_component parent); 
        return null;
      endfunction
    
    
      // Function: get_type_name
      // 
      // Derived classes implement this method to return the type name of the object
      // created by <create_component> or <create_object>. The factory uses this
      // name when matching against the requested type in name-based lookups.
    
      pure virtual function string get_type_name();
    
    endclass

    从代码注释来看,都是虚类,这只是轻量级的代理proxy, 它只负责搭台,具体实现让子类去实现,也就是所在uvm中create class,无非就两种uvm_object 和uvm_componet. 它只有这两个儿子,古人云:儿孙自有儿孙福,莫为儿孙做远忧。所以,具体的实现还是让我们进一步去看uvm_object_registry(uvm_register.svh中).

    首先来看用法:

    // Group: Usage
    //
    // This section describes usage for the uvm_*_registry classes.
    //
    // The wrapper classes are used to register lightweight proxies of objects and
    // components.
    //
    // To register a particular component type, you need only typedef a
    // specialization of its proxy class, which is typically done inside the class.
    //
    // For example, to register a UVM component of type ~mycomp~
    //
    //|  class mycomp extends uvm_component;
    //|    typedef uvm_component_registry #(mycomp,"mycomp") type_id;
    //|  endclass
    //
    // However, because of differences between simulators, it is necessary to use a
    // macro to ensure vendor interoperability with factory registration. To
    // register a UVM component of type ~mycomp~ in a vendor-independent way, you
    // would write instead:
    //
    //|  class mycomp extends uvm_component;
    //|    `uvm_component_utils(mycomp);
    //|    ...
    //|  endclass
    //
    // The <`uvm_component_utils> macro is for non-parameterized classes. In this
    // example, the typedef underlying the macro specifies the ~Tname~
    // parameter as "mycomp", and ~mycomp~'s get_type_name() is defined to return 
    // the same. With ~Tname~ defined, you can use the factory's name-based methods to
    // set overrides and create objects and components of non-parameterized types.
    //
    // For parameterized types, the type name changes with each specialization, so
    // you cannot specify a ~Tname~ inside a parameterized class and get the behavior
    // you want; the same type name string would be registered for all
    // specializations of the class! (The factory would produce warnings for each
    // specialization beyond the first.) To avoid the warnings and simulator
    // interoperability issues with parameterized classes, you must register
    // parameterized classes with a different macro.
    //
    // For example, to register a UVM component of type driver #(T), you
    // would write:
    //
    //|  class driver #(type T=int) extends uvm_component;
    //|    `uvm_component_param_utils(driver #(T));
    //|    ...
    //|  endclass
    //
    // The <`uvm_component_param_utils> and <`uvm_object_param_utils> macros are used
    // to register parameterized classes with the factory. Unlike the non-param
    // versions, these macros do not specify the ~Tname~ parameter in the underlying
    // uvm_component_registry typedef, and they do not define the get_type_name
    // method for the user class. Consequently, you will not be able to use the
    // factory's name-based methods for parameterized classes.
    //
    // The primary purpose for adding the factory's type-based methods was to
    // accommodate registration of parameterized types and eliminate the many sources
    // of errors associated with string-based factory usage. Thus, use of name-based
    // lookup in <uvm_factory> is no longer recommended.

    uvm_object_register的定义如下:

    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;

    type::id::create()

      // Function: create
      //
      // Returns an instance of the object type, ~T~, represented by this proxy,
      // subject to any factory overrides based on the context provided by the
      // ~parent~'s full name. The ~contxt~ argument, if supplied, supersedes the
      // ~parent~'s context. The new instance will have the given leaf ~name~,
      // if provided.
    
      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

    create() 调用factory.create_object_by_type()函数,该函数又调用create_object()

    // 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

    所以tpye::id::create()本质上就是调用该class的new()函数。

  • 相关阅读:
    写给大数据开发初学者的话 | 附教程
    Mysql 到 Hbase 数据如何实时同步,强大的 Streamsets 告诉你
    如何学习大数据?阿里大数据开发师分享学习知识
    最简大数据Spark2.1.0
    从技术 Leader 的招聘需求看,如何转岗为当前紧缺的大数据相关人才?
    Redis内核原理及读写一致企业级架构深入剖析1综合组件环境实战
    为什么85%的大数据项目总是失败?
    js中的this关键字
    php百度api调用简单实例
    nginx常用命令
  • 原文地址:https://www.cnblogs.com/dpc525/p/7865807.html
Copyright © 2020-2023  润新知