跳转至

输入查询内容

    本页内容

    跨版本位流与显式序列化格式

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

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

    结果对比

    观察内容 UVM 1.2 UVM 2.0
    packet 的位数与位流 packet_bits 148:1100001101010101010101100100110100000000000000000000000000000000000000100000000000000000000000000001000100000000000000000000000000011101100010010110 308:11000011010101010101011001001101000000000000000000000000000000000000001000000000000000000000000000010001000000000000000000000000000111010000000000000000000000000000000101110011011001010111001001101001011000010110110001101001011110100110010101100100010111110110110001100101011000010110011000000000100101101000
    同库 packet 打包再解包一致(1=是) packet_roundtrip 1 1
    自定义固定格式的位数与位流 explicit_wire_bits 148:1100001101010101010101100100110100000000000000000000000000000000000000100000000000000000000000000001000100000000000000000000000000011101100010010110 148:1100001101010101010101100100110100000000000000000000000000000000000000100000000000000000000000000001000100000000000000000000000000011101100010010110
    自定义格式打包再解包一致(1=是) explicit_wire_roundtrip 1 1
    深拷贝后的叶对象数据 deep_copy_leaf 96 96
    GP 使用兼容 packer 的打包位数 gp_compat_count 240 241
    GP 解包后:地址、两个数据字节(十六进制)、DMI 标志 gp_roundtrip 1234:96:21:0 1234:96:21:1
    长度异常对象的 compare 返回值(1=相等) bad_size_equal 1 0
    长度异常引起的消息数 bad_size_messages 0 1
    未 flush 时重复输出产生的消息数 no_flush_messages 0 1
    copy(null) 产生的旧版消息数 copy_null_legacy 1 0
    copy(null) 产生的目标版消息数 copy_null_new 0 1

    运行命令

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

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

    最小源码

    serialization_probe.sv

    serialization_probe.sv
    `timescale 1ns/1ps
    `include "uvm_macros.svh"
    import uvm_pkg::*;
    `ifdef REVIEW_UVM20
    import uvm_compat_pkg::*;
    `endif
    
    class serialized_leaf extends uvm_object;
      byte unsigned value;
      `uvm_object_utils_begin(serialized_leaf)
        `uvm_field_int(value, UVM_ALL_ON)
      `uvm_object_utils_end
      function new(string name="serialized_leaf"); super.new(name); endfunction
    endclass
    
    class serialized_packet extends uvm_object;
      byte unsigned tag;
      string label;
      int values[];
      serialized_leaf leaf;
      `uvm_object_utils_begin(serialized_packet)
        `uvm_field_int(tag, UVM_ALL_ON)
        `uvm_field_string(label, UVM_ALL_ON)
        `uvm_field_array_int(values, UVM_ALL_ON)
        `uvm_field_object(leaf, UVM_ALL_ON)
      `uvm_object_utils_end
      function new(string name="serialized_packet"); super.new(name); leaf = new(); endfunction
    endclass
    
    class serialization_catcher extends uvm_report_catcher;
      int seen[string];
      function new(); super.new("serialization_catcher"); endfunction
      function action_e catch();
        if (get_id() inside {"UVM/COMPARER/INT/BAD_SIZE", "UVM/PRINT/NO_FLUSH", "NULLCP", "OBJ/COPY"}) begin
          seen[get_id()]++;
          return CAUGHT;
        end
        return THROW;
      endfunction
    endclass
    
    class legacy_wire_packet extends uvm_object;
      `uvm_object_utils(legacy_wire_packet)
      serialized_packet payload;
      function new(string name="legacy_wire_packet"); super.new(name); payload = new(); endfunction
      function void do_pack(uvm_packer packer);
        packer.pack_field_int(payload.tag, 8);
        packer.pack_string(payload.label);
        packer.pack_field_int(payload.values.size(), 32);
        foreach (payload.values[i]) packer.pack_field_int(payload.values[i], 32);
        // The legacy object marker is four LSB-first bits, followed by the leaf value.
        for (int i=0; i<4; i++) packer.pack_field_int(i == 0 && payload.leaf != null, 1);
        if (payload.leaf != null) packer.pack_field_int(payload.leaf.value, 8);
      endfunction
      function void do_unpack(uvm_packer packer);
        int size, marker;
        payload.tag = packer.unpack_field_int(8);
        payload.label = packer.unpack_string();
        size = packer.unpack_field_int(32);
        if (size < 0 || size > 16) `uvm_fatal("WIRE", "Invalid fixture length")
        payload.values = new[size];
        foreach (payload.values[i]) payload.values[i] = packer.unpack_field_int(32);
        for (int i=0; i<4; i++) marker |= packer.unpack_field_int(1) << i;
        if (marker == 0) payload.leaf = null;
        else begin
          if (payload.leaf == null) payload.leaf = new();
          payload.leaf.value = packer.unpack_field_int(8);
        end
      endfunction
    endclass
    
    module serialization_probe;
      initial begin
        serialized_packet original = new("original"), restored = new("restored"), copied = new("copied");
        legacy_wire_packet wire_original = new(), wire_restored = new();
        uvm_tlm_generic_payload gp = new("gp"), restored_gp = new("restored_gp");
        serialization_catcher catcher = new();
        uvm_packer packer;
        uvm_comparer comparer = new();
        uvm_table_printer printer = new();
        byte unsigned data[] = '{8'h96, 8'h21};
        byte unsigned restored_data[];
        bit stream[];
        string stream_text, formatted;
        int count;
        bit equal;
    `ifdef REVIEW_UVM20
        uvm_compat_packer legacy = new();
        packer = legacy;
    `else
        packer = new();
    `endif
        #1;
        uvm_report_cb::add(null, catcher);
        comparer.verbosity = UVM_DEBUG;
        original.tag = 'hc3; original.label = "UVM";
        original.values = '{17, 29}; original.leaf.value = 'h96;
    `ifdef REVIEW_UVM20
        legacy.use_metadata = 1;
    `else
        packer.use_metadata = 1;
    `endif
        count = original.pack(stream, packer);
        stream_text = "";
        foreach (stream[i]) stream_text = {stream_text, stream[i] ? "1" : "0"};
        $display("REVIEW|packet_bits|%0d:%s", count, stream_text);
        count = restored.unpack(stream, packer);
        equal = original.compare(restored, comparer);
        $display("REVIEW|packet_roundtrip|%0d", equal);
        wire_original.payload = original;
        count = wire_original.pack(stream, packer);
        stream_text = "";
        foreach (stream[i]) stream_text = {stream_text, stream[i] ? "1" : "0"};
        $display("REVIEW|explicit_wire_bits|%0d:%s", count, stream_text);
        count = wire_restored.unpack(stream, packer);
        $display("REVIEW|explicit_wire_roundtrip|%0d", original.compare(wire_restored.payload, comparer));
        copied.copy(original);
        original.leaf.value = 'h55;
        $display("REVIEW|deep_copy_leaf|%0h", copied.leaf.value);
    
        gp.set_address('h1234); gp.set_write(); gp.set_data(data);
        gp.set_data_length(2); gp.set_streaming_width(2);
        gp.set_response_status(UVM_TLM_OK_RESPONSE); gp.set_dmi_allowed(1);
        count = gp.pack(stream, packer);
        $display("REVIEW|gp_compat_count|%0d", count);
        count = restored_gp.unpack(stream, packer);
        restored_gp.get_data(restored_data);
        $display("REVIEW|gp_roundtrip|%0h:%0h:%0h:%0d", restored_gp.get_address(), restored_data[0], restored_data[1], restored_gp.is_dmi_allowed());
    
        equal = comparer.compare_field_int("too_wide", 0, 0, 65);
        $display("REVIEW|bad_size_equal|%0d", equal);
        $display("REVIEW|bad_size_messages|%0d", catcher.seen["UVM/COMPARER/INT/BAD_SIZE"]);
        printer.print_field("value", 5, 8, UVM_HEX);
        formatted = printer.emit();
        formatted = printer.emit();
        $display("REVIEW|no_flush_messages|%0d", catcher.seen["UVM/PRINT/NO_FLUSH"]);
        copied.copy(null);
        $display("REVIEW|copy_null_legacy|%0d", catcher.seen["NULLCP"]);
        $display("REVIEW|copy_null_new|%0d", catcher.seen["OBJ/COPY"]);
        $display("REVIEW|done|1");
        $finish;
      end
    endmodule
    

    全部用例 · 证据摘要

    版本适用范围