跳转至

输入查询内容

    本页内容

    32 位寄存器与总线的单拍大端数据问题

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

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

    修改前后对比

    观察内容 1.2 旧写法 2.0 旧写法 1.2 改写后 2.0 改写后
    写操作成功(1=是) write_ok 1 1 1 1
    实际硬件数据(十六进制) hardware 12345678 00000000 12345678 12345678
    读操作成功(1=是) read_ok 1 1 1 1
    读回数据(十六进制) read_value 12345678 00000000 12345678 12345678
    总线传输次数 transfers 2 2 2 2

    运行命令

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

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

    改写后运行命令

    uv run tools/run_uvm_review.py --case reg_width_probe --variants 12,20 --plusarg +MIGRATED --check tests/uvm_review/reg_width_migrated.expected.json
    

    最小源码

    reg_width_probe.sv

    reg_width_probe.sv
    `timescale 1ns/1ps
    `include "uvm_macros.svh"
    import uvm_pkg::*;
    
    class width_item extends uvm_sequence_item;
      bit write;
      bit [31:0] data;
      function new(string name="width_item"); super.new(name); endfunction
    endclass
    
    class width_adapter extends uvm_reg_adapter;
      function new(string name="width_adapter"); super.new(name); endfunction
      function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);
        width_item item = new();
        uvm_reg_data_t data = rw.data;
    `ifdef REVIEW_UVM20
        if ($test$plusargs("MIGRATED") && rw.kind == UVM_WRITE) data = {<< byte {data}};
    `endif
        item.write = rw.kind == UVM_WRITE;
        item.data = data;
        return item;
      endfunction
      function void bus2reg(uvm_sequence_item bus, ref uvm_reg_bus_op rw);
        width_item item;
        if (!$cast(item, bus)) `uvm_fatal("WIDTH", "Unexpected bus item")
        rw.kind = item.write ? UVM_WRITE : UVM_READ;
        rw.data = item.data;
    `ifdef REVIEW_UVM20
        if ($test$plusargs("MIGRATED") && !item.write) rw.data = {<< byte {rw.data}};
    `endif
        rw.status = UVM_IS_OK;
      endfunction
    endclass
    
    class width_driver extends uvm_driver#(width_item);
      bit [31:0] hardware;
      int transfers;
      function new(string name, uvm_component parent); super.new(name, parent); endfunction
      task run_phase(uvm_phase phase);
        width_item item;
        forever begin
          seq_item_port.get_next_item(item);
          #1;
          if (item.write) hardware = item.data;
          else item.data = hardware;
          transfers++;
          seq_item_port.item_done();
        end
      endtask
    endclass
    
    class width_register extends uvm_reg;
      uvm_reg_field value;
      function new(string name="reg32"); super.new(name, 32, UVM_NO_COVERAGE); endfunction
      function void build();
        value = new("value");
        value.configure(this, 32, 0, "RW", 0, 0, 1, 0, 1);
      endfunction
    endclass
    
    class width_block extends uvm_reg_block;
      width_register reg32;
      function new(string name="model"); super.new(name, UVM_NO_COVERAGE); endfunction
      function void build();
        reg32 = new(); reg32.configure(this); reg32.build();
        default_map = create_map("map", 0, 4, UVM_BIG_ENDIAN, 1);
        default_map.add_reg(reg32, 0, "RW");
        lock_model();
      endfunction
    endclass
    
    class width_test extends uvm_test;
      `uvm_component_utils(width_test)
      uvm_sequencer#(width_item) sequencer;
      width_driver driver;
      width_adapter adapter;
      width_block model;
      function new(string name, uvm_component parent); super.new(name, parent); endfunction
      function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        sequencer = new("sequencer", this); driver = new("driver", this);
        adapter = new(); model = new(); model.build();
      endfunction
      function void connect_phase(uvm_phase phase);
        driver.seq_item_port.connect(sequencer.seq_item_export);
        model.default_map.set_sequencer(sequencer, adapter);
        model.default_map.set_auto_predict(1);
      endfunction
      task run_phase(uvm_phase phase);
        uvm_status_e status;
        uvm_reg_data_t value;
        phase.raise_objection(this);
        model.reg32.write(status, 'h12345678);
        $display("REVIEW|write_ok|%0d", status == UVM_IS_OK);
        $display("REVIEW|hardware|%08h", driver.hardware);
        driver.hardware = 'h12345678;
        model.reg32.read(status, value);
        $display("REVIEW|read_ok|%0d", status == UVM_IS_OK);
        $display("REVIEW|read_value|%08h", value[31:0]);
        $display("REVIEW|transfers|%0d", driver.transfers);
        $display("REVIEW|done|1");
        phase.drop_objection(this);
      endtask
    endclass
    
    module reg_width_probe;
      initial run_test("width_test");
    endmodule
    

    全部用例 · 证据摘要

    版本适用范围