class TP # ( type T = int , T A = 10 ) ;
T b ; // Could be anything based on T
endclass
typedef int unsigned UINT ;
TP #( UINT , 10 ) tp1 ;
TP #( int , 10 ) tp2 ;
Inside the class specialization is there a way to know if type parameter T is signed or unsigned ?
Based on LRM :: $typename() . " In the returned string The default signing is removed " .
So using $typename( T ) inside the class declaration wouldn’t be the solution
The type of a parameter with no explicit datatype in its declaration gets the type of whatever the RHS default value is, or whatever the type of its final overwritten value. The numeric literal 100 is defined to have an integer type, which is a 32-bit signed 4-state type.
Once you declare a parameter with an explicit datatype, any override must be assignment compatible with declared type, and the parameter keeps its explicitly declared type.
$typename is not very well defined, so I suspect it does not get used that often, and has a number of tool specific issues.
LRM 6.20.2 ::
"A parameter declaration with no type or range specification shall default to the type and range of the final value assigned to the parameter, after any value overrides have been applied. If the expression is real, the parameter is real.
If the expression is integral, the parameter is a logic vector of the
same size with range [size-1:0] ."
Since override in our case is 2 ** 32 - 1 , the expression is integral . So the parameter is a logic vector ( 4-state ) of size [31:0] .
Since 2 ** 32 - 1 is signed decimal by default , Main1::SIZE is logic signed [31:0]
Also could you please elaborate on ::
" any override must be assignment compatible with declared type"
class Main2 has an explicit datatype ( unsigned ) , so irrespective of the
overridden value ( 2**32 - 1 via m2 in our case )
Both Main2::SIZE and Main2::SIZE would ALWAYS be unsigned right ?
A parameter with an explicit data type in its declaration always keeps it type. The RHS default or any override cannot change the parameter’s type. That value will be implicitly cast to the declared type.
Main2::SIZE will always be unsigned. Main2::SIZE becomes unsigned because Main2::SIZE is unsigned.
As you have stated $typename() doesn’t work according to LRM
Eg: LRM states signedness should Never be displayed via $typename .
LRM 20.6.1 ::
// source code // $typename would return
typedef bit node; // "bit"
node [2:0] X; // "bit [2:0]"
int signed Y; // "int"
class Main1 #( SIZE = 100 ) ;
......................
endclass
Main1 #( 128 ) m1 ; // 128 is 4 - state signed parameter of Min size [31:0]
parameter int unsigned UINT = 128 ;
Main1 #( UINT ) m2 ; // 128 is 2 - state unsigned parameter of Min size [31:0]
[Q] Since I can’t rely on $typename( SIZE ) within class Main1 to tell me
whether Value parameter is actually signed OR unsigned ,
Is there a better solution ?
[Q2] Isn’t m2 a Different Specialization than m1 since Value parameter is
different ( Unsigned N Signed resp. )
// Within function of class Main1
$display(" Parameter SIZE is %0s " , ( SIZE > 0 ) ? "unsigned" : "signed" ) ;
However this isn’t correct as m1 has Value Parameter as Signed whereas the
above display would give me Unsigned
Unfortunaltely Type Operator [ type( ) ] doesn’t work too :(