SV contraint to repeat elements n time

How do i create an dyn array with repeating elements n time. For eg in a[20] - 1 should be 10, 2 should be 5, 3 should be 5 times

In reply to ak_verifsj:

//How do i create an dyn array with repeating elements n time. For eg in a[20] - 1 should be 10, 2 should be 5, 3 should be 5 times
module tb;
class Packet;
  rand int a[];
 
  constraint a_c {a.size == 20;
 
                       foreach (a[i]) a[i] inside {1,2,3};
                       //   a[i] dist{(a[i] == 1):= 10, (a[i] == 2) := 5, (a[i] == 3) := 5};} // this doesn't work for some reason, CAn some one explain?
  
                       a.sum() with ((item == 1) ? 1 :0) == 10;
                       a.sum() with ((item == 2) ? 1:0)  == 5;
                       a.sum() with ((item == 3) ?1 : 0) == 5;
                      }
  endclass
 
initial begin
  Packet p1;
  p1 = new();
  
  if (!p1.randomize()) begin
    $display ("Randomization Error");
  end
 
  $display ("Value of array A is %p",p1.a);

 
end
endmodule

In reply to n347:

Hi, thank you for the solution. Can you please explain how this statement work?

a.sum() with ((item == 1) ? 1 :0) == 10;

In reply to ak_verifsj:

Hi,

(item == 1) ? 1:0 

will return either 1 or 0 depending on the values of each element in the array. If the item value is equal to 1, it will return 1, else, it will return 0. For example, if the array “a” contains elements like {1,6,1,4,1}, then,

(item == 1) ? 1:0 

will return {1,0,1,0,1}.

a.sum() with ((item == 1) ? 1:0) 

will calculate the sum of these 1’s and 0’s. And finally, the constraint

 a.sum() with ((item == 1) ? 1 :0) == 10; 

will make sure that, the sum of these 1’s and 0’s is 10. and thus, this constraint will ensure that, the no. of 1’s in this array is 10.

Hope this helps.

Putta Satish

In reply to n347:

Distribution constraint will not be useful in this case, because, you are not randomizing multiple times. You are calling randomize method only once. The weights, that you are specifying while writing distribution constraints will be used by simulator if you randomizing multiple times.

Hope this helps
Putta Satish

I have a follow-up question . I notice that following code in procedural block ( like initial block ) works fine and give same result ::


bit [3:0] b [$] = '{ 1 , 6 , 2 , 1 , 9 , 1  , 2 , 10 , 15 } ;
int b1 ;

initial begin

b1 = b.sum() with ( ( item == 1 ) ? item : 0  ) ;

$display(" b is %0p",b);

$display(" Result of b.sum() with ( ( item == 1 ) ? item : 0  ) is %0d ",b.sum() with ( ( item == 1 ) ? item : 0  ));

$display(" Result of b.sum() with ( ( item == 1 ) ? 1 : 0  ) is %0d ",b.sum() with ( ( item == 1 ) ? 1 : 0  ));

$display(" Result of b.sum() with ( ( item == 1 ) ? ( item == 1 ) : 0  ) is %0d ",b.sum() with ( ( item == 1 ) ? ( item == 1)  : 0  ));

end

Whereas if I try it in a Constraint all 3 of the variation fails ::


    // TYPE 1 
a.sum() with ((item == 1) ? item == 1 : 0 ) == 10 ;
a.sum() with ((item == 2) ? item == 2 : 0 ) == 5 ;
a.sum() with ((item == 3) ? item == 3 : 0 ) == 5 ;
                                                    
    // TYPE 2 
a.sum() with ((item == 1) ? item : 0 ) == 10 ;
a.sum() with ((item == 2) ? item : 0 ) == 5 ;
a.sum() with ((item == 3) ? item : 0 ) == 5 ;
                                                    
    // TYPE 3
a.sum() with ((item == 1) ? 1 : 0 ) == 10 ;
a.sum() with ((item == 2) ? 2 : 0 ) == 5 ;
a.sum() with ((item == 3) ? 3 : 0 ) == 5 ;


In reply to ABD_91:

It might help to explain how the sum() reduction method calculates its result.

array.sum() without awith {} clause expands to

typedef int element_type;
element_type array[];
element_type item;
element_type sum = 0;
foreach (array[index] ) begin
     item= array[index];
     sum = sum + item;
end

It’s important to note that the datatype of
item
and
sum
is the same datatype as each element of the array. That means if the array element type is a single bit, the
item
and
sum
type is also a single bit. Instead of getting an intended count of 1’s, you get the odd parity of 1’s

The with {} clause substitutes what gets added to the sum. It also changes the sum data type to match the type the with {} clause. So if you had

bit array [];
array.sum with (int'(item));

that gets expanded to

typedef bit element_type;
element_type array[];
element_type item;
int sum = 0;
foreach (array[index] ) begin
     item= array[index];
     sum = sum + int'(item);
end

which gives you the count of 1’s as an int.

When you tried

a.sum() with (item == 1)

that has the problem that the resulting datatype of an equality expression is 1 bit. You run intto the same problem of not counting the number of times the expression is true. To fixe that you can do

a.sum() with (int'(item == 1))

Using the conditional operator achieves the same thing a little bit more cryptically because the bare numeric literals 1 and 0 are implicitly 32-bit signed decimal numbers. And that becomes the return datatype of the with {} clause.

.

In reply to dave_59:

Hi Dave ,

I understand the concept of using static cast eg: int’( item ) inside with () to avoid overflow cases .

I am unable to understand , how are these 2 different ::


a.sum() with ((item == 1) ? 1 : 0 ) == 10 ; // RHS of ? when true is 32-signed
a.sum() with ((item == 2) ? 2 : 0 ) == 5 ;  // RHS of ? when true is 32-signed
a.sum() with ((item == 3) ? 3 : 0 ) == 5 ;  // RHS of ? when true is 32-signed

 **VS** 

a.sum() with ((item == 1) ? 1 : 0 ) == 10 ;  // RHS of ? when true is 32-signed
a.sum() with ((item == 2) ? 1 : 0 ) == 5 ;   // RHS of ? when true is 32-signed
a.sum() with ((item == 3) ? 1 : 0 ) == 5 ;   // RHS of ? when true is 32-signed

In both cases when condition is true , the RHS of ? is 32-bit signed .

When I write

a.sum() with ((item == 2) ? item : 0 ) == 5 ;

Since item is 4-bit , sum of 5 shouldn’t lead to overflow anyways .

I believe when condition ( item == 2 ) is true the item [ item would be 2 ALWAYS since ( item == 2 is True ) ] should be used to calculate sum .

So effectively reduced to

 a.sum() with ( elements with value 2 ) == 5 ;

Please correct me if my interpretation it wrong .

EDIT :: The constraint reduces to ::


   1 == 10 ;  2 == 5 ; 3 == 5 ; 
 

Which can NEVER be true , hence the Failure !!

In reply to ABD_91:

The length of the result of (i ? j : k) is Max(Length(j),Length(k). So result of (a.sum() with ((item == 2) ? item : 0 ) gets evaluated in 32-bits since the numeric literal 0 is 32-bits.

The following two constraints will never succeed because there is no multiple of 2 or 3 that could ever equal 5.

a.sum() with ((item == 2) ? 2 : 0 ) == 5 ; 
a.sum() with ((item == 3) ? 3 : 0 ) == 5 ; 

You many want to read https://go.mentor.com/5cdxN

In reply to UVM_SV_101:

In reply to n347:
Hi, thank you for the solution. Can you please explain how this statement work?

a.sum() with ((item == 1) ? 1 :0) == 10;

below code demonstrates how .sum() with() works:


module m();

  byte a[] = {3, 1, 1, 3, 1, 2, 1, 3, 1, 2};

  initial
  begin  
    $display("sum = %0d", a.sum());                            //18   = 3    + 1    + 1    + 3    + 1    + 2    + 1    + 3    + 1    + 2
    $display("sum = %0d", a.sum() with (item==1));             //1'b1 = 1'b0 + 1'b1 + 1'b1 + 1'b0 + 1'b1 + 1'b0 + 1'b1 + 1'b0 + 1'b1 + 1'b0
    $display("sum = %0d", a.sum() with (item==2));             //1'b0 = 1'b0 + 1'b0 + 1'b0 + 1'b0 + 1'b0 + 1'b1 + 1'b0 + 1'b0 + 1'b0 + 1'b1  
    $display("sum = %0d", a.sum() with (int'(item==1)));       //5    = 0    + 1    + 1    + 0    + 1    + 0    + 1    + 0    + 1    + 0
    $display("sum = %0d", a.sum() with (int'(item==2)));       //2    = 0    + 0    + 0    + 0    + 0    + 1    + 0    + 0    + 0    + 1
    $display("sum = %0d", a.sum() with ((item==2) ? 1 : 0));   //2    = 0    + 0    + 0    + 0    + 0    + 1    + 0    + 0    + 0    + 1
    $display("sum = %0d", a.sum() with ((item==2) ? item : 0));//4    = 0    + 0    + 0    + 0    + 0    + 2    + 0    + 0    + 0    + 2
    $display("sum = %0d", a.sum() with ((item==2)*item));      //4    = 0    + 0    + 0    + 0    + 0    + 1*2  + 0    + 0    + 0    + 1*2
  end

endmodule