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

  • Start Here6
  • SystemVerilog Language Foundations28
  • Object-Oriented SystemVerilog for Verification30
  • Constraint Randomization — Interview-Critical Deep Dive36
  • SystemVerilog Assertions — Interview-Critical Deep Dive40
  • Functional Coverage in SystemVerilog22
  • Testbench Architecture in SystemVerilog23
  • Advanced Language & Integration25
    • DPI-C: Calling C from SystemVerilog
    • bind: Attaching Verification to RTL
    • Macros, Defines & Compilation
    • Plusargs, Files & Runtime Configuration
    • Simulation Performance & TB Memory
      • Where Simulation Time Goes
      • Testbench Hotspots
      • TB Memory Discipline
      • Visibility Cost and Debug Strategy
    • RTL/TB Boundaries, Races & Timing
  • Senior & Interview Preparation21
  • Principal-Level Verification28
Loading lesson

‹Simulation Performance & TB Memory
  1. Topics
  2. SystemVerilog
  3. Advanced Language & Integration
  4. Simulation Performance & TB Memory
  5. Where Simulation Time Goes

Part 7 · Advanced & Integration · Intermediate

Where Simulation Time Goes

Cost breakdown of RTL, testbench, waves and coverage, plus profiling before optimizing.

On this page

    The cost breakdown

    Wall-clock time splits across several consumers, and the split shifts with design size and testbench style. In a class-based environment on a mid-size block, the testbench plus instrumentation often costs more than the RTL itself.

    The shares below are illustrative, not measured on any one design. They show the usual ranking for a reasonably written testbench.

    Diagram
    WHERE WALL-CLOCK TIME GOES (illustrative class-based TB, mid-size block)
    
      RTL event evaluation       roughly one third
      TB procedural code         roughly one quarter
      Wave dumping (full hier)   roughly one fifth
      Coverage sampling          under one tenth
      Assertions (SVA)           under one tenth
      Logging and file I/O       a few percent
    
      The ranking INVERTS for badly written TBs:
      one polling loop or per-cycle sformatf can push
      TB procedural code past half the total on its own.

    Consumer

    Scales with

    Controlled from

    RTL evaluation

    Design activity

    Mostly fixed from the testbench side.

    TB procedural code

    How the testbench is written

    Fully under the testbench author control.

    Waves and coverage

    Whether they are enabled

    Easiest wins when speed matters.

    Assertions

    Checker density

    Usually worth the cost. Disable only with sign-off.

    Profile before touching anything

    Every major simulator ships a profiler that attributes CPU time to modules, processes and source lines. The workflow is the same across vendors: run a representative test with profiling on, fix the single biggest consumer, and re-run.

    Diagram
    PROFILING WORKFLOW
    
      1. Pick a representative test, not the shortest smoke test.
      2. Run once with the vendor profiler enabled.
      3. Read the report top-down and fix rank 1 only.
      4. Re-run the profiler and repeat.
    
      Anti-pattern: trimming coverage cost while a
      scoreboard polling loop burns the top entry unexamined.

    Without a profiler, differential runs localize cost with zero tool knowledge. Toggle one feature per run and compare wall-clock times.

    Diagram
    DIFFERENTIAL RUNS (illustrative example, minutes per run)
    
      run A: everything on                   42
      run B: waves off                       31   waves cost about 11
      run C: B plus coverage off             27   coverage about 4
      run D: C plus suspect monitor off      14   the monitor is the story

    Reading a testbench-dominant profile

    A healthy environment is RTL-dominant. A testbench-dominant profile is a bug report on the testbench.

    • RTL dominant: the testbench is healthy. Speedups come from compile flags or running fewer cycles.

    • TB dominant: look for polling loops, hot-path string building and copy storms. The next lesson covers each.

    • Waves dominant: the run dumps too much hierarchy, or waves are on in regression.

    • Coverage dominant: a covergroup sampled per clock instead of per transaction.

    • File I/O dominant: verbose logging at scale. A million detail lines is real CPU and disk time.

    Common mistakes

    Common pitfall

    Profiling a 100-cycle smoke test misleads. Startup cost dominates short runs, so the report ranks consumers that do not matter in the full regression. Profile a representative test.

    Interview

    Likely question: “The profile says the testbench costs more than the RTL. Where do you look first.”

    • Call counts: a monitor or scoreboard task near the top with huge call counts means polling.

    • Differential runs: waves off, coverage off, suspect monitor off, one at a time.

    • One fix at a time: fix the top consumer, re-measure, then move on.

    Check yourself The profiler ranks a scoreboard task first with ten million calls in a ten-million-cycle test. What is the likely cause?

    A polling loop. One wake-up per cycle for the whole test means the process checks a condition ten million times. An event wait or wait expression wakes it exactly when the condition becomes true.

    Check yourself Run B (waves off) saves 11 of 42 minutes, and run C (coverage off too) saves 4 more. What should the next run test?

    Whether a suspect testbench process dominates the remaining 27 minutes. Disable the suspect monitor or driver in run D. The pattern isolates one consumer per run.

    Testbench

    A small testbench with the measurement hooks used through this topic: an opt-in +WAVES dump, a verbosity knob and a logged seed that really seeds the run.

    perf_dut.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    timeunit 1ns; timeprecision 1ps;
    
    module perf_dut (
      input  logic clk,
      output logic [7:0] count
    );
      // Plain always: an always_ff variable may not also be written by an initial.
      initial count = '0;
      always @(posedge clk) count <= count + 8'd1;
    endmodule
    

    Related topics

    • Plusargs and runtime control — dump scope, verbosity and seeds

    Previous

    203 / 259

    Next: Testbench Hotspots

    Up next

    Up nextTestbench Hotspots

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • TB Memory Discipline
    • Visibility Cost and Debug Strategy