TO Be coming

Nov 14, 2026

UVM Course: Day 13: Debugging and Reporting — uvm_info Verbosity, ID Filters, Transaction Recording, Waveforms

Day 13: Debugging and Reporting — uvm_info Verbosity, ID Filters, Transaction Recording, Waveforms
Advertisement
Top banner — drop your 728×90 or responsive ad unit here.

Day 13: Debugging and Reporting — uvm_info Verbosity, ID Filters, Transaction Recording, Waveforms

A 30-day SystemVerilog/UVM verification series. The tools today do not add features. They make features debuggable.

You cannot fix what you cannot see. UVM gives you three layers of visibility: the text log (uvm_info and friends), the transaction database (uvm_tr_database), and the waveform viewer. Each answers a different kind of question. Today is about knowing which one to reach for, and how to configure it so the answer is right there instead of buried in a thousand INFO lines.


1. uvm_info Verbosity Levels

Every uvm_info call takes a verbosity as its last argument. The simulator suppresses any message whose verbosity is higher than the current global verbosity. The levels, in increasing order of detail:

LevelMeaningUse for
UVM_NONEAlways printed, cannot be suppressedUnrecoverable failure context; almost never correct to use
UVM_LOWImportant, shown by defaultTest start/end, major milestones
UVM_MEDIUMDefault levelPer-transaction summaries, config reports
UVM_HIGHDebug onlyPer-cycle details, per-field comparisons
UVM_FULL, UVM_DEBUGExtreme detailBring-up of the testbench itself

The critical rule: a default run should show at most a few hundred lines. If your default run produces thousands of lines, nobody will read the log, and the day a failure is in there, nobody will find it.

`uvm_info("TEST", "starting", UVM_LOW)
`uvm_info("DRV", $sformatf("driving wdata=%0h", tr.wdata), UVM_HIGH)
`uvm_info("SB", $sformatf("mismatch: exp %0h got %0h", exp, got), UVM_NONE)

Notice the ID — the first argument. It is what filtering operates on.


2. ID Filtering

Each component can set its own default verbosity and its own ID filter. That means you can turn on HIGH for one component without drowning in HIGH from every other component:

// In a driver's build_phase:
set_report_verbosity_level(UVM_HIGH);
// or per-ID:
set_report_id_verbosity("DRV", UVM_HIGH);

// In the test, to disable a specific component's output entirely:
env.wr_agent.drv.set_report_id_action("DRV", UVM_NO_ACTION);

At the command line, without changing code:

+UVM_VERBOSITY=UVM_HIGH        // global
+UVM_VERBOSITY=UVM_LOW         // global, less verbose
// per-ID filtering is done via the report server or in code
Rule of thumb: UVM_LOW for test-level milestones, UVM_MEDIUM for per-transaction summaries that a reader would actually want, UVM_HIGH for anything that would appear more than once per transaction. UVM_NONE is reserved for unrecoverable failures.

3. Transaction Recording

The text log tells you what the testbench did. The waveform tells you what the pins did. Neither tells you what the transactions did — unless you record them into the transaction database.

UVM's uvm_tr_database and uvm_tr_stream record transaction begin/end and field values into a format that waveform viewers like Verdi or Questa can read. In modern UVM, this is mostly automatic if you call accept_tr() and begin_tr()/end_tr() on your sequence item:

function void do_record(uvm_recorder recorder);
    super.do_record(recorder);
    `uvm_record_field("wdata", wdata)
    `uvm_record_field("rdata", rdata)
    `uvm_record_field("wr_en", wr_en)
endfunction

Once recorded, transactions appear as a second timeline above the signal waveforms. When a scoreboard reports "ID 0x42 mismatch: exp 0x10 got 0x11", you can find the transaction in the viewer, see its begin/end time, and correlate with the exact pins.

Recording cost: transaction recording is not free. It allocates objects and writes to disk. For long regressions, either disable it (uvm_tr_database::do_open gated on a plusarg) or use it only on the failing seed.

4. Waveform Debugging Strategies

When a failure occurs, the instinct is to open the waveform and search for the bug. That works, but slowly. A better workflow:

  1. Find the first mismatching transaction in the log. Note the transaction ID and the simulation time.
  2. Set a breakpoint or a "when" condition in the waveform viewer at that exact time.
  3. Add the scoreboard's expected queue to the waveform as a variable, if the viewer supports it.
  4. Look at the interface signals for one transaction before and one after the failure. The failure is usually the boundary.
  5. Look at the DUT's internal state at that time — full/empty, pointers, registers.

The failure mode to avoid: opening the waveform at time 0 and scrolling forward. On any real design that is hopeless. Start from the failure, work backwards.

The three-question checklist for any mismatch: (1) Did the driver drive what the sequence sent? Look at driver-side stimulus. (2) Did the DUT receive what the driver drove? Look at the pins after the driver handoff. (3) Did the monitor publish what the DUT returned? Look at monitor sampling time and values. Whichever of the three is wrong tells you which component to fix.

5. Log Parsing

A UVM log for a 10-second simulation is enormous. Grep is your friend:

grep "UVM_ERROR\|UVM_FATAL" sim.log
grep -n "SB" sim.log | head -20
grep "TEST_PASS\|TEST_FAIL" sim.log

Teams that run large regressions typically wrap this in a Makefile target or a Python script. The two lines that matter most are the summary:

UVM_INFO @ 5000ns: reporter [TEST_DONE] Test finished
UVM_ERROR :    3
UVM_FATAL :    0

If UVM_ERROR is nonzero, the test failed. If UVM_FATAL is nonzero, the test crashed before finishing. Those two numbers are the pass/fail criterion.


6. What Day 14 Will Add

Tomorrow is the Week 2 Review + Advanced Mini-Project. You will take everything from Days 8–13 and build a FIFO environment with virtual sequences, an out-of-order scoreboard, coverage collection, and end-of-test discipline. The mini-project is the checkpoint before Week 3's RAL work.


7. Quiz

Ten questions on verbosity, filtering, transaction recording, and debugging.

Question 1 of 10
Loading…
    0 / 10
    Advertisement
    Bottom banner — drop your 728×90 or responsive ad unit here.

    Coming Up Next: Day 14 — Week 2 Review + Advanced Mini-Project

    • Assemble Week 2's pieces — virtual sequence, two-import scoreboard, coverage collector, drain-time discipline.
    • Run a full regression — multiple seeds, coverage database merged across runs, scoreboard clean.
    • Close at least two coverage holes — write targeted sequences for what random regression did not hit.
    • Document the environment — what each agent does, what the scoreboard checks, what the coverage model covers.
    ← Back to the 30-Day UVM Course
    See all 30 days, week by week.

    Series: 30 days of SystemVerilog/UVM verification. Day 13's debugging discipline.

    No comments:

    Post a Comment

    SiteMap