Hello.
I’m describing constraints for selecting multiple byte lanes.
For expandability and maintenance, I want to modify my code. My code is not clear.
The code below is simplified. Please correct it if it has errors.
class my_class;
rand logic [2:0] size;
rand logic [31:0] array[];
endclass
...
my_class my_obj;
my_obj = new;
my_obj.randomize() with {
array.size() = size;
foreach(array[i]) {
if (size == 1) {
array[i] == 'h0 || array[i] == 'hf;
} else if (size == 2) {
array[i] == 'h0 || array[i] == 'hf ||
array[i] == 'hf0 || array[i] == 'hff;
} else if (size == 3) {
array[i] == 'h0 || array[i] == 'hf ||
array[i] == 'hf0 || array[i] == 'hff ||
array[i] == 'hf00 || array[i] == 'hf0f ||
array[i] == 'hff0 || array[i] == 'hfff ||
array[i] == 'hf000 || array[i] == 'hf00f ||
array[i] == 'hf0f0 || array[i] == 'hf0ff ||
array[i] == 'hff00 || array[i] == 'hff0f ||
array[i] == 'hfff0 || array[i] == 'hffff;
} else if (size == 4) {
array[i] == 'h0 || array[i] == 'hf ||
array[i] == 'hf0 || array[i] == 'hff ||
array[i] == 'hf00 || array[i] == 'hf0f ||
array[i] == 'hff0 || array[i] == 'hfff ||
array[i] == 'hf000 || array[i] == 'hf00f ||
array[i] == 'hf0f0 || array[i] == 'hf0ff ||
array[i] == 'hff00 || array[i] == 'hff0f ||
array[i] == 'hfff0 || array[i] == 'hffff ||
...
} ...
}
}
Please, comment
In reply to jh_veryveri:
This can be done using a helper array (an array used to make constraints easier to write). In this case, the helper lets you iterate over each byte lane.
module top;
class my_class;
rand logic [2:0] size;
rand logic [31:0] array[];
rand bit helper[8];
constraint c {
array.size() == size;
foreach(helper[lane]) {
helper[lane] == lane < size;
foreach(array[i])
if (helper[lane])
array[i][lane*4+:4] inside {'0,'1};
else
array[i][lane*4+:4] == '0;
}
}
endclass
my_class c = new;
initial repeat(5) begin
assert(c.randomize() );
$displayh("%p %p",c.array,c.helper);
end
endmodule
In reply to dave_59:
Thanks for your comment and code.
Please refer my code…
In my case, I describe constraints to `uvm_rand_send_with.
I try to refer your code. The ‘size’ and ‘array’ are declare in the ‘tr’ class. But ‘helper’ isn’t declare in the class.
I want to use ‘helper’ as local rand variable in the ‘seq’ class even though I can declare a variable like ‘helper’ in the ‘tr’ class.
Can I use a ‘helper’ variable in the ‘seq’ class?
My code is below.
class seq;
tr tr_obj;
task body ();
`uvm_create(tr_obj);
...
`uvm_rand_send_width(tr_obj, {
// constraint for selecting byte lane
}
endtask
endclass
class tr;
rand logic [2:0] size;
rand logic [31:0] array[];
endclass
I trying like below. This code doesn’t work. I trying to fix it.
class seq;
tr tr_obj;
rand helper[];
task body ();
`uvm_create(tr_obj);
...
`uvm_rand_send_width(tr_obj, {
local::helper.size() inside {1,2,3,4,5,6,7,8};
tr_obj.array.size() == tr_obj.size;
foreach ( local::helper[select_lane] ) {
foreach ( tr_obj.array[i] ) {
tr_obj[i][(select_lane)*4+;4] inside {'0, '1};
}
}
}
endtask
endclass
class tr;
rand logic [2:0] size;
rand logic [31:0] array[];
endclass
In reply to jh_veryveri:
A couple of problems with your code.
helper has to be a fixed sized array of 8 1-bit elements. Based on your original example, this assumes each array element is a fixed 32-bits wide, and each byte lane is 4-bits wide.
Even though you declared helper as rand in your seq class, it is not part of the tr object that is being randomized. Unfortunately the call to tr_obj.rnadomize() is buried inside the `uvm_rand_send_with macro. So the helper array gets treated as a non-random state variable.
If you can’t modify the tr class directly, you should extend it adding the helper array. Then use the UVM factory to override the tr class.