Part 9 · Register Model (RAL) · Intermediate
uvm_reg_field::configure Walkthrough
Parameter-by-parameter explanation of configure(), with field layout examples, mutability choices, and practical modeling guidelines.
The configure() contract
Most field behavior originates from one call: uvm_reg_field::configure. Teams often copy-paste this call without understanding each argument, then spend days debugging behavior that was accidentally encoded in metadata.
The method signature is compact but dense. Understanding each parameter gives you deterministic control over layout, side effects, reset semantics, randomization, and access granularity.
function void configure(
uvm_reg parent,
int unsigned size,
int unsigned lsb_pos,
string access,
bit volatile,
uvm_reg_data_t reset,
bit has_reset,
bit is_rand,
bit individually_accessible
);[RAL] configure() argument map
parent -> which register owns this field
size -> number of bits in field
lsb_pos -> starting bit position in register
access -> RW/RO/W1C/... policy string
volatile -> can DUT change without software access?
reset -> reset value bits for this field
has_reset -> whether reset value is defined/checked
is_rand -> include field in randomization flows
individually_accessible -> legal partial-lane direct accessEvery argument should be traceable to explicit specification text.
Wrong size/lsb_pos silently corrupts mapping and check interpretation.
volatile and has_reset are behavior flags, not convenience defaults.
Parameter deep dive
parent, size, lsb_pos
These three parameters define bit placement. Incorrect placement yields the most dangerous class of bug: accesses appear to work, but they target wrong bits.
err_code.configure(this, 4, 8, "RO", 1, 4'h0, 1, 0, 0);
// means err_code occupies reg[11:8]Ensure fields do not overlap unless explicitly intended by spec aliases.
Validate total field coverage against register width.
Keep a bit-map comment near build() for reviewer clarity.
access, volatile
access encodes software operation semantics. volatile indicates the DUT may update this field outside explicit software writes. Volatile fields are common in counters, FIFO levels, and asynchronous status.
pkt_count.configure(this, 8, 16, "RO", 1, 8'h00, 1, 0, 0);
irq_stat.configure(this, 1, 7, "W1C", 0, 1'b1, 1, 0, 1);Volatile does not disable checking; it changes expectation strategy.
Pair volatile fields with deliberate read timing and predictor setup.
Do not use volatile as a blanket fix for mirror mismatches.
reset, has_reset
reset is the modeled reset value for this field. has_reset tells RAL whether reset is defined and therefore checkable. If has_reset is 0, reset comparisons for that field are intentionally skipped.
version_id.configure(this, 8, 24, "RO", 0, 8'h00, 0, 0, 0);
// has_reset=0: version register may not have deterministic reset valueSet has_reset=1 only when spec guarantees deterministic reset state.
For unknown-on-reset fields, use has_reset=0 and document rationale.
Keep reset value width consistent with field size.
is_rand, individually_accessible
is_rand controls whether field participates in randomization helpers. individually_accessible indicates whether software can target field independently (often relevant for bus byte-lane semantics and tool-generated behavior).
cfg_sel.configure(this, 3, 0, "RW", 0, 3'h0, 1, 1, 1);
// randomizable and individually accessibleDisable is_rand for status fields to avoid unrealistic sequence randomization.
Mark individually_accessible conservatively unless architecture guarantees it.
Consistency here improves built-in sequence usefulness.
Full register walkthrough with annotations
Example: a mixed control/status register where each field uses different configure choices. Comments explain why each parameter is selected.
class ctrl_status_reg extends uvm_reg;
`uvm_object_utils(ctrl_status_reg)
uvm_reg_field enable; // bit0, RW
uvm_reg_field mode; // bits[2:1], RW
uvm_reg_field soft_reset; // bit3, WO pulse
uvm_reg_field irq_status; // bit4, W1C
uvm_reg_field fifo_level; // bits[12:8], RO volatile
uvm_reg_field rev_id; // bits[31:24], RO constant
function new(string name = "ctrl_status_reg");
super.new(name, 32, UVM_NO_COVERAGE);
endfunction
virtual function void build();
enable = uvm_reg_field::type_id::create("enable");
enable.configure(
this, // parent
1, // size
0, // lsb_pos
"RW", // access
0, // volatile
1'b0, // reset
1, // has_reset
1, // is_rand
1 // individually_accessible
);
mode = uvm_reg_field::type_id::create("mode");
mode.configure(this, 2, 1, "RW", 0, 2'b00, 1, 1, 1);
soft_reset = uvm_reg_field::type_id::create("soft_reset");
soft_reset.configure(this, 1, 3, "WO", 0, 1'b0, 1, 0, 1);
irq_status = uvm_reg_field::type_id::create("irq_status");
irq_status.configure(this, 1, 4, "W1C", 0, 1'b1, 1, 0, 1);
fifo_level = uvm_reg_field::type_id::create("fifo_level");
fifo_level.configure(this, 5, 8, "RO", 1, 5'h00, 1, 0, 0);
rev_id = uvm_reg_field::type_id::create("rev_id");
rev_id.configure(this, 8, 24, "RO", 0, 8'h3A, 1, 0, 0);
endfunction
endclass[REG][FIELD] annotated layout
31:24 rev_id RO reset=0x3A
23:13 reserved (separate reserved handling)
12:8 fifo_level RO volatile
7:5 reserved
4 irq_status W1C reset=1
3 soft_reset WO
2:1 mode RW
0 enable RWMixed fields in one register are normal; each field carries unique semantics.
Use comments sparingly but deliberately for non-obvious choices.
Keep build() deterministic and easy to diff during spec changes.
Debugging configure() mistakes
When behavior is wrong, isolate configure metadata before blaming adapters, predictors, or RTL. A quick field-dump utility often surfaces model issues immediately.
function void dump_field_meta(uvm_reg rg);
uvm_reg_field fields[$];
rg.get_fields(fields);
foreach (fields[i]) begin
`uvm_info(
"FIELD_META",
$sformatf("name=%s access=%s n_bits=%0d lsb=%0d volatile=%0d",
fields[i].get_name(),
fields[i].get_access(),
fields[i].get_n_bits(),
fields[i].get_lsb_pos(),
fields[i].is_volatile()),
UVM_LOW
)
end
endfunction[RAL] configure triage flow
unexpected read/write behavior?
├─ dump access policy + lsb/size
├─ confirm reset/has_reset values
├─ confirm volatile flag intent
├─ check map address/adapter only after metadata passes
└─ re-run directed per-field checkKey takeaways
configure() arguments encode most field runtime semantics.
Treat each argument as spec-bound data, not template filler.
Use metadata dump helpers to localize model issues quickly.
Correct configure choices reduce downstream debug complexity across the stack.
Common pitfalls
Copying configure lines across fields without revisiting each argument.
Using has_reset=1 for unknown-reset fields and forcing false failures.
Setting is_rand on status fields and generating nonsensical stimulus.
Ignoring bit placement validation until integration phase.