跳转至

输入查询内容

    本页内容

    旧数组录制上限失效:显式控制记录项数

    影响范围

    运行参数含 +UVM_ARRAY_NUM_LIMIT,或自定义 recorder/字段操作调用 verdi_get_array_limit()、访问 max_array_limit_check/max_array_num_limit

    具体差异

    VCS 1.2 的 recorder 读取 +UVM_ARRAY_NUM_LIMIT,数组/队列 field 宏调用 verdi_get_array_limit() 选择记录项数;目标 recorder 与 Accellera 2.0 相同,已无该方法和配置字段,旧 plusarg 没有原来的消费路径。直接调用旧方法会报成员不存在;只留下 plusarg 通常不能通过编译报错发现失效。此项是 VCS 旧版定制的移除,不是所有 recorder 的通用数组限制。

    修改方案

    先确认需要记录全部元素还是限定元素;需要上限时,给对应字段的 field FLAGUVM_NORECORD,在 do_record(uvm_recorder recorder) 中按显式上限调用 record_field_int/record_object 等对应接口。调用旧 getter 的代码改读自己维护的配置;验证记录内容后再删除旧 plusarg。已有手工录制字段不要同时启用自动录制。

    旧写法通过仿真参数控制自动录制:+UVM_ARRAY_NUM_LIMIT=2。下面给出整数数组只记录前两项的显式写法;data 若仍注册 field 宏,应在原 FLAG 上增加 UVM_NORECORD,保留所需 copy/compare/pack 操作。

    class bounded_record_item extends uvm_object;
      int data[] = '{11, 22, 33, 44};
      int unsigned record_limit = 2;
      function new(string name = "bounded_record_item"); super.new(name); endfunction
      // This example does not register data with a field macro.
      function void do_record(uvm_recorder recorder);
        super.do_record(recorder);
        foreach (data[i]) begin
          if (i >= record_limit) break;
          recorder.record_field_int($sformatf("data[%0d]", i), data[i], 32, UVM_DEC);
        end
      endfunction
    endclass
    

    这里的上限 0 表示不记录任何元素,与旧开关的 0 分支不同;迁移配置时明确转换含义。对象数组用相应的 record_object 并单独验证对象身份和递归。

    兼容措施与范围deprecated、legacy field 开关和 compat 包都不恢复这套 VCS 数组上限;显式 do_record 的上限由用户配置维护。

    迁移后验证

    用超过上限的数组检查记录项数、索引和值;也覆盖空数组、短数组及所用元素类型。确认没有自动录制叠加,并检查实际后端输出与所需的文件体积;不能把文本 recorder 实验扩展到全部 Verdi 工作流。

    记录本条结果M02-016 · 状态与证据

    已有实测与复现

    vendor_compile_probe 的旧 getter 调用在 1.2 编译通过,2.0 报 Error-[MFNF]vendor_migration_probe 两库对四项整数数组均记录两项,值之和为 33,最后字段为 data[1];只验证手工 do_record 与文本 recorder 调用,不代表所有 field 宏或 Verdi 文件格式等价。

    补充查阅

    扫描定位与记录结果

    有扫描规则,覆盖部分可识别写法。脚本检查名称、参数和部分 FLAG 表达式,并对少数直接声明关联使用点;未做完整类型解析或预处理,行为结果仍需验证。

    uv run tools/uvm_migration_scan.py <SoC代码目录> --rules D13
    

    核对命中对象及生效分支后,在条目清单记录修改与验证证据;扫描规则记录用于整理命中位置。

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

    源码与标准依据

    核查方式:源码与实测核对。实测仅覆盖本条所列场景。

    1. 旧上限由 recorder 读取,field 宏消费

    VCS 内置 UVM-1.2:getter 读取 plusarg:uvm_recorder.svh:145–155;整型数组宏按上限分支记录:uvm_object_defines.svh:2668–2740

    VCS 内置 uvm-ieee-2020-2.0:目标 field 宏调用 qda 宏:uvm_object_defines.svh:1451–1453;qda 录制宏没有该 getter:uvm_recorder_defines.svh:237–262。方法删除同时依据 recorder 全文件核对和编译断点,不能仅由该片段推断。

    补充定位

    VCS 内置 UVM-1.2uvm_recorder.svh:124–155uvm_object_defines.svh:2668–2740

    VCS 内置 uvm-ieee-2020-2.0src/vcs-uvm-ieee-2020-2.0/src/base/uvm_recorder.svh 全文件不含旧方法和字段;uvm_recorder_defines.svh:237–262

    标准依据:VCS 1.2 私有扩展;两侧 Accellera recorder 无该 getter,不作为 IEEE 标准要求。

    标为“源码标注”或未注明原文核对的条款仅作定位;具体库行为以源码和实测为准。

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

    src/vcs-uvm-1.2/base/uvm_recorder.svh
      uvm_recursion_policy_enum policy = UVM_DEFAULT_POLICY;
    
      // Modified by Verdi 9001505562
      bit max_array_limit_check = 0;
      longint max_array_num_limit = -1;
      // end
    
       // Variable- m_ids_by_recorder
       // An associative array of integers, indexed by uvm_recorders.  This
       // provides a unique 'id' or 'handle' for each recorder, which can be
       // used to identify the recorder.
       //
       // By default, neither ~m_ids_by_recorder~ or ~m_recorders_by_id~ are
       // used.  Recorders are only placed in the arrays when the user
       // attempts to determine the id for a recorder.
       local static integer m_ids_by_recorder[uvm_recorder];
    
    
      function new(string name = "uvm_recorder");
         super.new(name);
         m_stream_dap = new("stream_dap");
         m_warn_null_stream = 1;
      endfunction
    
      // Modified by Verdi 9001505562
      function longint verdi_get_array_limit();
         if(max_array_limit_check==0) begin
            string val_str = "";
            max_array_limit_check = 1;
            if ($value$plusargs("UVM_ARRAY_NUM_LIMIT=%s", val_str))
                max_array_num_limit = val_str.atoi();
         end
         return max_array_num_limit;
      endfunction
      //
    
       // Group: Configuration API
    
       // Function: get_stream
       // Returns a reference to the stream which created
    

    完整源码 · SHA256:c27078db07e6a49a9e91f17c4c41251a60b1d6f1bad2c8adbc959a5f7322f6c1

    src/vcs-uvm-1.2/macros/uvm_object_defines.svh
    // --------------------
    // Modified by Verdi 9001505562
    
    `define m_uvm_record_qda_int(ARG, FLAG, SZ) \
      begin \
        if(!((FLAG)&UVM_NORECORD)) begin \
          int sz__ = SZ; \
          int max_array_num_limit = __m_uvm_status_container.recorder.verdi_get_array_limit(); \
          if (max_array_num_limit < 0) begin \
              if(sz__ == 0) begin \
                __m_uvm_status_container.recorder.record_field_int(`"ARG`", 0, 32, UVM_DEC); \
              end \
              else if(sz__ < 10) begin \
                foreach(ARG[i]) begin \
                   __m_uvm_status_container.scope.set_arg_element(`"ARG`",i); \
                   if ($bits(ARG[i]) > 64) \
                     __m_uvm_status_container.recorder.record_field(__m_uvm_status_container.scope.get(), ARG[i], $bits(ARG[i]), uvm_radix_enum'((FLAG)&UVM_RADIX)); \
                   else \
                     __m_uvm_status_container.recorder.record_field_int(__m_uvm_status_container.scope.get(), ARG[i], $bits(ARG[i]), uvm_radix_enum'((FLAG)&UVM_RADIX)); \
                end \
              end \
              else begin \
                for(int i=0; i<5; ++i) begin \
                   __m_uvm_status_container.scope.set_arg_element(`"ARG`", i); \
                   if ($bits(ARG[i]) > 64) \
                     __m_uvm_status_container.recorder.record_field(__m_uvm_status_container.scope.get(), ARG[i], $bits(ARG[i]), uvm_radix_enum'((FLAG)&UVM_RADIX)); \
                   else \
                     __m_uvm_status_container.recorder.record_field_int(__m_uvm_status_container.scope.get(), ARG[i], $bits(ARG[i]), uvm_radix_enum'((FLAG)&UVM_RADIX)); \
                end \
                for(int i=sz__-5; i<sz__; ++i) begin \
                   __m_uvm_status_container.scope.set_arg_element(`"ARG`", i); \
                   if ($bits(ARG[i]) > 64) \
                     __m_uvm_status_container.recorder.record_field(__m_uvm_status_container.scope.get(), ARG[i], $bits(ARG[i]), uvm_radix_enum'((FLAG)&UVM_RADIX)); \
                   else \
                     __m_uvm_status_container.recorder.record_field_int(__m_uvm_status_container.scope.get(), ARG[i], $bits(ARG[i]), uvm_radix_enum'((FLAG)&UVM_RADIX)); \
                end \
              end \
          end \
          else begin \
              if(sz__ == 0) begin \
                __m_uvm_status_container.recorder.record_field(`"ARG`", 0, 32, UVM_DEC); \
              end \
              else begin \
                if (max_array_num_limit == 0) begin \
                    foreach(ARG[i]) begin \
                      __m_uvm_status_container.scope.set_arg_element(`"ARG`",i); \
                      if ($bits(ARG[i]) > 64) \
                       __m_uvm_status_container.recorder.record_field(__m_uvm_status_container.scope.get(), ARG[i], $bits(ARG[i]), uvm_radix_enum'((FLAG)&UVM_RADIX)); \
                      else \
                       __m_uvm_status_container.recorder.record_field_int(__m_uvm_status_container.scope.get(), ARG[i], $bits(ARG[i]), uvm_radix_enum'((FLAG)&UVM_RADIX)); \
                    end \
                end \
                else begin \
                    if (sz__ >= max_array_num_limit) begin \
                      for(int i=0; i<max_array_num_limit; ++i) begin \
                        __m_uvm_status_container.scope.set_arg_element(`"ARG`", i); \
                        if ($bits(ARG[i]) > 64) \
                         __m_uvm_status_container.recorder.record_field(__m_uvm_status_container.scope.get(), ARG[i], $bits(ARG[i]), uvm_radix_enum'((FLAG)&UVM_RADIX)); \
                        else \
                         __m_uvm_status_container.recorder.record_field_int(__m_uvm_status_container.scope.get(), ARG[i], $bits(ARG[i]), uvm_radix_enum'((FLAG)&UVM_RADIX)); \
                      end \
                    end \
                    else begin \
                      for(int i=0; i<sz__; ++i) begin \
                        __m_uvm_status_container.scope.set_arg_element(`"ARG`", i); \
                        if ($bits(ARG[i]) > 64) \
                         __m_uvm_status_container.recorder.record_field(__m_uvm_status_container.scope.get(), ARG[i], $bits(ARG[i]), uvm_radix_enum'((FLAG)&UVM_RADIX)); \
                        else \
                         __m_uvm_status_container.recorder.record_field_int(__m_uvm_status_container.scope.get(), ARG[i], $bits(ARG[i]), uvm_radix_enum'((FLAG)&UVM_RADIX)); \
                      end \
                    end \
                end \
              end \
          end \
        end \
      end
    

    完整源码 · SHA256:fad4b0a983286e771a025f28de582e35b21fd1dc49d8fcc5c1b2be9f4ebe99d1

    src/vcs-uvm-ieee-2020-2.0/macros/uvm_recorder_defines.svh
    // uvm_record_qda_int
    // ------------------
    
      `define uvm_record_qda_int(ARG, RADIX,RECORDER=recorder) \
      begin \
        int sz__ = $size(ARG); \
        if(sz__ == 0) begin \
          `uvm_record_int(`"ARG`", 0, 32, UVM_DEC,RECORDER) \
        end \
        else if(sz__ < 10) begin \
          foreach(ARG[i]) begin \
            string nm__ = $sformatf("%s[%0d]", `"ARG`", i); \
            `uvm_record_int(nm__, ARG[i], $bits(ARG[i]), RADIX, RECORDER) \
          end \
        end \
        else begin \
          for(int i=0; i<5; ++i) begin \
            string nm__ = $sformatf("%s[%0d]", `"ARG`", i); \
            `uvm_record_int(nm__, ARG[i], $bits(ARG[i]), RADIX, RECORDER) \
          end \
          for(int i=sz__-5; i<sz__; ++i) begin \
            string nm__ = $sformatf("%s[%0d]", `"ARG`", i); \
            `uvm_record_int(nm__, ARG[i], $bits(ARG[i]), RADIX, RECORDER) \
          end \
        end \
      end 
    
    // uvm_record_qda_object
    // ---------------------
    

    完整源码 · SHA256:182dfa5e33826150d5ad29527498a0dfb0418ab868e578332308841cb4c84c00

    src/vcs-uvm-ieee-2020-2.0/macros/uvm_object_defines.svh
        `m_uvm_field_op_begin(UNPACK,FLAG) \
          `uvm_unpack_``TYPE``(ARG, __local_packer__) \
        `m_uvm_field_op_end(UNPACK) \
        `m_uvm_field_op_begin(RECORD,FLAG) \
          `uvm_record_qda_int(ARG, `m_uvm_field_radix(FLAG), __local_recorder__) \
        `m_uvm_field_op_end(RECORD) \
        `m_uvm_field_op_begin(PRINT,FLAG) \
          `uvm_print_qda_int(TYPE, ARG, `m_uvm_field_radix(FLAG),,__local_printer__) \
        `m_uvm_field_op_end(PRINT) \
        `m_uvm_field_op_begin(SET,FLAG) \
          if(local_rsrc_name__ == `"ARG`") begin \
            `uvm_resource_builtin_int_read(local_success__, \
                                           local_rsrc__, \
                                           local_size__, \
                                           this) \
            if (local_success__) \
              `m_uvm_``TYPE``_resize(ARG, local_size__) \
          end \
          else begin \
    

    完整源码 · SHA256:072baece05e653f6811936de05739a8ff55c02651d89a9278f39cca11372a260

    术语解释 · 兼容配置

    返回Comparer / Printer / Packer / Recorder · 迁移清单

    版本适用范围