What Constitutes a Unique Class Specialization

I have following code ::


typedef  int  unsigned  UINT32 ; 

  class  env #( BITWIDTH = 100 ) ;

   const  static  string  type_name  =  get() ;

   static  function  string  get() ;
      string  Sign ;

      Sign  =  $sformatf( "%0s" , ( ( BITWIDTH << 24 )  > 0 )  ? "unsigned" : "signed" ) ;
      
      //  128  has  7'th  bit  set  i.e  1_0000_0000  .  So  Left  Shift  by  24  times  would  make  MSb  i.e  31'st  bit  Set  !!
      
      $display(" Within  class  env_%0d_%0s " , BITWIDTH , Sign ) ;

      return $sformatf("%0d_%0s" , BITWIDTH , Sign ) ;

   endfunction

  endclass


  class  wrapper #( UINT32 WIDTH = 100 ) ;

    env #( WIDTH )  e1 ;

   const  static  string  type_name  =  get() ;

   static  function  string  get() ;
      string  Sign ;

      Sign  =  $sformatf( "%0s" , ( ( WIDTH << 24 )  > 0 )  ? "unsigned" : "signed" ) ;
      
      //  128  has  7'th  bit  set  i.e  1_0000_0000  .  So  Left  Shift  by  24  times  would  make  MSb  i.e  31'st  bit  Set  !!
      
      $display(" Within  class  wrapper_%0d_%0s " , WIDTH , Sign ) ;

      return $sformatf("%0d_%0s" , WIDTH , Sign ) ;

   endfunction

  endclass

[ Q1 ]
A parameter can be 2 - state / 4 - state , signed / unsigned , different width , different range .
So what exactly is recognized as a Unique Specialization for a Parameterized Class ?
My expectation is that Non - Matching types for the value parameter should be counted as Unique Specialization


 //   CODE  1   ::  Initial  Code  
 
  env #( 128 )  env_128 ;
  wrapper #( 128 )  wrapper_128 ;
     

I Observe Output ::

Within class env_128_signed
Within class env_128_unsigned
Within class wrapper_128_unsigned

So an unsigned N signed specialization are recognized as Two different Specializations ( via env_128 )


//   CODE  2  ::  Added  Later to   CODE  1

  parameter  bit [ 31:0 ]  bit_31_0  =  128  ;  
  
  parameter  bit [ 0:31 ]  bit_0_31  =  128  ;
  
  parameter  bit [ 131:100 ]  bit_131_100  =  128  ;
  
  parameter  bit [ 100:131 ]  bit_100_131  =  128  ;

  env #( bit_31_0 )      env_bit_31_0 ;     //  Same  Specialization  as  e1  via  wrapper  #( 128 ) due  to   
                                            //  Same  Range  [ 31 : 0 ] , Same  Size  N  Both are  2-state
       
  env #( bit_0_31 )      env_bit_0_31 ;     //  Non - Matching  type  to  e1  due  to  Range
  
  env #( bit_131_100 )   env_bit_131_100 ;  //  Non - Matching  type  to  e1  due  to  Range
  
  env #( bit_100_131 )   env_bit_100_131 ;  //  Non - Matching  type  to  e1  due  to  Range


**For env_bit_0_31 , env_bit_131_100 N env_bit_100_131 I expected them to be considered as Unique Specializations for env class

However I don’t Observe any displays for them**

( The O/P for Code 2 is same as that of Code 1 )

If I were to add ::


  parameter  bit [ 10:0 ]  bit_10_0  =  128  ;  //  Parameter  Size  of  11 bits  wide  
  
   env  #( bit_10_0 )  env_bit_10_0 ;  //  Non - Matching  due  to  Size results  in    
                                       //  Unique  Specialization as expected .

  

In reply to ABD_91:

This is something that was just corrected in the next revision of the IEEE 1800 LRM.

The current LRM text in section 8.25 of the IEEE 1800-2017 SystemVerilog LRM
that type parameters must have matching explicitly requires unique matching types to have unique class specializations. But the next sentence says value parameters must have the same type and value. The “same” type is ambiguous in SystemVerilog.

Unfortunately most tools have interpreted same to mean equivalent types. But the text should have said matching types and values. This could be a problem if you every tried to use $left or $right functions on a value parameter. The way around this, and a better coding style is to always give value parameters an explicit data type. A parameter’s data type cannot be overridden.