The function 'foo' is not a valid constant function error occurs only in large builds

When attempting to compile the following code in a large environment I get the error message:

** Error: The function ‘count_1s’ is not a valid constant function

The code:

function automatic integer count_1s(input [32:0] in,integer count);
integer idx = 0;
begin
count_1s = '0;
repeat(count) begin
if(in[idx])
count_1s += 1;
idx++;
end
end
endfunction

localparam [328-1:0] NUM_IN_STAGE0 = {
count_1s(PIPE_TYPE[7
33+:33],33),
count_1s(PIPE_TYPE[633+:33],33),
count_1s(PIPE_TYPE[5
33+:33],33),
count_1s(PIPE_TYPE[433+:33],33),
count_1s(PIPE_TYPE[3
33+:33],33),
count_1s(PIPE_TYPE[233+:33],33),
count_1s(PIPE_TYPE[1
33+:33],33),
count_1s(PIPE_TYPE[0*33+:33],33)
};

When compiling standalone (small debug testbench) or with other simulators this code works fine. I have also tried changing the name of the function and the localparam to be very unique names and that does not resolve the issue - concern was regarding namespace collision but that does not appear to be the problem. Any suggestions?

In reply to jeromeburke2:

If your code works in one simulator but not another, then you have a tool issue. Since this forum isn’t for tool issues, you need to contact your vendor support team for additional assistance.

In reply to jeromeburke2:

It seems to me your function does meet the definition for a “constant function” as defined in the SystemVerilog spec. But I’m thinking there’s a bit of gray area here. After all there’s an implicit “loops must be unrollable at elaboration time” requirement for constant functions too.

I’m thinking your function would work if you removed the argument “count” as your repeat loop iterator, and just hardcoded 33 as your loop count?

Personally, I’ve not used repeat() statements, but have constant functions using fixed for loops doing very similar things to yours. All my tools accept such constructs as constant functions.

Edit - I’m wondering if the automatic tag is tripping the tool too. It’s not necessary is it?

Regards,
Mark

In reply to Mark Curry:

I am the other engineer working on this. I have tried using different methods for the ‘for’ loop, foreach, for(;;), and all produce the same results.

I haven’t tried using a hardcoded loop count. Could be worth a shot.

The automatic tag was also an attempt to get this to compile. It made no difference whether it was there or not.

In reply to cdjones42:

Can you show a complete example? Maybe you’re missing something in the large design. It’s still possible there are tool specific features getting in the way (like parameter overrides), so you.may have to contact your tool vendor.

just figured out the issue.

this is an example of the code that failed:


module top();

logic [2:0] in;
logic [2:0] out;

foo foo_i(
    .*
    );

endmodule

module foo (
    input logic [2:0] in,
    output reg [2:0] out
);

generate
  if(1)
    `include "foo.svh"
endgenerate

logic [32:0] wdata_all;

assign out = in - P;

always_comb begin
  $display("P = 0x%x",P);
end
endmodule

function integer count_1s;
  input [32:0] in;
  input integer count;
  integer idx;
  begin
    count_1s = 0;
    for(idx = 0; idx<count; idx=idx+1)begin
      if(in[idx])
        count_1s = count_1s+1;
    end
  end
endfunction


notice that we were including the foo.svh inside a generate statement. This is where the problem lies. If we remove the generate statement it compiles just fine.

Edit: it helps to know that the function is located in foo.svh

In reply to cdjones42:
*Can you show a complete example?
*

In reply to cdjones42:

Edit: it helps to know that the function is located in foo.svh

There’s your problem right there. You’re including the function declaration within a generate block.
From the standard, one of the requirements for a constant function:

Constant functions shall not be declared inside a generate block

Regards,
Mark