Reputation: 867
I am creating a class that needs a reference to the test bench's configuration object. Since the configuration must be intact throughout the simulation, I pass it as a const ref
object. Here is pseudo code that I want to run:
class tb_config;
int unsigned rate;
int unsigned chnls[];
const int unsigned nb_chnls;
function new (int unsigned rate, int unsigned nb_chnls);
this.rate = rate;
this.nb_chnls = nb_chnls;
chnls = new[nb_chnls];
endfunction
endclass
class tx_phy;
static int phy_id;
tb_config cfg;
function new (int unsigned phy_id, const ref tb_config cfg);
this.phy_id = phy_id;
this.cfg = cfg;
endfunction
endclass
module test;
tb_config cfg = new(100, 4);
tx_phy phy = new(1234, cfg);
endmodule
The code above works perfectly fine and it meets my expectation. But if I change the arguments in tx_phy::new
to function new (const ref tb_config cfg, int unsigned phy_id);
and pass the values to the constructor accordingly I get the following error in Cadence Incisive:
invalid ref argument usage because actual argument is not a variable.
Also same thing happens when I test it with Aldec in edaplayground:
https://www.edaplayground.com/x/5PWV
I assume this is a language limitation, but is there any other reason for that?
Upvotes: 3
Views: 3949
Reputation: 42698
The reason for this is because the argument kind is implicit if not specified. You specified const ref
for the first argument, but nothing for the second argument, so it is also implicitly const ref
. Adding input
to the second argument declaration fixes this.
function new (const ref tb_config cfg, input int unsigned phy_id);
I also want to add const ref tb_config cfg
is equivalent to writing
function new (tb_config cfg, int unsigned phy_id);
Both of these arguments are implicitly input
arguments, which means they are copied upon entry.
A class variable is already a reference. Passing a class variable by ref
means that you can update the handle the class variable has from within the function. Making the argument a const ref
means you will not be able to update the class variable, but you can still update members of the class the variable references. There is no mechanism to prevent updating members of class object if you have a handle to it other than by declaring them protected
or local
.
The only place it makes sense to pass function arguments by ref
in SystemVerilog is as an optimization when the arguments are large data structures like an array, and you only need to access a few of the elements of the array. You can use task ref
arguments when the arguments need to be updated during the lifetime of the task (i.e. passing a clock as an argument).
Upvotes: 4