HomeProblemsTheoryUVM
Beginner3 min readChapter 4

uvm_object & uvm_component

The two base classes of UVM — understand when to extend uvm_object vs uvm_component and the utility macros.

uvm_object & uvm_component

Everything in UVM inherits from one of two base classes. Knowing which to use is essential.


The Class Hierarchy

text
uvm_void uvm_object ← Data / transient items ┌─────┴──────┐ uvm_transaction uvm_component ← Structural / persistent │ ┌────┴─────┐ uvm_sequence_item uvm_driver uvm_monitor uvm_env ...

uvm_object — For Data Items

Use uvm_object for things that represent data or configuration:

  • Sequence items (transactions)
  • Configuration objects
  • Register models
  • Anything created, used, and discarded
systemverilog
class apb_transaction extends uvm_sequence_item; `uvm_object_utils(apb_transaction) rand bit [31:0] addr; rand bit [31:0] data; rand bit write; function new(string name = "apb_transaction"); super.new(name); endfunction // Convert to human-readable string for debug function string convert2string(); return $sformatf("addr=0x%08h data=0x%08h %s", addr, data, write ? "WR" : "RD"); endfunction endclass

Key characteristics of uvm_object:

PropertyValue
ConstructorTakes only name
Phases❌ No phases
LifetimeTransient — created and destroyed
Hierarchy❌ No parent-child tree
Copy/Compare✅ Supports clone(), copy(), compare()

uvm_component — For Structural Elements

Use uvm_component for things that are part of the testbench structure:

  • Drivers, monitors, sequencers
  • Agents, environments
  • Scoreboards, coverage collectors
systemverilog
class apb_driver extends uvm_driver #(apb_transaction); `uvm_component_utils(apb_driver) virtual apb_if vif; function new(string name, uvm_component parent); super.new(name, parent); // Note: takes parent! endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); if (!uvm_config_db#(virtual apb_if)::get(this, "", "vif", vif)) `uvm_fatal("NOVIF", "Virtual interface not found") endfunction task run_phase(uvm_phase phase); // Drive signals... endtask endclass

Key characteristics of uvm_component:

PropertyValue
ConstructorTakes name and parent
Phases✅ build, connect, run, report, etc.
LifetimePersistent — lives for entire simulation
Hierarchy✅ Forms a parent-child tree
Copy/Compare❌ Not supported

The Utility Macros

MacroUse WithWhat It Does
\uvm_object_utils(T)uvm_object subclassesRegisters type T with the factory
\uvm_component_utils(T)uvm_component subclassesRegisters type T with the factory

Always register your classes. Without registration, the factory can't create or override them.


Quick Decision Guide

QuestionAnswer
Does it have a parent in the hierarchy?uvm_component
Is it data flowing through the testbench?uvm_object
Does it need build/connect/run phases?uvm_component
Is it a transaction or config?uvm_object

Field Automation (Optional)

UVM provides field macros for automatic copy(), compare(), print(), pack():

systemverilog
class my_txn extends uvm_sequence_item; `uvm_object_utils_begin(my_txn) `uvm_field_int(addr, UVM_ALL_ON) `uvm_field_int(data, UVM_ALL_ON) `uvm_field_enum(op_t, op, UVM_ALL_ON) `uvm_object_utils_end rand bit [31:0] addr; rand bit [31:0] data; rand op_t op; function new(string name = "my_txn"); super.new(name); endfunction endclass

Now you can do:

systemverilog
my_txn a, b; a = my_txn::type_id::create("a"); a.randomize(); // Clone b = my_txn::type_id::create("b"); b.copy(a); // Compare if (!a.compare(b)) `uvm_error("CMP", "Mismatch!") // Print a.print();

Performance note: Field macros add overhead. In high-performance simulations, implement do_copy() and do_compare() manually.