跳转至

输入查询内容

    本页内容

    后门 Backdoor map 告警:reg/field/mirror 分支与限定 RW 字段替代

    环境:VCS W-2024.09-SP2-8。1.2 使用 uvm-1.2,2.0 使用 uvm-ieee-2020-2.0

    实验检查观察值是否符合预期;成功复现问题不代表问题已修复。

    结果对比

    观察内容 UVM 1.2 UVM 2.0
    已映射 reg 后门访问,省略 map:Backdoor map 归属告警次数 reg_null_warnings 0 0
    已映射 reg 后门访问,省略 map:status、读回、硬件与镜像符合断言(1=是) reg_null_data_ok 1 1
    reg 后门访问,显式伪 map:Backdoor map 归属告警次数 reg_pseudo_warnings 0 3
    reg 后门访问,显式伪 map:status、读回、硬件与镜像符合断言(1=是) reg_pseudo_data_ok 1 1
    field 后门访问,省略 map:Backdoor map 归属告警次数 field_null_warnings 0 3
    field 后门访问,省略 map:status、读回、硬件与镜像符合断言(1=是) field_null_data_ok 1 1
    field 后门访问,传实际 map:Backdoor map 归属告警次数 field_real_warnings 0 3
    field 后门访问,传实际 map:status、读回、硬件与镜像符合断言(1=是) field_real_data_ok 1 1
    未关联实际 map 的 reg 后门访问:Backdoor map 归属告警次数 reg_unmapped_warnings 0 3
    未关联实际 map 的 reg 后门访问:status、读回、硬件与镜像符合断言(1=是) reg_unmapped_data_ok 1 1
    reg 后门访问,传实际 map:Backdoor map 归属告警次数 reg_real_warnings 0 0
    reg 后门访问,传实际 map:status、读回、硬件与镜像符合断言(1=是) reg_real_data_ok 1 1
    已映射 reg 的 mirror 传伪 map:Backdoor map 归属告警次数 mirror_pseudo_warnings 0 0
    已映射 reg 的 mirror 传伪 map:status、读回、硬件与镜像符合断言(1=是) mirror_pseudo_data_ok 1 1
    field 改由父寄存器读取与限定 RW 合成写:Backdoor map 归属告警次数 field_via_reg_warnings 0 0
    field 改由父寄存器读取与限定 RW 合成写:status、读回、硬件与镜像符合断言(1=是) field_via_reg_data_ok 1 1

    运行命令

    目录与环境准备;从解包根目录执行:

    uv run tools/run_uvm_review.py --case backdoor_map_probe --variants 12,20
    

    最小源码

    backdoor_map_probe.sv

    backdoor_map_probe.sv
    `timescale 1ns/1ps
    `include "uvm_macros.svh"
    import uvm_pkg::*;
    
    interface map_storage_if;
      bit [31:0] value;
    endinterface
    
    class map_storage_backdoor extends uvm_reg_backdoor;
      virtual map_storage_if vif;
      function new(string name = "bd"); super.new(name); endfunction
      virtual task write(uvm_reg_item rw);
        do_pre_write(rw);
        vif.value = rw.value[0];
        rw.status = UVM_IS_OK;
        do_post_write(rw);
      endtask
      virtual function void read_func(uvm_reg_item rw);
        rw.value[0] = vif.value;
        rw.status = UVM_IS_OK;
      endfunction
    endclass
    
    class map_storage_reg extends uvm_reg;
      uvm_reg_field low_byte, value, high_half;
      function new(string name = "rg"); super.new(name, 32, UVM_NO_COVERAGE); endfunction
      function void build();
        low_byte = new("low_byte");
        value = new("value");
        high_half = new("high_half");
        low_byte.configure(this, 8, 0, "RW", 0, 0, 1, 0, 1);
        value.configure(this, 8, 8, "RW", 0, 0, 1, 0, 1);
        high_half.configure(this, 16, 16, "RW", 0, 0, 1, 0, 1);
      endfunction
    endclass
    
    class map_storage_block extends uvm_reg_block;
      map_storage_reg rg;
      function new(string name = "model"); super.new(name, UVM_NO_COVERAGE); endfunction
      function void build(bit mapped = 1);
        rg = new(); rg.configure(this); rg.build();
        if (mapped) begin
          default_map = create_map("map", 0, 4, UVM_LITTLE_ENDIAN, 1);
          default_map.add_reg(rg, 0, "RW");
        end
        lock_model();
      endfunction
    endclass
    
    class backdoor_map_observer extends uvm_report_catcher;
      int map_warnings;
      function new(string name = "observer"); super.new(name); endfunction
      virtual function action_e catch();
        if (get_severity() == UVM_WARNING && get_id() == "RegModel" &&
            uvm_is_match("*is not contained within map 'Backdoor'*", get_message()))
          map_warnings++;
        return THROW;
      endfunction
    endclass
    
    module backdoor_map_probe;
      map_storage_if hw();
      initial begin
        map_storage_block model = new();
        map_storage_block unmapped_model = new("unmapped_model");
        map_storage_backdoor bd = new();
        backdoor_map_observer observer = new();
        uvm_status_e status;
        uvm_reg_data_t value, full_value, mask, expected;
        string scenario_names[8] = '{"reg_null", "reg_pseudo", "field_null", "field_real",
                                    "reg_unmapped", "reg_real", "mirror_pseudo", "field_via_reg"};
        model.build();
        unmapped_model.build(0);
        bd.vif = hw;
        model.rg.set_backdoor(bd);
        unmapped_model.rg.set_backdoor(bd);
        uvm_report_cb::add(null, observer);
        mask = '1;
        mask >>= $bits(uvm_reg_data_t) - model.rg.value.get_n_bits();
    
        for (int scenario = 0; scenario < 8; scenario++) begin
          hw.value = 'h12345678;
          void'(model.rg.predict(hw.value));
          void'(unmapped_model.rg.predict(hw.value));
          observer.map_warnings = 0;
          $display("PROBE|begin|%s", scenario_names[scenario]);
          case (scenario)
            0: model.rg.read(status, value, UVM_BACKDOOR);
            1: model.rg.read(status, value, UVM_BACKDOOR, uvm_reg_map::backdoor());
            2: model.rg.value.read(status, value, UVM_BACKDOOR);
            3: model.rg.value.read(status, value, UVM_BACKDOOR, model.default_map);
            4: unmapped_model.rg.read(status, value, UVM_BACKDOOR);
            5: model.rg.read(status, value, UVM_BACKDOOR, model.default_map);
            6: begin
              model.rg.mirror(status, UVM_CHECK, UVM_BACKDOOR, uvm_reg_map::backdoor());
              value = model.rg.get_mirrored_value();
            end
            7: begin
              model.rg.read(status, full_value, UVM_BACKDOOR);
              value = (full_value >> model.rg.value.get_lsb_pos()) & mask;
            end
          endcase
          expected = (scenario inside {2, 3, 7}) ? 'h56 : 'h12345678;
          if (status != UVM_IS_OK || value != expected)
            `uvm_fatal("BACKDOOR_MAP", "Read status/data mismatch")
    
          // This fixture has RW fields and no concurrent hardware writer.
          case (scenario)
            0, 6: model.rg.write(status, 'h89abcdef, UVM_BACKDOOR);
            1: model.rg.write(status, 'h89abcdef, UVM_BACKDOOR, uvm_reg_map::backdoor());
            2: model.rg.value.write(status, 'hab, UVM_BACKDOOR);
            3: model.rg.value.write(status, 'hab, UVM_BACKDOOR, model.default_map);
            4: unmapped_model.rg.write(status, 'h89abcdef, UVM_BACKDOOR);
            5: model.rg.write(status, 'h89abcdef, UVM_BACKDOOR, model.default_map);
            7: begin
              model.rg.read(status, full_value, UVM_BACKDOOR);
              if (status != UVM_IS_OK) `uvm_fatal("BACKDOOR_MAP", "RMW read failed")
              full_value = (full_value & ~(mask << model.rg.value.get_lsb_pos())) |
                           ((uvm_reg_data_t'('hab) & mask) << model.rg.value.get_lsb_pos());
              model.rg.write(status, full_value, UVM_BACKDOOR);
            end
          endcase
          expected = (scenario inside {2, 3, 7}) ? 'h1234ab78 : 'h89abcdef;
          if (status != UVM_IS_OK || hw.value != expected)
            `uvm_fatal("BACKDOOR_MAP", "Write status/hardware mismatch")
          if (scenario == 6) begin
            model.rg.mirror(status, UVM_CHECK, UVM_BACKDOOR, uvm_reg_map::backdoor());
            if (status != UVM_IS_OK) `uvm_fatal("BACKDOOR_MAP", "Mirror failed")
          end
          if (((scenario == 4) ? unmapped_model.rg.get_mirrored_value() :
                                model.rg.get_mirrored_value()) != expected)
            `uvm_fatal("BACKDOOR_MAP", "Mirror value mismatch")
          $display("REVIEW|%s_warnings|%0d", scenario_names[scenario], observer.map_warnings);
          $display("REVIEW|%s_data_ok|1", scenario_names[scenario]);
        end
        $display("REVIEW|done|1");
        $finish;
      end
    endmodule
    

    全部用例 · 证据摘要

    版本适用范围