Constraint existence of value into an array

Hi,
I wish to randomize an unpacked array so that its values are 0, 1, 2, 3, with the values 1, 2, 3 appearing once each, and the rest of the entries are 0.

Is this possible with inline constraints without a 2 step randomization?

here’s an attempt which is met with compilation errors



class some_object extends uvm_object;
  `uvm_object_utils(some_object)

  rand bit [1:0] arr[6];
	
  
  constraint the_constraint_c{
    
    arr.find(item) with (item == 2'b00) == {2'b00, 2'b00, 2'b00};
    arr.find(item) with (item == 2'b01) == {2'b01};
    arr.find(item) with (item == 2'b10) == {2'b10};
    arr.find(item) with (item == 2'b11) == {2'b11};
  }

function new(string name = "some_object");
  super.new(name);
endfunction


  
endclass: some_object



Error-[NYI-CSTR-SYS-FTC] NYI constraint: sys function calls
testbench.sv, 26
the_pkg, “this.arr.find(item) with ((item == 2’b0))”
System function calls are not yet implemented in constraints.
Remove the function call or if possible replace it with an integral state
variable assigned in pre_randomize().

Error-[IAAC] Illegal arguments in comparison
testbench.sv, 26
the_pkg, “(this.arr.find(item) with ((item == 2’b0)) == {2’b0, 2’b0, 2’b0})”
Illegal aggregate comparison because arrays to be compared must have
identical packed/unpacked dimensions.

In reply to nimrodw:
Either you can have named constraint and post_randomize method as below.

  constraint arr_c{
    foreach(arr[i]){
      if(i>3) arr[i]==0;
      else arr[i]==i;
    }
  }
  
  function void post_randomize();
    arr.shuffle();
  endfunction

Or you can covert the same logic to inline constraint.


some_object so=new(); 
assert(so.randomize(arr) with {foreach(arr[i]){
                                                if(i>3) arr[i]==0;
                                                else arr[i]==i;}
                                              }) so.arr.shuffle();
else $error("so.arr randomization is failed");

In reply to bdreku:

The intention is to have the result within randomize if possible, not after.

In reply to nimrodw:

You cannot have expressions containing unpacked arrays unless you use a foreach loop or a reduction method.

class some_object extends uvm_object;
  rand bit [1:0] arr[6];
  constraint the_constraint_c{
    arr.sum() with {int'(item==1)) == 1;
    arr.sum() with {int'(item==2)) == 1;
    arr.sum() with {int'(item==3)) == 1;
  }
 
function new(string name = "some_object");
  super.new(name);
endfunction
endclass: some_object

I am constraining the sum of the number of times each elements equals 1,2, or 3 to be 1.

In reply to dave_59:

Hi Dave,

I don’t want to open a new thread because it is very similar to this one.

I have a situation where one element (or more) has to be of specific value (19).
I tried your solution but I don’t get good results. I don’t get any element with specified value, more like normal randomization.


rand int max_def[];
rand int max_nesting_depth;       // randomized to 19
rand bit force_max_nesting_depth; // randomized to 1

if (force_max_nesting_depth) {
   max_def.sum() with (int'(item == max_nesting_depth)) == 1;
}

I have other constraints for max_def, but randomization should fail if there is no solution to randomization.

In reply to beslo:

Hard to say what might be wrong without a more complete example. If force_max_nesting_depth is being set to 1, I don’t know how it would not work unless you have not proper typed in the constraint.

The following works for me.

class A;
  rand int max_def[] = new[10];
  rand int max_nesting_depth;       // randomized to 19
  rand bit force_max_nesting_depth; // randomized to 1
  constraint c{
    max_nesting_depth == 19;
    force_max_nesting_depth == 1;
    if (force_max_nesting_depth) {
       max_def.sum() with (int'(item == max_nesting_depth)) == 1;
    }
  }
endclass
      
module top;
  A a = new;
  initial begin
    assert(a.randomize());
    foreach(a.max_def[i]) $write(a.max_def[i],);
    $display;
      end
endmodule

prints:

#  1907083669  -719142008          19  -399841475  1096848187  -575642381  1926162295 -1284042096   433992243 -2056237441

In reply to dave_59:

You are correct! I made a stupid typo and didn’t randomize force_max_nesting_depth to 1.
It works now.
Thanks for the help.
P.S. I learned a lot from you on this forum thought the years.