← Design Verification Interviews
Interview Question · Code Reading
A Static Variable That Lost Its Value
The Question
The interviewer asks
What does this print? The packet of length 10 carries an inner packet of length 4.
// C
static int cur_len; // the packet being parsed
extern "C" int c_parse(int len, int inner_len) {
cur_len = len;
sv_on_header(inner_len); // export: may parse an inner packet
return cur_len;
}
// SystemVerilog
import "DPI-C" context function int c_parse(input int len, input int inner_len);
export "DPI-C" function sv_on_header;
function void sv_on_header(input int inner_len);
if (inner_len != 0) void'(c_parse(inner_len, 0)); // a tunnelled packet
endfunction
initial $display("%0d", c_parse(10, 4));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
It prints 4, not 10. The export runs inside the outer call and calls c_parse again for the inner packet. That nested call writes the one static cur_len, so the outer call returns the inner length. A static is safe only if nothing can re-enter before the call finishes. A callback can re-enter, and so can a context task that waits in an exported task. Keep in-progress state in local variables or a per-call struct.
Self-Check
Tick each key point you covered in your answer.
What Interviewers Listen For (Mid-Level)
Traces the nested call through the export and predicts 4.
What Interviewers Listen For (Senior)
Lists both ways back into C, callbacks and suspended tasks, and rejects a mutex as the fix.
Cross-Questions
Where the interviewer goes next. Open a node to practise that follow-up.
WhyWhat IfBreak ItCompare
- A Static Variable That Lost Its Value
-
WhyWhy Forked Threads Do Not Interleave in CL2 Mid-Level
Why is a C static safe when two forked SystemVerilog threads call the same plain import?
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
An imported function returns in zero time and cannot block. So the scheduler never switches threads while it runs. The second thread enters only after the first call has returned. The danger starts only when C calls back into SystemVerilog, or when an imported task suspends.
Self-Check
Tick each key point you covered in your answer.
Misconception
"Each SystemVerilog thread is an OS thread, so C needs locks."
SystemVerilog threads are simulator processes, not OS threads. The simulator runs DPI calls one at a time on its own thread.
Source IEEE 1800-2017 §35.5.1 (imported functions complete without consuming time)
-
CompareThree Places for C StateL2 Mid-Level
Compare the three places C state can live: a local variable, a struct behind a handle, and a static or global.
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 local lasts for one call, so re-entry cannot harm it. A struct behind a
chandlelasts as long as the model, and each instance owns its own. A static lasts for the whole simulation and is shared by every caller and every instance. Use locals for work in progress, the struct for model state, and statics almost never.Storage Lifetime Shared by Breaks when Local variable One call Nobody Never, for re-entry Struct behind a chandle From model_newtomodel_deleteHolders of that handle The handle is copied by mistake Static or global The whole simulation Every call and instance A second instance or a nested call Pick the shortest lifetime that still works.
Self-Check
Tick each key point you covered in your answer.
Missed Corner
"A static is fine while the bench has one agent."
The next project adds a second agent, and both share the static. Lesson D1.6 measured exactly that failure.
Source Lesson D1.6 review claims (a shared global gave a=4 b=4)
-
What IfRe-Entry Through a Suspended TaskL3 Senior
Asked if the import is a context task
What if the import is a
contexttask that waits inside an exported task, and two agents call it?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
Agent A enters C and suspends inside the export. While it waits, agent B calls the same C function and runs it from the top. Both calls are now live in C at once. Any static they touch is shared, so the C code must be reentrant.
Self-Check
Tick each key point you covered in your answer.
Misconception
"The simulator queues agent B until agent A's C call returns."
Nothing queues it. A suspended task has handed control back to the scheduler, and B's call proceeds at once.
Source IEEE 1800-2017 §35.5.1.5 (reentrancy of imported tasks)
-
Break ItA Mutex That Hangs the SimulationL3 Senior
Break it: someone wraps the C task in a
std::mutexto fix the re-entry. What happens?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
Agent B's call comes from the same OS thread that still holds the lock for agent A. Locking a
std::mutexyou already own is undefined, and usually blocks forever. Agent A can never resume, because the simulator thread is now stuck. Remove the static instead.Self-Check
Tick each key point you covered in your answer.
Half-Truth
"Use a recursive mutex, then."
It stops the hang, but both calls still edit the same static. The lock protects nothing when the re-entry is on one thread.
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 variable is private to the call that set it."
There is one copy for the whole program. The twin's nested parse writes 4 over the 10 that the outer call stored.
Run It
A C parser keeps the current length in a static. An export parses a tunnelled packet through the same import.
outer length returned=4 FAIL: the nested call overwrote the static cur_len before the outer call returnedSee the Fix
module tb;
import "DPI-C" context function int c_parse(input int len, input int inner_len);
export "DPI-C" function sv_on_header;
// The header hook parses a tunnelled inner packet through the same import.
function void sv_on_header(input int inner_len);
if (inner_len != 0) void'(c_parse(inner_len, 0));
endfunction
int outer;
initial begin
outer = c_parse(10, 4);
$display("outer length returned=%0d", outer);
if (outer != 10) $display("FAIL: the nested call overwrote the static cur_len before the outer call returned");
else $display("PASS: each call kept its own length in a local variable");
$finish;
end
endmodule
Prints: outer length returned=10 PASS: each call kept its own length in a local variable
Misconception
"Two forked threads can interleave inside a plain import function."
An imported function runs to completion on the simulator thread. The scheduler cannot switch to another SystemVerilog thread in the middle of it.
Source Spear & Tumbush, SystemVerilog for Verification (3rd ed.), §12.6 (a call to an imported routine is never interrupted by the scheduler)
Wrong Altitude
"Protect the static with a mutex."
The nested call comes from the same thread. A normal mutex locked twice by one thread is undefined behaviour, and in practice it hangs the simulation.
Source ISO C++17 [thread.mutex.requirements.mutex] (lock by the owning thread is undefined)