跳转至

输入查询内容

    本页内容

    后门编解码可能失效:同时检查硬件值与读回值

    已复现的目标库问题

    目标库 backdoor 编解码未写回问题已复现;单 codec 替代已验证。

    影响范围

    使用注册在 uvm_reg_backdoor 实例上的 uvm_reg_cbs::encode/decode 修改数据时核对本条。下面的替代限定codec、受控 backdoor 回调链。普通无 codec 的 backdoor 访问不需要套用此补偿;本例未验证 frontdoor 回调、寄存器镜像及失败读取。

    具体差异

    1.2 将 rw.value 直接作为 ref 实参;目标先 get_value_array,再调用 codec,但未 set_value_array。backdoor_probe 用 XOR 0x55 编码,写入逻辑值 1 后硬件值为 54 / 1;读取硬件 54 后逻辑值为 1 / 54。编译和访问 status 均不能发现错误。

    修改方案

    codec、受控回调链可在 pre_write/post_read 直接更新 rw.value,停用旧 encode/decode;相同探针两版均恢复硬件 54、读值 1。多 codec 的 decode 原为逆序调用,post_read 为正序,不能机械迁移,需在自定义 backdoor 中显式维持编码顺序、逆序解码与写回,并另行验证。

    旧回调通过数组引用执行 XOR 编解码;目标库调用它时操作的是未写回的副本:

    1
    2
    3
    4
    5
    6
    virtual function void encode(ref uvm_reg_data_t data[]);
      foreach (data[i]) data[i] ^= 'h55;
    endfunction
    virtual function void decode(ref uvm_reg_data_t data[]);
      foreach (data[i]) data[i] ^= 'h55;
    endfunction
    

    codec 方案直接操作寄存器事务中的值,同时移除或停用上面的旧 encode/decode 实现,避免两次转换:

    1
    2
    3
    4
    5
    6
    virtual task pre_write(uvm_reg_item rw);
      foreach (rw.value[i]) rw.value[i] ^= 'h55;
    endtask
    virtual task post_read(uvm_reg_item rw);
      foreach (rw.value[i]) rw.value[i] ^= 'h55;
    endtask
    

    回调应挂到 backdoor 实例,完整示例中的注册语句为:

    uvm_callbacks#(uvm_reg_backdoor, uvm_reg_cbs)::add(bd, codec);
    

    bd 是实际 backdoor,codec 是上述派生回调。不要将替代直接挂到 reg/field 的共享回调链,否则可能在 frontdoor 访问时也转换数据。自定义 backdoor 的 write/read 必须按契约调用相应 do_pre/do_post 方法;失败读取是否允许解码也须明确。多 codec 原本按逆序 decode,而 post_read 按正序执行,不能逐个机械搬移。示例用本地变量模拟硬件,只覆盖成功访问的数据与回调路径。

    兼容措施与范围:主库与 compat 包均未提供此数据路径的自动恢复。单 codec 替代不能直接推广到多 codec

    已知限制KI-005

    迁移后验证

    访问 status 成功不足以核销本条;环境级断言应同时检查总线或硬件值与逻辑读回值,并覆盖实际使用的全部 codec 组合。

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

    已有实测与复现

    所有数据值均为十六进制。先写逻辑值 0x1,再从硬件值 0x54 读取:

    观察量 1.2 旧写法 2.0 旧写法 修改后,两版
    encoded_hardware:实际写入值 0x54 0x1 0x54
    decoded_value:逻辑读回值 0x1 0x54 0x1

    补充查阅

    扫描定位与记录结果

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

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

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

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

    源码与标准依据

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

    证据tests/uvm_review/backdoor_probe.sv,默认及 +MIGRATED 两组。

    VCS 内置 UVM-1.2uvm_reg_backdoor.svh:75uvm_reg_backdoor.svh:93

    VCS 内置 uvm-ieee-2020-2.0uvm_reg_backdoor.svh:68uvm_reg_backdoor.svh:84;数组访问器 uvm_reg_item.svh:435

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

    src/vcs-uvm-1.2/reg/uvm_reg_backdoor.svh
       protected task do_post_read(uvm_reg_item rw);
          uvm_callback_iter#(uvm_reg_backdoor, uvm_reg_cbs) iter = new(this);
          for(uvm_reg_cbs cb = iter.last(); cb != null; cb=iter.prev())
             cb.decode(rw.value);
          `uvm_do_obj_callbacks(uvm_reg_backdoor,uvm_reg_cbs,this,post_read(rw))
          post_read(rw);
       endtask
    
    
       // Task: do_pre_write
       //
       // Execute the pre-write callbacks
       //
       // This method ~must~ be called as the first statement in
       // a user extension of the <write()> method.
       //
       protected task do_pre_write(uvm_reg_item rw);
          uvm_callback_iter#(uvm_reg_backdoor, uvm_reg_cbs) iter = new(this);
          pre_write(rw);
          `uvm_do_obj_callbacks(uvm_reg_backdoor,uvm_reg_cbs,this,pre_write(rw))
          for(uvm_reg_cbs cb = iter.first(); cb != null; cb = iter.next())
             cb.encode(rw.value);
       endtask
    
    
       // Task: do_post_write
       //
       // Execute the post-write callbacks
       //
       // This method ~must~ be called as the last statement in
       // a user extension of the <write()> method.
       //
       protected task do_post_write(uvm_reg_item rw);
          `uvm_do_obj_callbacks(uvm_reg_backdoor,uvm_reg_cbs,this,post_write(rw))
          post_write(rw);
       endtask
    

    完整源码 · SHA256:96182add2c5ffbd7daec3b9e2adc33c77f7141e4bfd77ff2ca26ac1579ae2d68

    src/vcs-uvm-ieee-2020-2.0/reg/uvm_reg_backdoor.svh
          uvm_reg_data_t value_array[];
          uvm_callback_iter#(uvm_reg_backdoor, uvm_reg_cbs) iter = new(this);
          for(uvm_reg_cbs cb = iter.last(); cb != null; cb=iter.prev()) begin
             rw.get_value_array(value_array);
             cb.decode(value_array);
          end
          `uvm_do_obj_callbacks(uvm_reg_backdoor,uvm_reg_cbs,this,post_read(rw))
          post_read(rw);
       endtask
    
    
    
       // @uvm-ieee 1800.2-2020 auto 19.5.2.4
       protected task do_pre_write(uvm_reg_item rw);
          uvm_reg_data_t rw_value[];
          uvm_callback_iter#(uvm_reg_backdoor, uvm_reg_cbs) iter = new(this);
          pre_write(rw);
          `uvm_do_obj_callbacks(uvm_reg_backdoor,uvm_reg_cbs,this,pre_write(rw))
          for(uvm_reg_cbs cb = iter.first(); cb != null; cb = iter.next()) begin
             rw.get_value_array(rw_value);
             cb.encode(rw_value);
          end
       endtask
    
    
    
       // @uvm-ieee 1800.2-2020 auto 19.5.2.5
       protected task do_post_write(uvm_reg_item rw);
          `uvm_do_obj_callbacks(uvm_reg_backdoor,uvm_reg_cbs,this,post_write(rw))
          post_write(rw);
       endtask
    
    
    
       // @uvm-ieee 1800.2-2020 auto 19.5.2.6
    

    完整源码 · SHA256:650338e20279134559f2ddcc0e250b941e1722e1e69d3edc937c637de14590df

    src/vcs-uvm-ieee-2020-2.0/reg/uvm_reg_item.svh
      this.value = value;
    endfunction
    
    function void uvm_reg_item::get_value_array(ref uvm_reg_data_t value[]);
      value = this.value;
    endfunction
    
    function void uvm_reg_item::set_offset(uvm_reg_addr_t offset);
      this.offset = offset;
    endfunction
    
    function uvm_reg_addr_t uvm_reg_item::get_offset();
      return offset;
    endfunction
    
    function void uvm_reg_item::set_status(uvm_status_e status);
      this.status = status;
    endfunction
    

    完整源码 · SHA256:f0ef6373d2292ca32e5dcbb2ba20db3542bef2cd68fd1e00a57d2f3019ef9a36

    术语解释 · 兼容配置

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

    版本适用范围