Classes, Objects & Handles

Classes, constructors, this, static members, and the difference between copying a handle and copying an object.

Classes are the foundation of modern testbenches: transactions, generators, drivers, monitors and scoreboards are all classes. A class defines fields and methods; new() creates an object; a variable of the class type holds a handle — a reference — to an object, exactly as in Java or C#.

A packet class

Packet p1; declares a handle; it is null until new() creates an object.

p2 = p1; copies the handle: both refer to one object, so a change through p2 is seen through p1.

p3 = p1.copy(); creates a separate object with the same contents.

Packet::count reads the static member through the class name.

Memory and copying

Packet p; p.addr = 5; // null handle Packet p = new(); p.addr = 5;

A declared handle is null; using it is a run-time error. Create the object first.

expected.push_back(t); // then reusing t for the next item t.addr = next_addr;

expected.push_back(t.copy()); // or create a new object per item

Pushing a handle stores a reference, not the data. Changing t afterwards changes the item already in the queue — a classic scoreboard bug.

What does p2 = p1; do for class handles?

Copies the reference: p1 and p2 now point to the same object. No new object is created.

What is a static class member?

A field or method that belongs to the class itself rather than to each object; all objects share it, and it is accessed as Class::name.