Part 4 · TLM & Analysis · Intermediate
Debug Macros and Tools: uvm_tlm_if and Verbosity Control
Tooling for TLM diagnosis: endpoint-level traces, uvm_tlm_if-style interfaces, focused report IDs, and runtime verbosity controls.
Instrumentation principles
Effective TLM debug requires targeted visibility: publish points, consume points, and translation boundaries should emit concise traces with stable IDs.
Avoid global noise by using report IDs and component-local verbosity controls. Keep trace content structured so logs can be diffed across seeds.
[UVM][TLM] instrumentation layers
Layer 1: structural
print_topology / print_connections
Layer 2: flow
publish + consume + queue depth logs
Layer 3: semantics
payload fields and comparison decisions
enable progressively to control noise[UVM] recommended report IDs
TLM_FLOW - publish/consume events
TLM_TYPE - type/cast info
TLM_QUEUE - fifo depth and timing
TLM_AUDIT - structural checksUse layered instrumentation to scale from quick checks to deep forensics.
Prefer stable, grep-friendly report IDs over ad-hoc free text.
Turn on only the minimum verbosity needed for current hypothesis.
Using uvm_tlm_if-style hooks and endpoint wrappers
Projects often wrap TLM interactions behind interface-like helpers to centralize logging and policy checks. This keeps endpoint code consistent.
class tlm_trace_if #(type T = uvm_sequence_item) extends uvm_object;
`uvm_object_param_utils(tlm_trace_if#(T))
function new(string name = "tlm_trace_if");
super.new(name);
endfunction
virtual function void on_publish(string src, T t);
`uvm_info("TLM_FLOW",
$sformatf("publish src=%s type=%s", src, t.get_type_name()), UVM_HIGH)
endfunction
virtual function void on_consume(string dst, T t);
`uvm_info("TLM_FLOW",
$sformatf("consume dst=%s type=%s", dst, t.get_type_name()), UVM_HIGH)
endfunction
endclassclass tracing_monitor extends uvm_component;
`uvm_component_utils(tracing_monitor)
uvm_analysis_port #(txn_item) ap;
tlm_trace_if #(txn_item) tr_if;
function void publish(txn_item t);
if (tr_if != null) tr_if.on_publish(get_full_name(), t);
ap.write(t);
endfunction
endclass[TLM] wrapper benefits
single policy point for:
- connection guards
- type traces
- payload digests
- drop counters
result:
less duplicated debug code across componentsInterface-style wrappers keep debug behavior consistent across endpoints.
Hook publish/consume events without changing every sink implementation.
Use wrappers to inject policy toggles from config_db.
Verbosity control for focused TLM tracing
UVM verbosity should be tuned to the failing flow, not increased globally for all components. Set per-ID and per-component where possible.
function void start_of_simulation_phase(uvm_phase phase);
super.start_of_simulation_phase(phase);
// Keep default noise low.
uvm_top.set_report_verbosity_level_hier(UVM_LOW);
// Raise only for selected components/IDs in debug mode.
if ($test$plusargs("TLM_TRACE")) begin
mon.set_report_id_verbosity("TLM_FLOW", UVM_HIGH);
sb.set_report_id_verbosity("TLM_FLOW", UVM_HIGH);
sb.set_report_id_verbosity("TLM_TYPE", UVM_HIGH);
end
endfunction[UVM] runtime knobs
+UVM_VERBOSITY=UVM_MEDIUM
raises global level
+uvm_set_verbosity=<comp>,<id>,<verbosity>,<phase>
targeted control for noisy IDs
+TLM_TRACE
project-local plusarg for enabling TLM wrappers`define TLM_DBG(ID, FMT, ARG...) `uvm_info(ID, $sformatf(FMT, ##ARG), UVM_HIGH)
function void write(txn_item t);
`TLM_DBG("TLM_FLOW", "recv name=%s id=%0d", t.get_name(), t.id)
// checker logic...
endfunctionDefault to low verbosity and elevate only targeted IDs.
Gate deep traces behind explicit plusargs for reproducibility.
Prefer macros/helpers to standardize trace message structure.
Tool-assisted triage workflow
Combine structural printouts, flow IDs, and type IDs into a fixed triage script so every engineer debugs missing transactions the same way.
[UVM][TLM] 5-step tooling flow
1) print_connections for producers/sinks
2) enable TLM_AUDIT and TLM_FLOW at UVM_HIGH
3) run one deterministic transaction
4) inspect TLM_TYPE and cast diagnostics
5) downgrade verbosity once fault is found[TLM] expected log chain (single transaction)
TLM_AUDIT : mon.ap subscribers=2
TLM_FLOW : publish src=env.agt.mon type=pkt_axi
TLM_FLOW : consume dst=env.sb type=pkt_axi
TLM_QUEUE : depth after push=1
TLM_CHECK : compare passed txn_id=42Key takeaways
Debug wrappers and report IDs make TLM behavior observable without chaos.
uvm_tlm_if-style helper hooks centralize trace and policy logic.
Per-ID verbosity targeting is critical for scalable debug.
Use a repeatable tool-assisted workflow for consistent triage quality.
Common pitfalls
Turning global UVM_HIGH on permanently and drowning useful signals.
Embedding custom trace strings without IDs, making CI parsing brittle.
Copy-pasting instrumentation differently across monitors/sinks.
Debugging without deterministic single-transaction runs.