Seek suggestions for following SV constraints

Hi All ,
I was seeking suggestions for following requirements

  1. Size of array to 10 , each element would be within value 1,3 or 5. Elements should be in ascending order
rand bit[3:0] arr[];    
constraint SIZE { arr.size() == 10; }
constraint element_value  {      
          foreach( arr[i] ) { arr[i] inside { 1 , 3 , 5 } ;  }                        
                           }
function void post_randomize();        
    arr.sort();
 endfunction 

However one limitation is that there is no constraint to ensure that there is at least one occurrence of each of 1,3 and 5.
Eg: One possible output is '{'h3, 'h3, 'h5, 'h5, 'h5, 'h5, 'h5, 'h5, 'h5, 'h5}

I then tried using sum() constraint

//  Instead of constraint 'element_value' 
constraint element_value_using_sum  {      
        arr.sum() with ( int'(item==1) ) + arr.sum() with ( int'(item==3) )       
      + arr.sum() with ( int'(item==5) ) == arr.size() ;              
                           }

However this too has the similar limitation as above
[Q1] Is it possible to constraint the elements within values 1,3 and 5 as well as constraint at least one occurrence of each value, using a single constraint expression ?

  1. Randc behavior using rand
rand bit[3:0] a;
     bit[3:0] q[$];
constraint rand_cyclic { if( q.size() != 0 ) !( a inside { q } ); }
function void post_randomize();        
    if( q.size() == 16 ) q.delete();
 endfunction

Q2] If I were to remove the constraint-guard ( if( q.size() != 0 ) ) , during the 1st call to randomize, would the constraint !( a inside { q } ) have any side-effects ( since the queue is empty ) ?

You were on the right track with the sum() constraints

class A;
  rand bit[3:0] arr[];    
  constraint c {arr.size() == 10 &&
                arr.sum() with (int'(item == 1)) >= 1 &&
                arr.sum() with (int'(item == 3)) >= 1 &&
                arr.sum() with (int'(item == 5)) >= 1 &&
                arr.sum() with (int'(!(item inside {1,3,5}))) == 0 &&
                arr.and() with (item.index>0 -> arr[item.index-1] <= arr[item.index]);
               }
endclass

module top;
  A h = new;
  initial repeat(10) begin
    assert(h.randomize());
    $display("%p",h.arr);
  end
endmodule

Thanks Dave, for the alternative solution to achieve ascending order elements
( another solution is using simple foreach ).

[Q1] Is it possible to constraint the elements within values 1,3 and 5 as well as constraint at least one occurrence of each value, using a single constraint expression ?

Using ā€˜&&ā€™ I could achieve it with a single constraint expression.

Would like to hear your thoughts on Q2.

constraint rand_cyclic { !( a inside { q } ); } // What if queue is empty ?

During the 1st call to randomize() is there any possible side-effect ? ( as the queue is empty during the 1st call to randomize() )
Does there essentially exist any constraint when the queue is empty ?

Your queue is always empty because you forgot to push anything into it.

!(a inside { q }) is true when the queue is empty. No need for a guard.

Hi,

Iā€™m trying to understand how
arr.and() with (item.index>0 -> arr[item.index-1] <= arr[item.index]);

this constraint is working.

Remember that the implication operator A -> B is the same as !A || B. Then you just need to unroll it for each item in the array

arr.and() with (item.index>0 -> arr[item.index-1] <= arr[item.index]);
(0>0) -> arr[0-1] <= arr[0] &&
(1>0) -> arr[1-1] <= arr[1] &&
(2>0) -> arr[2-1] <= arr[2] &&
(3>0) -> arr[3-1] <= arr[3] &&
(4>0) -> arr[4-1] <= arr[4] &&
(5>0) -> arr[5-1] <= arr[5] &&
(6>0) -> arr[6-1] <= arr[6] &&
(7>0) -> arr[7-1] <= arr[7 &&
(8>0) -> arr[8-1] <= arr[8] &&
(9>0) -> arr[9-1] <= arr[9]
1 &&
arr[0] <= arr[1]) &&
arr[1] <= arr[2]) &&
arr[2] <= arr[3]) &&
arr[3] <= arr[4]) &&
arr[4] <= arr[5]) &&
arr[5] <= arr[6]) &&
arr[6] <= arr[7]) &&
arr[7] <= arr[8]) &&
arr[8] <= arr[9]

Hi @LFT
I tried solving the above query in my own way:
Hope this is what you were expecting:

class abc;
  rand bit[7:0] arr[];
  
  constraint a_c{
    arr.size() == 10;
    foreach(arr[i]){
      arr[i] inside {1,3,5};
    }
    arr.sum with (int'(item==1))>=1;
    arr.sum with (int'(item==1))>=3;
    arr.sum with (int'(item==1))>=5;
  }
     function void post_randomize();
       arr.sort();
      $display("value of array is %p",arr);
    endfunction   
endclass: abc

  module tb;
   abc abc_inst;
  initial begin 
    abc_inst = new();
    //repeat(10)
    abc_inst.randomize();

  end
endmodule