Part 5 · Sequences · Intermediate
Verbosity Tracing & Plusargs: uvm_set_verbosity
Targeted uvm_set_verbosity plusargs, strategic uvm_info placement, and localizing stalls without log flood.
Tracing without flooding
Turning UVM_FULL on the entire testbench produces gigabyte logs that hide the one line you need. Effective sequence debug uses scoped verbosity — raise level on one sequencer, one driver, or the uvm_sequence reporter id — and strategic uvm_info at handshake boundaries.
[UVM] verbosity strategy
BAD: +uvm_set_verbosity=*,_ALL_,UVM_FULL,time → unreadable log
GOOD: +uvm_set_verbosity=env.axi_agent.drv,_ALL_,UVM_HIGH,time
+uvm_set_verbosity=env.axi_agent.sqr,_ALL_,UVM_HIGH,time
grep "waiting get_next_item|start_item|finish_item"uvm_set_verbosity plusargs
# Trace one sequencer component from time 0
+uvm_set_verbosity=env.apb_agent.sqr,_ALL_,UVM_HIGH,time
# Trace all sequences globally by reporter id (still verbose — use for short repro)
+uvm_set_verbosity=*,uvm_sequence,UVM_FULL,time
# Print every item at medium during run_phase only
+uvm_set_verbosity=*,_ALL_,UVM_MEDIUM,run
# Trace driver and sequencer together
+uvm_set_verbosity=env.axi_agent.drv,DRV,UVM_HIGH,time \
+uvm_set_verbosity=env.axi_agent.sqr,_ALL_,UVM_HIGH,timetime vs run — time starts at 0ns; run limits to run_phase window only.
Component path must match get_full_name() — typo = no extra messages.
Reporter id filter (e.g. DRV) limits to uvm_info with that id string.
Strategic uvm_info placement
Place four log points per beat and you can localize any stall to one handshake phase without UVM_FULL:
// Sequence — log at handshake boundaries
task automatic send_beat(axi_item req);
`uvm_info(get_type_name(), "pre start_item", UVM_HIGH)
start_item(req);
`uvm_info(get_type_name(), "post start_item, pre randomize", UVM_HIGH)
assert(req.randomize());
`uvm_info(get_type_name(), req.sprint(), UVM_MEDIUM)
`uvm_info(get_type_name(), "pre finish_item", UVM_HIGH)
finish_item(req);
`uvm_info(get_type_name(), "post finish_item", UVM_HIGH)
endtask
// Driver — mirror the four boundaries
task run_phase(uvm_phase phase);
forever begin
`uvm_info("DRV", "pre get_next_item", UVM_HIGH)
seq_item_port.get_next_item(req);
`uvm_info("DRV", $sformatf("post get_next_item: %s", req.sprint()), UVM_MEDIUM)
drive(req);
`uvm_info("DRV", "pre item_done", UVM_HIGH)
seq_item_port.item_done();
`uvm_info("DRV", "post item_done", UVM_HIGH)
end
endtaskWalkthrough — reading a stall from log grep
Legend: [SEQ] [DRV]
LAST LOG LINES:
axi_burst_seq: pre finish_item
DRV: post get_next_item: { addr:'h1000 ... }
(nothing after)
INTERPRETATION:
sequence waiting at finish_item
driver got item, has NOT called item_done
stall inside drive() — NOT sequencer, NOT randomize
NEXT STEP:
add uvm_info inside drive() channels
check for early return path skipping item_doneDebug playbook — ordered grep commands
# 1. Did driver start?
grep "run_phase started" sim.log
# 2. Is driver waiting for items?
grep "get_next_item" sim.log | tail -5
# 3. Did sequence reach handshake?
grep "start_item\|finish_item" sim.log | tail -10
# 4. Any randomize failures?
grep "RAND\|randomize" sim.log
# 5. Lock activity?
grep -i "lock\|grab\|unlock" sim.logRun short repro (micro-second) with UVM_HIGH on drv+sqr only.
Compare last seq message vs last drv message — gap reveals stall side.
Add one log line per hypothesis — remove after fix to keep regression log lean.
Key takeaways
Scope verbosity to drv + sqr — never UVM_FULL on whole bench for seq debug.
Four boundary logs per beat localize stall to start_item, drive, or finish_item.
grep playbook faster than wave debug for handshake stalls.
Common pitfalls
UVM_FULL on * — sim slows, log rotates, you lose the stall line.
uvm_info in tight loop at UVM_LOW — floods log even without UVM_FULL.
Verbosity plusarg typo in path — silent, you think tracing is on but it is not.
Removing all debug uvm_info after fix — leave UVM_HIGH boundaries for next debug.