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.