Part 11 · Senior Prep · Intermediate

Objections Interview Q&A: Raise, Drop, Propagation, Debug

Model answers on uvm_objection mechanics — hierarchical propagation, source vs total count, drain_time, and hang triage.

Core objection questions

Objections are the quiescence contract for task phases. Senior answers must cover propagation, not just raise/drop syntax.

Q: What is a UVM objection and why does it exist?

diagram
[INT][SENIOR][UVM] MODEL ANSWER

Q: What is a UVM objection?

A:
  MECHANISM:  A per-phase counter at the phase root; raise increments, drop decrements;
              phase ends when count reaches zero plus drain_time.
  MOTIVATION:  Task phases run in parallel — agents, sequences, and tests need a
              shared signal that work is still active without central polling.
  WHEN:       Any task phase (run_phase, main_phase, reset_phase). Never in function
              phases like build_phase or connect_phase.
  PITFALL:    Using #delay in test run_phase instead of objections — hides leaks and
              makes regression runtime non-deterministic.
  EXAMPLE:    Virtual sequence raises in run_phase, starts agent sequences, drops after
              all branches join; phase proceeds to extract only when count hits zero.

Q: How do objections propagate through the hierarchy?

diagram
[INT][SENIOR][UVM] MODEL ANSWER

Q: How do objections propagate?

A:
  MECHANISM:  raise_objection(this) at a leaf propagates up parent chain to the phase
              root; each component tracks source count (own raises) and total count
              (includes children).
  MOTIVATION:  Parent does not need to re-raise for child activity — propagation
              aggregates automatically so one root counter governs phase end.
  WHEN:       Always in standard UVM — understand propagation when debugging hangs
              where child dropped but parent still holds objection.
  PITFALL:    Assuming child drop ends the phase — parent or sibling may still object.
  EXAMPLE:    driver raises, agent also raises for reset hold; driver drops but agent
              still objects — run_phase continues until agent drops too.

Q: What is drain_time and when do you tune it?

diagram
[INT][SENIOR][UVM] MODEL ANSWER

Q: What is drain_time?

A:
  MECHANISM:  After objection count hits zero at phase root, UVM waits drain_time
              before triggering phase_done — allows trailing bus activity to finish.
  MOTIVATION:  Driver may drop objection after last item_done but monitor still sees
              in-flight beats; drain_time absorbs pipeline latency without re-raising.
  WHEN:       Protocols with post-transaction response windows (AXI, PCIe). Set via
              phase.phase_done.set_drain_time(this, N) from test or env.
  PITFALL:    Setting drain_time to milliseconds on every test — silently inflates
              nightly regression wall-clock time across hundreds of seeds.
  EXAMPLE:    AXI test sets 500ns drain_time on run_phase so outstanding B responses
              complete after sequence drops objection.

Q: How do you debug an objection leak?

diagram
[INT][SENIOR][UVM] MODEL ANSWER

Q: How do you debug objection leaks?

A:
  MECHANISM:  phase.phase_done.display_objections() prints all components with
              non-zero source or total count, including description strings.
  MOTIVATION:  Hang means some task phase never completes — objection trace localizes
              the holder in seconds instead of random waveform probing.
  WHEN:       First move on any hung simulation before opening waves or adding delays.
  PITFALL:    Adding global timeout without fixing leak — masks bug, wastes farm time.
  EXAMPLE:    display_objections shows env.v_sqr still holds objection because forked
              branch in virtual sequence never joined before drop_objection.

Key takeaways

  • Objections propagate up — child drop does not guarantee phase end.

  • drain_time is a settle window, not a substitute for proper objection balance.

  • display_objections() is the first debug move on any hang.

Common pitfalls

  • Raising objections in build_phase — only valid for task phases.

  • Using set() on objection count without understanding source vs total semantics.


Advanced objection scenarios

Q: What is phase_ready_to_end and why does it matter?

diagram
[INT][SENIOR][UVM] MODEL ANSWER

Q: What is phase_ready_to_end?

A:
  MECHANISM:  Callback fired after count=0 and drain_time expires, before phase_done
              triggers — component can re-raise to extend the phase one last time.
  MOTIVATION:  Allows trailing checks (scoreboard drain, coverage sample flush) without
              keeping objection raised for the entire run_phase duration.
  WHEN:       Scoreboard needs N cycles after last txn; coverage collector flush; late
              interrupt handler registration before shutdown sub-phases.
  PITFALL:    Re-raising unconditionally in phase_ready_to_end — infinite phase extension
              if drop never happens.
  EXAMPLE:    Scoreboard phase_ready_to_end re-raises briefly while pending queue drains,
              then drops — phase ends cleanly after quiescence confirmed.

Q: Can sequences raise objections?

diagram
[INT][SENIOR][UVM] MODEL ANSWER

Q: Can sequences raise objections?

A:
  MECHANISM:  Sequences are uvm_object — they do not have phase methods directly.
              They receive uvm_phase handle via starting_phase or raise/drop through
              the sequence's parent component context in body().
  MOTIVATION:  Sequence body() is where stimulus runs — objection scope should match
              active stimulus window, not the entire test run_phase.
  WHEN:       Sequence raises at body() entry, drops after all fork branches join.
              Test may raise umbrella objection and let sequences manage sub-windows.
  PITFALL:    Sequence raises objection but forked parallel branch outlives body() —
              classic leak when drop happens before join.
  EXAMPLE:    vseq.run_phase raises, forks per-agent sequences, join_any without join
              — fix: join all branches before drop_objection.
systemverilog
// objection debug — know this API for interviews
phase.phase_done.display_objections();
phase.phase_done.set_drain_time(this, 500ns);

// safe sequence pattern
task body();
  if (starting_phase != null)
    starting_phase.raise_objection(this, "seq active");
  fork
    agt_seq.start(m_sequencer);
  join
  if (starting_phase != null)
    starting_phase.drop_objection(this, "seq done");
endtask

Q: Objection vs global timeout — how do they coexist?

diagram
[INT][SENIOR][UVM] MODEL ANSWER

Q: Objection vs global timeout?

A:
  MECHANISM:  Objections signal intentional work completion; global timeout (fork/join_any
              in test run_phase or uvm_root timeout) is a safety net for leaks.
  MOTIVATION:  Objections give deterministic end when TB is healthy; timeout catches
              bugs that objections cannot express (infinite wait in driver).
  WHEN:       Always pair base_test timeout with proper objection policy — timeout
              should fire rarely and be treated as a test failure, not normal end.
  PITFALL:    Using only timeout — every test runs full timeout duration even when
              stimulus finished at T+1ms on a 10ms timeout guard.
  EXAMPLE:    base_test forks main flow vs #(cfg.timeout); main drops objection at
              T+2ms, phase ends at T+2ms+drain; timeout never fires on passing tests.

Key takeaways

  • phase_ready_to_end is the last-chance extension hook — use sparingly.

  • Sequences raise through starting_phase; fork/join before drop.

  • Timeout is a safety net, not a substitute for objection-driven end.

Common pitfalls

  • Re-raising in phase_ready_to_end without a guaranteed drop path.

  • Test holds umbrella objection while sequences also raise — double-count confusion.