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

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • How to Use This Course
  • Reading Paths
  • Concept Map
  • Meet DCRouter
  • Glossary
  • Part 0: What Verification Is8
  • Part 1: What Can Go Wrong11
  • Part 2: Specifications as Checkable Rules8
  • Part 3: Observability and Controllability7
  • Part 4: Stimulus11
  • Part 5: Checking11
  • Part 6: Coverage10
  • Part 7: Formal and Simulation10
  • Part 8: Verification Levels and Reuse8
  • Part 9: Planning and Risk9
  • Part 10: Emulation and Prototyping8
  • Part 11: Post-Silicon Validation8
  • Part 12: Bug Economics8
  • Part 13: Debug7
    • The Debug Loop
    • Reproducing Failures
    • Following the Wait
    • Bisection and Delta Debugging
    • Triage at Scale
    • Is It the Testbench?
    • Drills: Debug
  • Part 14: Sign-Off7
  • Part 15: Verification in Context8
  • Part 16: Case Studies5
  • Part 17: Capstones5
  • Part 18: Interview Preparation6
Loading lesson

‹Part 13: Debug
  1. Topics
  2. First Principles of Verification Strategy
  3. Part 13: Debug
  4. Reproducing Failures

Part 13 · Debug · Working (W)

Reproducing Failures

A failure you cannot reproduce cannot be debugged, and a fix you cannot reproduce the failure for cannot be verified. How to make failures reproducible (seeds, builds, environment, determinism), what to do when a failure will not reproduce, and how to shrink a reproduction until it is fast and small.

On this page

    Note

    Level: Working (W) · Answers: How do we find the cause fast?

    Before this: The Debug Loop, Seeds and Regressions

    A random DCRouter test failed overnight. The engineer reruns it in the morning and it passes. The log shows the test name but not the seed; the regression script picked one at random and did not print it. The failure was real (lesson 4.9 showed the random hunt missing BUG_21 with four seeds out of twenty and catching it with the rest), and it is now gone. Without the seed, the only way back to it is luck.

    A failure won't reproduce. What do you do?

    The obvious answer, and why it breaks

    The obvious response is to rerun until it fails again, or to close it as flaky. Rerunning with new seeds samples different tests (lesson 4.9); a rare failure may not return for hundreds of runs. Closing it discards a real bug. Reproducibility has to be designed in before the failure, and recovered methodically after.

    The idea: everything that decides a run, recorded

    Ingredient

    Why it matters

    The seed

    With random stability, the same seed and code give the same run (fact V7)

    The exact build

    RTL, testbench, tools and versions; a testbench edit changes what a seed produces

    Plusargs and configuration

    Test options, knobs, verbosity that alters timing or randomisation

    Environment

    Simulator version, libraries, operating-system differences, licence-dependent options

    Non-determinism in the testbench

    Races between processes, uninitialised variables, wall-clock time, hash ordering

    When it will not reproduce

    • Same seed, same build? Check the log records both; rebuild the exact version from the commit if needed.

    • Different simulator, machine or options? Run where it failed, with the same options.

    • Race in the testbench? Look for processes writing the same variable at the same time, or blocking assignments to signals read by other processes at the same edge.

    • Uninitialised state? X versus 0 differences between simulators or options.

    • Truly rare? Run many seeds of the same test in parallel, with the failure signature as the stop condition (lesson 13.5).

    Shrinking a reproduction

    Technique

    Effect

    Start closer to the failure

    Checkpoint or backdoor setup instead of replaying from reset (lessons 3.5, 10.6)

    Remove stimulus that does not matter

    Delta debugging (lesson 13.4)

    Turn the case into a directed test

    Survives testbench changes that break the seed

    Fix the seed in a regression list

    The failure stays checked after the fix (lesson 4.9)

    How real teams keep failures reproducible

    Practice

    Purpose

    Seed, build hash and command line printed in every log

    Any failure can be rerun exactly

    Regression systems that store failing seeds and builds

    Reproduction is one command

    Lint and race detection for testbench code

    Non-determinism removed before it hides failures

    Failures never closed as flaky without root cause

    Rare real bugs kept

    What breaks

    A team (illustrative) had a test that failed about once a week and was eventually marked flaky and excluded. Months later the same signature appeared in emulation. The cause was a real design race between a register write and a counter increment in the same cycle, which only some seeds produced. The excluded test had been reporting it all along.

    Why this matters

    Senior lens. Make reproducibility a property of the regression system: every run logs its seed, build and options, every failure can be rerun with one command, and no failure is closed as flaky without a cause. Then shrink reproductions to directed tests, which outlive the seed.

    Interview

    Asked: "A failure won't reproduce. What do you do?"

    Weak answer: Rerun it a few times; if it passes, close it as flaky.

    Strong answer: First check I'm really rerunning the same thing: the same seed, the exact build including the testbench, the same options and simulator version. If that's identical and it still passes, I look for non-determinism in the testbench (races between processes, uninitialised state, wall-clock or hash ordering). If it's genuinely rare, I run many seeds in parallel with the failure signature as the stop condition. Once reproduced, I shrink it to a short directed test and keep the seed in the regression. I never close a failure as flaky without a cause.

    Follow-ups: (1) What testbench constructs cause non-determinism? (2) Why convert the failure to a directed test?

    Check yourself Why can a failing seed stop reproducing after an unrelated testbench edit?

    Random stability ties values to the order of random calls; adding or moving a call changes what every seed produces.

    Check yourself What should every regression log contain so a failure can be rerun?

    The seed, the exact build (commit or hash of RTL and testbench), the command line and options, and the tool version.

    Key takeaways

    • A failure that cannot be reproduced cannot be debugged or its fix verified.

    • Record seed, build, options and environment for every run; remove testbench non-determinism.

    • Shrink reproductions into directed tests, and never close a failure as flaky without a cause.

    Keep going

    Next: Lesson 13.3, Following the Wait. The waveform method for hangs and corruption.

    Related topics

    • Part 13 overview: Debug

    Previous

    124 / 160

    Next: Following the Wait

    Up next

    Up nextFollowing the Wait

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Bisection and Delta Debugging
    • Triage at Scale
    • Is It the Testbench?