200 int in the array, random array to have only 5 different numbers in the range [0:50], make sure every number appears 40 times and no same number in any 4 consecutive slots.
Below is the code I have come up with and I am still working on the solution.
class packet;
rand int unsigned array[];
//create the size of the dynamic array to hold 5 random integers
array = new[5];
//array can have 5 random numbers in the range [0:50]
constraint c1 {foreach(array[i]) array[i] inside {[0:50};}
//constraint such that each element should appear exactly 40 times in the array with 200 elements
constraint c2 {foreach(array[i]) array[i] dist {:= 40};}
//constraint such that no same number should appear in any 4 consecutive slots
constraint c3 {i inside {[0:197]};}
constraint c4 {foreach(array[i]) array[i] != array[i+1];
array[i] != array[i+2];
array[i] != array[i+3];}
endclass
module top;
initial begin
//handle and constructor for the class
packet pkt;
pkt = new();
repeat(200)begin
pkt.randomize();
$display ("array size is %d", pkt.array.size);
foreach (s1.array[i]) $display("square of array[i] = %d,%d",i,s1.array[i]);
end
endmodule
It would be great if anyone could help me out figure out how to make the above code work.
Thanks in advance for any additional solutions too.
Your approach to learning Constrained Randomization reminds me of the Infinite Monkey Protocol. If you keep throwing arbitrary constraints at the problem, you’ll eventually get the correct result! It looks like you cut and pasted code snippets from different examples and tried putting them together into a single randomization.
You wanted to create an array of 200 integers, yet nowhere do you create an array of 200 integers. You cannot use a distribution constraint if you need an exact count. You need to use the sum() reduction method to count the number of occurances.
This is the brute force way of creating the constraints, but you probably won’t be able to run this with the tools on EDAPlayground as it creates way too many interconnected constraints.
class packet;
parameter int N = 15;
rand byte unsigned array[N];
rand byte unsigned list[5];
//array can have 5 random numbers in the range [0:50]
constraint c1 {foreach(list[i]) list[i] inside {[0:50]}; unique {list}; }
//constraint such that each element should appear exactly 40 times in the array with 200 elements
constraint c2 {
foreach(list[i]) array.sum() with (int'(item==list[i])) == N/5; }
//constraint such that no same number should appear in any 4 consecutive slots
constraint c4 {foreach(array[i]) i< N-3 ->
{array[i] == array[i+1] ->
array[i] == array[i+2] ->
array[i] != array[i+3];
}}
endclass
module top;
initial begin
//handle and constructor for the class
packet pkt;
pkt = new();
repeat(200) begin
assert(pkt.randomize());
foreach (pkt.array[i]) $display("array[%0d] = %d",i,pkt.array[i]);
$display;
end
end
endmodule
You might have to break it up into two separate randomizations:
class packet;
parameter int N = 200;
rand byte unsigned array[N];
byte unsigned list[5];
function void pre_randomize();
//array can have 5 random numbers in the range [0:50]
assert(std::randomize(list) with {
foreach(list[i]) list[i] inside {[0:50]}; unique {list}; });
endfunction
//constraint such that each element should appear exactly 40 times in the array with 200 elements
constraint c2 {
foreach(list[i]) array.sum() with (int'(item==list[i])) == N/5; }
//constraint such that no same number should appear in any 4 consecutive slots
constraint c4 {foreach(array[i]) i< N-3 ->
{array[i] == array[i+1] ->
array[i] == array[i+2] ->
array[i] != array[i+3];
}}
endclass
module top;
initial begin
//handle and constructor for the class
packet pkt;
pkt = new();
repeat(2) begin
assert(pkt.randomize());
foreach (pkt.array[i]) $display("array[%0d] = %d",i,pkt.array[i]);
$display;
end
end
endmodule
In your above solution, you said to use the sum() reduction method to count the number of occurrences. How will sun() count the number of occurrences? Isn’t sum mean to add all the elements inside the array? And since I don’t know what elements would be in what indices, how should I understand the sum() reduction method to count the number of occurrences?
Could you please explain the below constraint:
constraint c2 {
foreach(list[i]) array.sum() with (int’(item==list[i])) == N/5; }
Also in method 1, can you please let me know why do we need the parameter N to be to 15?
The way I tried approaching the problem is to break it into multiple sub-problems.
I did not copy-paste the snippets but translated the problem into comments and then substituted each comment with a constraint. Since I am in the learning stage, I did refer to multiple websites for syntax and working style of each constraint and kept working on the code in eda playground: Edit code - EDA Playground
Please let me know if there’s a better approach to learn randomization.
I am currently following multiple websites: verificationguide.com/chipverify.com/siemens videos by chirs spear and system Verilog lrm.
The sum() array reduction method sums up all the elements or sums up whatever is inside the with() clause. You can think of
array.sum() the same as
array.sum with (item), and
item gets replaced with each element. You should look at this.
Your last $display statement references s1, which does not exist your example, and tries to print “Square of array” which has nothing to do with anything in this discussion, so I assumed you had pasted from some other example. You should at least get your code compiling and executing. Then focus on getting the correct results.
N=15 was just the larges value I get get a result with using the tools on EDAPlayground.
Sometimes the constraint solving problem becomes too complicated to be solved in a reasonable amount of time. This example has an array of 200 elements each needing to be at least 6 bits. So that is 1200 bits all with many interwoven constraints between them. Breaking the constraints into two separate sets reduces the complexity.
The repeat(2) is insignificant, it was just for debugging. I should have changed it back to 200 as in your original example.
In reply to sk7799:
Sometimes the constraint solving problem becomes too complicated to be solved in a reasonable amount of time. This example has an array of 200 elements each needing to be at least 6 bits. So that is 1200 bits all with many interwoven constraints between them. Breaking the constraints into two separate sets reduces the complexity.
The repeat(2) is insignificant, it was just for debugging. I should have changed it back to 200 as in your original example.
Hi Dave,
we have an issue with solver, at integration of chain of blocks sequences as sub sequence one of another (dinamic tree of sub sequences with constraitns between), relying on this sentence in LRM: (IEEE 1800-2017 SV LRM section 18.5.9 Global constraints)
“… A class may declare an object
member (i.e. class instance) as “rand”. When the top-level object is randomized, the lower level objects are also randomized. All rand variables and constraints in the top- and lower-level objects are solved simultaneously…”
is solver work similar between this example (LRM’s example) and using array with foreach?
class A;
rand bit [7:0] v;
endclass
class B extends A;
rand A left;
rand A right;
//...CHAINS_SPLIT
constraint heapcond {left.v <= v; right.v > v;}
endclass
Class C extends A;
rand A[];
constraints heapcond {
A.size() == CHAINS_SPLIT;
foreach(A[i]){
(A.size() > i+1) -> A[i].v <= A[i+1].v;
}
}
endclass
In other words, is there a difference between the solver’s work in B vs C?
CHAINS_SPLIT is a project and structure dependent parameter, the easy way is to implement with an array but if another way reduces the solver’s effort, it can make the simulation faster and thrift
just to correct, in our situation the C looks more like this: