跳转至

输入查询内容

    本页内容

    后门访问告警:not contained within map 'Backdoor'

    影响范围

    UVM_WARNING .../uvm_reg.svh(1198) ... [RegModel]
    Register 'top_rgm.bbbb_rgm.CCCC' is not contained within map 'Backdoor'
    

    Backdoor 通常是 uvm_reg_map::backdoor() 返回的特殊对象,不需要把寄存器 add_reg 到它。field 内部会设置它,因此只给 field 调用传 map=null 或实际 map 不能消除告警。

    具体差异

    字段后门 read/write 在两版都支持。2.0 的 field 路径仍把 map 设为 Backdoor 伪 map,但父寄存器新增的权限查询按普通 map 查找归属,因而报 UVM_WARNING。这是目标实现的处理不一致,不表示字段接口被删除或调用必然错误;告警后访问仍可能成功。

    修改方案

    字段调用不要求改成手工位操作。需要寄存器访问语义时保留 field.read/write,确认实际数据与副作用;若已定位为本库问题且必须消除告警,使用该最小实验核对工具修复。仅需直接取值或赋值时可选 peek/poke。reg 读写显式传伪 map 的情况按下方改为 null。

    字段访问先按语义选接口,UVM-1.2 和 2.0 都有这些方法:

    目的 调用 语义
    模拟寄存器读写 fld.read(status, data, UVM_BACKDOOR) / fld.write(status, data, UVM_BACKDOOR) 遵守字段访问策略,例如 RC 读清零、W1C 写一清零。
    直接读取或设置原值 fld.peek(status, data) / fld.poke(status, data) 采样或原样赋值,不由 RAL 模拟上述硬件副作用;仍执行镜像预测。

    字段截取及合成由库完成,无需自己实现 read-modify-write。peek/poke 不传 UVM_BACKDOOR,其第三个参数是 HDL 路径种类 kind。自定义后门仍执行自己的访问与回调逻辑。

    整寄存器 read/write 显式传了伪 map,且寄存器已关联合适的实际 map 时:

    1
    2
    3
    4
    // 修改前
    rg.read(status, data, UVM_BACKDOOR, uvm_reg_map::backdoor());
    // 修改后;write 同理
    rg.read(status, data, UVM_BACKDOOR);
    

    rg.get_n_maps()==0,null 仍会回退到伪 map,先核对模型是否漏建实际映射。mirror 有有效后门时会重选默认 map,不能仅凭它传了 backdoor() 就认定告警来自该调用。复制旧 reg_access_seq 时,可同步目标写法 rg.mirror(status, UVM_CHECK, UVM_BACKDOOR, null, this)

    兼容措施与范围deprecated、legacy field 开关及 compat 包不修复这条 map 调用链;也不需要靠这些开关恢复 field.read/write。peek/poke 不模拟 read/write 的硬件访问副作用,不能无条件替换。

    迁移后验证

    定位告警处的 reg/field 调用,核对 status、硬件值和镜像;有 RC/W1C 等字段时检查实际副作用。仅凭告警不能判断访问失败,status 成功也不证明数据正确。S38 只覆盖显式伪 map/sequence 线索,field 和默认后门封装需另查。

    记录本条结果M07-005 · 状态与证据

    已有实测与复现

    补充查阅

    扫描定位与记录结果

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

    • S38 · 启发式RAL Backdoor 伪 map、内置 sequence 访问次数与随机激励。
    uv run tools/uvm_migration_scan.py <SoC代码目录> --rules S38
    

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

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

    实现细节

    目标调用链:field 的 Xcheck_accessX 设置伪 map → 父寄存器 do_read/do_writeget_rightsget_local_map 发出告警。Accellera 2.0 参照也有该分支;归属查询失败后 get_rights 返回 RW,所以访问仍可能继续成功。

    原条目的 sequence 遍历变化仍适用:get_blocks(..., UVM_NO_HIER) 加逐层递归避免重复访问;bit_bash 有同类调整,复制旧实现时核对访问次数。

    源码与标准依据

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

    证据tests/uvm_review/backdoor_map_probe.sv;两版 8 种调用场景,逐项断言该告警次数、访问 status、返回值、硬件值和镜像。对应调用逻辑在 Accellera 2.0 参照源码中也存在,不是仅由 VCS 定制造成。

    1. 找不到 map 的诊断本来就存在;新增调用路径使后门访问触发它

    VCS 内置 UVM-1.2uvm_reg.svh:1665–1685 查本地 map 和父 map,失败时 warning。

    VCS 内置 uvm-ieee-2020-2.0uvm_reg.svh:1183–1201 保留归属检查;uvm_reg.svh:1248–1260 中 get_rights 在查询失败后返回 RW。

    2. 寄存器后门读写开始使用所选 map 查询权限

    VCS 内置 UVM-1.2uvm_reg.svh:2498–2520 后门读直接调用 backdoor,字段使用伪 map 获取权限;uvm_reg.svh:2299–2307 后门写直接执行并预测。

    VCS 内置 uvm-ieee-2020-2.0uvm_reg.svh:2043–2065 将 rw.map 作为 local_map,再调用 get_rights;uvm_reg.svh:1794–1803 选择写入 local_map,uvm_reg.svh:1832–1844 检查写权限。

    3. field 入口内部仍设置伪 map,再降为整寄存器访问

    VCS 内置 UVM-1.2uvm_reg_field.svh:1393–1403 后门分支写 rw.map;uvm_reg_field.svh:1641–1647 调用父寄存器 do_read。

    VCS 内置 uvm-ieee-2020-2.0uvm_reg_field.svh:1044–1053 覆盖 map,即使调用方传 null/实际 map;uvm_reg_field.svh:1304–1312 调用父寄存器 do_read,uvm_reg_field.svh:1191–1198 写入也降为父寄存器 do_write。

    4. reg 的 null map 与 mirror 的重选逻辑有明确条件

    VCS 内置 UVM-1.2uvm_reg.svh:2668–2681 有后门时直接设置伪 map;uvm_reg.svh:2999–3005 mirror 同样使用伪 map。

    VCS 内置 uvm-ieee-2020-2.0uvm_reg.svh:2248–2266 reg 后门且 map 为 null 时先取默认 map,无可用 map 才回退到伪 map;uvm_reg.svh:2609–2618 mirror 有后门时重选默认 map。

    5. 字段接口保留;read/write 与 peek/poke 的语义不同

    VCS 内置 UVM-1.2uvm_reg_field.svh:455–479uvm_reg_field.svh:497–512 说明后门 write/read 模拟访问策略;uvm_reg_field.svh:534–577 说明 poke 原样写、peek 采样。

    VCS 内置 uvm-ieee-2020-2.0uvm_reg_field.svh:1496–1561 保留 field.poke/peek,并由父寄存器完成位操作;uvm_reg.svh:2415–2525 直接调用后门,不经 do_read/do_write 的权限与硬件副作用处理。

    补充定位

    VCS 内置 UVM-1.2uvm_reg_access_seq.svh:165mirror 传 backdoor())

    VCS 内置 uvm-ieee-2020-2.0uvm_reg_access_seq.svh:171mirror 改传 null)

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

    src/vcs-uvm-1.2/reg/sequences/uvm_reg_access_seq.svh
             end
             #1;
    
             rg.mirror(status, UVM_CHECK, UVM_BACKDOOR, uvm_reg_map::backdoor(), this);
             if (status != UVM_IS_OK) begin
                `uvm_error("uvm_reg_access_seq", {"Status was '",status.name(),
                                     "' when reading reset value of register '",
                                     rg.get_full_name(), "' through backdoor"})
             end
    
             rg.write(status, v, UVM_BACKDOOR, maps[j], this);
             if (status != UVM_IS_OK) begin
                `uvm_error("uvm_reg_access_seq", {"Status was '",status.name(),
                                     "' when writing '",rg.get_full_name(),
                                     "' through backdoor"})
             end
    
             rg.mirror(status, UVM_CHECK, UVM_FRONTDOOR, maps[j], this);
             if (status != UVM_IS_OK) begin
    

    完整源码 · SHA256:c4e857d21ced74ca3009c66b173422f428007cbcfad92da5940a246a73cf7c8a

    src/vcs-uvm-ieee-2020-2.0/reg/sequences/uvm_reg_access_seq.svh
             end
             #1;
    
             rg.mirror(status, UVM_CHECK, UVM_BACKDOOR, null, this);
             if (status != UVM_IS_OK) begin
                `uvm_error("uvm_reg_access_seq", {"Status was '",status.name(),
                                     "' when reading reset value of register '",
                                     rg.get_full_name(), "' through backdoor"})
             end
    
             rg.write(status, v, UVM_BACKDOOR, maps[j], this);
             if (status != UVM_IS_OK) begin
                `uvm_error("uvm_reg_access_seq", {"Status was '",status.name(),
                                     "' when writing '",rg.get_full_name(),
                                     "' through backdoor"})
             end
    
             rg.mirror(status, UVM_CHECK, UVM_FRONTDOOR, maps[j], this);
             if (status != UVM_IS_OK) begin
    

    完整源码 · SHA256:5d3fef76394bf2192992ccd6f8c751f54168de97b68f5717691955f8b6f62487

    src/vcs-uvm-1.2/reg/uvm_reg.svh
    // get_local_map
    
    function uvm_reg_map uvm_reg::get_local_map(uvm_reg_map map, string caller="");
       if (map == null)
         return get_default_map();
       if (m_maps.exists(map))
         return map; 
       foreach (m_maps[l]) begin
         uvm_reg_map local_map=l;
         uvm_reg_map parent_map = local_map.get_parent_map();
    
         while (parent_map != null) begin
           if (parent_map == map)
             return local_map;
           parent_map = parent_map.get_parent_map();
         end
       end
       `uvm_warning("RegModel", 
           {"Register '",get_full_name(),"' is not contained within map '",map.get_full_name(),"'",
            (caller == "" ? "": {" (called from ",caller,")"}) })
       return null;
    endfunction
    

    src/vcs-uvm-1.2/reg/uvm_reg.svh
                   final_val |= field_val << lsb;
                end
             end
             rw.kind = UVM_WRITE;
             rw.value[0] = final_val;
    
             if (bkdr != null)
               bkdr.write(rw);
             else
               backdoor_write(rw);
    
             do_predict(rw, UVM_PREDICT_WRITE);
          end
    
          UVM_FRONTDOOR: begin
    
             uvm_reg_map system_map = rw.local_map.get_root_map();
    
             m_is_busy = 1;
    

    src/vcs-uvm-1.2/reg/uvm_reg.svh
       case (rw.path)
    
          // ...VIA USER BACKDOOR
          UVM_BACKDOOR: begin
             uvm_reg_backdoor bkdr = get_backdoor();
    
             uvm_reg_map map = uvm_reg_map::backdoor();
             if (map.get_check_on_read()) exp = get();
    
             if (bkdr != null)
               bkdr.read(rw);
             else
               backdoor_read(rw);
    
             value = rw.value[0];
    
             // Need to clear RC fields, set RS fields and mask WO fields
             if (rw.status != UVM_NOT_OK) begin
    
                uvm_reg_data_t wo_mask;
    
                foreach (m_fields[i]) begin
                   string acc = m_fields[i].get_access(uvm_reg_map::backdoor());
                   if (acc == "RC" ||
                       acc == "WRC" ||
                       acc == "WSRC" ||
    

    src/vcs-uvm-1.2/reg/uvm_reg.svh
       if (rw.path == UVM_DEFAULT_PATH)
         rw.path = m_parent.get_default_path();
    
       if (rw.path == UVM_BACKDOOR) begin
          if (get_backdoor() == null && !has_hdl_path()) begin
             `uvm_warning("RegModel",
                {"No backdoor access available for register '",get_full_name(),
                "' . Using frontdoor instead."})
             rw.path = UVM_FRONTDOOR;
          end
          else
            rw.map = uvm_reg_map::backdoor();
       end
    
    
       if (rw.path != UVM_BACKDOOR) begin
    
         rw.local_map = get_local_map(rw.map,caller);
    

    src/vcs-uvm-1.2/reg/uvm_reg.svh
       m_lineno = lineno;
    
    
       if (path == UVM_DEFAULT_PATH)
         path = m_parent.get_default_path();
    
       if (path == UVM_BACKDOOR && (bkdr != null || has_hdl_path()))
         map = uvm_reg_map::backdoor();
       else
         map = get_local_map(map, "read()");
    
       if (map == null)
         return;
    
       // Remember what we think the value is before it gets updated
       if (check == UVM_CHECK)
         exp = get_mirrored_value();
    
       XreadX(status, v, path, map, parent, prior, extension, fname, lineno);
    

    完整源码 · SHA256:a01d27ace4190cce87f4bf8f78d0db63b1517ffb43a412e187e67391984971b6

    src/vcs-uvm-ieee-2020-2.0/reg/uvm_reg.svh
    // get_local_map
    
    function uvm_reg_map uvm_reg::get_local_map(uvm_reg_map map);
       if (map == null)
         return get_default_map();
       if (m_maps.exists(map))
         return map; 
       foreach (m_maps[l]) begin
         uvm_reg_map local_map=l;
         uvm_reg_map parent_map = local_map.get_parent_map();
    
         while (parent_map != null) begin
           if (parent_map == map)
             return local_map;
           parent_map = parent_map.get_parent_map();
         end
       end
       `uvm_warning("RegModel", 
           {"Register '",get_full_name(),"' is not contained within map '",map.get_full_name(),"'"})
       return null;
    endfunction
    

    src/vcs-uvm-ieee-2020-2.0/reg/uvm_reg.svh
    // get_rights
    
    function string uvm_reg::get_rights(uvm_reg_map map = null);
    
       uvm_reg_map_info info;
    
       map = get_local_map(map);
    
       if (map == null)
         return "RW";
    
       info = map.get_reg_map_info(this);
       return info.rights;
    
    endfunction
    

    src/vcs-uvm-ieee-2020-2.0/reg/uvm_reg.svh
       case (rw.get_door())
    
          // ...VIA USER BACKDOOR
          UVM_BACKDOOR: begin
             uvm_reg_data_t final_val;
             uvm_reg_backdoor bkdr = get_backdoor();
    
             if (rw.get_map() != null)
               rw.set_local_map(rw.get_map());
             else 
               rw.set_local_map(get_default_map());
    
             value = rw.get_value(0);
    
             // Mimick the final value after a physical read
             rw.set_kind(UVM_READ);
             if (bkdr != null)
               bkdr.read(rw);
             else
    

    src/vcs-uvm-ieee-2020-2.0/reg/uvm_reg.svh
             rw.set_kind(UVM_WRITE);
             rw.set_value(final_val, 0);
    
            if (get_rights(rw.get_local_map()) inside {"RW", "WO"}) begin
              if (bkdr != null)
               bkdr.write(rw);
              else
               backdoor_write(rw);
    
              do_predict(rw, UVM_PREDICT_WRITE);
            end
            else begin
               rw.set_status(UVM_NOT_OK);
            end
    
    
          end
    
          UVM_FRONTDOOR: begin
    

    src/vcs-uvm-ieee-2020-2.0/reg/uvm_reg.svh
       case (rw.get_door())
    
          // ...VIA USER BACKDOOR
          UVM_BACKDOOR: begin
             uvm_reg_backdoor bkdr = get_backdoor();
    
             uvm_reg_map map;  // = uvm_reg_map::backdoor();
             if (rw.get_map() != null)
                rw.set_local_map(rw.get_map());
             else
                rw.set_local_map(get_default_map());  
    
             map = rw.get_local_map();
    
             if (map.get_check_on_read()) exp = get_mirrored_value();
    
             if (get_rights(rw.get_local_map()) inside {"RW", "RO"}) begin
               if (bkdr != null)
                 bkdr.read(rw);
               else
                 backdoor_read(rw);
             end
             else begin
                 rw.set_status(UVM_NOT_OK);
             end
    

    src/vcs-uvm-ieee-2020-2.0/reg/uvm_reg.svh
       uvm_reg_map tmp_map;
       uvm_reg_map tmp_local_map;
    
       if (rw.get_door() == UVM_DEFAULT_DOOR)
         rw.set_door(m_parent.get_default_door());
    
       if (rw.get_door() == UVM_BACKDOOR) begin
          if (get_backdoor() == null && !has_hdl_path()) begin
             `uvm_warning("RegModel",
                {"No backdoor access available for register '",get_full_name(),
                "' . Using frontdoor instead."})
             rw.set_door(UVM_FRONTDOOR);
          end
          else if (rw.get_map() == null) begin
            uvm_reg_map  bkdr_map = get_default_map();
            if (bkdr_map != null)
                rw.set_map(bkdr_map);
            else
                rw.set_map(uvm_reg_map::backdoor());
          end
    
       end
    

    src/vcs-uvm-ieee-2020-2.0/reg/uvm_reg.svh
    // poke
    
    task uvm_reg::poke(output uvm_status_e      status,
                       input  uvm_reg_data_t    value,
                       input  string            kind = "",
                       input  uvm_sequence_base parent = null,
                       input  uvm_object        extension = null,
                       input  string            fname = "",
                       input  int               lineno = 0);
    
       uvm_reg_backdoor bkdr = get_backdoor();
       uvm_reg_item rw;
    
       m_fname = fname;
       m_lineno = lineno;
    
    
       if (bkdr == null && !has_hdl_path(kind)) begin
          `uvm_error("RegModel",
            {"No backdoor access available to poke register '",get_full_name(),"'"})
          status = UVM_NOT_OK;
          return;
       end
    
       if (!m_is_locked_by_field)
         XatomicX(1);
    
       // create an abstract transaction for this operation
       rw = uvm_reg_item::type_id::create("reg_poke_item",,get_full_name());
       rw.set_element(this);
       rw.set_door(UVM_BACKDOOR);
       rw.set_element_kind(UVM_REG);
       rw.set_kind(UVM_WRITE);
       rw.set_bd_kind(kind);
       rw.set_value((value & ((1 << m_n_bits)-1)),0);
       rw.set_parent_sequence(parent);
       rw.set_extension(extension);
       rw.set_fname(fname);
       rw.set_line(lineno);
    
       if (bkdr != null)
         bkdr.write(rw);
       else
         backdoor_write(rw);
    
       status = rw.get_status();
    
       `uvm_info("RegModel", $sformatf("Poked register \"%s\": 'h%h",
                                  get_full_name(), value),UVM_HIGH)
    
       do_predict(rw, UVM_PREDICT_WRITE);
    
       if (!m_is_locked_by_field)
         XatomicX(0);
    endtask: poke
    
    
    // peek
    
    task uvm_reg::peek(output uvm_status_e      status,
                       output uvm_reg_data_t    value,
                       input  string            kind = "",
                       input  uvm_sequence_base parent = null,
                       input  uvm_object        extension = null,
                       input  string            fname = "",
                       input  int               lineno = 0);
    
       uvm_reg_backdoor bkdr = get_backdoor();
       uvm_reg_item rw;
    
       m_fname = fname;
       m_lineno = lineno;
    
       if (bkdr == null && !has_hdl_path(kind)) begin
          `uvm_error("RegModel",
            $sformatf("No backdoor access available to peek register \"%s\"",
                      get_full_name()))
          status = UVM_NOT_OK;
          return;
       end
    
       if(!m_is_locked_by_field)
          XatomicX(1);
    
       // create an abstract transaction for this operation
       rw = uvm_reg_item::type_id::create("mem_peek_item",,get_full_name());
       rw.set_element(this);
       rw.set_door(UVM_BACKDOOR);
       rw.set_element_kind(UVM_REG);
       rw.set_kind(UVM_READ);
       rw.set_bd_kind(kind);
       rw.set_parent_sequence(parent);
       rw.set_extension(extension);
       rw.set_fname(fname);
       rw.set_line(lineno);
    
       if (bkdr != null)
         bkdr.read(rw);
       else
         backdoor_read(rw);
    
       status = rw.get_status();
       value = rw.get_value(0);
    
       `uvm_info("RegModel", $sformatf("Peeked register \"%s\": 'h%h",
                              get_full_name(), value),UVM_HIGH)
    
       do_predict(rw, UVM_PREDICT_READ);
    
       if (!m_is_locked_by_field)
          XatomicX(0);
    endtask: peek
    

    src/vcs-uvm-ieee-2020-2.0/reg/uvm_reg.svh
       m_lineno = lineno;
    
    
       if (path == UVM_DEFAULT_DOOR)
         path = m_parent.get_default_door();
    
       if (path == UVM_BACKDOOR && (bkdr != null || has_hdl_path())) begin
         map = get_default_map();
         if (map == null) 
             map = uvm_reg_map::backdoor();
       end
       else
         map = get_local_map(map);
    
       if (map == null) begin
         XatomicX(0);
         return;
       end
    

    完整源码 · SHA256:a0b3ba54fe8e7a696018aa531a0e93c98cfdc89c74073dfcf7eed58b9833618e

    src/vcs-uvm-1.2/reg/uvm_reg_field.svh
       // Task: write
       //
       // Write the specified value in this field
       //
       // Write ~value~ in the DUT field that corresponds to this
       // abstraction class instance using the specified access
       // ~path~. 
       // If the register containing this field is mapped in more
       //  than one address map, 
       // an address ~map~ must be
       // specified if a physical access is used (front-door access).
       // If a back-door access path is used, the effect of writing
       // the field through a physical access is mimicked. For
       // example, read-only bits in the field will not be written.
       //
       // The mirrored value will be updated using the <uvm_reg_field::predict()>
       // method.
       //
       // If a front-door access is used, and
       // if the field is the only field in a byte lane and
       // if the physical interface corresponding to the address map used
       // to access the field support byte-enabling,
       // then only the field is written.
       // Otherwise, the entire register containing the field is written,
       // and the mirrored values of the other fields in the same register
       // are used in a best-effort not to modify their value.
       //
       // If a backdoor access is used, a peek-modify-poke process is used.
    

    src/vcs-uvm-1.2/reg/uvm_reg_field.svh
       // Task: read
       //
       // Read the current value from this field
       //
       // Read and return ~value~ from the DUT field that corresponds to this
       // abstraction class instance using the specified access
       // ~path~. 
       // If the register containing this field is mapped in more
       // than one address map, an address ~map~ must be
       // specified if a physical access is used (front-door access).
       // If a back-door access path is used, the effect of reading
       // the field through a physical access is mimicked. For
       // example, clear-on-read bits in the field will be set to zero.
       //
       // The mirrored value will be updated using the <uvm_reg_field::predict()>
       // method.
       //
       // If a front-door access is used, and
       // if the field is the only field in a byte lane and
    

    src/vcs-uvm-1.2/reg/uvm_reg_field.svh
                                  input  int                lineno = 0);
    
    
       // Task: poke
       //
       // Deposit the specified value in this field
       //
       // Deposit the value in the DUT field corresponding to this
       // abstraction class instance, as-is, using a back-door access.
       // A peek-modify-poke process is used
       // in a best-effort not to modify the value of the other fields in the
       // register.
       //
       // The mirrored value will be updated using the <uvm_reg_field::predict()>
       // method.
       //
       extern virtual task poke  (output uvm_status_e       status,
                                  input  uvm_reg_data_t     value,
                                  input  string             kind = "",
                                  input  uvm_sequence_base  parent = null,
                                  input  uvm_object         extension = null,
                                  input  string             fname = "",
                                  input  int                lineno = 0);
    
    
       // Task: peek
       //
       // Read the current value from this field
       //
       // Sample the value in the DUT field corresponding to this
       // abstraction class instance using a back-door access.
       // The field value is sampled, not modified.
       //
       // Uses the HDL path for the design abstraction specified by ~kind~.
       //
       // The entire containing register is peeked
       // and the mirrored value of the other fields in the register
       // are updated using the <uvm_reg_field::predict()> method.
       //
       //
       extern virtual task peek  (output uvm_status_e       status,
                                  output uvm_reg_data_t     value,
                                  input  string             kind = "",
                                  input  uvm_sequence_base  parent = null,
                                  input  uvm_object         extension = null,
                                  input  string             fname = "",
                                  input  int                lineno = 0);
    

    src/vcs-uvm-1.2/reg/uvm_reg_field.svh
         uvm_reg_block blk = m_parent.get_block();
         rw.path = blk.get_default_path();
       end
    
       if (rw.path == UVM_BACKDOOR) begin
          if (m_parent.get_backdoor() == null && !m_parent.has_hdl_path()) begin
             `uvm_warning("RegModel",
                {"No backdoor access available for field '",get_full_name(),
                "' . Using frontdoor instead."})
             rw.path = UVM_FRONTDOOR;
          end
          else
            rw.map = uvm_reg_map::backdoor();
       end
    
       if (rw.path != UVM_BACKDOOR) begin
    
         rw.local_map = m_parent.get_local_map(rw.map,caller);
    

    src/vcs-uvm-1.2/reg/uvm_reg_field.svh
       bad_side_effect = 1;
    `else
    
       if (!is_indv_accessible(rw.path,rw.local_map)) begin
          rw.element_kind = UVM_REG;
          rw.element = m_parent;
          bad_side_effect = 1;
          m_parent.do_read(rw);
          rw.value[0] = (rw.value[0] >> m_lsb) & ((1<<m_size))-1;
       end
       else begin
    
         uvm_reg_map system_map = rw.local_map.get_root_map();
         uvm_reg_field_cb_iter cbs = new(this);
    
         m_parent.Xset_busyX(1);
    
         rw.status = UVM_IS_OK;
    

    完整源码 · SHA256:203f137cd6cc544089313f20cbc64046691beb899d7596db93e03b9d1968d3f2

    src/vcs-uvm-ieee-2020-2.0/reg/uvm_reg_field.svh
         rw.set_door(blk.get_default_door());
       end
    
       if (rw.get_door() == UVM_BACKDOOR) begin
          if (m_parent.get_backdoor() == null && !m_parent.has_hdl_path()) begin
             `uvm_warning("RegModel",
                {"No backdoor access available for field '",get_full_name(),
                "' . Using frontdoor instead."})
             rw.set_door(UVM_FRONTDOOR);
          end
          else
            rw.set_map(uvm_reg_map::backdoor());
       end
    
       if (rw.get_door() != UVM_BACKDOOR) begin
    
         rw.set_local_map(m_parent.get_local_map(rw.get_map()));
    
         if (rw.get_local_map() == null) begin        
    

    src/vcs-uvm-ieee-2020-2.0/reg/uvm_reg_field.svh
       m_parent.do_write(rw);   
    `else        
    
       if (!is_indv_accessible(rw.get_door(),rw.get_local_map())) begin
          rw.set_element_kind(UVM_REG);
          rw.set_element(m_parent);
          rw.set_value(value_adjust, 0);
          m_parent.do_write(rw);
    
          if (bad_side_effect) begin
             `uvm_warning("RegModel", $sformatf("Writing field \"%s\" will cause unintended side effects in adjoining Write-to-Clear or Write-to-Set fields in the same register", this.get_full_name()))
          end
       end
       else begin
         uvm_reg_map item_map = rw.get_local_map();
         uvm_reg_map system_map = item_map.get_root_map();
         uvm_reg_field_cb_iter cbs = new(this);
    
         m_parent.Xset_busyX(1);
    

    src/vcs-uvm-ieee-2020-2.0/reg/uvm_reg_field.svh
       bad_side_effect = 1;
    `else
    
       if (!is_indv_accessible(rw.get_door(),rw_local_map)) begin
          uvm_reg_data_t value;
          rw.set_element_kind(UVM_REG);
          rw.set_element(m_parent);
          bad_side_effect = 1;
          m_parent.do_read(rw);
          value = rw.get_value(0);
          rw.set_value(((value >> m_lsb) & ((1<<m_size))-1),0);
       end
       else begin
    
         uvm_reg_map system_map = rw_local_map.get_root_map();
         uvm_reg_field_cb_iter cbs = new(this);
    
         m_parent.Xset_busyX(1);
    

    src/vcs-uvm-ieee-2020-2.0/reg/uvm_reg_field.svh
    // poke
    
    task uvm_reg_field::poke(output uvm_status_e      status,
                             input  uvm_reg_data_t    value,
                             input  string            kind = "",
                             input  uvm_sequence_base parent = null,
                             input  uvm_object        extension = null,
                             input  string            fname = "",
                             input  int               lineno = 0);
       uvm_reg_data_t  tmp;
    
       m_fname = fname;
       m_lineno = lineno;
    
       if (value >> m_size) begin
          `uvm_warning("RegModel",
             {"uvm_reg_field::poke(): Value exceeds size of field '",
              get_name(),"'"})
          value &= value & ((1<<m_size)-1);
       end
    
    
       m_parent.XatomicX(1);
       m_parent.m_is_locked_by_field = 1'b1;
    
       tmp = 0;
    
       // What is the current values of the other fields???
       m_parent.peek(status, tmp, kind, parent, extension, fname, lineno);
    
       if (status == UVM_NOT_OK) begin
          `uvm_error("RegModel", {"uvm_reg_field::poke(): Peek of register '",
             m_parent.get_full_name(),"' returned status ",status.name()})
          m_parent.XatomicX(0);
          m_parent.m_is_locked_by_field = 1'b0;
          return;
       end
    
       // Force the value for this field then poke the resulting value
       tmp &= ~(((1<<m_size)-1) << m_lsb);
       tmp |= value << m_lsb;
       m_parent.poke(status, tmp, kind, parent, extension, fname, lineno);
    
       m_parent.XatomicX(0);
       m_parent.m_is_locked_by_field = 1'b0;
    endtask: poke
    
    
    // peek
    
    task uvm_reg_field::peek(output uvm_status_e      status,
                             output uvm_reg_data_t    value,
                             input  string            kind = "",
                             input  uvm_sequence_base parent = null,
                             input  uvm_object        extension = null,
                             input  string            fname = "",
                             input  int               lineno = 0);
       uvm_reg_data_t  reg_value;
    
       m_fname = fname;
       m_lineno = lineno;
    
       m_parent.peek(status, reg_value, kind, parent, extension, fname, lineno);
       value = (reg_value >> m_lsb) & ((1<<m_size))-1;
    
    endtask: peek
    

    完整源码 · SHA256:08e4cb573f5f6f23fb1c7ae019ed2b4f7f08c9631878d5f88df2464858fa5bbb

    术语解释 · 兼容配置

    返回RAL(寄存器模型) · 迁移清单

    版本适用范围