跳转至

输入查询内容

    本页内容

    新增 config_db / resource_db implementation 类,DB 行为可工厂级替换

    新增功能:目标库新增的 API 和可选替代接口;已有用法的迁移要求列在用户接口与行为中。

    影响范围

    派生 config_db/resource_db implementation 或替换资源池。

    具体差异

    config_db 的 get/set/exists/wait_modified 等外观接口委托 implementation 实例,可经 set_imp() 或 factory override 定制(@uvm-contrib)。trigger_modified(inst_name, field_name) 是 implementation 类的方法,不能直接写为 uvm_config_db#(T)::trigger_modified(...)。接口保留不代表所有资源查询行为等价,优先级、入池和单侧 override 变化见 M05-003/004/005/010。

    修改方案

    常规 config_db 外观调用可保留;定制实现需覆盖既有 get/set/wait_modified 契约,并回归资源查找路径。

    兼容措施与范围:本条是新增能力或实现说明,无需恢复旧接口;按使用条件核对行为。

    迁移后验证

    对 set/get/exists/wait_modified 分别运行受控用例,检查选中值和通知次数;默认实现结果不能证明定制实现等价。

    补充查阅

    扫描定位与记录结果

    无对应规则。当前脚本没有针对本条的直接检测规则。

    本条处理级别为“可选采用”,按修改方案评估;缺少扫描规则本身不增加迁移改造要求。

    扫描器下载、输入范围与报告说明

    源码与标准依据

    核查方式:源码核对。未单独进行 VCS 行为实测。

    VCS 内置 UVM-1.2:无(1.2 逻辑内联于 uvm_config_db.svh:89–298uvm_resource_db.svh:54–329

    VCS 内置 uvm-ieee-2020-2.0uvm_config_db_implementation.svh:44(uvm_config_db_implementation_t)、uvm_config_db_implementation.svh:152(uvm_config_db_default_implementation_t);uvm_resource_db_implementation.svh:30(uvm_resource_db_implementation_t)、uvm_resource_db_implementation.svh:194(uvm_resource_db_default_implementation_t)

    引用代码(高亮为引用行);上方行号链接可直接定位。

    src/vcs-uvm-1.2/base/uvm_config_db.svh
      //| get_config_string(...) => uvm_config_db#(string)::get(cntxt,...)
      //| get_config_object(...) => uvm_config_db#(uvm_object)::get(cntxt,...)
    
      static function bit get(uvm_component cntxt,
                              string inst_name,
                              string field_name,
                              inout T value);
    //TBD: add file/line
        int unsigned p;
        uvm_resource#(T) r, rt;
        uvm_resource_pool rp = uvm_resource_pool::get();
        uvm_resource_types::rsrc_q_t rq;
        uvm_coreservice_t cs = uvm_coreservice_t::get();
    
        if(cntxt == null) 
          cntxt = cs.get_root();
        if(inst_name == "") 
          inst_name = cntxt.get_full_name();
        else if(cntxt.get_full_name() != "") 
          inst_name = {cntxt.get_full_name(), ".", inst_name};
    
        rq = rp.lookup_regex_names(inst_name, field_name, uvm_resource#(T)::get_type());
        r = uvm_resource#(T)::get_highest_precedence(rq);
    
        if(uvm_config_db_options::is_tracing())
          m_show_msg("CFGDB/GET", "Configuration","read", inst_name, field_name, cntxt, r);
    
        if(r == null)
          return 0;
    
        value = r.read(cntxt);
    
        return 1;
      endfunction
    
      // function: set 
      //
      // Create a new or update an existing configuration setting for
      // ~field_name~ in ~inst_name~ from ~cntxt~.
      // The setting is made at ~cntxt~, with the full scope of the set 
      // being {~cntxt~,".",~inst_name~}. If ~cntxt~ is ~null~ then ~inst_name~
      // provides the complete scope information of the setting.
      // ~field_name~ is the target field. Both ~inst_name~ and ~field_name~
      // may be glob style or regular expression style expressions.
      //
      // If a setting is made at build time, the ~cntxt~ hierarchy is
      // used to determine the setting's precedence in the database.
      // Settings from hierarchically higher levels have higher
      // precedence. Settings from the same level of hierarchy have
      // a last setting wins semantic. A precedence setting of 
      // <uvm_resource_base::default_precedence>  is used for uvm_top, and 
      // each hierarchical level below the top is decremented by 1.
      //
      // After build time, all settings use the default precedence and thus
      // have a last wins semantic. So, if at run time, a low level 
      // component makes a runtime setting of some field, that setting 
      // will have precedence over a setting from the test level that was 
      // made earlier in the simulation.
      //
      // The basic ~set_config_*~ methods from <uvm_component> are mapped to
      // this function as:
      //
      //| set_config_int(...) => uvm_config_db#(uvm_bitstream_t)::set(cntxt,...)
      //| set_config_string(...) => uvm_config_db#(string)::set(cntxt,...)
      //| set_config_object(...) => uvm_config_db#(uvm_object)::set(cntxt,...)
    
      static function void set(uvm_component cntxt,
                               string inst_name,
                               string field_name,
                               T value);
    
        uvm_root top;
        uvm_phase curr_phase;
        uvm_resource#(T) r;
        bit exists;
        string lookup;
        uvm_pool#(string,uvm_resource#(T)) pool;
        string rstate;
        uvm_coreservice_t cs = uvm_coreservice_t::get();
    
        //take care of random stability during allocation
        process p = process::self();
        if(p != null) 
            rstate = p.get_randstate();
    
        top = cs.get_root();
    
        curr_phase = top.m_current_phase;
    
        if(cntxt == null) 
          cntxt = top;
        if(inst_name == "") 
          inst_name = cntxt.get_full_name();
        else if(cntxt.get_full_name() != "") 
          inst_name = {cntxt.get_full_name(), ".", inst_name};
    
        if(!m_rsc.exists(cntxt)) begin
          m_rsc[cntxt] = new;
        end
        pool = m_rsc[cntxt];
    
        // Insert the token in the middle to prevent cache
        // oddities like i=foobar,f=xyz and i=foo,f=barxyz.
        // Can't just use '.', because '.' isn't illegal
        // in field names
        lookup = {inst_name, "__M_UVM__", field_name};
    
        if(!pool.exists(lookup)) begin
           r = new(field_name, inst_name);
           pool.add(lookup, r);
        end
        else begin
          r = pool.get(lookup);
          exists = 1;
        end
    
        if(curr_phase != null && curr_phase.get_name() == "build")
          r.precedence = uvm_resource_base::default_precedence - (cntxt.get_depth());
        else
          r.precedence = uvm_resource_base::default_precedence;
    
        r.write(value, cntxt);
    
        if(exists) begin
          uvm_resource_pool rp = uvm_resource_pool::get();
          rp.set_priority_name(r, uvm_resource_types::PRI_HIGH);
        end
        else begin
          //Doesn't exist yet, so put it in resource db at the head.
          r.set_override();
        end
    
        //trigger any waiters
        if(m_waiters.exists(field_name)) begin
          m_uvm_waiter w;
          for(int i=0; i<m_waiters[field_name].size(); ++i) begin
            w = m_waiters[field_name].get(i);
            if(uvm_re_match(uvm_glob_to_re(inst_name),w.inst_name) == 0)
               ->w.trigger;  
          end
        end
    
        if(p != null)
            p.set_randstate(rstate);
    
        if(uvm_config_db_options::is_tracing())
          m_show_msg("CFGDB/SET", "Configuration","set", inst_name, field_name, cntxt, r);
      endfunction
    
    
      // function: exists
      //
      // Check if a value for ~field_name~ is available in ~inst_name~, using
      // component ~cntxt~ as the starting search point. ~inst_name~ is an explicit
      // instance name relative to ~cntxt~ and may be an empty string if the
      // ~cntxt~ is the instance that the configuration object applies to.
      // ~field_name~ is the specific field in the scope that is being searched for.
      // The ~spell_chk~ arg can be set to 1 to turn spell checking on if it
      // is expected that the field should exist in the database. The function
      // returns 1 if a config parameter exists and 0 if it doesn't exist.
      //
    
      static function bit exists(uvm_component cntxt, string inst_name,
        string field_name, bit spell_chk=0);
        uvm_coreservice_t cs = uvm_coreservice_t::get();
    
        if(cntxt == null)
          cntxt = cs.get_root();
        if(inst_name == "")
          inst_name = cntxt.get_full_name();
        else if(cntxt.get_full_name() != "")
          inst_name = {cntxt.get_full_name(), ".", inst_name};
    
        return (uvm_resource_db#(T)::get_by_name(inst_name,field_name,spell_chk) != null);
      endfunction
    
    
      // Function: wait_modified
      //
      // Wait for a configuration setting to be set for ~field_name~
      // in ~cntxt~ and ~inst_name~. The task blocks until a new configuration
      // setting is applied that effects the specified field.
    
      static task wait_modified(uvm_component cntxt, string inst_name,
          string field_name);
        process p = process::self();
        string rstate = p.get_randstate();
        m_uvm_waiter waiter;
        uvm_coreservice_t cs = uvm_coreservice_t::get();
    
        if(cntxt == null)
          cntxt = cs.get_root();
        if(cntxt != cs.get_root()) begin
          if(inst_name != "")
            inst_name = {cntxt.get_full_name(),".",inst_name};
          else
            inst_name = cntxt.get_full_name();
        end
    
        waiter = new(inst_name, field_name);
    
        if(!m_waiters.exists(field_name))
          m_waiters[field_name] = new;
        m_waiters[field_name].push_back(waiter);
    
        p.set_randstate(rstate);
    
        // wait on the waiter to trigger
        @waiter.trigger;
    
        // Remove the waiter from the waiter list 
        for(int i=0; i<m_waiters[field_name].size(); ++i) begin
          if(m_waiters[field_name].get(i) == waiter) begin
    

    完整源码 · SHA256:8c3f79dad00da1cb7514f4c77072e39de74ae23cbb9ead18a83de04bcd0c8070

    src/vcs-uvm-1.2/base/uvm_resource_db.svh
    // resource operations.
    //
    //----------------------------------------------------------------------
    class uvm_resource_db #(type T=uvm_object);
    
      typedef uvm_resource #(T) rsrc_t;
    
      protected function new();
      endfunction
    
      // function: get_by_type
      //
      // Get a resource by type.  The type is specified in the db
      // class parameter so the only argument to this function is the
      // ~scope~.
    
      static function rsrc_t get_by_type(string scope);
        return rsrc_t::get_by_type(scope, rsrc_t::get_type());
      endfunction
    
      // function: get_by_name
      //
      // Imports a resource by ~name~.  The first argument is the current 
      // ~scope~ of the resource to be retrieved and the second argument is
      // the ~name~. The ~rpterr~ flag indicates whether or not to generate
      // a warning if no matching resource is found.
    
      static function rsrc_t get_by_name(string scope,
                                         string name,
                                         bit rpterr=1);
    
        return rsrc_t::get_by_name(scope, name, rpterr);
      endfunction
    
      // function: set_default
      //
      // add a new item into the resources database.  The item will not be
      // written to so it will have its default value. The resource is
      // created using ~name~ and ~scope~ as the lookup parameters.
    
      static function rsrc_t set_default(string scope, string name);
    
        rsrc_t r;
    
        r = new(name, scope);
        r.set();
        return r;
      endfunction
    
      // function- show_msg
    
      // internal helper function to print resource accesses
    
      protected static function void m_show_msg(
              input string id,
              input string rtype,
              input string action,
              input string scope,
              input string name,
              input uvm_object accessor,
              input rsrc_t rsrc);
    
              T foo;
              string msg=`uvm_typename(foo);
    
              $sformat(msg, "%s '%s%s' (type %s) %s by %s = %s",
                  rtype,scope, name=="" ? "" : {".",name}, msg,action,
                  (accessor != null) ? accessor.get_full_name() : "<unknown>",
                  rsrc==null?"null (failed lookup)":rsrc.convert2string());
    
              `uvm_info(id, msg, UVM_LOW)
      endfunction
    
      // function: set
      //
      // Create a new resource, write a ~val~ to it, and set it into the
      // database using ~name~ and ~scope~ as the lookup parameters. The
      // ~accessor~ is used for auditing.
      static function void set(input string scope, input string name,
                               T val, input uvm_object accessor = null);
    
        rsrc_t rsrc = new(name, scope);
        rsrc.write(val, accessor);
        rsrc.set();
    
        if(uvm_resource_db_options::is_tracing())
          m_show_msg("RSRCDB/SET", "Resource","set", scope, name, accessor, rsrc);
      endfunction
    
      // function: set_anonymous
      //
      // Create a new resource, write a ~val~ to it, and set it into the
      // database.  The resource has no name and therefore will not be
      // entered into the name map. But is does have a ~scope~ for lookup
      // purposes. The ~accessor~ is used for auditing.
      static function void set_anonymous(input string scope,
                                         T val, input uvm_object accessor = null);
    
        rsrc_t rsrc = new("", scope);
        rsrc.write(val, accessor);
        rsrc.set();
    
        if(uvm_resource_db_options::is_tracing())
          m_show_msg("RSRCDB/SETANON","Resource", "set", scope, "", accessor, rsrc);
      endfunction
    
      // function set_override
      //
      // Create a new resource, write ~val~ to it, and set it into the
      // database.  Set it at the beginning of the queue in the type map and
      // the name map so that it will be (currently) the highest priority
      // resource with the specified name and type.
    
      static function void set_override(input string scope, input string name,
                                        T val, uvm_object accessor = null);
        rsrc_t rsrc = new(name, scope);
        rsrc.write(val, accessor);
        rsrc.set_override();
    
        if(uvm_resource_db_options::is_tracing())
          m_show_msg("RSRCDB/SETOVRD", "Resource","set", scope, name, accessor, rsrc);
      endfunction
    
    
    
      // function set_override_type
      //
      // Create a new resource, write ~val~ to it, and set it into the
      // database.  Set it at the beginning of the queue in the type map so
      // that it will be (currently) the highest priority resource with the
      // specified type. It will be normal priority (i.e. at the end of the
      // queue) in the name map.
    
      static function void set_override_type(input string scope, input string name,
                                             T val, uvm_object accessor = null);
        rsrc_t rsrc = new(name, scope);
        rsrc.write(val, accessor);
        rsrc.set_override(uvm_resource_types::TYPE_OVERRIDE);
    
        if(uvm_resource_db_options::is_tracing())
          m_show_msg("RSRCDB/SETOVRDTYP","Resource", "set", scope, name, accessor, rsrc);
      endfunction
    
      // function set_override_name
      //
      // Create a new resource, write ~val~ to it, and set it into the
      // database.  Set it at the beginning of the queue in the name map so
      // that it will be (currently) the highest priority resource with the
      // specified name. It will be normal priority (i.e. at the end of the
      // queue) in the type map.
    
      static function void set_override_name(input string scope, input string name,
                                      T val, uvm_object accessor = null);
        rsrc_t rsrc = new(name, scope);
        rsrc.write(val, accessor);
        rsrc.set_override(uvm_resource_types::NAME_OVERRIDE);
    
        if(uvm_resource_db_options::is_tracing())
          m_show_msg("RSRCDB/SETOVRDNAM","Resource", "set", scope, name, accessor, rsrc);
      endfunction
    
      // function: read_by_name
      //
      // locate a resource by ~name~ and ~scope~ and read its value. The value 
      // is returned through the output argument ~val~.  The return value is a bit 
      // that indicates whether or not the read was successful. The ~accessor~
      // is used for auditing.
      static function bit read_by_name(input string scope,
                                       input string name,
                                       inout T val, input uvm_object accessor = null);
    
        rsrc_t rsrc = get_by_name(scope, name);
    
        if(uvm_resource_db_options::is_tracing())
          m_show_msg("RSRCDB/RDBYNAM","Resource", "read", scope, name, accessor, rsrc);
    
        if(rsrc == null)
          return 0;
    
        val = rsrc.read(accessor);
    
        return 1;
    
      endfunction
    
      // function: read_by_type
      //
      // Read a value by type.  The value is returned through the output
      // argument ~val~.  The ~scope~ is used for the lookup. The return
      // value is a bit that indicates whether or not the read is successful.
      // The ~accessor~ is used for auditing.
      static function bit read_by_type(input string scope,
                                       inout T val,
                                       input uvm_object accessor = null);
    
        rsrc_t rsrc = get_by_type(scope);
    
        if(uvm_resource_db_options::is_tracing())
          m_show_msg("RSRCDB/RDBYTYP", "Resource","read", scope, "", accessor, rsrc);
    
        if(rsrc == null)
          return 0;
    
        val = rsrc.read(accessor);
    
        return 1;
    
      endfunction
    
      // function: write_by_name
      //
      // write a ~val~ into the resources database.  First, look up the
      // resource by ~name~ and ~scope~.  If it is not located then add a new 
      // resource to the database and then write its value.
      //
      // Because the ~scope~ is matched to a resource which may be a
      // regular expression, and consequently may target other scopes beyond
      // the ~scope~ argument. Care must be taken with this function. If
      // a <get_by_name> match is found for ~name~ and ~scope~ then ~val~
      // will be written to that matching resource and thus may impact
      // other scopes which also match the resource.
      static function bit write_by_name(input string scope, input string name,
                                        input T val, input uvm_object accessor = null);
    
        rsrc_t rsrc = get_by_name(scope, name);
    
        if(uvm_resource_db_options::is_tracing())
          m_show_msg("RSRCDB/WR","Resource", "written", scope, name, accessor, rsrc);
    
        if(rsrc == null)
          return 0;
    
        rsrc.write(val, accessor);
    
        return 1;
    
      endfunction
    
      // function: write_by_type
      //
      // write a ~val~ into the resources database.  First, look up the
      // resource by type.  If it is not located then add a new resource to
      // the database and then write its value.
      //
      // Because the ~scope~ is matched to a resource which may be a
      // regular expression, and consequently may target other scopes beyond
      // the ~scope~ argument. Care must be taken with this function. If
      // a <get_by_name> match is found for ~name~ and ~scope~ then ~val~
      // will be written to that matching resource and thus may impact
      // other scopes which also match the resource.
      static function bit write_by_type(input string scope,
                                        input T val, input uvm_object accessor = null);
    
        rsrc_t rsrc = get_by_type(scope);
    
        if(uvm_resource_db_options::is_tracing())
          m_show_msg("RSRCDB/WRTYP", "Resource","written", scope, "", accessor, rsrc);
    
        if(rsrc == null)
          return 0;
    
        rsrc.write(val, accessor);
    
        return 1;
      endfunction
    
      // function: dump
      //
      // Dump all the resources in the resource pool. This is useful for
      // debugging purposes.  This function does not use the parameter T, so
      // it will dump the same thing -- the entire database -- no matter the
      // value of the parameter.
    
      static function void dump();
        uvm_resource_pool rp = uvm_resource_pool::get();
        rp.dump();
      endfunction
    
    endclass
    

    完整源码 · SHA256:5ddba99ccd715439588a6af1823c2a6ed34162edddb1e884c9d41c3fb8ad1d65

    src/vcs-uvm-ieee-2020-2.0/base/uvm_config_db_implementation.svh
    // uvm_config_db#(T) to allow users to create alternate implementations 
    //
    // @uvm-contrib
    virtual class uvm_config_db_implementation_t #(type T=int) extends uvm_object;
       typedef uvm_resource #(T) rsrc_t;
    
       `uvm_object_abstract_param_utils(uvm_config_db_implementation_t #(T))
    
       local static uvm_config_db_implementation_t #(T) m_config_db_imp;
    
        // Function: set_imp
        //
        // Sets the implementation to be used to:
        //   1) the imp argument if it is not null, else
        //   2) the relevant factory override of uvm_config_db_implementation_t#(T) if such an override exists, else
        //   3) a new creation of uvm_config_db_default_implementation_t#(T)
        // @uvm-contrib
       static function void set_imp(uvm_config_db_implementation_t #(T) imp = null);
          if (imp == null) begin
    

    src/vcs-uvm-ieee-2020-2.0/base/uvm_config_db_implementation.svh
    // a variation of the library implementation.
    //
    // @uvm-contrib
    class uvm_config_db_default_implementation_t #(type T=int) extends uvm_config_db_implementation_t#(T);
    
      function new (string name = "uvm_config_db_default_implementation");
         super.new();
      endfunction : new
    
      `uvm_object_param_utils(uvm_config_db_default_implementation_t #(T))
    
      // Function: get
      //
      // Provides an implementation of get, including support for  
      // config_db tracing
      // @uvm-accellera
      virtual function bit get (uvm_component     cntxt,
                                      string            inst_name,
                                      string            field_name,
    

    完整源码 · SHA256:3b8fc1506c85209e497bdaf2d8dbc8c25a88dac65075c4894207091ce4ca21f0

    src/vcs-uvm-ieee-2020-2.0/base/uvm_resource_db_implementation.svh
    // uvm_resource_db#(T) to allow users to create alternate implementations
    //
    // @uvm-contrib
    virtual class uvm_resource_db_implementation_t #(type T=uvm_object) extends uvm_object;
        typedef uvm_resource #(T) rsrc_t;
    
        `uvm_object_abstract_param_utils(uvm_resource_db_implementation_t #(T))
    
        local static uvm_resource_db_implementation_t #(T) m_rsrc_db_imp;
    
        // Function: set_imp
        //
        // Sets the implementation to be used to:
        //   1) the imp argument if it is not null, else
        //   2) the relevant factory override of uvm_resource_db_implementation_t#(T) if such an override exists, else
        //   3) a new creation of uvm_resource_db_default_implementation_t#(T)
        // @uvm-contrib
        static function void set_imp(uvm_resource_db_implementation_t #(T) imp = null);
          if (imp == null) begin
    

    src/vcs-uvm-ieee-2020-2.0/base/uvm_resource_db_implementation.svh
    // a variation of the library implementation.
    //
    // @uvm-contrib
    class uvm_resource_db_default_implementation_t #(type T=uvm_object) extends uvm_resource_db_implementation_t #(T);
        typedef uvm_resource #(T) rsrc_t;
    
        `uvm_object_param_utils(uvm_resource_db_default_implementation_t #(T))
    
        function new(string name = "uvm_resource_db_default_implementation_t"); 
            super.new();
        endfunction : new
    
    
        // Function: get_by_type
        //
        // Provides an implementation of get_by_type, with a 
        // warning if the resource was not located.
        // @uvm-accellera
        virtual function rsrc_t get_by_type(string scope);
    

    完整源码 · SHA256:1723734791fc6fa7e934c3210294a4e45425ce5ee7ea5b110a46a14985484ced

    术语解释 · 兼容配置

    uvm_config_db#(T)::set 改进非空 context 下 /regex/ 拼接(M05-003)

    返回Config DB / Resource DB · 迁移清单

    版本适用范围