Class recursion due to parameterization

I’ve just stumbled on something in setting up parameterized classes that’s got me stumped for the moment. An simple example:


package foo_pkg;

  class foo_c
  #(
    parameter BITS = 8,
    parameter bit I_SIGN = 1
  );

    function bit bar();
      if( I_SIGN == 0 )
      begin : fix_sign
        foo_c
	#(
	  .BITS( BITS + 1 ),
	  .I_SIGN( 1 )
	) foo_fix = new();
	return( foo_fix.bar() );
      end
      else
        return( 1 );
    endfunction
  endclass

endpackage

module tb;
 foo_pkg::foo_c #( .BITS( 8 ), .I_SIGN( 0 ) ) my_foo = new();

 initial
   $display( "my_foo.bar() = %0d", my_foo.bar() );
  
endmodule

As you can see, I’ve create a parameterized class. Within the class, I need to well it’s kindof recursion (but not really). Within the class, I need to conditionally create a new class obj, based on a parameter. The depth of the “recursion” is fixed at two.

However my simulator is complaining about a “deeply recursive parameterized class”.

I think I understand what’s tripping up the simulator at elaboration - but I’m not clear at the moment what’s the best path forward. I think this sort of thing could be made to work if a conditional generate was allowed within a class, … but that’s not allowed.

I’ve played with making my function a static function, and not actual constructing either of the class members. i.e. just relying the use of class scope resolution operators to parameters to access the static function directly - foo_c#(8,1)::bar(). Same errors.

Any ideas / pointers?

Thanks,
Mark

In reply to Mark Curry:

It’s definitely a recursive class definition because each class specialization requires a new class specialization.

You can break the recursion by putting an expression into your parameter override.

 function bit bar();
      if( I_SIGN == 0 )
      begin : fix_sign
        foo_c
	#(
	  .BITS( BITS + (I_SIGN==0) ),
	  .I_SIGN( 1 )
	) foo_fix = new();
	return( foo_fix.bar() );
      end
      else
        return( 1 );
    endfunction
  endclass

In reply to dave_59:

Ok, but I’m not sure I understand how the edit is successfully breaking the recursion - or what’s sufficient in the general case.

In general, I must ensure that the terminating condition must only call out a specialization that’s already been defined?

Thanks,

Mark

In reply to Mark Curry:

Every unique set of parameter overrides creates a new class specialization. Repeating an existing class specialization breaks the recursion.