maskarih
maskarih

Reputation: 867

Systemverilog const ref arg position when constructing an object

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

Answers (1)

dave_59
dave_59

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

Related Questions