Part 6 · Agents & Protocol IP · Intermediate

Cfg Debug Patterns: Propagation Tracing and Mismatch Isolation

Debug config issues with producer-transport-consumer-behavior checkpoints, structured dumps, and deterministic triage order.

Debug model and symptom classification

Configuration bugs look like protocol bugs unless cfg flow is observable. Instrument checkpoints so you can isolate where intent diverges from effective behavior.

diagram
[UVM][AGT][DRV][TLM] four-checkpoint model

C1 producer:
  env/test values before set

C2 transport:
  path/key and precedence at set/get boundaries

C3 consumer:
  effective values after get + normalize

C4 behavior:
  evidence in driver/monitor/checker actions
diagram
[CFG] symptom map

unexpected passive mode:
  likely precedence/path mismatch

driver NOVIF fatal:
  missing binding or wrong cfg target

checker unexpectedly disabled:
  stale cfg override or interpretation bug

seed-specific behavior drift:
  random cfg not logged or hidden mutation
  • Classify symptoms before diving into waveforms.

  • Checkpoint deltas identify root-cause zone quickly.

  • Behavior should be diagnosed against effective cfg, not intended cfg.


Structured dump and probe utilities

systemverilog
function string cfg_to_string(bus_agent_cfg c);
  return $sformatf(
    "{mode=%s timeout=%0d gap=[%0d,%0d] rsp=%0d chk=%0d tr=%0d vif=%s}",
    c.is_active.name(),
    c.timeout_cycles,
    c.req_gap_min_cycles,
    c.req_gap_max_cycles,
    c.send_rsp,
    c.enable_protocol_checks,
    c.trace_transactions,
    (c.vif == null) ? "NULL" : "SET");
endfunction

function void cfg_log(string stage, bus_agent_cfg c);
  `uvm_info("CFG_DBG",
    $sformatf("stage=%s path=%s cfg=%s", stage, get_full_name(), cfg_to_string(c)),
    UVM_LOW)
endfunction
systemverilog
function void build_phase(uvm_phase phase);
  super.build_phase(phase);
  if (!uvm_config_db#(bus_agent_cfg)::get(this, "", "cfg", cfg))
    `uvm_fatal("NOCFG", "cfg missing")

  cfg_log("agent_get", cfg);
  cfg.normalize_compat();
  cfg_log("agent_norm", cfg);

  uvm_config_db#(bus_agent_cfg)::set(this, "mon", "cfg", cfg);
  if (cfg.is_active == UVM_ACTIVE)
    uvm_config_db#(bus_agent_cfg)::set(this, "drv", "cfg", cfg);
endfunction
diagram
[UVM][AGT][DRV][TLM] recommended log stages

S1 env_populated
S2 env_set_path
S3 agent_get
S4 agent_normalized
S5 child_get (drv/mon)
S6 end_of_elaboration summary
  • Use fixed field ordering in dumps to simplify diffing.

  • Include full path and stage tags in every log line.

  • Prefer concise structured logs over verbose free-form dumps.


Deterministic triage procedure

diagram
[UVM][AGT][DRV][TLM] triage ladder

step 1 producer check:
  was cfg populated with intended values?

step 2 transport check:
  did set/get paths and keys match?

step 3 consumer check:
  did wrapper/children observe same effective cfg?

step 4 behavior check:
  did driver/monitor behavior reflect effective cfg?

stop at first mismatch boundary
diagram
[CFG] one-seed isolation recipe

1) run deterministic seed with minimal traffic
2) enable cfg stage logs only
3) trigger one request/response flow
4) compare observed behavior to effective cfg
5) patch first failed boundary, rerun same seed
systemverilog
task cfg_probe_tree(my_env env);
  `uvm_info("CFG_PROBE", "begin cfg probe", UVM_LOW)
  env.cfg_probe();
  env.agt.cfg_probe();
  if (env.agt.drv != null) env.agt.drv.cfg_probe();
  env.agt.mon.cfg_probe();
endtask

Key takeaways

  • Cfg debugging is fastest when producer, transport, consumer, and behavior are all observable.

  • Structured stage logs provide repeatable, low-noise triage.

  • Deterministic triage order prevents circular debugging.

  • Fix the first failing boundary; downstream symptoms are usually secondary.

Common pitfalls

  • Debugging protocol behavior before confirming cfg propagation.

  • Logging only producer intent, not consumer-effective values.

  • No path/stage metadata in cfg logs.

  • Changing multiple boundaries at once and losing causal traceability.