← Design Verification Interviews
Interview Question · Concept
Static Members of a Parameterized Class
The Question
The interviewer asks
class box #(type T = int); has a static int created; that its constructor increments. You construct two box#(int) and one box#(byte). What do box#(int)::created and box#(byte)::created read, and why?
You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
They read 2 and 1. Each distinct set of parameter values makes a separate class type, called a specialization. Each specialization has its own copy of every static member. So a parameterized class cannot hold one counter for all its specializations. Put that state in a non-parameterized base class or a package.
axi_txn with a static counter, and a parameterized id_pool used with two widths. Dashed badges are calls or reads of a static; solid badges are values that come back or counts that change.- Three reads
Each read takes its ID from the 4-bit pool: 0, 1 and 2. Each constructor also increments
created.Follow the calls, values and waits
- call alloc(), 3 times: Three reads → id_pool #(4)::next_id
- data IDs 0, 1, 2: id_pool #(4)::next_id → Three reads
- data created: 1, 2, 3: Three reads → axi_txn::created
- Two error transactions
They draw IDs 0 and 1 from the 8-bit pool, a separate counter. Their
super.newincrements the samecreated, which reaches 5.Follow the calls, values and waits
- call alloc(), 2 times: Two err_txns → id_pool #(8)::next_id
- data IDs 0, 1: id_pool #(8)::next_id → Two err_txns
- data created: 4, 5: Two err_txns → axi_txn::created
- Fourteen more from the 4-bit pool
The 4-bit pool hands out 3 to 15, wraps, and hands out 0. Its
next_idis now 1, while the 8-bit pool still holds 2.Follow the calls, values and waits
- call alloc(), 14 times: Test code → id_pool #(4)::next_id
- data 3 to 15, then 0: id_pool #(4)::next_id → Test code
- The default specialization
id_pool #()takes the defaultWIDTHof 4, so it is the same class asid_pool #(4)and reads the same counter: 1.Follow the calls, values and waits
- call id_pool #()::next_id: Test code → id_pool #(4)::next_id
- data 1: id_pool #(4)::next_id → Test code
Read the diagram as text
- Three reads: axi_txn objects
- Two err_txns: derived objects
- axi_txn::created: static, in the base class
- id_pool #(4)::next_id: wraps after 15
- id_pool #(8)::next_id: a separate class
- Test code: 14 more alloc() calls
- Three reads → id_pool #(4)::next_id: alloc()
- Two err_txns → id_pool #(8)::next_id: alloc()
- Three reads → axi_txn::created: created++
- Two err_txns → axi_txn::created: created++ in super.new
- Test code → id_pool #(4)::next_id: alloc(), next_id
A static exists once per class. Each specialization of id_pool is its own class; err_txn is not.
Self-Check
Tick each key point you covered in your answer.
What Interviewers Listen For (Mid-Level)
A good mid-level answer predicts 2 and 1. It moves shared state into a base class that has no parameters.
What Interviewers Listen For (Senior)
A good senior answer explains why a registry of parameterized classes still needs one collector without parameters. It keeps static members out of classes that every agent creates.
Cross-Questions
Where the interviewer goes next. Open a node to practise that follow-up.
WhyWhat IfProve ItCompareScale It
- Static Members of a Parameterized Class
-
WhyWhy Each Specialization Is Its Own ClassL2 Mid-Level
Why doesn't the language share statics across all specializations of a parameterized class?
2:30You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
A type parameter can change the type and size of members, including statics declared with
T. Sobox#(int)andbox#(string)may not even have compatible statics. The language therefore treats every specialization as a separate class, generated from one template, and the statics follow.Self-Check
Tick each key point you covered in your answer.
Tool as Truth
"It is a simulator optimisation and tools differ."
The rule is in the standard: a specialization is a distinct type with its own static members.
Source IEEE 1800-2017 §8.25
-
What IfOne Counter for Every SpecializationL2 Mid-Level
What if you want one counter shared by every specialization, such as a global transaction ID?
2:30You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
Put the static in a base class without parameters, and derive the parameterized class from it. Derived classes share the static properties of their base class. So every specialization then updates the same counter. Reach it through the base class name, such as
item_base::next_id.Self-Check
Tick each key point you covered in your answer.
Misconception
"Declare it
staticin the parameterized class; static means one copy."Each specialization is its own class with its own statics.
box#(int)andbox#(string)then count separately.Source IEEE 1800-2017 §8.25
-
What IfTwo Agents, One Static SettingL1 JuniorL2 Mid-Level
Asked if they use statics for configuration
Port 0's agent writes to
2004although it was configured with base address1000. Port 1 was configured with2000. The agent stores its base address in astatic int. What happened?log cfg: port0 base_addr=1000 cfg: port1 base_addr=2000 port0: write addr=2004 <-- expected 10042:30You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
A static member is one variable per class, shared by every instance. Configuring port 1 overwrote the value port 0 had set. Make the setting an instance member, or pass a per-instance configuration object.
Self-Check
Tick each key point you covered in your answer.
Misconception
"Each agent object keeps its own static value."
There is only one, no matter how many objects exist. The twin configures two agents and port 0 ends up with port 1's address.
Run It
Two agents configure a
static int base_addrin turn.RUNVerilator · simulator serviceExpected:port0 writes to 00002004FAIL: a static is shared by every instance, so port1 overwrote port0's addressSee the Fix
class agent; int base_addr; // the fix: per-instance configuration function void configure(int a); base_addr = a; endfunction function int target(int off); return base_addr + off; endfunction endclass module tb; agent port0, port1; initial begin port0 = new; port0.configure('h1000); port1 = new; port1.configure('h2000); $display("port0 writes to %h", port0.target(4)); if (port0.target(4) == 'h1004) $display("PASS: each agent kept its own address"); else $display("FAIL: a static is shared by every instance, so port1 overwrote port0's address"); end endmodulePrints:
port0 writes to 00001004PASS: each agent kept its own address -
Prove ItSolve 6.4.3: The Monitors That Watched One BusSimulator-graded
Show it, don't just say it: this Silicon Lab problem is graded by the simulator.
-
CompareForward Class DeclarationsL1 JuniorL2 Mid-Level
A
driverclass holds a handle to asequencer, and thesequencerholds a handle back to thedriver. Comparetypedef classwith reordering the file to make this compile.2:30You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
Reordering cannot work, because each class names the other before it is declared.
typedef class sequencer;declares the name first, sodrivercan hold asequencerhandle. The full class can follow later in the same scope. Reordering is enough only when the dependency runs one way.Self-Check
Tick each key point you covered in your answer.
Misconception
"
typedef classcopies the class definition earlier in the file."It only declares the name as a class type; the definition must still appear later in the same scope.
Source IEEE 1800-2017 §6.18
-
Scale ItType Parameters vs a Common Base ClassL3 Senior
You are designing a reusable scoreboard. Do you parameterize it by transaction type, or write it against a common base transaction class?
2:30You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
A type parameter gives full type safety and needs no casts. But
scoreboard#(axi_txn)andscoreboard#(apb_txn)share no type, so they cannot sit in one array. A base-class design can hold any transaction and swap types at run time. The price is a cast wherever code needs derived fields. Many teams combine them: a parameterized class that extends a non-parameterized base holding the common interface.Self-Check
Tick each key point you covered in your answer.
What Interviewers Listen For (Senior)
A good senior answer names what each choice makes impossible. It picks the mixed design only after saying what must be shared while the test runs.
Half-Truth
"Parameterize everything; it is more reusable."
Unrelated specializations cannot be stored or handled together, which hurts reuse when an environment needs to treat many scoreboards alike.
-
Prove ItSolve 4.6.1: Typed Value BoxSimulator-graded
Show it, don't just say it: this Silicon Lab problem is graded by the simulator.
What People Get Wrong
Common wrong answers and why they fail. Run It shows the wrong belief failing on a real simulator.
Misconception
"A static member is shared by every object of box."
It is shared by every object of one specialization. The twin counts three boxes and no single counter reaches 3.
Run It
Two box#(int) and one box#(byte), each constructor incrementing a static counter.
box#(int)::created=2 box#(byte)::created=1 FAIL: each specialization has its own static, so no counter saw all three boxesSee the Fix
class box_base;
static int created; // the fix: one counter in a non-parameterized base
endclass
class box #(type T = int) extends box_base;
function new(); created++; endfunction
endclass
module tb;
box #(int) a, b;
box #(byte) c;
initial begin
a = new; b = new; c = new;
$display("boxes created: %0d", box_base::created);
if (box_base::created == 3) $display("PASS: the base class counted every specialization");
end
endmodule
Prints: boxes created: 3 PASS: the base class counted every specialization
Spec Misquote
"box and box#() are two different types."
The bare name and #() both mean the default specialization, so they share statics.
Source IEEE 1800-2017 §8.25
Half-Truth
"Statics are the easy way to share configuration between components."
They are shared with every instance of the class, including a second agent that needs a different setting.