"Range must be bounded by constant expression" - Error from a constraint block

Hi,

I am writing a constraint and the snippet is below:
constraint next_con {
foreach (next[i])
next[i] inside {current [0 : (total_count[i]/2)]};
}
}

total_count value is constrained using a different constraint. I am seeing error during compilation.
I did try using, +: operator. But that didn’t help.

Kindly help.

In reply to naveensv:

The ‘+:’ is meant to be used when slicing a vector, not when specifying a range. The inside operator takes a range as an input, not a slice.

In reply to Tudor Timi:

Thanks for the reply Tudor.

Probably I should have been more clear when explaining the question.

I have tried to explain this a little more detailed.
current[i] is a dynamic array of size greater than that of next[i]

I need to have a constraint where next[i] is one of the values of current[i] with one more constraint on the indices of current

One typical output should look like this:
Lets assume the size of current is 10, size of next is 1 and size of total_count is 5.
next[0] should take one of the values of current [0 : 5]

Kindly let me know if I can specify a dynamic range in the constraint.

In reply to naveensv:

You can’t specify a dynamic range when slicing a dynamic array (regardless of whether it’s in a constraint or anywhere else). This is an LRM limitation. You can work around this by using an intermediary variable:


class some_class;
  rand int current[], next[];
  rand int unsigned total_count[];

  constraint legal_total_counts {
    total_count.size() == current.size();
    foreach (total_count[ i]) {
      total_count[ i] > 0;
      total_count[ i] < total_count.size();
    }
  }

  local rand int legal_nexts[][];
  
  constraint next_vals {
    next.size() == current.size();
    
    legal_nexts.size() == next.size();
    foreach (legal_nexts[ i])
      legal_nexts[ i].size() == total_count[ i];
    foreach (legal_nexts[ i, j])
      legal_nexts[ i][j] == current[j];

    foreach (next[ i])
      next[ i] inside { legal_nexts[ i] };
  }
endclass

The ‘legal_nexts’ 2D array will hold all valid values for each value of the next array. You need to construct it “yourself” using constraints. After you’re finished with it, it might be a good idea to destroy it to free up memory:


function void post_randomize();
  legal_nexts = '{};
endfunction

In reply to Tudor Timi:

Brilliant !
It works for me.
But just to cross check my coding, I am trying to print the contents of legal_nexts array.
However I try to print, my simulation is getting stuck.
If I comment out that printing section, simulation proceeds smoothly.

Any idea?

In reply to naveensv:

I am retaining the legal_nexts declaration as local only and not freeing up in the post_randomize().
Should this affect the simulation so badly?

In reply to naveensv:

I’m not sure how you’re printing. I used:


$display("%p", legal_nexts);

and it worked fine for me, but I was using a small number for the array size.

W.r.t. not freeing up in post_randomize(), it depends on how big your arrays are. You’re going to be allocating a lot of memory during randomization that’s just going to get wasted afterwards. If you anyway throw away the object after randomization or only create a few objects of that class, you shouldn’t see any big improvement. The only way to say for sure if it noticeably affects performance is to do a profiler run.

In reply to Tudor Timi:

Yep, $display worked for me!
I used nested-for loop to print out the 2D contents. Probably that made the testbench slow, I believe.

I use Questa for running simulations. I will check if I can perform profiling there.

In reply to naveensv:

Hi Tudor,

I am stuck at one point where I need to get a 2D array from a one dimensional array in a constraint.
Snippet:

rand int total_count[];
local rand int legal_next[][];
constraint
total_count.size() == 2;

foreach (legal_next[i])
legal_next.size() == 2; //I am hard-coding here intentionally

foreach (legal_next[i])
legal_next[i].size() == total_count[i];

foreach (even[i])
single_dimension[2*i] = even[i];

foreach (odd[i])
single_dimension[2*i +1] = odd[i];

Now single_dimension has all elements and I need to select legal range in them.

Now I am trying to split single_dimension and assign to legal_next portion by portion
For ex:
If single_dimension = {1,2,3,4,5,6,7,8,9,10};
total_count[0] = 4 and total_count[1] = 5
Then,
legal_next[0] = {1,2,3,4}
legal_next[1] = {5,6,7,8,9}

Unfortunately I cannot use for loop in the constraint.
I tried my best to achieve this. But that didn’t help much.
Could you suggest any best way to do this?

In reply to naveensv:

It’s not really clear how total_count and legal_next are related to each other. Is it that total_count[0] selects the first t0 elements from single_dimension, followed by total_count[i] selecting the next t1 elements and so on?

In reply to Tudor Timi:

You are right

In reply to naveensv:

I don’t see any way of doing it, since this would ultimately mean using a random variable to index single_dimension, which isn’t allowed by the LRM.

In reply to Tudor Timi:

Thanks Tudor for confirmation.
I made use of different single dimensional arrays to achieve the same.

Regards,
Naveen