`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