Difficulty: Easy · Puzzle 4 of 6 · Topic: randomize() with Puzzles
Call #1 disables c_secure. Call #2 enables it back. Which call passes?
class sec_req;
rand bit secure;
rand bit [3:0] addr;
constraint c_addr { addr inside {[0:15]}; }
constraint c_secure { secure -> addr[3] == 1'b1; }
endclass
sec_req s = new();
s.c_secure.constraint_mode(0);
assert(s.randomize() with { secure == 1; addr inside {[0:3]}; }); // Call #1
s.c_secure.constraint_mode(1);
assert(s.randomize() with { secure == 1; addr inside {[0:3]}; }); // Call #2With secure==1 and c_secure enabled, addr[3] must be 1.
1) Call #1: c_secure disabled, so secure==1 with addr 0..3 is legal -> pass (4 solutions).
2) Call #2: c_secure enabled, secure==1 implies addr[3]==1 -> addr must be 8..15.
3) Inline addr 0..3 conflicts with required 8..15, so intersection is empty -> fail: randomize returns 0, the assert fires, and s keeps the values from Call #1.Answer: Call #1 passes and Call #2 fails; enabling c_secure makes the inline addr range illegal for secure==1.
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). Counts the (secure,addr) pairs left by the inline constraints with c_secure disabled and enabled. Verilator 5.048: Call #1 returns 1, Call #2 returns 0, and the follow-up window 8..11 returns 1.
A disabled constraint is removed from the solve set completely, and constraint_mode(0) sticks until you turn it back on. Call #1 passing proves nothing about Call #2. A failed randomize() leaves the object's fields unchanged (no partial solution), so s still holds Call #1's addr.
What inline change makes Call #2 pass while keeping secure==1? Model answer: change the address window to the top half, e.g. `addr inside {[8:11]}` (or any subset of 8..15). Then c_secure (addr[3]==1) and the inline agree, giving 4 solutions with secure==1.
Call one passes and call two fails. With c_secure disabled, the inline address zero to three is legal for secure equal to one, so four solutions. When c_secure is enabled again, secure one requires address bit three, meaning eight to fifteen, which conflicts with the inline, so randomize returns zero and the fields keep their old values. The trap is that constraint_mode zero sticks until you turn it back on, so call one passing proves nothing about call two. Next I would pick an inline window inside eight to fifteen to make call two pass.