Difficulty: Medium · Puzzle 2 of 6 · Topic: randomize() with Puzzles
Predict pass/fail and the len values for: (1) dov.randomize(), (2) dnw.randomize(), (3) dnw.randomize() after c_len is switched off and with inline len inside {[6:10]}.
class bt;
rand bit [3:0] len;
constraint c_len { len inside {[1:8]}; }
endclass
class dov extends bt; // same constraint name
constraint c_len { len inside {[9:12]}; }
endclass
class dnw extends bt; // different constraint name
constraint c_len2 { len inside {[9:12]}; }
endclass
dov d = new(); dnw e = new();
r1 = d.randomize();
r2 = e.randomize();
e.c_len.constraint_mode(0);
r3 = e.randomize() with { len inside {[6:10]}; };A derived constraint with the same name replaces the base one; a differently named one is ANDed with it.
1) dov redeclares c_len: it REPLACES the base constraint. Only len in 9..12 applies, so r1 passes with len in 9..12 (1/4 each). This holds through a base-class handle too, because constraints are virtual.
2) dnw adds c_len2 under a new name: the base c_len (1..8) and c_len2 (9..12) are both active, the intersection is empty, so r2 fails (returns 0).
3) After e.c_len.constraint_mode(0) only c_len2 (9..12) remains. With the inline 6..10, len is in {9,10}, 1/2 each, and r3 passes.Answer: r1 passes with len in 9..12; r2 fails (1..8 AND 9..12 is empty); r3 passes with len in {9,10}, 50/50.
Checked by running a model of the rule in a Python model and Verilator 5. Exact enumeration of the constraint set per the LRM (the LRM defines the distribution; simulator solvers need not be uniform). Override-by-name vs. different-name is modelled as replace vs. intersect of the legal len sets. Verilator 5.048: same-name override passes with len in 9..12, the differently named constraint fails, and after constraint_mode(0) the inline 6..10 leaves only 9..10; switching the derived c_len off frees len.
People say inheritance 'adds' constraints, so dov would fail like dnw. Only a different name conjoins; the same name overrides. Executed on Verilator 5.048: dov gave len 9 (pass), dnw failed with an unsatisfied-constraint warning, and after constraint_mode(0) it passed with a value in the 9..10 window.
What range is legal for dov if you switch its (derived) c_len off with d.c_len.constraint_mode(0)? Model answer: len is then unconstrained over its 4-bit range, 0..15 (16 values). The base c_len was replaced, not hidden, so turning the derived one off does not bring back 1..8.
For the first call, the derived class redeclares c_len with the same name, so it replaces the base constraint and len is nine to twelve, a pass. In the second class the new constraint has a different name, so both ranges are active, one to eight and nine to twelve, the intersection is empty and randomize fails. In the third call, with c_len switched off, only nine to twelve remains, and the inline six to ten leaves nine or ten, half each. The trap is thinking inheritance always adds constraints; only a different name conjoins. Next I would check the constraint names.