Week 5 · Day 23 · 7 hours

Day 23 — SystemVerilog OOP I: Transaction Classes

Build a reusable packet transaction library with constructors, methods, copy, compare, print, and safe object-handle semantics.

01

Concept lesson

Understand the language feature before coding

Day 23 — SystemVerilog OOP I

Simulation status (28 Oct 2026): The commands below pass on Verilator 5.052. Icarus Verilog 12 does not support classes. Details: Week 5 validation record (VALIDATION.md).

XLS source: Day 23, 7 hours (theory 2 + guided 2 + independent 2 + debug 1).
Deliverable: OOP transaction library.

Workspace

project_workspace/week5_systemverilog/day23_oop_i

Guided lab (6 activities)

  1. Define a basic packet class.
  2. Create an object with new.
  3. Add a constructor.
  4. Use this to assign fields.
  5. Add a display method.
  6. Add an independent copy method.

Independent lab (6 activities)

  1. Add a compare method.
  2. Demonstrate handle assignment (aliasing).
  3. Guard null handles.
  4. Store objects in a fixed array.
  5. Store objects in a queue.
  6. Build a reusable transaction utility class.

Debug challenge

Demonstrate that alias_handle = original shares the same object; after mutation, the alias changes. Demonstrate that original.copy() preserves independent state. Show a null-handle guard without dereferencing null.

Commands

mkdir -p tb sim logs
verilator --binary --timing --top-module day23_oop_i tb/day23_oop_i.sv -o day23_sim
./obj_dir/day23_sim | tee logs/day23.log

These commands pass on Verilator 5.052. Record your simulator version, exit status and complete log. If your simulator lacks class support, mark execution blocked rather than reporting PASS.

Evidence

Submit SV sources, PASS/FAIL logs, alias-versus-copy output, null-handle evidence, four written explanations, and version compatibility notes. Do not include Week 6 constraints/interfaces or Week 8 UVM content.

02

Visual explanation

Connect syntax with simulator behavior

Class handles and object identity: a = new(); b = a;; Both handles refer to one object; Independent copy must allocate new object
Class handles and object identity
Reusable transaction class: Constructor initializes fields; copy() / compare() / display(); Null checks and independent object state
Reusable transaction class
03

Worked example

Read and run the supplied SystemVerilog source

Example source · Day 23
// Day 23 — SystemVerilog OOP I; simulator support must be verified.
class packet;
  int unsigned addr;
  int unsigned data;
  function new(int unsigned addr = 0, int unsigned data = 0);
    this.addr = addr;
    this.data = data;
  endfunction
  function void display();
    $display("packet addr=%0h data=%0h", addr, data);
  endfunction
  function packet copy();
    packet result = new(this.addr, this.data);
    return result;
  endfunction
  function bit compare(packet rhs);
    if (rhs == null) return 0;
    return this.addr == rhs.addr && this.data == rhs.data;
  endfunction
endclass

module day23_oop_i;
  packet original, alias_handle, independent, nullable;
  packet fixed_array[2];
  packet packet_queue[$];
  initial begin
    original = new('h10, 'hAA);
    original.display();
    alias_handle = original; // handle assignment: alias, not a copy
    independent = original.copy();
    if (!independent.compare(original)) $fatal(1, "copy mismatch");
    original.data = 'h55;
    if (alias_handle.data != 'h55) $fatal(1, "alias did not reflect mutation");
    if (independent.data != 'hAA) $fatal(1, "SHALLOW_COPY_BUG");
    if (independent.compare(original)) $fatal(1, "compare failed to detect difference");
    nullable = null;
    if (nullable == null) $display("NULL_HANDLE_GUARD PASS");
    else $fatal(1, "null guard failed");
    fixed_array[0] = original;
    fixed_array[1] = independent;
    packet_queue.push_back(original);
    packet_queue.push_back(independent);
    if (packet_queue.size() != 2 || fixed_array[1].data != 'hAA)
      $fatal(1, "object collection mismatch");
    if (packet_queue.pop_front() != original) $fatal(1, "queue order mismatch");
    $display("DAY23 PASS");
    $finish;
  end
endmodule

Compile and run

  1. mkdir -p sim logs
  2. verilator --binary --timing --top-module day23_oop_i tb/day23_oop_i.sv -o day23_sim
  3. ./obj_dir/day23_sim | tee logs/day23.log

What to verify

  • constructor and this
  • display
  • copy independence
  • compare equal/different
  • handle aliasing
  • null guard
  • object array
  • object queue
  • transaction utility

Pass condition: All checks pass, copied object stays independent after original changes, null is guarded and simulator reports DAY23 PASS.

04

Hands-on practice

Complete the exercises in order

    Written assignment

    1. Draw a class/object/handle diagram.
    2. Explain why assigning one class handle to another is not a deep copy.
    3. Compare original, alias and copied transactions after mutation.
    4. Provide null-handle guard and simulator/version evidence.

    Debug challenge

    Demonstrate null-handle failure safely and prove that handle assignment aliases an object while explicit copy produces an independent object.

    Completion criteria

    All 12 XLS activities mapped; reusable transaction library passes class-construction, compare, independent copy, object array/queue, and null-handle guard tests.

    05

    Knowledge check

    Check your understanding

    What does a SystemVerilog class variable hold?

    A handle to an object, or null; it does not embed the object itself.

    What is the purpose of this in a constructor?

    It refers to the current object, disambiguating object properties from arguments.

    Why does assigning one object handle to another not copy the object?

    Both handles reference the same object; use an explicit copy method to create independent state.

    What should be checked before calling a method through an optional handle?

    Check that the handle is not null.

    What does new do when assigned to a class handle?

    It constructs an object and returns its handle.

    What is a shallow copy of an object containing another object handle?

    The outer fields are copied but both objects still reference the same nested object.

    Evidence to retain

    • SystemVerilog source
    • simulator/version and commands
    • PASS/FAIL log
    • alias versus copy results
    • null-handle guard proof
    • written explanation