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
    • Directed Tests
    • Why Random Works
    • Constrained Random
    • Distributions and Bias
    • The Long Tail
    • Scenarios and Layered Stimulus
    • Error Injection
    • Timing and Back-Pressure
    • Seeds and Regressions
    • Hunting the Zoo with Random
    • Drills: Stimulus
  • 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
  • Part 14: Sign-Off7
  • Part 15: Verification in Context8
  • Part 16: Case Studies5
  • Part 17: Capstones5
  • Part 18: Interview Preparation6
Loading lesson

‹Part 4: Stimulus
  1. Topics
  2. First Principles of Verification Strategy
  3. Part 4: Stimulus
  4. Distributions and Bias

Part 4 · Stimulus · Senior (S)

Distributions and Bias

Uniform random reaches the middle of the input space and rarely its corners; bias pushed too far reaches only the corners. A model of three DCRouter length distributions shows the trade-off between breadth and corner hits, and why a mixture (mostly broad, with weight on the boundaries) gets most of both.

On this page

    Note

    Level: Senior (S) · Answers: How do we drive the design into the states that matter?

    Before this: Constrained Random

    After a corner-case bug escapes, a team over-corrects: every random length is now 0, 1 or 15, because "bugs live at the boundaries". Their next regression hammers the boundaries thousands of times. It never sends a packet of length 7. When a bug turns up in the CRC of mid-length packets, the regression that was meant to be thorough has not sent a single packet that could reveal it.

    How do you shape random stimulus toward corners without losing everything else?

    The obvious answer, and why it breaks

    Two obvious answers pull in opposite directions. Uniform random is fair to every value, so it reaches the middle quickly and the corners rarely, and corners need several rare values at once (lesson 4.5). Pure corner bias does the reverse: it reaches the corners constantly and never visits the middle. Bugs live in both places. The question is not uniform or biased but how much weight each region gets.

    The idea: a mixture

    • Mostly broad: most draws spread over the whole legal range, so every value is reached eventually.

    • Extra weight on boundaries: minimum, maximum, zero and full get far more than their uniform share, so corners built from several boundary values become reachable.

    • Corners multiply: raising one boundary value's probability by a factor k raises a corner needing it on four inputs by k⁴.

    In SystemVerilog the mixture is one dist (fact V6):

    design.sv
    // snippet: the mixed length distribution, as in lesson 4.10 (weights are percent)
    constraint c_len { len dist {0 := 2, 1 := 10, [2:14] :/ 70, 15 := 18}; }

    Build it: breadth against corners

    The model compares three length distributions for DCRouter packets, with destination and priority uniform. Breadth is how many of the 128 header kinds are seen after N packets. The corner is lesson 4.5's: four inputs sending length 15 to the same output in one group, tried 100,000 times. Here uniform covers all 16 lengths, including 0.

    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    """Distributions and bias: reaching corners without losing breadth.
    
    Three ways to choose a DCRouter packet length (destination and priority stay uniform):
      uniform   every length 0-15 equally likely
      corners   only the boundary lengths 0, 1 and 15, a third each (bias taken too far)
      mixed     0: 2%, 1: 10%, 15: 18%, 2-14: 70% spread evenly (the distribution of lesson 4.10)
    Breadth: the expected number of the 128 header kinds (4 dst x 2 prio x 16 len) seen after N
    packets, the sum over kinds of 1 - (1 - p_kind)^N. Corner: the chance that, in 100,000
    groups of four packets (one per input), all four go to the same output with length 15 at
    least once (lesson 4.5's corner). A Monte Carlo run checks the mixed breadth at N = 500.
    """
    import random
    
    def mixed(l):
        return {0: 0.02, 1: 0.10, 15: 0.18}.get(l, 0.70 / 13)
    
    dists = {
        "uniform": lambda l: 1 / 16,
        "corners": lambda l: 1 / 3 if l in (0, 1, 15) else 0.0,
        "mixed":   mixed,
    }
    Ns = [100, 200, 500, 1000, 2000, 5000]
    print("packets N:          " + " ".join(f"{n:>6d}" for n in Ns) + "   corner in 100k groups")
    rows = {}
    for name, pl in dists.items():
        assert abs(sum(pl(l) for l in range(16)) - 1) < 1e-9
        kinds = [pl(l) / 8 for l in range(16) for _ in range(8)]
        rows[name] = [sum(1 - (1 - p) ** n for p in kinds) for n in Ns]
        corner = 4 * (pl(15) / 4) ** 4
        hit = 1 - (1 - corner) ** 100_000
        print(f"{name:8s} kinds seen " + " ".join(f"{v:6.1f}" for v in rows[name]) + f"   {hit:.3f}")
    
    rng = random.Random(11)
    lens = list(range(16))
    w = [mixed(l) for l in lens]
    runs, n = 400, 500
    sim = sum(len({(rng.randrange(4), rng.randrange(2), rng.choices(lens, w)[0]) for _ in range(n)}) for _ in range(runs)) / runs
    print(f"Monte Carlo, mixed, N = {n}: {sim:.1f} kinds seen (formula {rows['mixed'][2]:.1f})")
    
    assert abs(sim - rows["mixed"][2]) < 1.5
    assert max(rows["corners"]) <= 24.0 + 1e-9 and rows["mixed"][-1] > 127
    print("PASS: corners-only never sees more than 24 of 128 kinds; mixed sees all 128 by 5,000 packets and hits the corner far more often than uniform")

    It prints:

    Diagram
    packets N:             100    200    500   1000   2000   5000   corner in 100k groups
    uniform  kinds seen   69.6  101.3  125.5  127.9  128.0  128.0   0.024
    corners  kinds seen   23.7   24.0   24.0   24.0   24.0   24.0   1.000
    mixed    kinds seen   65.7   95.5  122.1  127.2  127.9  128.0   0.806
    Monte Carlo, mixed, N = 500: 122.1 kinds seen (formula 122.1)
    PASS: corners-only never sees more than 24 of 128 kinds; mixed sees all 128 by 5,000 packets and hits the corner far more often than uniform
    The model's numbers: uniform and mixed both reach about 128 kinds by 1,000 to 2,000 packets; corners-only stops at 24. Corner hit chance in 100,000 groups: uniform 0.024, mixed 0.806, corners-only 1.000.

    How to read it: corners-only hits the four-way corner with certainty but can never see more than 24 of the 128 header kinds, because lengths 2 to 14 never occur. Uniform sees every kind fastest but has only a 2.4% chance of the corner in 100,000 groups. The mixture is a little slower to full breadth (127.2 against 127.9 kinds at 1,000 packets) and has an 81% chance of the corner: most of both benefits. The Monte Carlo line checks the breadth formula.

    Choosing weights

    Guideline

    Reason

    Keep most of the weight broad (60 to 80% is common)

    Middle values must still appear often enough to reach every kind

    Put boundary weight on values that start corners (0, 1, max, full)

    Corners are products of boundary values

    Different tests can use different mixes

    A corner-hunting test and a breadth test complement each other

    Let coverage decide

    Weights are a guess; coverage shows what they actually reached (Part 6)

    How real teams shape distributions

    Practice

    Purpose

    Default distributions with boundary weight in the base class

    Every test gets corner pressure without asking

    Test-specific overrides

    Stress tests push harder on boundaries; soak tests stay broad

    Weights tuned from coverage results

    Spend probability where bins are still empty

    What breaks

    The opening story is the corners-only row of the model: a regression that hits its chosen corners every run and has never sent a mid-length packet. The opposite failure is just as common and quieter: a uniform regression that runs for months without hitting a four-way corner it would reach in one night with boundary weight.

    Why this matters

    Senior lens. Treat a distribution as a budget: most of it buys breadth, some of it buys corners, and coverage tells you whether the split was right. Ask of any stimulus plan both "which values can never occur?" and "which corners are a million to one?"; a good mixture answers both.

    Interview

    Asked: "How do you hit rare cases with random stimulus?"

    Weak answer: Run more seeds.

    Strong answer: Shape the distribution. Corners are products of rare values, so raising each boundary value's weight multiplies the chance of the corner: weighting length 15 to 18% instead of 1 in 16 makes a four-input corner dozens of times more likely. But I keep most of the weight broad, because a corners-only distribution never sends middle values; in DCRouter's model it can see at most 24 of 128 header kinds. A mixture of about 70% broad and 30% boundaries gets nearly full breadth and a high corner hit rate, and coverage tells me whether to adjust.

    Follow-ups: (1) Why does boundary weight help corners so much? (2) What does a corners-only distribution miss?

    Check yourself Why can the corners-only distribution see at most 24 of the 128 header kinds?

    Only lengths 0, 1 and 15 occur: 4 destinations × 2 priorities × 3 lengths = 24 kinds.

    Check yourself The mixed distribution gives length 15 a probability of 0.18 instead of 1/16. By roughly what factor does that change a corner needing length 15 on four inputs?

    (0.18 × 16)⁴ ≈ 2.88⁴ ≈ 69 times more likely per group.

    Key takeaways

    • Uniform random gives breadth but rarely corners; corner-only bias gives corners but loses breadth.

    • A mixture (mostly broad, extra weight on boundary values) gets most of both.

    • Corners multiply boundary probabilities, so modest bias has a large effect; let coverage tune the weights.

    Keep going

    Next: Lesson 4.5, The Long Tail. How long random takes to reach a rare corner, worked out.

    Related topics

    • Part 4 overview: Stimulus

    Previous

    43 / 160

    Next: The Long Tail

    Up next

    Up nextThe Long Tail

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Directed Tests
    • Why Random Works
    • Scenarios and Layered Stimulus