In C++ you can have a class without parameters (templates), and have methods that have parameters (templates). E.g.:
class C
{
public:
int cnt;
template<int W>
void add() {
for(int i=0;i<W;i++) {
cnt++;
}
}
};
I am in need for such a thing in SystemVerilog, but I do not seem to be able to figure out how to do so in a simple way. The LRM (section 13.8) tells me that to do a parameterized function (and so assume also a method in a non-parameterized class should be wrapped by a parameterized class.
This is the code that resembles what I need to do:
class T#(int W);
bit [W-1:0] s;
function new();
s=2**(W-1);
endfunction
endclass
class C;
bit [31:0] cnt;
function void print();
$display("cnt=%0d",cnt);
endfunction
function void incr();
cnt=cnt+1;
endfunction
function void clear();
cnt=0;
endfunction
function void addT10(T#(10) t);
cnt=cnt+t.s;
endfunction
function void addT9(T#(9) t);
cnt=cnt+t.s;
endfunction
endclass
module Top();
initial begin
automatic C myC=new();
automatic T#(10) myT10=new();
automatic T#(9) myT9=new();
myC.clear();
myC.addT10(myT10);
myC.addT9(myT9);
myC.print();
$finish;
end
endmodule
But obviously I do not want to write all the addTxx functions for any possible value of the W parameter. How can I write addT once, so that it can accept any T class with whatever parameter?
My first try was to add a nested class around the add function, i.e. add inside the C class:
class add_class#(int W);
static function void add(T#(W) t);
cnt=cnt+t.s;
endfunction
endclass
However, this doesnt work as the static function is obviously not allowed to access the non-static variable “cnt”.
I have ended up with:
class T#(int W);
bit [W-1:0] s;
function new();
s=2**(W-1);
endfunction
endclass
class C;
bit [31:0] cnt;
function void print();
$display("cnt=%0d",cnt);
endfunction
function void incr();
cnt=cnt+1;
endfunction
function void clear();
cnt=0;
endfunction
class add_class#(int W);
function void add(C C_handle, T#(W) t);
C_handle.cnt=C_handle.cnt+t.s;
endfunction
endclass
endclass
module Top();
initial begin
automatic C myC=new();
automatic T#(10) myT10;
C::add_class#(10) A;
myT10=new();
A=new();
myC.clear();
A.add(myC,myT10);
myC.print();
$finish;
end
endmodule
I think it works, but it looks really messy.
Isn’t there a much simpler way of doing? I am also surprised that it does not let me make ‘cnt’ local any longer?