Skip to main content

UVM do_ Methods

· loading · loading · ·
Education UVM Verification UVM Verification SystemVerilog Do_ Methods
Education UVM Verification
Axolot Logic
Author
Axolot Logic
Digital Design Engineer
Table of Contents
UVM Series - This article is part of a series.
Part 7: This Article

🔧 UVM do_ Methods
#

🚀 Introduction
#

In UVM, methods prefixed with do_ are virtual methods designed to be overridden by the user. These methods are defined in UVM base classes and allow you to implement your own logic while keeping the standard UVM flow intact.

This concept typically follows the template method pattern, providing customization points without breaking the default flow.


🗂️ uvm_object do_ Methods
#

📝 do_copy()
#

This method handles object copying. It’s automatically called by the copy() method.

class my_transaction extends uvm_sequence_item;
  rand bit [31:0] address;
  rand bit [31:0] data;
  rand opcode_e opcode;
  time timestamp;

  function void do_copy(uvm_object rhs);
    my_transaction rhs_txn;
    super.do_copy(rhs);

    if (!$cast(rhs_txn, rhs)) begin
      `uvm_error("COPY_ERROR", "Failed to cast object in do_copy")
      return;
    end

    // Custom copy logic
    this.address = rhs_txn.address;
    this.data = rhs_txn.data;
    this.opcode = rhs_txn.opcode;
    this.timestamp = $time; // Set current time
  endfunction

  `uvm_object_utils(my_transaction)
endclass

🧐 do_compare()
#

Handles object comparison. It’s automatically called by the compare() method.

class my_transaction extends uvm_sequence_item;
  rand bit [31:0] address;
  rand bit [31:0] data;
  rand opcode_e opcode;
  bit ignore_timestamp = 1; // Control flag

  function bit do_compare(uvm_object rhs, uvm_comparer comparer);
    my_transaction rhs_txn;
    bit result = super.do_compare(rhs, comparer);

    if (!$cast(rhs_txn, rhs)) begin
      `uvm_error("COMPARE_ERROR", "Failed to cast object in do_compare")
      return 0;
    end

    // Custom comparison logic
    result &= (this.address == rhs_txn.address);
    result &= (this.data == rhs_txn.data);
    result &= (this.opcode == rhs_txn.opcode);

    // Optionally compare timestamp
    if (!ignore_timestamp)
      result &= (this.timestamp == rhs_txn.timestamp);

    return result;
  endfunction

  `uvm_object_utils(my_transaction)
endclass

📋 do_print()
#

Customizes object printing, used by print() and sprint().

class cpu_instruction extends uvm_sequence_item;
  rand bit [31:0] instruction;
  rand bit [4:0] rs, rt, rd;
  string mnemonic;

  function void do_print(uvm_printer printer);
    super.do_print(printer);

    // Custom print formatting
    printer.print_string("mnemonic", mnemonic);
    printer.print_field("instruction", instruction, 32, UVM_HEX);
    printer.print_field("rs", rs, 5, UVM_DEC);
    printer.print_field("rt", rt, 5, UVM_DEC);
    printer.print_field("rd", rd, 5, UVM_DEC);

    // Decoded instruction
    string decoded = decode_instruction();
    printer.print_string("decoded", decoded);
  endfunction

  function string decode_instruction();
    return $sformatf("%s r%0d, r%0d, r%0d", mnemonic, rd, rs, rt);
  endfunction

  `uvm_object_utils(cpu_instruction)
endclass

📦 do_pack() and do_unpack()
#

For serialization and deserialization.

class network_packet extends uvm_sequence_item;
  bit [47:0] dest_mac;
  bit [47:0] src_mac;
  bit [15:0] ethertype;
  byte payload[$];
  bit [31:0] crc;

  function void do_pack(uvm_packer packer);
    super.do_pack(packer);

    // Pack in network byte order
    packer.pack_field(dest_mac, 48);
    packer.pack_field(src_mac, 48);
    packer.pack_field(ethertype, 16);

    // Pack payload size then payload
    packer.pack_field(payload.size(), 32);
    foreach (payload[i])
      packer.pack_field(payload[i], 8);

    packer.pack_field(crc, 32);
  endfunction

  function void do_unpack(uvm_packer packer);
    int payload_size;
    super.do_unpack(packer);

    dest_mac = packer.unpack_field(48);
    src_mac = packer.unpack_field(48);
    ethertype = packer.unpack_field(16);

    // Unpack payload
    payload_size = packer.unpack_field(32);
    payload = new[payload_size];
    foreach (payload[i])
      payload[i] = packer.unpack_field(8);

    crc = packer.unpack_field(32);
  endfunction

  `uvm_object_utils(network_packet)
endclass

💡 Summary
#

🔹 do_ methods let you customize object behavior while preserving UVM’s standard workflow.
🔹 They’re typically called automatically by higher-level UVM methods like copy(), compare(), print(), etc.
🔹 Use them to integrate custom behavior, additional fields, or specialized functionality into your verification components.


UVM Series - This article is part of a series.
Part 7: This Article

Related

UVM Agent Usage and Adder Example
· loading · loading
Education UVM Verification UVM Verification SystemVerilog Uvm_agent Testbench Structure
Education UVM Verification
UVM Base Classes
· loading · loading
Education UVM Verification UVM Verification SystemVerilog Class Hierarchy
Education UVM Verification
UVM Driver Usage and Adder Example
· loading · loading
Education UVM Verification UVM Verification SystemVerilog Uvm_driver Stimulus Driving
Education UVM Verification
UVM Environment Usage and adder_env Example
· loading · loading
Education UVM Verification UVM Verification SystemVerilog Uvm_env Testbench Structure
Education UVM Verification
UVM Monitor Usage and Adder Example
· loading · loading
Education UVM Verification UVM Verification SystemVerilog Uvm_monitor Coverage
Education UVM Verification
UVM Object Class
· loading · loading
Education UVM Verification UVM Verification SystemVerilog Uvm_object
Education UVM Verification