The 1800-2012 LRM added the ability to use the array reduction methods in a constraint. This is already supported in recent releases of Questa. Be very careful using signed data types in a constraint to prevent unwanted negative numbers and overflow that will give you results that satisfy the constraints but not normally what you are expecting.

rand int arr[];
constraint c_arr{
arr.size() < 10;
arr.sum() inside {[1:1000]); // if you want a positive result
foreach(arr[i]) arr[i] inside ([0:1000]};
}

I have seen that there was a problem with the sum (WWW.TESTBENCH.IN - Systemverilog Randomization) and to be safe you had to use:
“with (item+32b’b0)”. That is to say, you had to sum a zero value of 32 bits to force a casting with the intern item in the sum loop. See below

rand int arr[];
constraint c_arr{
arr.size() < 10;
arr.sum with (item+32b'b0) inside {[1:1000]); // if you want a positive result
foreach(arr[i]) arr[i] inside ([0:1000]};
}

Now, i see that in your example you will not have problems because the type of arr is int arr; which is already 32bits, and the sum will not be saturated.

Cut/Saturating means that, when the sum overflows the bitwidth for your local sum constraint variable (in your example arr) then this is not seen by the sum constraint because the sum in the internal constraint will be cut and will only compare with the constraint the “bits cut”/bitwidth defined by your local variable,
e.g.

rand logic [1:0] arr[];
constraint c_arr{
arr.size() < 10;
arr.sum inside {[1:1000]); // WRONG SUM constraint in case
//This is wrong because if constraint solver tries a combination that sums e.g. 16='b10000, then constraint solver will see only the LSB 2 bits due to the logic[1:0] arr[] type 16='b100**00**=>2'b00=0 and will think that was a valid combination for your constraints since "0" meets constraint: arr.size() < 10;
//arr.sum with (32'(item)) inside {[1:1000]); // if you want a CORRECT constraint
foreach(arr[i]) arr[i] inside ([0:1000]};
}

converting the item variable in 32bits (or more) ensure that all sum possible combinations tried by the constraint solver will be seen correctly by the constraint solver (<10) ).

That problem is due to the fact that the resulting value from
array.sum() has the same type as each element in the array. That means it does not handle overflow unless you change type of each element being summed. My example does not have that problem because I was constraining the value of each element to a relatively small value that would never overflow.

I was exposing a slightly different problem that you can have anytime you deal with signed values in arithmetic expressions. most people forget that negative numbers can form valid solutions. So you either need to keep everything unsigned, or place constraints to keep the values positive.

That problem is due to the fact that the resulting value from array.sum() has the same type as each element in the array. That means it does not handle overflow unless you change type of each element being summed. My example does not have that problem because I was constraining the value of each element to a relatively small value that would never overflow.

This means that each element of
arr can have the value 0-15. Since the sum() method returns a value that is the same type of each element, that means
arr.sum() can only return a value between 0-15. However the maximum possible sum is 5x15=75 which requires at least 7 bits to represent. So you would have to write
arr.sum() with ( 7’(item) ) to get a result without overflowing. However, if if you constrain each element to 3 or less, the maximum sum is 5x3=15, and that does not overflow the element type.

As i commented in a previous comment, maybe, the problem you have is due to the intern 32bit item value used in systemverilog to perform the sum.
In your case “vf” is a bit variable of 12 bits. Systemverilog “sum”-function uses the intern “item” 32bit variable. The casting in the constraint of “sum” must be done to allow a proper constraint.

I’m using a Cadence simulator.
I get a constraint error using vf.sum (32’(item)) == 2048.
I tried vf.sum (item+32’b0) == 2048, but I get a constraint error.

Here’s my code.

``` verilog
class rand_vf_queues extends uvm_object;
rand bit [7:0] vf_size;
rand bit [11:0] vf[];
constraint c_num_vf {vf_size == 248;}
constraint c_vf_queues {
vf.size == 248;
vf.sum == 2048;
foreach (vf[i]) {
vf[i] inside {[0:2048]};
}
}
function new (string name = "");
endfunction // new
function void post_randomize();
int sum_vf = 0;
`uvm_info(get_type_name(), $psprintf("vf_size = %0d, total_qctl_queues = %0d",vf_size,total_qctl_queues), UVM_LOW)
for(int i=0; i<vf_size; i++) begin
`uvm_info(get_type_name(), $psprintf("VF[%0d] = %0d",i,vf[i]), UVM_LOW)
sum_vf = sum_vf + vf[i];
end
`uvm_info(get_type_name(), $psprintf("VF.SUM() = %0d, sum_vf = %0d",vf.sum(),sum_vf), UVM_LOW)
endfunction
endclass // rand_vf_queues

> Here's partial display results showing the end of the array values and sum_vf. Notice VF.SUM() has maxed out to 2048 but the actual sum_vf is much larger.
``` verilog
[0ns] reporter: VF[242] = 1455
[0ns] reporter: VF[243] = 19
[0ns] reporter: VF[244] = 469
[0ns] reporter: VF[245] = 353
[0ns] reporter: VF[246] = 946
[0ns] reporter: VF[247] = 2038
[0ns] reporter: VF.SUM() = 2048, sum_vf = 256000

What I would like to do is constrain all the values from 0-2048 and have the total array sum = 2048 and I want the possibility to have only a couple of the vf[i] to have a couple of indexes = > 0 and all the other indexes = 0.
i.e. vf[0] = 2000, vf[230] = 48, all other indexes will = 0.

In reply to dave_59:
I was able to get this working using int’(item) when using Cadence.

class rand_vf_queues extends uvm_object;
rand bit [7:0] vf_size;
rand bit [11:0] vf[];
rand int queues;
constraint c_num_vf {vf_size == 248;}
constraint c_num_queues {queues == 2048;}
constraint c_vf_queues {
vf.size == vf_size;
vf.sum with (int'(item)) == queues;
foreach (vf[i]) {
vf[i] inside {[0:queues]};
}
}
function new (string name = "");
endfunction // new
endclass

Hi,

In Cadence tool I am getting the following output with the below code:
B2B_seq_array[0] === 1712505664
B2B_seq_array[1] === 1648995472
B2B_seq_array[2] === 1324445776
B2B_seq_array[3] === 3903987720

Code:

module tb;
class muneeb;
rand int unsigned B2B_seq_array[];
constraint sum_c { B2B_seq_array.sum with (int'(item)) ==40;}
// I even tried the below constraint but still no sucess
// constraint sum_c { B2B_seq_array.sum() with (32'(item)) == 40;}
constraint b2b_array_c { B2B_seq_array.size() == 4; }
constraint mm_c { foreach(B2B_seq_array[i]) {
(B2B_seq_array[i] % 8) == 0;
B2B_seq_array[i] != 0;
}
}
endclass
muneeb m1;
initial
begin
m1 = new();
if(!m1.randomize())
$display("Randomizeation failed");
else
begin
foreach(m1.B2B_seq_array[i])
begin
$display("B2B_seq_array[%0d] === %0d",i,m1.B2B_seq_array[i]);
end
end
end
endmodule

With the code that you have, you are casting an unsigned int to an signed int, you are getting negative numbers in your array. And in the code you commented out, the cast does nothing because a unsigned int is already 32 bits. There the problem is the sum is 32-bits, but you need more than 32 bits to hold the sum of 4 32-bit numbers.

The key to using the sum() method is to consider the maximum possible value of each element, and make sure you either constrain each element to a value that would not cause overflow, or cast the elements to a type that would not overflow.

In your example, you could:

Constrain each element inside the range [0:40]

Use longint’(item)

Declare the array with each element width of bit [5:0], and use int’(item)