Part 6 · Agents & Protocol IP · Intermediate
Cfg Validation Checks: Fail-Fast Legality and Topology Coherence
Layer validation for field legality, integration binding, and topology coherence before run-phase behavior begins.
Validation layers and boundaries
Good validation gates structural construction and prevents deep runtime failures. Combine class constraints, semantic validators, and component-level coherence checks.
[UVM][AGT][DRV][TLM] validation stack
layer 1 class constraints:
bounds and direct dependencies
layer 2 cfg.validate():
semantic and integration-aware checks
layer 3 wrapper checks:
mode -> topology coherence
layer 4 child checks:
local mandatory requirements[CFG] severity policy
fatal:
null mandatory handles, illegal ranges, structural contradictions
warning:
deprecated or ignored optional fields
info:
normalization/defaults appliedRun core checks in build/end_of_elaboration for deterministic failure points.
Return actionable messages with offending values.
Keep validation side-effect free; normalization belongs in separate methods.
validate() and wrapper gating example
class spi_agent_cfg extends uvm_object;
`uvm_object_utils(spi_agent_cfg)
uvm_active_passive_enum is_active = UVM_ACTIVE;
virtual spi_if vif;
int unsigned timeout_cycles = 256;
int unsigned cs_hold_cycles = 1;
bit send_rsp = 1;
bit enable_checks = 1;
function bit validate(ref string err);
if (timeout_cycles < 8) begin
err = "timeout_cycles must be >= 8";
return 0;
end
if (cs_hold_cycles > 64) begin
err = "cs_hold_cycles must be <= 64";
return 0;
end
if (is_active == UVM_ACTIVE && vif == null) begin
err = "active mode requires non-null vif";
return 0;
end
err = "";
return 1;
endfunction
endclass
function void build_phase(uvm_phase phase);
string err;
super.build_phase(phase);
if (!uvm_config_db#(spi_agent_cfg)::get(this, "", "cfg", cfg))
`uvm_fatal("NOCFG", "spi_agent_cfg missing")
if (!cfg.validate(err))
`uvm_fatal("BADCFG", $sformatf("invalid cfg: %s", err))
endfunctionfunction void end_of_elaboration_phase(uvm_phase phase);
super.end_of_elaboration_phase(phase);
if (cfg.is_active == UVM_ACTIVE) begin
if (drv == null || sqr == null)
`uvm_fatal("TOPO", "active mode requires drv+sqr")
end
if (mon == null)
`uvm_fatal("TOPO", "monitor must exist in both active/passive modes")
endfunctionCall validate immediately after cfg get.
Gate topology creation decisions with validated cfg.
Cross-check cfg mode against actual constructed components.
Validation checklist and CI hooks
[UVM][AGT][DRV][TLM] validation checklist
cfg object:
[ ] required fields set
[ ] ranges legal
[ ] dependencies coherent
binding:
[ ] vif non-null when required
[ ] mode override precedence resolved
topology:
[ ] active -> drv+sqr+mon
[ ] passive -> mon only
run-safety:
[ ] one cfg summary log per instance[CFG] CI strategy
smoke test should assert:
cfg validate passes
topology coherence passes
no fatal/warning spikes from deprecations
regression metadata should capture:
effective cfg summary
seed + test idKey takeaways
Fail-fast validation prevents expensive deep-debug cycles.
Layered checks catch both field legality and structural coherence issues.
Severity discipline keeps hard failures visible and optional issues informative.
CI smoke gates should include cfg validation and effective-summary capture.
Common pitfalls
Continuing after null-handle or structural validation failures.
Scattered validation logic with inconsistent semantics.
Warnings used where fatal behavior is required.
No topology checks after cfg-driven build decisions.