Packing more than 4KB with uvm_packer results in a silent buffer overflow. This then causes silent data corruption on unpack. This issue is present in both UVM 1.2 and UVM 1800.2 2020.
The attached test case was run on Questa 2020.4_2.
UVM 1800.2-2020 1.1
Commands:
gcc -m64 -fPIC -DQUESTA -g -W -shared -x c -I${QUESTA_ROOT}/include ${UVM_HOME}/src/dpi/uvm_dpi.cc -o uvm_dpi.so
qrun -sv +incdir+${UVM_HOME}/src +define+UVM_1800_2_2020 -sv_lib uvm_dpi ${UVM_HOME}/src/uvm_pkg.sv uvm_packer_buffer_overflow.sv
Errors:
# UVM_ERROR uvm_packer_buffer_overflow.sv(49) @ 0: reporter [uvm_packer_buffer_overflow] data_out[1024]:0x00000000 != data_in[1022]:0x9b387ab5
# UVM_ERROR uvm_packer_buffer_overflow.sv(49) @ 0: reporter [uvm_packer_buffer_overflow] data_out[1025]:0x00000000 != data_in[1023]:0x5d3822c4
# UVM_ERROR uvm_packer_buffer_overflow.sv(49) @ 0: reporter [uvm_packer_buffer_overflow] data_out[1026]:0x00000000 != data_in[1024]:0xc6462f4a
UVM 1.2
Command:
qrun -sv +define+UVM_1_2 uvm_packer_buffer_overflow.sv
Error:
# UVM_ERROR uvm_packer_buffer_overflow.sv(49) @ 0: reporter [uvm_packer_buffer_overflow] data_out[1024]:0x00000000 != data_in[1024]:0xc6462f4a
Test
program uvm_packer_buffer_overflow;
import uvm_pkg::*;
`include "uvm_macros.svh"
initial begin
int uvm_packer_max_bytes = 4096;
int uvm_packer_max_dwords = uvm_packer_max_bytes / 4;
int unsigned data_in[] = new[uvm_packer_max_dwords + 1];
int unsigned data_out[];
int offset;
uvm_packer p = new();
foreach (data_in[i]) begin
data_in[i] = $urandom();
end
foreach (data_in[i]) begin
p.pack_field_int(data_in[i], $size(data_in[i]));
end
`ifdef UVM_1_2
p.set_packed_size();
p.get_ints(data_out);
`endif
`ifdef UVM_1800_2_2020
p.get_packed_ints(data_out);
// 1800.2 2020 prepends m_pack_iter and m_unpack_iter
offset = 2;
`endif
assert (data_out.size() == (data_in.size() + offset)) else begin
`uvm_error("uvm_packer_buffer_overflow", $sformatf(
"data_out.size:%0d != (data_in.size:%0d + offset:%0d):%0d",
data_out.size(),
data_in.size(),
offset,
data_in.size() + offset
))
end
foreach (data_out[i]) begin
// Don't compare the following entries for UVM 1800.2 2020:
// data_out[0]: m_pack_iter
// data_out[1]: m_unpack_iter
if (i < offset) continue;
if (data_out[i] != data_in[i - offset]) begin
`uvm_error("uvm_packer_buffer_overflow", $sformatf(
"data_out[%0d]:0x%x != data_in[%0d]:0x%x",
i,
data_out[i],
i - offset,
data_in[i - offset]
))
end
end
end
endprogram
uvm_packer_buffer_overflow.sv