Array Constraints every N elements

Hi,

If I got huge int array and want to make sure every N (a big number, e.g 100) element, there is must have a specific value within this range.
for smaller N, I can handle in following way, how about big N range?

If N is huge, and constraint block doesn’t support for-loop, how can I achieve it?
Thanks for any suggestion.

example : N = 5 : every 5 entries, there is exact 1 specific value in this range.


class my_item;
  
  rand int vec[1000];
  rand int val;

  constraint c {
    val == 1;
    foreach(vec[i]) {
       // iterage array and check N=5 entry subgroup here
      (i inside {[2:vec.size-3]}) ->
      ( (vec[i-2]==val) + (vec[i-1]==val) + 
        (vec[i]==val) + (vec[i+1]==val) + 
        (vec[i+2]==val)
      ) == 3'd1; // exact 1 entry == val is allowed
    }
  }
endclass

class A;
   rand bit [7:0] vec[20];
   rand bit [7:0] val;
   int N=5;
   
   constraint c_range {
      foreach (vec[ii]) ii % N == 0 -> 
             vec.sum() with (int'(item == val && item.index inside {[ii:ii+N-1]})) == 1;
   }
     endclass
module top;

   A a=new;
   initial repeat (10) begin
      assert(a.randomize());
      $display("val: %0d %p",a.val,a.vec);
   end
endmodule

In reply to dave_59:

Thanks, Dave.
It’s good to know we have item.index syntax!
level up!

I was also able to solve this question by

class A
   rand bit [7:0] vec[20];
   rand bit [7:0] val;
   int N=5;
   rand int j[];

   function new();
    j = new[20/5]; //calculate the number of indexes for val
   endfunction
   constraint c_range {
     foreach(j[i]) j[i] inside {[0:N-1]}; //calculate those indexes
     foreach(vec[ii]) {
      if((ii % N) == 0) {
        vec[ii + j[ii/N]] == val;  //add the val to those indexes
      }
     }
     solve j before vec;
  }
endclass

In reply to jsaluja:

using extra memory to store random offset isn’t a great move.
prefer a light weighted solution to offload random solver, but thanks.
it like this code to me ha


    int q[$];
    int a[5];
    int val = 111;
    repeat(9999) begin
      std::randomize(a) with { a.sum() with (int'(item==val)) == 1;};
      q = {q, a};
    end

In reply to dave_59:

class A;
rand bit [7:0] vec[20];
rand bit [7:0] val;
int N=5;
constraint c_range {
foreach (vec[ii]) ii % N == 0 -> 
vec.sum() with (int'(item == val && item.index inside {[ii:ii+N-1]})) == 1;
}
endclass
module top;
A a=new;
initial repeat (10) begin
assert(a.randomize());
$display("val: %0d %p",a.val,a.vec);
end
endmodule

What if this was a 10x10 2D array, where I want a value of 1 to be present atleast once if the item index was between 3 and 7 ?

I have this so far but it doesn’t work:

rand int arr[10][10];
  constraint C {foreach(arr[i,j]){arr[i][j] inside {[1:50]}};};
  constraint C1{foreach(arr[item1,item2]){
    arr.sum(item1) with (item1.sum(item2) with (int'(item2==1 && item2.index inside {[3:7]}))) ==1;
    
  }}

In reply to Tr0408:
Not sure if you meant for both dimension indexes to be constrained or just one.

class A;
  rand int arr[10][10];
  constraint C {foreach(arr[i,j]){arr[i][j] inside {[1:20]}};}
  constraint C1{
    arr.sum(item1) with (item1.index inside {[3:7]} ? 
                         item1.sum(item2) with (item2.index inside {[3:7]} ?
                                                item2 == 1 : 0) 
                         : 0 ) > 0; // at least once means a sum greater than 0
  }
endclass

module top;
  A a = new();
  initial repeat (5) begin
    assert(a.randomize());
    $display("arr = ");
    foreach(a.arr[i]) begin
      foreach(a.arr[,j]) $write("%3d", a.arr[i][j]);
      $display;
    end
  end
endmodule

In reply to dave_59:

Hi Dave,

Looks like you missed one thing in code. please review below code once

class A;
   rand bit [7:0] vec[20];
   rand bit [7:0] val;
   int N=5;
 
   constraint c_range {
      foreach (vec[ii]) (ii % N == 0 && ii < (vec.size-N+1)) -> 
             vec.sum() with (int'(item == val && item.index inside {[ii:ii+N-1]})) == 1;
   }
     endclass
module top;
 
   A a=new;
   initial repeat (10) begin
      assert(a.randomize());
      $display("val: %0d %p",a.val,a.vec);
   end
endmodule

In reply to rambabu_g:

I don’t think the
&& ii < (vec.size-N+1
is necessary. Can you explain a case where you think it is needed.