class A;
rand bit [7:0]mask;
rand bit [7:0]b;
function void display();
$display("Mask is %8b::b=%8b",mask,b);
endfunction
//mask_validation function is to be used in the constraint block.
//This fucntion returns "1" if input mask value is having continuous 1s.
//Otherwise returns zero.
//example: 1111,1110,1100,1000,0111,0110,0100,0011,0010,0001,0000 should return "1".
//Other values will return "0".
//Explanation: Here it will keep on checking the each bit, If "1" is appeared,
//then it will set the first_one_occured = 1. After a one if zero will be hit,
//then it sets zero_after_one = 1. If after this again a one come then it will return "0".
//As mask value is non continuous. (e.g. 1010.1001,1101 etc)
function bit mask_validation(bit [7:0]mask);
bit first_one_occured = 0;
bit zero_after_one = 0;
foreach(mask[i]) begin
if (mask[i]) begin
if(!first_one_occured)
first_one_occured = 1;
if(zero_after_one) begin
return 0;
end
end
else begin
if(first_one_occured)
zero_after_one=1;
end
end//foreach
return 1;
endfunction
constraint nonzero_b{b != 8'b00000000;}
constraint nonzero_mask{mask!=8'b00000000;}
constraint valid_mask{mask_validation(mask) == 1;}
endclass
module test;
A a;
initial begin
a=new();
repeat (10) begin
void'(a.randomize());
a.display();
end
end
endmodule
Please point me where I am doing wrong. It shows constraint failure.
Please correct me.
If there is any simpler logic to generate a continuous mask, then please share.
I rewrote your function, but I still got the same results of No solutions exist
Like you, I fail to understand why.
I tried other approaches, but my algorithms are wrong.
Perhaps this will help you into a different solution.
Also, perhaps someone else can explain why the failure.
class A;
rand bit [7:0]mask;
rand bit [7:0]b;
function void display();
$display("Mask is %8b::b=%8b",mask,b);
endfunction
//mask_validation function is to be used in the constraint block.
//This fucntion returns "1" if input mask value is having continuous 1s.
//Otherwise returns zero.
//example: 1111,1110,1100,1000,0111,0110,0100,0011,0010,0001,0000 should return "1".
//Other values will return "0".
//Explanation: Here it will keep on checking the each bit, If "1" is appeared,
//then it will set the a_one_occurred = 1. After a one if zero will be hit,
//then it sets zero_after_one = 1. If after this again a one come then it will return "0".
//As mask value is non continuous. (e.g. 1010.1001,1101 etc)
function bit mask_validation(bit [7:0]mask);
bit a_one_occurred = 0;
bit zero_after_one = 0;
bit fail=0;
foreach(mask[i]) begin // Mask is 01110010::b=00011010
case({a_one_occurred, zero_after_one})
2'b00: if(mask[i]) a_one_occurred=1'b1;
//2'b01: if(mask[i]) a_one_occurred=1'b1;
2'b10: if(mask[i]==1'b0) zero_after_one=1'b1;
2'b11: if(mask[i]) fail=1'b1; // mask[i]==1'b0; // must be 0
endcase
end
return fail;
endfunction
constraint nonzero_b{b != 8'b00000000;}
constraint nonzero_mask{mask!=8'b00000000;}
constraint valid_maskF{mask_validation(mask) == 0;}
/* constraint valid_mask{{mask[7:4]!=4'b1001}; //2 zeros and 1
{mask[6:3]!=4'b1001};
{mask[5:2]!=4'b1001};
{mask[4:1]!=4'b1001};
{mask[3:0]!=4'b1001};
{mask[7:3]!=5'b10001}; //3 zeros and 1
{mask[6:2]!=5'b10001};
{mask[5:1]!=5'b10001};
{mask[4:0]!=5'b10001};
{mask[7:1]!=6'b100001}; //4 zeros and 1
{mask[6:0]!=6'b100001}; } */
/*constraint new_mask{ {mask[7]==1 -> mask[6:4]!= 3'b001 &&
mask[5:3]!= 3'b001 &&
mask[4:2]!= 3'b001 &&
mask[3:1]!= 3'b001 &&
mask[2:0]!= 3'b001};
{mask[6]==1 -> mask[5:3]!= 3'b001 &&
mask[4:2]!= 3'b001 &&
mask[3:1]!= 3'b001 &&
mask[2:0]!= 3'b001};
{mask[5]==1 -> mask[4:2]!= 3'b001 &&
mask[3:1]!= 3'b001 &&
mask[2:0]!= 3'b001};
{mask[4]==1 -> mask[3:1]!= 3'b001 &&
mask[2:0]!= 3'b001}; }*/
endclass
module test;
A a;
initial begin
a=new();
repeat (10) begin
void'(a.randomize());
a.display();
end
end
endmodule
In reply to Tapas:
Calling a user defined function in a constraint breaks the solution space in half. The inputs to the function get randomized to a solution first, then the function gets called, and the output of the function becomes a non-random state variable.In your example. if the output of mask_validation returns 0, it won’t go back and try another set of inputs until the output returns 1. the constraint will just fail.
What you need to do is express your constraints entirely as a set of equations.
class A;
rand bit [7:0] mask;
rand int unsigned N; // Number of ones
rand int unsigned S; // shifted position
constraint valid_mask {
N inside {[1:8]};
S <= 8-N;
(9'b1 << N)-9'd1 << S == mask;
}
endclass
module top;
A a= new;
initial repeat(100) begin
assert(a.randomize());
$display("mask %b N %0d S %0d",a.mask,a.N, a.S);
end
endmodule
In reply to dave_59:
That was a clever solution Dave!
On inputs to the function get randomized to a solution first, then the function gets called:
Isn’t that similar to a post-randomize with the exception that if the result of the function is zero you fail the randomize? What are the benefits of the function call in a constraint? To fine-tune it after the randomization of the variable?
Ben
In reply to dave_59:
Changing bit size 9 to 8 have impact? I didn’t get any issues. Do you have any specific region to use bit size equals to 9 not 8 in following constraint.
(9’b1 << N)-9’d1 << S == mask;
You can use a function in a constraint as long as the random variable dependencies flow through correctly. For examlpe in the orginal example , you could write instead
constraint valid_mask{mask_validation(mask) -> b < 10; }
and that will always find a solution.
In reply to voraravi:
Yes, you’re correct the bit-width doesn’t matter in this case. I was worried that when N==8 the 'b1 would get truncated. But it turns out (9’b1_00000000 - 9’b0_00000001) and (8’b00000000 - 8’b00000001) both give me 'b11111111
In reply to dave_59:
Thanks for your earlier input.
constraint valid_mask{mask_validation(mask) -> b < 10; }
But for this constraint, I am not able to get the proper output. Will you please explain a bit, how it is going to work? Actually I am not able to figure out the idea behind this.
You have to run more than 10 randomization’s to see it working. The mask becomes an unconstrained random variable, and there’s less than a 15% chance (37/256) that the mask has a continuous set of ones. See function in constraint - EDA Playground.
Hi Dave, can you please explain what was your thought process when you start working on this problem?(which are the points that decided that streaming operator will be used?)