UVM field macros are the `uvm_field_* macros placed between `uvm_object_utils_begin and `uvm_object_utils_end (or the component equivalents). Each one registers a single class property, so that the automatic copy(), compare(), print(), pack() and record() methods include it. A flag argument decides which of those operations apply to the field and how it is printed.

Data objects and configuration objects are copied, compared and printed constantly as they move through a testbench. Field macros let you get all of that working with one line per field instead of writing do_copy(), do_compare() and do_print() for every class.

7 min read | Intermediate Level

What You'll Learn

  • Pick the right field macro for each data type
  • Use FLAG values to include or exclude a field from individual operations
  • Control the print radix of integral fields
  • Use field macros in components for automatic configuration

Syntax


`uvm_object_utils_begin(TYPE)
  `uvm_field_int    (ARG, FLAG)          // integral property
  `uvm_field_enum   (T, ARG, FLAG)       // enum property of enum type T
  `uvm_field_string (ARG, FLAG)          // string property
  `uvm_field_object (ARG, FLAG)          // class handle derived from uvm_object
`uvm_object_utils_end
  • ARG is the property name. Its type must match the macro, so a string uses `uvm_field_string, not `uvm_field_int.
  • FLAG controls which operations include the field, plus an optional print radix. UVM_DEFAULT is the recommended value; it currently turns every operation on, the same as UVM_ALL_ON.
  • Enum fields need the extra type argument T, so the printer can show the enum's name rather than its number.

Field Macros by Data Type

There is a macro for every common property type, and for arrays of each type.

PropertyMacros
Single value`uvm_field_int, `uvm_field_enum, `uvm_field_string, `uvm_field_real, `uvm_field_object, `uvm_field_event
Static array`uvm_field_sarray_int, _sarray_enum, _sarray_string, _sarray_object
Dynamic array`uvm_field_array_int, _array_enum, _array_string, _array_object
Queue`uvm_field_queue_int, _queue_enum, _queue_string, _queue_object
Associative array`uvm_field_aa_int_string, `uvm_field_aa_string_string, `uvm_field_aa_object_string, and `uvm_field_aa_int_<key> for integral keys

For associative arrays the macro name encodes both types: `uvm_field_aa_int_string is an array of integral values indexed by strings.

FLAG Values

Flags are combined with the | operator. A flag other than UVM_ALL_ON or UVM_DEFAULT names the operations to leave out, and the field still takes part in all the others.

FlagEffect
UVM_ALL_ONTurn every operation on
UVM_DEFAULTRecommended setting; currently identical to UVM_ALL_ON
UVM_NOCOPYLeave the field out of copy()
UVM_NOCOMPARELeave the field out of compare()
UVM_NOPRINTLeave the field out of print() and sprint()
UVM_NOPACKLeave the field out of pack() and unpack()
UVM_REFERENCEFor object fields, act on the handle only, with no deep copy
UVM_READONLYDo not let automatic configuration set this field

A typical use is a checksum or timestamp field. You want it copied and printed, but two otherwise identical transactions captured at different times should still compare equal, so it gets UVM_NOCOMPARE.

Print Radix

Integral fields print in hexadecimal unless you OR a radix flag into FLAG. The radix affects only printing and recording, never copy or compare.

FlagPrints as
UVM_BINBinary
UVM_OCTOctal
UVM_DECSigned decimal
UVM_UNSIGNEDUnsigned decimal
UVM_HEXHexadecimal (the default)
UVM_STRINGString
UVM_TIMETime

For example, `uvm_field_int(m_len, UVM_ALL_ON | UVM_DEC) prints a length as 16 instead of 'h10.

Example: Nested Objects

In this example Parent registers an enum, an integral field, a queue, a string and a handle to a Child object, which registers its own two fields.


typedef enum {FALSE, TRUE} e_bool;

class Child extends uvm_object;
  string 	 m_name;
  logic[3:0] m_age;

  `uvm_object_utils_begin(Child)
  	`uvm_field_string 	(m_name, UVM_ALL_ON)
  	`uvm_field_int 		(m_age, UVM_ALL_ON)
  `uvm_object_utils_end

  function new(string name="Child");
    super.new(name);
  endfunction
endclass

class Parent extends uvm_object;

  string 	m_name;
  bit[15:0]	m_age;
  int 		m_numbers[$];
  e_bool 	m_employed;
  Child 	m_child;

  `uvm_object_utils_begin(Parent)
  	`uvm_field_enum			(e_bool, m_employed, UVM_ALL_ON)
  	`uvm_field_int			(m_age, UVM_ALL_ON)
  	`uvm_field_queue_int 	(m_numbers, UVM_ALL_ON)
  	`uvm_field_string 		(m_name, UVM_ALL_ON)
  	`uvm_field_object 		(m_child, UVM_ALL_ON)
  `uvm_object_utils_end

  function new(string name="Parent");
    super.new(name);
  endfunction

endclass

module tb;
  initial begin
    Parent p = Parent::type_id::create("Parent");
    p.m_name = "Joey";
    p.m_employed = TRUE;
    p.m_age = 29;
    p.m_numbers = '{1234, 5678, 9011};
    p.m_child = new();
    p.m_child.m_name = "Joey Jr";
    p.m_child.m_age  = 1;

    p.print();
  end
endmodule
Output
ncsim> run
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_root.svh(392) @ 0: reporter [UVM/RELNOTES]

-----------------------------------------
Name          Type          Size  Value
-----------------------------------------
Parent        Parent        -     @1829
  m_employed  e_bool        32    TRUE
  m_age       integral      16    'h1d
  m_numbers   da(integral)  3     -
    [0]       integral      32    'h4d2
    [1]       integral      32    'h162e
    [2]       integral      32    'h2333
  m_name      string        4     Joey
  m_child     Child         -     @1830
    m_name    string        7     Joey Jr
    m_age     integral      4     'h1
-----------------------------------------
ncsim: *W,RNQUIE: Simulation is complete.

The fields print in the order they were registered, not the order they were declared, which is why m_employed comes first. Integral values use the default hex radix, so m_age value 29 appears as 'h1d. The nested m_child is printed in full, indented under its handle, because `uvm_field_object without UVM_REFERENCE works on the object's contents.

Quick Check

Q: How would you change Parent so that m_age prints as 29 and is ignored by compare()?

Show Answer

Use `uvm_field_int(m_age, UVM_ALL_ON | UVM_DEC | UVM_NOCOMPARE). UVM_DEC changes the print radix and UVM_NOCOMPARE removes the field from comparisons, while copy, print and pack still include it.

When to Use Field Macros

Field macros are ideal for configuration objects and low-traffic classes, where convenience matters more than speed. For transactions that are created millions of times in a regression, the generic code the macros expand into adds measurable simulation time, and many teams write do_copy(), do_compare() and do_print() by hand instead. Both approaches can be mixed in one testbench, as covered in UVM Utility & Field Macros.

Field Macros in Components

Components can register fields with `uvm_component_utils_begin too, and there they add one more feature: automatic configuration. In uvm_component::build_phase, UVM looks up every configuration setting aimed at the component and assigns matching registered fields for you.


class my_agent extends uvm_agent;
  int unsigned num_masters = 1;            // default if nobody configures it

  `uvm_component_utils_begin(my_agent)
    `uvm_field_int(num_masters, UVM_DEFAULT)
  `uvm_component_utils_end

  function new(string name = "my_agent", uvm_component parent = null);
    super.new(name, parent);
  endfunction

  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);              // applies matching config settings to fields
    // num_masters now holds any value configured for this agent
    // Rest of the code (create driver, monitor, ...)
  endfunction
endclass

// In the test, before the agent's build_phase runs
uvm_config_int::set(this, "m_env.m_agent", "num_masters", 4);

uvm_config_int is a convenience typedef for the configuration database with the integral type that automatic configuration uses for `uvm_field_int fields. The call to super.build_phase(phase) is what triggers the lookup, so leaving it out turns automatic configuration off for that component. The full mechanism is covered in UVM Config Database.

Common Mistakes

Mistake #1: Registering a component handle without UVM_REFERENCE

Wrong: `uvm_field_object(m_sequencer, UVM_DEFAULT) in a configuration object
Right: `uvm_field_object(m_sequencer, UVM_DEFAULT | UVM_REFERENCE)

Why? Without UVM_REFERENCE, the macro tries to deep-copy the field, and copying a component is illegal. Copying or cloning the containing object then ends in a FATAL error, and printing shows duplicate entries for the component.

Mistake #2: Using the wrong macro for the property type

Wrong: `uvm_field_int(m_name, UVM_DEFAULT) for a string
Right: `uvm_field_string(m_name, UVM_DEFAULT)

Why? Each macro generates code for one data type. A mismatch either fails to compile or treats the value as the wrong type, for example printing a string as a large hex number.

Mistake #3: Skipping super.build_phase() and expecting auto-configuration

A component that registers fields but overrides build_phase without calling super.build_phase(phase) never has those fields configured. The value set in the test is silently ignored and the field keeps its default.

Mistake #4: Forgetting the enum type argument

`uvm_field_enum takes three arguments, with the enum type first: `uvm_field_enum(e_bool, m_employed, UVM_ALL_ON). Leaving the type out is a compile error, and using `uvm_field_int instead loses the readable enum names in printed output.

Summary

In this article, you learned:

  • Each `uvm_field_* macro registers one property for copy, compare, print, pack and record
  • There is a macro per data type and per array kind, and the macro must match the property's type
  • FLAG values such as UVM_NOCOMPARE leave a field out of specific operations, and UVM_DEFAULT includes it in all of them
  • Radix flags such as UVM_DEC change only printing and recording, and hex is the default
  • In components, registered fields are configured automatically when super.build_phase() runs, and component handles need UVM_REFERENCE
Did you find what you were looking for?

Quiz

Test Your Knowledge

1 of 5 Score: 0 / 5