Part 10 · Advanced Topics · Intermediate

Verbosity and Logging Cost

Reduce report overhead by controlling verbosity, avoiding unnecessary formatting, and using targeted debug gates.

Why logging gets expensive

The expensive part of logging is often string construction, not only file I/O. Calls like sprint(), deep object prints, and large sformatf payloads can dominate runtime in hot monitor and scoreboard paths.

diagram
[PERF] logging cost anatomy

  report call
    -> verbosity check
    -> message construction (sformatf/sprint)
    -> report server routing
    -> output sink (file/stdout)

  Critical insight:
    if message is built before verbosity guard,
    you pay cost even when log is suppressed.

Guard expensive formatting

systemverilog
function void write_act(bus_txn t);
  if (get_report_verbosity_level() >= UVM_HIGH) begin
    `uvm_info("SCB_TRACE", t.sprint(), UVM_HIGH)
  end
  compare(t);
endfunction
  • Check verbosity before calling sprint() in hot functions.

  • Prefer concise identifiers over full object dumps at low verbosity.

  • Keep UVM_FULL for targeted replay runs only.


Targeted verbosity instead of global noise

Use component- and ID-specific verbosity controls to inspect one area without slowing the whole run.

bash
# Global quiet mode
simv +UVM_TESTNAME=axi_long_random +UVM_VERBOSITY=UVM_LOW

# Raise only scoreboard diagnostics
simv +UVM_TESTNAME=axi_long_random +UVM_VERBOSITY=UVM_LOW \
     +uvm_set_verbosity=uvm_test_top.env.scb,SCB_TRACE,UVM_HIGH,run

# Raise one monitor path only
simv +UVM_TESTNAME=axi_long_random +UVM_VERBOSITY=UVM_LOW \
     +uvm_set_verbosity=uvm_test_top.env.axi_agt.mon,MON,UVM_HIGH,run
diagram
[REG] logging policy tiers

  farm default:
    global UVM_LOW
    no broad sprint dumps

  triage replay:
    scoped UVM_HIGH for one component ID
    preserve performance elsewhere

  deep debug:
    short run + UVM_FULL with strict time budget

Useful message design rules

  • Include compact keys (id, addr, phase, status).

  • Avoid redundant full transaction dumps in loops.

  • Emit one summary line per N events for throughput tracking.


Report server and sink considerations

Central report processing can become a bottleneck in massive logs. Keep report IDs stable and avoid overly dynamic formatting that bloats log volume.

systemverilog
// Lightweight periodic stats instead of per-transaction dumps
int txn_seen = 0;

function void write_act(bus_txn t);
  txn_seen++;
  if ((txn_seen % 1000) == 0) begin
    `uvm_info("SCB_RATE", $sformatf("txn_seen=%0d", txn_seen), UVM_LOW)
  end
  compare(t);
endfunction
bash
# Quick estimate of log volume and heavy IDs
wc -l out/logs/axi_long_random.log
rg "UVM_INFO|UVM_WARNING|UVM_ERROR" out/logs/axi_long_random.log | head -n 20

Key takeaways

  • Logging overhead is mostly formatting plus report routing in hot paths.

  • Guard expensive message construction behind verbosity checks.

  • Prefer targeted component verbosity over global verbosity increases.

  • Use compact periodic summaries to retain observability at scale.

Common pitfalls

  • Calling sprint() regardless of effective verbosity.

  • Running full-regression with UVM_HIGH/UVM_FULL globally enabled.

  • Producing verbose logs without stable IDs for parser tooling.