GLS · Chapter 13 · Simulation Performance & Regression Strategy
Speeding Up Gate-Level Runs
Gate-level simulation runs slowly, but a handful of levers make each run affordable without giving up the checks you need. Run zero-delay functional GLS wherever timing is not required and reserve timed SDF runs for a targeted subset. Bound unknowns with proper reset and initialization so they do not fan out and multiply activity. Disable timing checks only on specific paths where they are not meaningful, never across the whole design. Checkpoint after reset with save and restore so every test skips the bring-up sequence, and dump waveforms only on failure or within a window. This lesson pairs each lever with the slowness cause it attacks and shows where speed trades against fidelity, so you never mistake a zero-delay run for a timed one.
Foundation12 min readGLSPerformanceZero-DelaySave-RestoreOptimization
Chapter 13 · Section 13.2 · Simulation Performance & Regression Strategy
Project thread — the mini-SoC's GLS runs faster once these levers are applied. This lesson is the how of speed; 13.3 decides what to run so speed and coverage align.
1. Why Should I Learn This?
Each slowness cause (13.1) has a lever — knowing them turns an unaffordable run into a fast one.
- Zero-delay where timing isn't needed — the biggest win.
- Bound
X, save/restore, reduce dumping — steady gains. - Selective check disabling — speed without masking real bugs.
This is the how of affordability, paired with 13.3's what.
2. Real Silicon Story — a 5× speedup without losing a bug
A team's gate-level regression was unaffordable. Instead of buying machines, they pulled levers: ran most tests zero-delay (timed only a targeted subset), bounded X with proper reset, checkpointed after reset (save/restore), and windowed the dump.
The result was a ~5× speedup — and no loss of bug-finding: the gate-level-specific checks (X/reset/equivalence) ran zero-delay, and the timed subset still caught timing behavior. Crucially, they did not disable checks wholesale (which would have masked real violations, 8.4) or call the zero-delay runs 'timed' (which would have been a false claim, 0.4).
Lesson: speed comes from levers mapped to causes — zero-delay, bound X, save/restore, reduce dumping — without sacrificing fidelity (no wholesale check-disabling, no mislabeling zero-delay as timed).
3. Concept — the speedup levers
Each lever attacks a cause from 13.1:
- (1) Zero-delay where timing isn't needed (attacks timing cost). Skip SDF for equivalence/
X/reset/init checks — removes delay scheduling + firing checks (the biggest cost). Timed (SDF) only on a subset (13.3). - (2) Bound
X(attacks X-fanout). Proper reset, initialize memories/non-scan flops — unboundedXfans out (Ch6) and multiplies activity. - (3) Selective timing-check disabling (attacks timing cost). Disable checks per-path only where not meaningful (async crossings, 8.4/9.3). NEVER wholesale (masks real violations, 8.4/12.6).
- (4) Save/restore (checkpoint) (attacks repeated work). Checkpoint after reset/bring-up, restore per test — skip re-running the (expensive) reset sequence every time.
- (5) Reduce dumping (attacks I/O cost). Dump waveforms on failure or a window only — full-run dumping is a large overhead.
- (6) Compile optimization + parallelism (attacks raw throughput). Optimized compile; multicore/parallel across the pool.
The tradeoff (accuracy):
- Speed trades against fidelity. Zero-delay is not a timed run — label it (0.4); it can't catch timing behavior (run the timed subset for that).
- Never disable checks wholesale (8.4) — a speed hack that masks real bugs.
- Save/restore must checkpoint a valid (post-reset) state.
Scope: these are performance levers; they don't change what GLS is (dynamic, 0.3).
4. Mental Model — a race car: shed weight without removing the brakes
Speeding up GLS is like making a car faster.
- Shed dead weight you don't need for this lap — carry zero-delay (leave the heavy timing in the garage) when the lap is a function check, not a timing check.
- Clear the fog (bound
X) so the driver isn't fighting reduced visibility (X-fanout). - Start from a warm pit stop (save/restore) instead of driving from the parking lot every lap (re-running reset).
- Stop filming every lap (reduce dumping) unless something goes wrong.
- BUT never remove the brakes to save weight — disabling all timing checks (the brakes) makes you faster and blind to real crashes (masked violations, 8.4). And don't pretend a weight-stripped car (zero-delay) has full instrumentation (timing) — label it.
Shed weight, clear fog, warm-start — but keep the brakes and label the car honestly.
5. Working Example — applying the levers
The levers in a run flow (tool-neutral):
# Speedup levers — REPRESENTATIVE (tool-neutral):
# 1) zero-delay for function/X/reset tests (skip SDF): <sim> netlist + cells + tb (NO sdf_annotate)
# -> label the run 'zero-delay functional' (NOT timed, 0.4)
# 2) bound X: proper reset before stimulus; $readmem/init memories; init non-scan flops
# 3) selective checks: disable timing checks ONLY on async-crossing paths (8.4/9.3) -- never all
# 4) reduce dumping: dump only on failure or a time window (not the whole run)
# 5) compile opt + parallel across the machine pool# 6) save/restore: checkpoint AFTER reset/bring-up, restore per test — REPRESENTATIVE (tool-neutral)
run_until_reset_done
save checkpoint_post_reset ;# valid post-reset state
# for each test:
restore checkpoint_post_reset ;# skip re-running the (expensive) reset sequence
apply_test_stimulusPractical context (representative, tool-neutral):
# Speedup checklist (tool-neutral) — map each lever to a cause (13.1):
# [ ] zero-delay where timing NOT needed (attacks timing cost) — LABEL as zero-delay (0.4)
# [ ] bound X: reset + init memories/non-scan flops (attacks X-fanout)
# [ ] disable checks ONLY per-path where not meaningful (async, 8.4) — NEVER wholesale
# [ ] save/restore after reset (attacks repeated bring-up)
# [ ] dump on failure / window (attacks I/O)
# [ ] optimized compile + parallel (raw throughput)
# tradeoff: speed vs fidelity — zero-delay has NO timing; keep the checks (brakes)Zero-delay (fast) vs timed (slow, but real timing), as a real waveform:
Zero-delay run (fast, no timing) vs timed SDF run (slower, real clk-to-Q) — same logic, different fidelity
8 cycles6. Debugging Session — a speedup that masked a bug
A gate-level run is sped up by disabling all timing checks and running zero-delay but labeling it a timing run, which masks a real violation and misrepresents the run; the correct levers speed it up without losing fidelity
SPEED WITHOUT SACRIFICING FIDELITY: NO WHOLESALE CHECK-DISABLE, LABEL ZERO-DELAYA gate-level run is made fast, but a real timing violation later escapes — the sped-up run had hidden it — and a 'timing' regression turns out to have been zero-delay.
Speed bought by sacrificing fidelity. Two wrong levers: (a) timing checks were disabled wholesale to go faster (8.4/12.6) — which masks real violations (the escaped one); and (b) a zero-delay run (no SDF) was labeled 'timed' — a false claim (0.4), since zero-delay can't catch timing behavior. Both are speed hacks that break correctness: the run is fast because it's not actually checking what it claims to. The right levers (zero-delay for function/X/reset, bound X, save/restore, reduce dumping, selective per-path check disabling, parallel) speed the run without losing fidelity — but wholesale check-disabling and mislabeling zero-delay are not among them.
Apply the fidelity-preserving levers: run zero-delay where timing isn't needed (and label it zero-delay, 0.4), run timed (SDF) on a targeted subset for real timing; bound X (reset/init); save/restore after reset; reduce dumping (on failure/window); optimized compile + parallel. Disable timing checks only per-path where they aren't meaningful (async crossings, 8.4/9.3) — never wholesale. Re-run: the regression is fast and honest — the timed subset still catches the violation, and no run misrepresents its fidelity. The lesson: speed up GLS with levers mapped to causes (zero-delay where timing isn't needed, bound X, save/restore, reduce dumping, parallel) — but never trade away fidelity: don't disable checks wholesale (masks real bugs, 8.4) and don't label a zero-delay run 'timed' (0.4). (Levers are performance; GLS stays dynamic, 0.3.)
7. Common Mistakes
- Disabling all timing checks to go faster. Masks real violations (8.4) — disable per-path only.
- Labeling a zero-delay run 'timed'. Zero-delay has no timing (0.4).
- Not bounding
X. X-fanout multiplies activity — reset/init. - Re-running reset every test. Use save/restore after bring-up.
- Dumping the whole run. Dump on failure/window only.
8. Industry Best Practices
- Run zero-delay where timing isn't needed; timed on a subset (13.3) — label each.
- Bound
X(reset + init memories/non-scan flops). - Save/restore after reset to skip repeated bring-up.
- Reduce dumping (on failure / window).
- Disable checks only per-path (justified) — never wholesale (8.4).
Senior Engineer Thinking
- Beginner: "To speed it up, I'll turn off the timing checks and skip SDF."
- Senior: "Zero-delay (skip SDF) is fine for function/X/reset — but I label it, and keep timed runs for a subset. And I never disable checks wholesale — that masks real bugs. I bound
X, save/restore after reset, and window the dump."
The senior speeds up with fidelity-preserving levers and refuses the ones that mask bugs.
Silicon Impact
The speedup levers are what make GLS affordable enough to actually run before tape-out — a 5×+ speedup from zero-delay + bound-X + save/restore + reduced dumping is routine, and it costs no bug-finding when done right. But the dangerous 'speed hacks' are the ones that buy speed by breaking correctness: disabling checks wholesale (8.4) masks real timing violations, and mislabeling zero-delay as timed (0.4) makes a fast run falsely claim timing coverage — either can let a real bug reach silicon while the regression looked green and fast (0.3). The discipline is to pull the fidelity-preserving levers (zero-delay where appropriate and labeled, bound X, save/restore, reduce dumping, parallel) and refuse the fidelity-breaking ones. That's how you get GLS fast and honest — the prerequisite for running it at scale (13.4).
Engineering Checklist
- Ran zero-delay where timing isn't needed; labeled it (0.4); timed on a subset.
- Bounded
X(reset + init memories/non-scan flops). - Used save/restore after reset to skip bring-up.
- Reduced dumping (on failure / window).
- Disabled checks only per-path (justified) — never wholesale (8.4); used compile-opt + parallel.
Try Yourself
- Run a design timed (SDF) and note the wall-clock time; then run it zero-delay (skip SDF) — much faster.
- Observe: zero-delay is fast but has no timing (label it); the timed run catches clk-to-Q behavior.
- Change: add save/restore after reset, bound
X(reset/init), and window the dump. - Expect: a large speedup with no loss of fidelity. Then try disabling all checks — note the (unacceptable) speed gain and how it would mask a violation. Revert.
Zero-delay, save/restore, and dump control are standard simulator features. No paid tool required for the concept.
Interview Perspective
- Weak: "I speed up GLS by turning off checks and skipping SDF."
- Good: "Zero-delay where timing isn't needed, bound
X, save/restore after reset, reduce dumping, parallel." - Senior: "Each lever attacks a cause: zero-delay (label it) removes timing cost for function/X/reset, bound
Xcuts fan-out, save/restore skips repeated bring-up, windowed dumping cuts I/O, parallel adds throughput. I disable checks only per-path where they aren't meaningful — never wholesale, which masks real bugs — and I never call a zero-delay run 'timed'. Speed without sacrificing fidelity."
9. Interview / Review Questions
10. Key Takeaways
- Speed up GLS with levers mapped to causes (13.1): (1) zero-delay where timing isn't needed (biggest win — but label it, not a timed run, 0.4); (2) bound
X(reset/init — cuts fan-out); (3) selective per-path check disabling (async only, 8.4/9.3); (4) save/restore after reset (skip bring-up); (5) reduce dumping (on failure/window); (6) compile-opt + parallel. - Speed trades against fidelity — zero-delay is not a timed run (run the timed subset for timing behavior).
- Never disable checks wholesale to go faster — it masks real violations (8.4/12.6); disable only per-path where justified.
- Save/restore must checkpoint a valid (post-reset) state; reduce dumping to failures/windows.
- These are performance levers — they don't change what GLS is (dynamic, 0.3) — and applied right they give a large speedup with no loss of bug-finding. Next: 13.3 — choosing what to run in GLS.
Quick Revision
Speed levers (each attacks a cause, 13.1): zero-delay where timing not needed (biggest win — label it, 0.4), bound X (reset/init), save/restore after reset, reduce dumping (failure/window), selective per-path check disable (async only, 8.4), compile-opt + parallel. Tradeoff: speed vs fidelity — zero-delay ≠ timed; NEVER disable checks wholesale (masks bugs, 8.4). Next: 13.3 — choosing what to run in GLS.