Part 6 · Agents & Protocol IP · Intermediate
Cfg Object Design: Schema Clarity, Defaults, and Evolution Rules
Design cfg objects as stable API schemas with grouped fields, explicit defaults, bounded values, and safe evolution patterns.
Schema-first thinking
Design cfg like a versioned schema. Every field should answer: who sets it, who consumes it, what default means, and what range is legal.
[UVM][AGT][DRV][TLM] field grouping model
group A: structure/mode
is_active, enable_driver
group B: integration handles
vif, clocking config, protocol id map
group C: driver flow knobs
timeout_cycles, gap cycles, retry limits
group D: checker/monitor knobs
strictness, trace level, assertion enables
group E: debug controls
cfg dump level, transaction trace gates[CFG] ownership matrix
test/env owns:
scenario intent values
agent owns:
interpretation and topology derivation
driver owns:
execution behavior under resolved knobs
monitor/checker owns:
observability policy under resolved knobsPrefer explicit names with units, e.g. `_cycles`, `_pct`, `_depth`.
Keep one behavior axis per field to preserve orthogonality.
Document default rationale for non-obvious policy knobs.
Reference cfg class
class bus_agent_cfg extends uvm_object;
`uvm_object_utils(bus_agent_cfg)
// Mode and binding
uvm_active_passive_enum is_active = UVM_ACTIVE;
virtual bus_if vif;
// Driver flow policy
rand int unsigned req_gap_min_cycles;
rand int unsigned req_gap_max_cycles;
int unsigned timeout_cycles = 512;
int unsigned retry_limit = 1;
// TLM/response policy
bit send_rsp = 1;
bit include_latency_in_rsp = 1;
// Checker and monitor policy
bit enable_protocol_checks = 1;
bit strict_ordering = 1;
bit trace_transactions = 0;
// Fault campaign knobs
bit inject_error = 0;
rand int unsigned inject_error_pct;
constraint c_req_gap {
req_gap_min_cycles inside {[0:16]};
req_gap_max_cycles inside {[req_gap_min_cycles:128]};
}
constraint c_error {
inject_error_pct inside {[0:100]};
if (!inject_error) inject_error_pct == 0;
}
function new(string name = "bus_agent_cfg");
super.new(name);
endfunction
endclassfunction void print_cfg(bus_agent_cfg c);
`uvm_info("CFG_SUMMARY",
$sformatf("mode=%s timeout=%0d gap=[%0d,%0d] rsp=%0d checks=%0d err=%0d/%0d",
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.inject_error,
c.inject_error_pct),
UVM_LOW)
endfunctionKeep integration handles non-random and mandatory when required.
Constrain random fields so randomization always stays meaningful.
Expose a concise summary function for debug consistency.
Evolution and compatibility
Cfg contracts evolve. Backward-safe changes are additive with conservative defaults; disruptive changes require migration scaffolding and explicit warnings.
[UVM][AGT][DRV][TLM] cfg evolution policy
safe change:
add optional field with default preserving old behavior
caution change:
tighten legal ranges with explicit validation message
migration change:
deprecate old field and map to replacement for one release
unsafe change:
silent semantic flip of existing fieldfunction void normalize_compat();
if (legacy_fast_mode) begin
req_gap_min_cycles = 0;
req_gap_max_cycles = 0;
`uvm_warning("CFG_DEPR",
"legacy_fast_mode is deprecated; use req_gap_* fields")
end
endfunctionKey takeaways
Cfg object design should optimize clarity, legality, and stable semantics.
Grouped fields and ownership rules reduce integration ambiguity.
Bounds and dependencies belong in constraints and validation layers.
Additive evolution with migration hooks preserves reuse across releases.
Common pitfalls
Ambiguous field names that hide units or intent.
Defaults tuned for stress instead of baseline bring-up.
Silent field repurposing that breaks legacy tests.
Random knobs without constraints causing impractical scenarios.