Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutRoadmapCareersInternshipsFAQContactPrivacyTerms
Skip to lesson

Course contents

  • How to Use This Puzzle Bank
  • SystemVerilog Language Puzzles25
  • Difficulty Guide
  • Full Topic Map
  • Interview-Day Tips
  • Study Route: One Week Before the Interview
  • Study Route: Two Weeks
  • Study Route: Four Weeks (Full Course)4
  • OOP & Testbench Puzzles25
  • Concurrency & Timing Puzzles25
  • Randomization & Constraint Puzzles25
  • SVA Assertion Puzzles25
  • Functional Coverage Puzzles25
  • Logic & Aptitude Puzzles25
  • Scenario & Debug Puzzles25
    • Testbench Debug Puzzles: Why Did the Test Hang?
    • Deadlock Scenario Puzzles: Objection and Phase Stalls
      • Early Return Leaves Objection Raised
      • Background Poller Keeps Running After Traffic Ends
      • Semaphore Token Leak on Error Path
      • join_any Ends the Task with the Mailbox Full
      • Lock Inversion with Two Semaphores
      • disable fork Kills the Thread That Owned the Drop
    • Scoreboard Puzzles: Mismatch or Ordering Bug?
    • Real Interview Rounds: End-to-End Debug Walkthrough
    • Scenario & Debug Puzzles: Tricky Q&A
  • UVM Testbench Puzzles25
  • Clock, Reset & CDC Puzzles25
  • Bus and Interface Protocol Puzzles25
  • Interview Prep: Puzzle Rounds7
  • DV Puzzle Cheatsheet
Loading lesson

←Deadlock Scenario Puzzles: Objection and Phase Stalls
  1. Topics
  2. DV Interview Puzzles
  3. Scenario & Debug Puzzles
  4. Deadlock Scenario Puzzles: Objection and Phase Stalls
  5. Background Poller Keeps Running After Traffic Ends
On this page

    VLSI DV Interview PuzzlesAll levels

    Background Poller Keeps Running After Traffic Ends

    Tests that pass every functional check still print UVM_ERROR [STATUS] 'unexpected power state', on every run, in the last microsecond or two, after the log already says 'all traffic done'. The run_phase drain time is 2us. Explain why the error appears after the test is finished, and fix it.

    Puzzle

    Difficulty: Medium · Puzzle 2 of 6 · Topic: Deadlock Scenario Puzzles: Objection and Phase Stalls

    Tests that pass every functional check still print UVM_ERROR [STATUS] 'unexpected power state', on every run, in the last microsecond or two, after the log already says 'all traffic done'. The run_phase drain time is 2us. Explain why the error appears after the test is finished, and fix it.

    Code

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    task run_phase(uvm_phase phase);
      phase.raise_objection(this);
      fork
        begin
          forever begin
            poll_status();      // flags an error if the DUT is not in ACTIVE state
            #100ns;
          end
        end
      join_none
      start_traffic();
      enter_low_power();        // last step of the test: DUT leaves ACTIVE state on purpose
      phase.drop_objection(this);
    endtask

    Hint

    Dropping an objection does not stop other threads in the phase; what keeps the run phase alive for the next 2us?

    Step-by-step solution

    Diagram
    1) Look at timestamps: the error comes after enter_low_power() and after the drop, inside the 2us drain time (or while other components still hold objections).
    2) drop_objection does not stop the poller thread. The run_phase process tree is only killed when the whole phase ends, which happens after the drain time and after all other objections drop (UVM kills the phase's process tree at phase end, so there is no permanent leak and no memory growth). The error is deterministic: the poller fires every 100ns for the whole 2us drain, so any run where the DUT is out of ACTIVE for more than 100ns reports it.
    3) During that window the forever poller keeps calling poll_status() against a DUT that is now deliberately in low power, so it raises a false error.
    4) Fix: stop the poller before the final step, with a flag (while (!stop_poll)) or a process handle (p.kill() or a labelled begin..end block you disable) set right after start_traffic() and before enter_low_power().
    5) Add a check that no background thread issues DUT accesses after the objection drop (for example an assertion on a 'test_done' flag inside poll_status).

    Answer

    Answer: Bug: the join_none poller is never stopped, so it runs through the drain window after the final objection drop and checks a DUT that is intentionally in low power. Fix: stop it explicitly (stop flag or process handle) before the last step of the test. UVM kills the phase process tree at phase end, so this is a false-error bug, not a permanent leak.

    How this was checked

    Checked by running the code in Verilator 5; the printed output supports the answer above. Plain-SV model of a join_none poller, not the UVM library: it keeps checking through the drain window unless stopped first.

    Why candidates get it wrong

    The common wrong explanation is 'a leaked thread that never dies': in UVM the phase kills the thread tree at phase end. The real damage is what the thread does before that. A true leak needs a thread started outside the phase tree (a module-level initial or a static object).

    Interviewer follow-up

    How would you standardize stoppable background threads across agents/components? Model answer: Give the component base class a start_bg(task) wrapper that stores the process handle (or uses a named fork block), plus a stop_bg() called from a phase hook (extract_phase or an explicit 'traffic done' event); pollers loop on while (!stop) with a wait or event rather than forever, so every background thread has one documented owner and one stop path.

    Say it out loud

    First I notice the error is reported after the final objection drop, during the drain window, so I look at what is still running then. The root cause is a join_none poller that is never stopped, so it checks a DUT that is intentionally in low power. It is a false error, not a permanent leak, because UVM kills the phase threads at phase end. I confirm it by logging the poller against the drop time, and the fix is to stop it with a flag or process handle before the last step of the test.

    Related topics

    • set_drain_time Deep Dive: Grace Period After Objections Clear

    • End-of-Test Strategy: Choosing a Mechanism

    • Back to Deadlock Scenario Puzzles: Objection and Phase Stalls

    • Scenario & Debug Puzzles section

    Previous

    193 / 293

    Next: Semaphore Token Leak on Error Path

    Up next

    Up nextSemaphore Token Leak on Error Path

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • join_any Ends the Task with the Mailbox Full
    • Lock Inversion with Two Semaphores
    • disable fork Kills the Thread That Owned the Drop