Part 6 · Agents & Protocol IP · Intermediate

Per-Field Knobs: Orthogonal Controls and Semantic Precision

Design per-field knobs that are composable, clearly scoped, and easy to validate and debug across agent components.

Knob taxonomy and semantics

Treat every knob as part of your integration API. One knob should control one axis, with units, default, and consumer documented.

diagram
[UVM][AGT][DRV][TLM] knob taxonomy

mode knobs:
  is_active, enable_driver

driver timing knobs:
  req_gap_*_cycles, timeout_cycles

handshake knobs:
  send_rsp, max_outstanding, retry_limit

checker knobs:
  enable_checks, strict_mode

debug knobs:
  trace_cfg, trace_tlm, dump_n_first
diagram
[CFG] naming pattern

boolean:
  enable_<feature>

count/range:
  <name>_count, <name>_min, <name>_max

time:
  <name>_cycles

ratio/probability:
  <name>_pct
  • Avoid generic fields like `mode2` or `policy` without semantics.

  • Capture units in field names to reduce misconfiguration.

  • Keep debug knobs separate from functional behavior knobs.


Reference design with consumer mapping

systemverilog
class uart_agent_cfg extends uvm_object;
  `uvm_object_utils(uart_agent_cfg)

  uvm_active_passive_enum is_active = UVM_ACTIVE;
  virtual uart_if vif;

  // Driver timing
  int unsigned tx_start_delay_cycles = 1;
  int unsigned rx_timeout_cycles = 512;

  // TLM/response
  bit send_rsp = 1;
  bit include_framing_status = 1;

  // Checker policy
  bit enable_frame_check = 1;
  bit strict_parity_check = 1;

  // Fault policy
  bit inject_noise = 0;
  int unsigned inject_noise_pct = 0;

  // Debug
  bit trace_cfg = 0;
  bit trace_rx = 0;
  bit trace_tx = 0;

  function new(string name = "uart_agent_cfg");
    super.new(name);
  endfunction
endclass
diagram
[UVM][AGT][DRV][TLM] consumer map

agent wrapper consumes:
  is_active

driver consumes:
  tx_start_delay_cycles, rx_timeout_cycles, inject_*

sequencer/sequence path consumes:
  send_rsp and response schema knobs

monitor/checker consumes:
  strict_parity_check, enable_frame_check, trace_rx/tx
  • Fields without consumers are dead knobs and should be removed.

  • Document consumer mapping to simplify code review.

  • Avoid hidden derived behavior that couples unrelated knobs.


Coherence checks and review checklist

systemverilog
function bit validate_knobs(ref string msg);
  if (rx_timeout_cycles < 16) begin
    msg = "rx_timeout_cycles must be >= 16";
    return 0;
  end

  if (inject_noise_pct > 100) begin
    msg = "inject_noise_pct must be <= 100";
    return 0;
  end

  if (!inject_noise && inject_noise_pct != 0) begin
    msg = "inject_noise_pct non-zero while inject_noise=0";
    return 0;
  end

  msg = "";
  return 1;
endfunction
diagram
[UVM][AGT][DRV][TLM] knob review checklist

[ ] single-purpose semantics
[ ] explicit units and legal bounds
[ ] documented consumers
[ ] dependencies validated
[ ] effective values included in cfg dump
[ ] no overlap with existing knobs

Key takeaways

  • Per-field knobs should be orthogonal, bounded, and consumer-mapped.

  • Semantic naming and units reduce ambiguity during integration.

  • Validation catches contradictory knob combinations before runtime.

  • Review knobs as API surface, not local implementation details.

Common pitfalls

  • Overloaded knobs controlling multiple behavior axes.

  • Dead knobs with no active consumers.

  • No validation for dependency pairs like enable/percentage.

  • Adding knobs without dump visibility or documentation.