Randomize a two-dimensional array with unique elements

Hi,

I am trying to generate a two-dimensional array with unique elements, without using the “unique” construct. However, the following code seems to produce zeros for quite a few elements.


class array2d;

//rand int unsigned array2d [] [];
rand bit[15:0] array2d [] [];


  constraint c {array2d.size() inside {[10:20]};
      foreach(array2d[ii])
		 array2d[ii].size inside {[10:20]};
  }

 constraint c_array2d_elem {

  foreach(array2d[i,j]) {
     if (i < array2d.size()) { array2d[i][j] != array2d[i+1][j];}
     if (j < array2d[i].size()) { array2d[i][j] != array2d[i][j+1];}

  }
 }


 function void print();
   $display("size of matrix row: %0d", array2d.size());
   foreach(array2d[i,j]) begin
     $display("array2d[%0d][%0d]: %0d", i, j, array2d[i][j]);
   end
 endfunction

endclass


In fact, I seem to get a randomization failure then the output with zeros:


Error-[CNST-IAIE] Constraint illegal array index error
two_dimen_dyn_array_with_unique_elements.sv, 37
  Constrained variable array2d[1][12] is outside of the array size.
  Please make sure variable array2d[1][12] is within the array size.


Q. What is wrong with the code above so as to generate zeros?
Q. Is there a way to print the two dimensions when I want to print the size.
Q. Also, how can I print the elements as a matrix (not like the one shown above)

In reply to mseyunni:

One problem is that your constraints create an irregularity shaped array with each row potentially having a different number of columns. You’ll get index range errors if the i+1 row has fewer columns than the row i. If the constraints fail, the solver leaves the array values unchanged. You should always check the return value from a call to randomize(). You should randomize the number of rows and columns as separate variables and then constrain the array to those variables.

Your general approach only checks that the values within each row and each column are unique, not unique within the entire array. It’s possible that there are many other non-unique values in the array; it’s just that the 0 values are easier to pick out. What you need to do is a nested set of foreach loops to compare every element with every other element.

To print the array as a matrix, you need a double nested for each loop and use the $write function which does not append a newline to the end of each output statement.

class array2d;
  rand bit[10:0] array2d [] [];
  rand int rows, cols;
 
 
  constraint sizes {
    rows inside {[10:20]}; cols inside {[5:10]};        
    array2d.size() == rows;
    foreach(array2d[ii])
      array2d[ii].size == cols;
  }
  constraint c_array2d_elem {
    foreach(array2d[i1,j1])
      foreach(array2d[i2,j2])
        i1!=i2 || j1!=j2 -> array2d[i1][j1] != array2d[i2][j2];
  }
  function void print();
    $display("size of matrix rows: %0d cols: %0d", rows, cols);
    foreach(array2d[i]) begin
      foreach(array2d[i][j])
        $write("%5d ", array2d[i][j]);
      $display;
    end
  endfunction
endclass
module top;
  array2d a = new;
  initial repeat(5)
    assert(a.randomize) a.print;
endmodule

In reply to dave_59:

You should always check the return value from a call to randomize().

I did have an if(!randomize()). Hence, I have randomization failure, but I also see some incorrect values being generated. I have mentioned in my original post the randomization failure.

It’s possible that there are many other non-unique values in the array; it’s just that the 0 values are easier to pick out

Q. Can you please elaborate what you mean by “0 values are easier to pick”?

i1!=i2 || j1!=j2 → array2d[i1][j1] != array2d[i2][j2];

Q. Are we trying to skip the same element to be compared?

Q. Another minor thing, when I run the above, it works perfectly fine, except that there is empty space created after every element on the rightmost column. Is there a way to eliminate printing an extra space in the end?

Regards,
Madhu