Sum query on a Multi D array

Consider an array.
pipe
I am trying to constraint it by using similar to following code.
pipe[i].sum with (item.index < j)

But I keep getting these failures
“This is not a valid built in method name for this object.”

How can I rewrite this. I did not want to do something like below which is hanging my solver. Something inbuilt is helpful
function int sumUntil(row, idx);
for(int i = 0; i < idx; i++) begin
sumUntil += int’(pipe[row][i]);
end
endfunction

In reply to sharatk:

You want to sum only some columns of your 2d array? Something like below? It was straight forward using a helper array, but I’d like to know if there is a single array solution.

module tb;
  
class twod;
  rand bit [7:0] cells[5][5];
  rand bit [7:0] trunc[5][5]; // helper array

  
  constraint c {
    // constrain the first two columns of cells to add up to 30
    foreach ( cells[r,c] ) {
      cells[r][c] inside { 5,10,15,20 };
      if ( c < 2 )
        trunc[r][c] == cells[r][c];
      else
        trunc[r][c] == 0;
    }
    
    foreach ( trunc[r,c] ) {
      if ( c == 0 ) {
        trunc[r].sum() == 30;
      }
    }
  }
  
  function void show();
      $write("trunc\n");
      foreach ( trunc[r,c] ) begin
        $write( "%3d ", trunc[r][c] );
        if ( c == 4 )
          $write("\n");
      end
      $write("cells\n");
      foreach ( cells[r,c] ) begin
        $write( "%3d ", cells[r][c] );
        if ( c == 4 )
          $write("\n");
      end
  endfunction
      
      
endclass

initial begin
  automatic twod td = new;
  $display( "randomize == %0b\n", td.randomize() );
  td.show();
end
      
endmodule
      
trunc
 20  10   0   0   0 
 10  20   0   0   0 
 10  20   0   0   0 
 15  15   0   0   0 
 20  10   0   0   0 
cells
 20  10  10  20  20 
 10  20  15  10  20 
 10  20  15  20  10 
 15  15   5  15  15 
 20  10   5   5  20

In reply to warnerrs:

Thanks for your reply.
I am not trying to sum all the columns. Here is my complete constraint.

constraint constraint_c3_c {
        foreach(pipe[i,j]){
            foreach(pipe[k,l]){
                if(({i,j} != {k,l}) && (pipe[i][j] == pipe[k][l])) {
                    //if((i+sumUntil(i,j)) >= (k+sumUntil(k,l))) {
                    //   i+sumUntil(i,j) >= (k+sumUntil(k,l))+int'(pipe[i][j]);
                    //}else {
                    //   i+sumUntil(i,j)+int'(pipe[i][j]) <= (k+sumUntil(k,l));
                    //}
                    if(i+pipe[i].sum with (item.index < j) >= (k+pipe[k].sum with (item.index < l))) {
                       i+pipe[i].sum with (item.index < j) >= k+pipe[k].sum with (item.index < l);
                    }else {
                       i+pipe[i].sum with (item.index < j) +int'(pipe[i][j]) <= k+pipe[k].sum with (item.index < l);
                    }
                }
        }   }
    }

Its basically adding a subset of the array together. The solver hangs if I use commented portion instead.

In reply to sharatk:

It might help to show some examples of array values you’re looking to see and explain in words, nut SystemVerilog syntax the requirements that the arrays need to meet.

Also, pipe[i].sum with (item.index < j) just returns j-1; a count of items whose index is less than j. You are probably looking for pipe[i].sum with ((item.index < j) ? item : 0 )

In reply to dave_59:

Hi Dave,

Sorry for being terse on my example.
Adding more details.

rand oper_e pipe[][]; //oper_e is an enum 
Complete constraints that refuses to compile is. I corrected it.
constraint constraint_c3_c  {
        foreach(pipe[i,j]){
            foreach(pipe[k,l]){
                if(({i,j} != {k,l}) && (pipe[i][j] == pipe[k][l])) {
                    if(i+pipe[i].sum with ((item.index < j)*item)>= (k+pipe[k].sum with ((item.index < l)*item))) {
                       i+pipe[i].sum with ((item.index < j)*item)>=  k+pipe[k].sum with ((item.index < l)*item);
                    }else {
                       i+pipe[i].sum with ((item.index < j)*item) +int'(pipe[i][j]) <= k+pipe[k].sum with ((item.index < l)*item);
                    }
                }
        }   }
    }

Error:
if(i+pipe[i].sum with ((item.index < j)*item)>= (k+pipe[k].sum with ((item.index < l)*item))) {
|
xmvlog: *E,QAANBI (fbPipe.sv,33|53): This is not a valid built in method name for this object. [SystemVerilog].

In reply to sharatk:
It seems that it is a simulator problem,

module sumExpt;

int arr[] = '{1, 2, 3, 4, 5, 6, 7, 8, 9, 3, 3, 3};
initial begin
    $display("arr.sum(item) with ((item._index_ < 3) ? item : 0)   = %0d", (arr.sum with ((item.index < 3) ? item : 0)));
end

endmodule

Hierarchical name component lookup failed at ‘index’.

In reply to dave_59:

Hi Dave,

So changing my example, is the following supposed to work? I want it to behave the same as my other example above.

module tb;
  
class twod;
  rand bit [7:0] cells[5][5];
  
  constraint c {
    // constrain the first two columns of cells to add up to 30
    foreach ( cells[r,c] ) {
      cells[r][c] inside { 5,10,15,20 };
      cells[r].sum() with ( item.index < 2 ? item : 0 ) == 30;
    }
  }
  
  function void show();
      $write("cells\n");
      foreach ( cells[r,c] ) begin
        $write( "%3d ", cells[r][c] );
        if ( c == 4 )
          $write("\n");
      end
  endfunction
      
      
endclass

initial begin
  automatic twod td = new;
  $display( "randomize == %0b\n", td.randomize() );
  td.show();
end
      
endmodule
 

In reply to warnerrs:

Works for me. The simulators on EDAPlayground are outdated.

In reply to dave_59:

Dave,

Thanks for the confirmation.

Doesn’t work on my local simulator though :(

Do you have a better work around to suggest than my previous example? I don’t like solution space partitioning that the function call approach creates.

In reply to dave_59:

Hi Dave ,

I didn’t quite understand the 2nd line of constraint c ::



constraint c {
    // constrain the first two columns of cells to add up to 30
    foreach ( cells[r,c] ) {
      cells[r][c] inside { 5,10,15,20 };
      cells[r].sum() with ( item.index < 2 ? item : 0 ) == 30; // How does it work ?
    }
  }


If ternary condition is false , how is the 0 used ?

In reply to Have_A_Doubt:

It means if the index is less than 2, 0 is used instead of the array element, effectively not contributing to the sum.

In reply to dave_59:

Was trying this at my end in Edaplayground and have been hitting errors. Wanted to know if my logic is wrong.

To start with I want to constraint a 2-D array which has its column values sum up to 30. Here’s my code inside a class -


  rand bit [7:0] array[5][5];
  
  constraint c_col_val {
    foreach(array[col,row])
      array[col].sum() == 30;
  };

In reply to tpan:

https://verificationacademy.com/forums/systemverilog/sum-query-multi-d-array#reply-78273

In reply to dave_59:

Thanks, Dave.