Soragim
Soragim

Reputation: 337

Sum 2D array in constraints in system verilog

I'm trying to create constraint using a 2d array filled with 1's and 0's. I want every row to have a total sum of either 0,1,2,4 and every column sums to 1. Moreover, I want the entire sum of the matrix to be equal to 8 (which worked using sum function). I tried using the function .sum() to constraint of every row and column to the value I demanded, but I keep getting syntax error. What am I doing wrong?

rand bit MAT[8][8];
constraint range { 
MAT.sum() with (32' (item)) == 8;
  foreach (MAT[j]){
      foreach(MAT[j][i]){
  MAT[j][].sum() with (32' (item)) == 1; 
  MAT[][i].sum() with (32' (item)) inside {0,1,2,4};
     }
 }

Upvotes: 4

Views: 4933

Answers (3)

Vrihad Agarwal
Vrihad Agarwal

Reputation: 1

For sum along 2nd index: Instead of MAT[j][].sum() with (32'(item)) Use MAT[j].sum() with (32'(item))

For sum along 1st index: Instead of MAT[][i].sum() with (32'(item)) Use MAT.sum() with (32'(item[i]))

Note: For sum along any index of a multi-dimensional array, specify the higher dimension indices and then reduce the sub array obtained, using with clause for lower dimension indices.

Example:

bit bit_array [n0][n1][n2][n3][n4];
int sum_0 = bit_array.sum() with (int'(item[i1][i2][i3][i4]));
int sum_1 = bit_array[i0].sum() with (int'(item[i2][i3][i4]));
int sum_2 = bit_array[i0][i1].sum() with (int'(item[i3][i4]));
int sum_3 = bit_array[i0][i1][i2].sum() with (int'(item[i4]));
int sum_4 = bit_array[i0][i1][i2][i3].sum() with (int'(item));

Upvotes: 0

Dustin
Dustin

Reputation: 1

Actually, array2d.sum() works with VCS.

Upvotes: 0

Tudor Timi
Tudor Timi

Reputation: 7573

Section 7.12.3 Array reduction methods of the IEEE 1800-2012 standard states that

[array] reduction methods may be applied to any unpacked array of integral values to reduce the array to a single value.

While MAT[0].sum() or MAT[1].sum() is allowed (apply sum on line 0 and 1 respectively of MAT), MAT.sum() is not. A line in MAT is an array of bit and bit is an integral type, but MAT is an array of unpacked array of bit which is not an integral type.

Also, it's not possible to select a single column from an array. You can only slice row-wise. This is a bit trickier to implement, but doable.

Let's look at each constraint. First, constraining the sum of each row is easily done with the sum() function:

  constraint sum_on_row {
    foreach (MAT[i])
      MAT[i].sum() with (32'(item)) inside { 0, 1, 2, 4 };
  }

To constraint the sum on a column you'll need to transpose the array (rows become columns, columns become rows) and constrain that. First, let's define the transpose of MAT:

  rand bit MAT_transp[8][8];

  constraint construct_MAT_transp {
    foreach (MAT[i,j])
      MAT_transp[j][i] == MAT[i][j];
  }

We allocate another array and keep its contents in sync with those of MAT. Any constraints on MAT_transp will indirectly affect MAT. As before, we can constrain the rows of MAT_transp, which will effectively constrain the columns of MAT:

  constraint sum_on_col {
    foreach (MAT_transp[i])
      MAT_transp[i].sum() with (32'(item)) == 1;
  }

And lastly, you want the sum of all elements in the array to be 8. This is the trickiest to do. While we can't constrain the array sum directly, we can split the problem into two parts. First, we can compute the sum for each row in MAT and store them all in an array:

  rand int unsigned row_sums[8];

  constraint compute_row_sums {
    foreach (row_sums[i])
      row_sums[i] == MAT[i].sum() with (32'(item));
  }

Now that we have the sum on each row, it's easy to constrain the sum of the entire array by constraining the sum of all row sums:

  constraint sum_of_matrix {
    row_sums.sum() == 8;
  }

The cool thing is that with this one problem we've covered a lot of the usual "tricks" we can apply when constraining arrays. You can find more array constraint idioms in an old post I wrote.

Upvotes: 3

Related Questions