Difficulty: Medium · Puzzle 4 of 6 · Topic: Sequences and Sequencers
UVM 1.2. A sequence has a member `addr` and wants the randomized item to use the same address. The test sees random addresses. Why, and what is the fix?
class my_seq extends uvm_sequence #(bus_item);
`uvm_object_utils(my_seq)
bit [7:0] addr = 8'h40;
function new(string name = "my_seq"); super.new(name); endfunction
task body();
`uvm_do_with(req, { addr == addr; })
endtask
endclassIn an inline constraint, which `addr` does an unqualified name refer to?
1) In an inline `with { ... }` constraint, unqualified names are looked up in the randomized object first, so both sides of `addr == addr` are `req.addr`.
2) The constraint is a tautology; the solver accepts it and leaves req.addr unconstrained (random).
3) Fix: qualify the sequence's member with `local::`: `{ addr == local::addr; }`, or use a differently named member (e.g. `m_addr`).Answer: Both `addr` names resolve to the item's field, so the constraint is always true; use `local::addr`.
Checked by running the code in Verilator 5; the printed output supports the answer above. Hand-written model of the documented UVM 1.2 behaviour in plain SystemVerilog (Verilator), not the UVM library: plain-SV randomize() with: shows that an unqualified name binds to the randomized object and local:: binds to the caller's member.
The solver reports success, so nothing fails: you only notice by checking the data, which is the worst kind of silent bug.
Does `local::` also matter in `req.randomize() with {...}` called from a plain method, outside uvm_do_with? Model answer: yes; `uvm_do_with` simply expands to a `randomize() with` on the item, so the same scoping rule applies and the same `local::` qualification is the cure.