• UVM-1.1学习(三)——`uvm_object_utils的本质


    在UVM中,我们经常使用`uvm_object_utils或者`uvm_component_utils来将uvm_object/uvm_component注册,但很多同学并不清楚注册是怎么实现的,因此本文主要分析下`uvm_object_utils的注册究竟做了什么。

    1 `uvm_object_utils(T)的展开

    `uvm_object_utils本质上是一个宏,这个宏由另外两个宏`xxx_begin、`xxx_end组成,而`xxx_begin又是由几段功能宏组成:

    `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 uvm_object_utils_end \
         end \
       endfunction \
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2 `uvm_object_utils_begin(T)的子内容

    2.1 `m_uvm_object_registry_internal(T,T)

    先看代码:

    //This is needed due to an issue in of passing down strings
    //created by args to lower level macros.
    `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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这个宏里面只做了两件事情:

    • 定义了一个参数化的类,这个参数化的类叫type_id;
    • 给class定义了两个函数,get_type()函数与get_object_type()函数。

    粗略一看,这两件事情好像和uvm_object的注册没有什么关系,其实不然。对于参数化的类type_id,我们可以把它抽象成一个简单的哈希(key-value,type_id的名字也是由此而来)。由于这些宏的参数实际上就是类名T。所以它的key-value就是uvm_object的类名(class name)和类的名称(string)。随着这个宏的展开,我们相当于给class额外定义了两个函数:get_type()和get_object_type()。由于uvm_object_registry #(T,“S”)是一个singletone的class,所以get_type()和get_object_type()的函数内容一样,区别在于返回值的句柄不同。对于get_type(),返回的是type_id的句柄;对于get_object_type(),返回uvm_object_wrapper的句柄。
    这里面还有一个细节,我们在上一层传递的宏参数是(T, T),但实际使用时第二个参数是被当作字符串来进行使用的。因此使用了`"S`"这样的语法。

    2.1.1 uvm_object_registry(T, S)

    上文中的type_id实际上是参数化的类,两个参数可以看成是哈希的key-value。在这个参数化的类的get()函数中,通过uvm_factory的register函数将它自己注册,或者说将这个哈希放到一个全局的登记表格中去了。
    顺带一提另一个经常看见的函数create()。它的作用也很简单,即根据给定名字(string),在全局的登记表格中查找匹配的句柄,并利用该句柄来创建一个新的实例。
    下面是摘自UVM的部分源代码:

    class uvm_object_registry #(type T=uvm_object, string Tname="")
                                            extends uvm_object_wrapper;
      typedef uvm_object_registry #(T,Tname) this_type;
      ...
        local static this_type me = get();
    
      // Function: get
      //
      // Returns the singleton instance of this type. Type-based factory operation
      // depends on there being a single proxy instance for each registered type. 
      static function this_type get();
        if (me == null) begin
          uvm_factory f = uvm_factory::get();
          
          me = new;
          f.register(me);
        end
        return me;
      endfunction
      ...
      // 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, supercedes 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_factory f = uvm_factory::get();
        if (contxt == "" && parent != null)
          contxt = parent.get_full_name();
        obj = f.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
      ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    uvm_object_registry比较有意思的是它利用了static method和get()函数结合,实现了singleton的效果。

    2.2 `m_uvm_object_create_func(T)

    这个宏里面完成的事情很简单,只是给class定义了create()函数。

    `define m_uvm_object_create_func(T) \
       `ifdef UVM_CREATE_OPT \
            virtual function void call_new(); \
            endfunction \
       `else \
        function uvm_object create (string name=""); \
            T tmp; \
           `ifdef UVM_OBJECT_MUST_HAVE_CONSTRUCTOR \
              if (name=="") tmp = new(); \
              else tmp = new(name); \
           `else \
              tmp = new(); \
              if (name!="") \
                tmp.set_name(name); \
           `endif \
           return tmp; \
        endfunction \
       `endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    至此,我们有了两种方式来创建uvm_object:

     - user_object.create("user_object");
     - user_object::type_id::create("user_object");
    
    • 1
    • 2

    注意第一种方式实际上只是new()的另一种写法而已。

    2.3 `m_uvm_get_type_name_func(T)

    这个宏里面完成的事情同样也很简单,只是给class定义了type_name变量和get_type_name()函数。

    `define m_uvm_get_type_name_func(T) \
       const static string type_name = `"T`"; \
       virtual function string get_type_name (); \
         return type_name; \
       endfunction
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.4 `uvm_field_utils_begin(T)

    这里面是和field automation相关的一些代码,这里就不展开进行说明了。

  • 相关阅读:
    软件测试学习(一)基础概念、实质、说明书测试、分类、动态黑盒测试
    css过渡属性的简单使用
    滴滴秋招提前批正式开始,现在投递免笔试
    外汇天眼:2022 年世界杯已经开始,但这将如何影响外汇交易?
    内网渗透系列之真实内网环境搭建
    Docker 哲学 - 容器操作 -cp
    Linux 安全 - Capabilities机制
    【小程序项目开发--京东商城】uni-app之自定义搜索组件(上)-- 组件UI
    LabVIEW使用ZigBee无线传感器开发住宅负载电力应用
    学习Python中turtle模块的基本用法(2:基本绘图函数测试)
  • 原文地址:https://blog.csdn.net/kevindas/article/details/124415319