Part 3 · Factory & Configuration · Intermediate

Print, Copy, Compare, and Pack: Using Generated Object Methods

Practical workflows for sprint, copy, compare, and pack on transaction and config objects — the methods field macros generate for you.

Auto-generated method workflows

Field macros generate do_print, do_copy, do_compare, do_pack so scoreboards, predictors, and debug logs can introspect transactions without hand-written boilerplate.

diagram
[UVM] generated method call graph

  sprint()     -> do_print()     -> per-field print per FLAGS
  copy(rhs)    -> do_copy()      -> deep copy per uvm_field_object
  compare(rhs) -> do_compare()   -> field-by-field per FLAGS
  pack/pack_bytes -> do_pack()   -> binary packing per FLAGS
systemverilog
bus_txn a = bus_txn::type_id::create("a");
assert(a.randomize());
`uvm_info("TXN", a.sprint(), UVM_MEDIUM)

bus_txn b = bus_txn::type_id::create("b");
b.copy(a);
if (!a.compare(b)) `uvm_error("CMP", "copy/compare mismatch after clone")

Key takeaways

  • sprint() is the fastest debug path for transaction contents.

  • copy() + compare() is the standard scoreboard reference-model check.

  • Custom do_compare overrides auto-compare when semantics are non-trivial.

Common pitfalls

  • Comparing before randomize settles — stale fields cause false mismatches.

  • Shallow copy on nested objects when uvm_field_object was omitted.

  • Calling compare() across unrelated types without casting guard.


Compare customization and pack patterns

When auto-compare is too strict, override do_compare. Use pack for streaming or recording, with NOPACK on heavy fields.

Custom compare

systemverilog
class timed_txn extends bus_txn;
  int cycle;

  `uvm_object_utils_begin(timed_txn)
    `uvm_field_int(cycle, UVM_ALL_ON | UVM_NOCOMPARE)
    `uvm_object_utils_end

  function bit do_compare(uvm_object rhs, uvm_comparer comparer);
    timed_txn r = timed_txn'(rhs);
    return (addr == r.addr && data == r.data);  // ignore cycle
  endfunction
endclass
diagram
[UVM] compare decision tree

fields match with same semantics?
  yes -> rely on auto-compare via field macros
  no  -> UVM_NOCOMPARE on excluded fields
        OR override do_compare for composite rules

Pack and record usage

systemverilog
// Pack for streaming or waveform record
bit [7:0] bytes[];
a.pack_bytes(bytes);

// Selective pack: exclude large payload
`uvm_field_array_int(payload, UVM_ALL_ON | UVM_NOPACK | UVM_NOCOMPARE)
  • Use UVM_NOCOMPARE on timestamps and simulator-time fields.

  • Use UVM_NOPACK on large arrays used only for stimulus, not checking.

  • Prefer sprint at UVM_MEDIUM for interactive debug, UVM_HIGH for field dumps.

Common pitfalls

  • Overriding do_compare without calling super when base fields still matter.

  • Packing objects with UVM_ALL_ON on multi-kilobyte arrays — regression slowdown.

  • Using compare() in hot loops without trimming FLAGS first.