Skip to content

UVM RAL · Chapter 2 · Register Model Basics

Modeling Field Access Policies

Section 1.5 gave you the catalog of access policies; this page shows how to model them and what to do when a field's behaviour is not in the catalog. Most of the time modelling a policy is just passing the right access string to configure. UVM ships built-in support for RW, RO, W1C, W1S, RC, WO, and many combinations, and the field applies that policy to predict its mirrored value on every operation. That automatic prediction is the whole mechanism. The interesting case is a field the catalog does not name, such as a bit that toggles on a write of one or a counter that saturates. For those you must not approximate with the nearest built-in, because it mispredicts the exact operations that make the field special. Instead you define a custom policy that teaches RAL the real transition rule. This page breaks a toggle field modelled as RW, so the mirror mispredicts every write.

Foundation12 min readUVM RALAccess Policydefine_accessCustom PolicyPredictMirror

Chapter 2 · Section 2.4 · Register Model Basics

1. Why Should I Learn This?

Modelling a policy correctly is what makes the mirror honest, and the mirror is what turns a read into a check. For the common policies this is free — the right access string and RAL predicts perfectly. The trap is the field whose behaviour is almost a built-in: a toggle that is almost W1S, a conditional clear that is almost W1C. Approximating it with the nearest built-in is the most seductive modelling error, because it compiles, it runs, and it is wrong on exactly the operations that field exists to perform.

Learning how policies are applied — and how to define a custom one — lets you refuse the approximation and model the field's actual transition rule, so the mirror predicts what the hardware really does. It is the difference between a model that verifies the field and a model that agrees with a fiction.

2. Industry Story — the bit that would not stay set

A block has a LED control bit specified as write-one-to-toggle: writing a 1 flips the bit's state, writing a 0 leaves it — a common hardware idiom for a single-line toggle. There is no W1T in the team's built-in set that the engineer remembers, so, under deadline, they model it as RW because 'writing sets it, close enough.'

The test writes 1 to turn the LED on, and the mirror — being RW — predicts the bit is now 1; the DUT, being a toggle, also goes to 1 (it was 0). It matches. Then the test writes 1 again to turn the LED off (toggle back to 0): the DUT toggles to 0, but the RW mirror predicts 1 (it wrote 1, so RW says the bit is 1). Mismatch. Every second write mismatches, in a pattern that looks like an intermittent hardware fault but is perfectly deterministic: the model and the DUT agree on the first toggle and disagree on the second, agree on the third, disagree on the fourth. Days go into 'the toggle bit is flaky' before someone notices the model's policy is not the hardware's policy — RW predicts assignment, the field does toggle, and the two only coincide when the toggle happens to land on the value RW assumed. The fix is to model the field's actual rule with a custom policy. The lesson: when the catalog does not name your field's behaviour, define the behaviour — do not approximate it with the nearest built-in, because the nearest built-in mispredicts exactly the operations that make the field special.

3. Concept — applying a policy, and defining one

Modelling a policy has two cases:

  • Built-in policies (the common case). UVM ships a set of access strings — RW, RO, W1C, W1S, W0C, W0S, RC, RS, WO, WC, WS, and combinations like W1SRC, WRC, WSRC — and passing the string to configure() is all it takes. The field then applies the policy to predict its mirrored value on every access: a write goes through the policy's write rule, a read through its read rule, and the mirror is updated accordingly. This prediction is automatic and is the mechanism the whole mirror rests on.
  • Custom policies (the catalog gap). When a field's behaviour is not a built-in — write-one-to-toggle, saturating counter, conditional clear — you register a user-defined access policy with uvm_reg_field::define_access("W1T") and provide the transition rule (via a custom field subtype that overrides the prediction, or a policy hook), so RAL predicts the field by your rule rather than a built-in one. The point is to make the mirror apply the field's real (on_read, on_write) function, whatever it is.

The pivotal idea is that a policy is applied to the mirror on every operation. Here is a W1C write flowing through the field's policy to update the mirror and drive the bus:

A W1C write: sequence to register to field applying the policy to the mirror, and register to busApplying a W1C policy on a writeApplying a W1C policy on a writeSequenceuvm_regfield + policyBus / DUTwrite(1) toW1C pendingapply policy towrite data (1)W1C: writing 1 clears -> predict mirror = 0W1C: writing 1clears -> predict…drive bus writetransfer completestatus OK
Figure 1 — a write to a W1C field flows through the field's access policy to update the mirror and drive the bus. The sequence issues the write; the register hands the field the write data; the field APPLIES its policy (W1C: writing 1 clears) to predict the new mirrored value; and the register drives the bus with the transaction. The mirror is updated by applying the policy's rule — for a built-in that is automatic, for a custom policy you supply the rule. Model the wrong policy and the field applies the wrong rule, so the mirror predicts a value the DUT will not hold.

4. Mental Model — the policy is the field's transition rule, and RAL runs it

5. Working Example — a built-in applied, and a custom policy defined

The built-in case is a string; the field applies it automatically:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Built-in: W1C. Passing the string is the entire modelling step.
pending.configure(this, 1, 0, "W1C", 0, 1, 0, 0);
// On a write of 1, the field applies W1C and predicts the mirror cleared to 0 — automatically.
pending.write(s, 1'b1);        // mirror(pending) predicted 0; no custom code needed

The custom case teaches RAL a rule the catalog does not have — here, write-one-to-toggle:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// 1. Register the new access name once (e.g., in an initial block or package init).
initial void'(uvm_reg_field::define_access("W1T"));   // write-1-to-toggle
 
// 2. Provide the transition rule. A focused approach: a field subtype whose
//    post-predict adjusts the mirror to the field's real behaviour.
class w1t_field extends uvm_reg_field;
  `uvm_object_utils(w1t_field)
  function new(string name = "w1t_field"); super.new(name); endfunction
 
  // Apply the toggle rule: on a write, each written 1 flips the bit; 0 leaves it.
  virtual function void do_predict(uvm_reg_item rw,
                                   uvm_predict_e kind = UVM_PREDICT_DIRECT,
                                   uvm_reg_byte_en_t be = -1);
    if (rw.kind == UVM_WRITE) begin
      // toggle = current XOR write-data; model it, then let the base bookkeeping run.
      rw.value[0] = get_mirrored_value() ^ rw.value[0];
    end
    super.do_predict(rw, kind, be);
  endfunction
endclass
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// 3. Use the custom field + access. Now the mirror toggles like the hardware.
led = w1t_field::type_id::create("led");
led.configure(this, 1, 0, "W1T", 0, 0, 1, 0);
led.write(s, 1'b1);   // DUT toggles 0->1; mirror predicts 1 (0 XOR 1)  -> match
led.write(s, 1'b1);   // DUT toggles 1->0; mirror predicts 0 (1 XOR 1)  -> match (RW would have said 1)

The built-in path is a string; the custom path is the field's real transition function taught to RAL, so the mirror predicts a toggle on every write instead of an assignment on every other one.

6. Debugging Session — the toggle modelled as read-write

1

A write-one-to-toggle field modelled RW because it was the closest built-in makes the mirror mispredict every write

NEAREST-MATCH POLICY
Buggy Code
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// LED is write-one-to-toggle in hardware, but modelled with the nearest built-in:
led.configure(this, 1, 0, "RW", 0, 0, 1, 0);   // BUG: RW predicts assignment, not toggle
led.write(s, 1'b1);   // DUT: 0 -> 1 (toggle).  RW mirror: predicts 1.  MATCH (by luck)
led.write(s, 1'b1);   // DUT: 1 -> 0 (toggle).  RW mirror: predicts 1.  MISMATCH
led.write(s, 1'b1);   // DUT: 0 -> 1 (toggle).  RW mirror: predicts 1.  MATCH (by luck)
Symptom

The toggle bit mismatches on every other write in a perfectly regular pattern — match, mismatch, match, mismatch — which reads as an intermittent or flaky hardware fault because the mismatches are periodic rather than constant. The DUT is toggling exactly as specified; the confusion is that the model agrees on the writes where a toggle happens to land on the value RW assumed (going to 1) and disagrees on the writes where the toggle goes the other way (back to 0). Time is lost hunting a hardware race that does not exist.

Root Cause

The field's modelled policy is not its hardware policy. RW predicts that a write assigns the written value, so after writing 1 it always predicts 1. The hardware toggles: writing 1 flips the bit, so the true value alternates 1, 0, 1, 0. The two coincide only when the toggle happens to produce the value RW assumed — every time the bit goes to 1 — which is every other write, producing the periodic mismatch. The DUT is correct; the model applied the wrong transition function because it approximated a behaviour the catalog did not name with the nearest one that did. A nearest-match policy is wrong precisely on the operations that distinguish the real field from the approximation.

Fix

Model the field's actual rule with a custom policy, as in Section 5: register a W1T access and provide the toggle transition (mirror XOR write-data) so the field predicts a flip on every write. Now the mirror alternates with the DUT and every write matches. The rule the bug teaches: when the catalog does not name your field's behaviour, define the behaviour with a custom policy — never approximate with the nearest built-in, because the approximation mispredicts exactly the operations that make the field special, and a model that is right by coincidence fails the moment the coincidence breaks.

7. Common Mistakes

  • Approximating a non-catalog behaviour with the nearest built-in. A toggle as RW, a conditional clear as W1C — right by coincidence, wrong on the defining operations.
  • Writing a custom policy for a plain built-in. Over-engineering; if the behaviour is W1C, use the string.
  • Forgetting to define_access before using a custom access name. The name must be registered or the field rejects it.
  • Putting the transition rule in the test instead of the model. Predicting the field's behaviour by hand in stimulus, rather than in the field, means every test re-implements it and the mirror is not self-consistent.
  • Not testing the custom policy's boundary behaviour. A saturating or toggling field needs a test that exercises the transition the built-in would get wrong.

8. Industry Best Practices

  • Use built-in access strings for catalog behaviours. Select the policy by name; let RAL apply it automatically.
  • Define a custom policy for anything the catalog does not name. Register the access and provide the real transition rule in a field subtype so the mirror predicts correctly.
  • Keep the transition rule in the model, not the stimulus. The field owns its behaviour; tests should not hand-predict it.
  • Write a policy behaviour test that targets the divergence. Exercise the second toggle, the saturation, the conditional clear — the operations a nearest-match policy would fail.
  • Prefer generated models where the generator supports custom policies. IP-XACT/RALF can carry non-standard access definitions consistently (Chapter 13).

9. Interview / Review Questions

10. Key Takeaways

  • Modelling a built-in policy is just the access string — the field automatically applies the policy to predict the mirror on every operation, which is the mechanism the whole mirror rests on.
  • UVM ships RW, RO, W1C, W1S, RC, WO, and many combinations; select the one that is the behaviour.
  • For behaviour the catalog does not name, define a custom policy (define_access plus a transition rule in a field subtype) — teach RAL the field's real (on_read, on_write) function.
  • Never approximate a non-catalog field with the nearest built-in — it mispredicts exactly the operations that make the field special, producing a periodic, misleading mismatch (the toggle-as-RW bug).
  • The transition rule belongs to the model, not the test, so the field's mirror is self-consistent and every read self-checks.