Solver fails to solve easy constraints

Here are the constraints the solver is unable to solve


  int      int_q[$] = {0, 1, 2};
  rand int q_size;
  rand int rand_int_q[$];

  constraint easy_constraint_c {
    q_size inside {[3:666]};
    rand_int_q.size() == q_size;
    foreach (rand_int_q[ii]) {
      rand_int_q[ii] inside {int_q};
    }
    unique {rand_int_q};
  }

I’ve purposely wrote these constraints in a way that q_size seemingly has many options:


    q_size inside {[3:666]};
    rand_int_q.size() == q_size;

However, these extra constraints should limit q_size (and thus rand_int_q.size()) to be == 3


    foreach (rand_int_q[ii]) {
      rand_int_q[ii] inside {int_q};
    }
    unique {rand_int_q};

if q_size == 3, which is allowed, everything else should fall into place.

However, the constraint solver fails to find this solution, and attempts to solve it with q_size > 3.

integer int_q[3] = '{ 0, 1, 2 };
rand integer rand_int_q[0]; // rand_mode = ON
rand integer rand_int_q[1]; // rand_mode = ON
rand integer rand_int_q[2]; // rand_mode = ON
rand integer rand_int_q[3]; // rand_mode = ON
rand integer rand_int_q[4]; // rand_mode = ON
.
.
.
rand integer rand_int_q[85]; // rand_mode = ON

constraint easy_constraint_c // (from this) (constraint_mode = ON) (testbench.sv:43)
{
unique {rand_int_q[0], rand_int_q[1], rand_int_q[2], rand_int_q[3], rand_int_q[4], rand_int_q[5], rand_int_q[6], rand_int_q[7], rand_int_q[8], rand_int_q[9], rand_int_q[10], rand_int_q[11], rand_int_q[12], rand_int_q[13], rand_int_q[14], rand_int_q[15], rand_int_q[16], rand_int_q[17], rand_int_q[18], rand_int_q[19], rand_int_q[20], rand_int_q[21], rand_int_q[22], rand_int_q[23], rand_int_q[24], rand_int_q[25], rand_int_q[26], rand_int_q[27], rand_int_q[28], rand_int_q[29], rand_int_q[30], rand_int_q[31], rand_int_q[32], rand_int_q[33], rand_int_q[34], rand_int_q[35], rand_int_q[36], rand_int_q[37], rand_int_q[38], rand_int_q[39], rand_int_q[40], rand_int_q[41], rand_int_q[42], rand_int_q[43], rand_int_q[44], rand_int_q[45], rand_int_q[46], rand_int_q[47], rand_int_q[48], rand_int_q[49], rand_int_q[50], rand_int_q[51], rand_int_q[52], rand_int_q[53], rand_int_q[54], rand_int_q[55], rand_int_q[56], rand_int_q[57], rand_int_q[58], rand_int_q[59], rand_int_q[60], rand_int_q[61], rand_int_q[62], rand_int_q[63], rand_int_q[64], rand_int_q[65], rand_int_q[66], rand_int_q[67], rand_int_q[68], rand_int_q[69], rand_int_q[70], rand_int_q[71], rand_int_q[72], rand_int_q[73], rand_int_q[74], rand_int_q[75], rand_int_q[76], rand_int_q[77], rand_int_q[78], rand_int_q[79], rand_int_q[80], rand_int_q[81], rand_int_q[82], rand_int_q[83], rand_int_q[84], rand_int_q[85]};
(rand_int_q[0] inside {int_q});
(rand_int_q[1] inside {int_q});
(rand_int_q[2] inside {int_q});
(rand_int_q[3] inside {int_q});
.
.
.
(rand_int_q[85] inside {int_q});
}

Error-[CNST-CIF] Constraints inconsistency failure
testbench.sv, 83
Constraints are inconsistent and cannot be solved.
Please check the inconsistent constraints being printed above and rewrite
them.

What am I missing and how can I achieve the desired result?

I should mention that in my actual code instead of numbers there are variables.
There’s a reason that I want that rand_int_q.size() to be within a range that is sometimes partially illegal.

My wish is that the solver will find the legal solutions for size and choose within them.

Thanks,
Nimrod

edit:

I was able to work around this issue in my own project, however still interested on why the constraint on queue size seems to work independently from other constraints.

In reply to nimrodw:

This is explained in the 1800-2017 SV LRM Section 18.5.8.1 foreach iterative constraints

class C;
rand int A[] ;
constraint c1 { A.size inside {[1:10]}; }
constraint c2 { foreach ( A[ k ] ) (k < A.size - 1) -> A[k + 1] > A[k]; }
endclass

“The size method of a dynamic array or queue can be used to constrain the size of the array (see constraint c1
above). If an array is constrained by both size constraints and iterative constraints, the size constraints are
solved first and the iterative constraints next. As a result of this implicit ordering between size constraints
and iterative constraints, the size method shall be treated as a state variable within the foreach block of the
corresponding array. For example, the expression A.size is treated as a random variable in constraint c1
and as a state variable in constraint c2. This implicit ordering can cause the solver to fail in some situations.

HTH,
-R