addrpropertydatapropertyformat()method
Part 1 · Objects and construction
Separate types, objects, and handles, then initialize inherited and parameterized class state with explicit visibility and ownership.
Question directory
Questions for Objects + construction
Open an authored answer, then use the adjacent object diagram or code example to verify the mechanism.
- class model and visibilityWhat is the difference between a class, an object, and an object handle?SystemVerilog OOP→
- class model and visibilityHow do encapsulation, abstraction, inheritance, and polymorphism differ?SystemVerilog OOP→
- class model and visibilityHow do public, protected, and local visibility work in SystemVerilog classes?SystemVerilog OOP→
- class model and visibilityDoes SystemVerilog support method overloading by argument type?SystemVerilog OOP→
- class model and visibilityWhy keep class state protected or local behind methods?SystemVerilog OOP→
- construction and specializationWhat does the new() constructor do in a SystemVerilog class?SystemVerilog OOP→
- construction and specializationWhen must a derived constructor call super.new()?SystemVerilog OOP→
- construction and specializationWhat is the difference between this and super?SystemVerilog OOP→
- construction and specializationHow do value and type parameters specialize a class?SystemVerilog OOP→
- construction and specializationWhat does static mean for a class property or method?SystemVerilog OOP→
SystemVerilog class model and visibilityKnow what the handle actually owns.
Start with the SystemVerilog object model, the four OOP ideas, and the visibility rules that keep verification classes reusable without exposing mutable internals.
A class defines behavior; handles reach objects
addr = 10addr = 42addr = 91unqualifiedclasschildoutsideprotectedclasschildoutsidelocalclasschildoutsideThe class is one type definition. Each new allocation creates a distinct object, while handle assignment can make multiple names refer to the same object.
A class is a type definition. An object is one allocated instance of that class. A class variable stores a handle that is either null or refers to an object; the handle is not the object itself.
Reason it through
- Declaring Packet p creates a handle initialized to null. Executing p = new allocates a Packet object and places its handle in p.
- Two different calls to new create two independent objects. Assigning one handle to another creates an alias to the same object.
- Methods execute against the object reached through the handle, so a null-handle dereference is a runtime error.
class Packet;
int id;
endclass
Packet p; // null handle
Packet alias_p;
p = new; // allocate one Packet object
p.id = 7;
alias_p = p; // same object, second handle
alias_p.id = 9; // p.id is now 9Encapsulation controls access to state, abstraction exposes the behavior callers need, inheritance extends an existing type, and polymorphism lets one base-typed call select behavior from the actual derived object.
Reason it through
- Encapsulation is the boundary around representation and invariants; visibility qualifiers are one implementation tool.
- Abstraction is about the public contract. A
virtual classor pure virtual method can make that contract explicit. - SystemVerilog supports single class inheritance through extends. Polymorphism depends on virtual methods, not inheritance alone.
| Principle | Question it answers | SystemVerilog mechanism |
|---|---|---|
| Encapsulation | Who may touch this state? | public, protected, local |
| Abstraction | What behavior is promised? | base API, virtual class |
| Inheritance | What definition is extended? | extends and super |
| Polymorphism | Which implementation runs? | virtual method dispatch |
Public members are visible wherever the object is visible. Protected members are visible inside the declaring class and its derived classes. Local members are visible only inside the declaring class.
Reason it through
- Public access is the default when no visibility qualifier is written; ordinary public members are left unqualified in SystemVerilog source.
- SystemVerilog uses
localfor the private-style visibility level; private is not the class-member keyword. - Prefer
protectedstate when derived verification classes need controlled access, and public methods when outside callers need a stable interface.
class Base;
int visible_everywhere; // public by default
protected int visible_to_children;
local int visible_only_here;
endclass
class Child extends Base;
function void configure();
visible_everywhere = 1; // legal
visible_to_children = 2; // legal
// visible_only_here = 3; // illegal
endfunction
endclassNo. A class cannot declare multiple methods with the same name and different argument lists the way C++ or Java can. Use distinct names, default arguments, or a typed wrapper instead.
Reason it through
- Overloading chooses among same-named signatures at compile time. That language feature is not available for SystemVerilog class methods.
- Overriding is different: a derived class supplies the same signature as a virtual base method.
- Default arguments can cover closely related call forms when one return type and one implementation are appropriate.
class MathOps;
function int add_int(int a, int b);
return a + b;
endfunction
function real add_real(real a, real b);
return a + b;
endfunction
endclassA method boundary lets the class preserve invariants, validate updates, and change its representation without forcing every caller to change.
Reason it through
- A setter can reject an illegal value or update related fields atomically.
- A getter can expose a stable view without giving an outside component permission to corrupt internal state.
- In a verification environment, a scoreboard should observe driver state through a deliberate interface rather than mutate the driver's internals.
SystemVerilog construction and specializationInitialize the hierarchy in order.
Reason about new(), base-constructor chaining, this and super, parameterized class types, and state shared at class scope.
Construction flows from base state to specialization
super.new(args)Base constructorestablish inherited statethis.tag = tagDerived constructorfinish specialized statePacket #(WIDTH, T)WIDTH = 64value parameterT = bit[15:0]type parameterPacket #(64, bit[15:0])A derived constructor establishes inherited state before its own fields. Value and type parameters specialize the class at compile time rather than at object creation.
new allocates an object and runs that class's constructor function to establish valid initial state. The constructor may accept arguments and assign instance properties, but it cannot consume simulation time.
Reason it through
- The constructor is declared as function new with no explicit return type.
- Use this.member when a formal argument has the same name as a property.
- Default property initialization happens before constructor statements execute.
class Packet;
int id;
string kind;
function new(int id = 0, string kind = "READ");
this.id = id;
this.kind = kind;
endfunction
endclass
Packet p = new(7, "WRITE");The base constructor always runs before the derived constructor body. If the base constructor needs arguments, the derived constructor must call super.new(...) as its first executable statement.
Reason it through
- When the base constructor has no required arguments, the compiler can insert an implicit super.new call.
- Explicitly calling super.new makes required base-state initialization visible in review.
- Construction proceeds from the oldest base class toward the most-derived class.
class BasePacket;
int id;
function new(int id);
this.id = id;
endfunction
endclass
class TaggedPacket extends BasePacket;
string tag;
function new(int id, string tag);
super.new(id);
this.tag = tag;
endfunction
endclassthis is the handle to the current object. super is a lexical keyword that selects the immediate base-class implementation or constructor; it is not a handle that can be stored.
Reason it through
- Use this.field to disambiguate an instance property from a same-named argument.
- Use super.method() to call the immediate base implementation from an override.
- Use
super.new(...)only in a constructor and with the arguments required by the immediate base.
A parameterized class is a family of class types. Value parameters control constants such as width, while type parameters substitute a data type; each distinct parameter tuple is a distinct specialized type.
Reason it through
- Defaults let callers use Packet #() while named overrides document specializations clearly.
- Fields and method signatures can derive from both the value and type parameters. If T is declared rand, callers must choose a type the randomization model supports.
- Parameter selection happens in the type declaration, not as arguments to new.
class Packet #(
parameter int WIDTH = 32,
type T = int
);
rand bit [WIDTH-1:0] data;
T id;
endclass
Packet #() default_packet = new;
Packet #(.WIDTH(64), .T(bit [15:0])) wide_packet = new;A static property has one value shared by every object of that class type. A static method belongs to class scope, cannot use per-object state without an explicit handle, and is normally called with ClassName::method().
Reason it through
- Use a static counter for type-wide statistics, instance numbering, registries, or one shared service handle.
- The class-scope operator makes the owning type explicit and does not require an object.
- A derived class that declares a same-named static member creates a separate hidden member; it does not override the base static.
class Counter;
static int total = 0;
int serial;
function new();
total++;
serial = total;
endfunction
static function int get_total();
return total;
endfunction
endclass
int count = Counter::get_total();