Reputation: 384
In a SystemVerilog UVM testbench, we're randomizing transaction objects, and for some specific tests, we create additional constraints. However those testcase constraints are only used by the randomization engine if you call the testcase randomize()
method and not obj.randomize()
. This is quite confusing.
I wonder why all constraints on the object are not used regardless of which randomize is called? Why do constraints have a scope?
For example:
class trans;
rand int addr;
constraint addr_c; // Method 1: constraint prototype
function void post_randomize();
$display("addr %d",addr);
endfunction
endclass
//////////////////// Test case code /////////////////
// Method 1: extend constraint prototype addr_c external to test class.
// constraint trans::addr_c { addr > 0 && addr < 10; }
// works but requires prototype, careful if trans is in another package
class my_test;
trans trans1;
// Method 2: Add constraint to the test
constraint test_constraint_c { trans1.addr > 11 && trans1.addr < 20; }
function new();
trans1 = new;
repeat (20) begin
// This doesn't use test_constraint_c (why??)
assert(trans1.randomize()) else $display("TEST", "Randomization Failed");
// This uses test_constraint_c
assert(randomize(trans1)) else $display("TEST", "Randomization Failed");
end
endfunction
endclass
module tb;
my_test test1;
initial test1 = new;
endmodule
Upvotes: 1
Views: 674
Reputation: 62164
You have 2 classes which are unrelated to each other: trans
and my_test
.
The trans
class does not know about the test_constraint_c
constraint because the constraint is only part of the my_test
class. Thus, when you call the randomize
function on the object (trans1.randomize()
), it has no constraints to apply.
In the test, when you call the randomize
method on the trans1
variable, it will apply any active constraints in the my_test
class, namely test_constraint_c
.
An alternate approach is to extend the trans
class with a new constraint block.
Upvotes: 1