Constraint for sum of products

The following code for constraint for sum of products results in error:

 class c;
    rand logic [7:0] dataq1 [];
    rand logic [7:0] dataq2 [];
    constraint data_size {dataq1.size() == 10; dataq2.size() == 10; }
    constraint data_items { 
       foreach(dataq1[i]) dataq1[i] < 100;
       foreach(dataq2[i]) dataq2[i] < 50; 
    }
    
    constraint sum_c { 
       dataq1.sum() with (int'(item)) < 1000; 
       dataq2.sum() with (int'(item)) < 1000; 
    }
    
    constraint sum_product_c {sum_pro() < 100000; }
    
    function longint sum_pro();
      sum_pro = 0;
      foreach(dataq1[i]) 
        sum_pro += dataq1[i] * dataq2[i];
			  
    endfunction 
 
endclass

module test;
   initial begin
      c c1 = new();

      void'(c1.randomize());

      foreach(c1.dataq1[i])
        $display("%0d  %0d", c1.dataq1[i], c1.dataq2[i]);

   end // initial begin
endmodule // test

Errors:
Error-[CSTR-UMC] Constraint: unsupported method call
ex04/mycode/sum_of_products.sv, 15
$unit, “this.sum_pro()”
Method c::sum_pro contains a construct not supported in constraint
functions: reference to a rand variable ‘dataq1’ at line 19 of
ex04/mycode/sum_of_products.sv.
Rewrite the method to avoid unsupported constructs.

Error-[CSTR-UMC] Constraint: unsupported method call
ex04/mycode/sum_of_products.sv, 15
$unit, “this.sum_pro()”
Method c::sum_pro contains a construct not supported in constraint
functions: reference to a rand variable ‘dataq1’ at line 20 of
ex04/mycode/sum_of_products.sv.
Rewrite the method to avoid unsupported constructs.

Error-[CSTR-UMC] Constraint: unsupported method call
ex04/mycode/sum_of_products.sv, 15
$unit, “this.sum_pro()”
Method c::sum_pro contains a construct not supported in constraint
functions: reference to a rand variable ‘dataq2’ at line 20 of
ex04/mycode/sum_of_products.sv.
Rewrite the method to avoid unsupported constructs.

In reply to csivas@gmail.com:

Normally the keyword unsupported is due to the tool limitation for that you need to contact your tool’s vendor, as I tried your code and it compiled, and ran without errors, or do as the log file is telling you “Rewrite the method to avoid unsupported constructs.”

Also you can check the LRM section 18.5.12 Functions in constraints to see what are the restrictions about calling functions in constraints, as they can change the order on how constraints are solved

HTH,

-R

In reply to csivas@gmail.com:

This would not work even if your tool did support the function. The function is not pure, meaning its return value is not solely determined by its inputs—it does not have any.

You can write this as

constraint sum_product_c {dataq1.sum(q1) with (int'(q1)*int'(dataq2(q1.index))) < 100000; }

In reply to dave_59:

Hi Dave,

While reading the LRM in the section I mentioned I don’t see any reference to “pure functions”, is this the part regarding to functions with no side effects or am I missing something here?

btw I know this not a tool specific forum, but will this yield in a randomisation failure or not, as per the LRM? as Questa and other simulator did not report any on checking the result of the randomize() call

-R

In reply to rgarcia07:

Dave,
I modified the code as follows and still an error:
// Code your testbench here
// or browse Examples

  class c;
    rand logic [7:0] dataq1 [];
    rand logic [7:0] dataq2 [];
    constraint data_size {dataq1.size() == 10; dataq2.size() == 10; }
    constraint data_items { foreach(dataq1[i]) 
                                dataq1[i] < 100;
                            foreach(dataq2[i])
                                dataq2[i] < 50; }
    constraint sum_c { dataq1.sum() < 10000; dataq2.sum() < 10000; }
    /*constraint sum_product_c {sum_pro() < 500000; }
 
    function longint sum_pro();
      sum_pro = 0;
      foreach(dataq1[i])
        sum_pro += dataq1[i] * dataq2[i]; 
    endfunction 
 */
    constraint sum_product_c {dataq1.sum(dataq1) with (int'(dataq1)*int'(dataq2(q1.index))) < 100000; }
    
  endclass

module tb;

 
  initial
    begin
      c c1;
      c c2;
      c1 = new;
      c2 = new;
      
      void'(c1.randomize());
      void'(c2.randomize());
      
      foreach(c1.dataq1[i])
        $display("%0d  %0d", c1.dataq1[i], c1.dataq2[i]);
      
      foreach(c1.dataq1[i])
        $display("%0d  %0d", c1.dataq1[i], c1.dataq2[i]);
    end
 
 
endmodule

In reply to csivas@gmail.com:

there was a typo in my code and yours

  constraint sum_product_c {dataq1.sum(q1) with (int'(q1)*int'(dataq2[q1.index])) < 100000; }

should work

In reply to dave_59:

ncelab: *W,DSEMEL: This SystemVerilog design will be simulated as per IEEE 1800-2009 SystemVerilog simulation semantics. Use -disable_sem2009 option for turning off SV 2009 simulation semantics.
constraint sum_product_c {dataq1.sum(q1) with (int’(q1)*int’(dataq2[q1.index])) < 100000; }
|
ncelab: *E,CUVUNF (./testbench.sv,25|77): Hierarchical name component lookup failed at ‘index’.

In reply to rgarcia07:

Yes, no side effects is part of the general software concept of a pure function call. (not to be confused with a pure virtual method declaration in SystemVerilog). Since the function call used in a constraint has no input arguments, there is no way to figure out the random variable ordering. So the function could be called before values have been placed in the dataq and meet the constraint.

In reply to csivas@gmail.com:
Please use code tags making your code easier to read. I have added them for you.

Please use a different simulator.