Thursday, August 22, 2013

SystemVerilog array of objects initialization

So I'm updating one of my testbenches and I want to create an array of objects. For example:
A_class a_instance[num];

I also want to pass these objects to modules and other created objects.

B_class b_instance = new (a_instance[0]);
C_mod c_modinst (.a(a_instance[0]));

The biggest issue is that a_instance isn't yet initialized.

If you try and initialize with

initial begin
for(genvar i = 0; i < num; i++) a_instance[i] = new();

This won't work. Has something to do with object and module creation running before initial lines. The initial statement is too late, a null object was passed in and that's what the object and modules will have.

When I was passing a non array, it would work b/c the declaration included an assignment:
A_class a_instance = new();
but you can't call new on an array.

Here's what appears to work:
A_class a_instance = '{num{A_class::create()}};

This surprised me as I am using replication. It looks like each instance points to its own object. This resolves the problem. Now on the declaration line, I can initialize the objects. Passing the objects around works well now.

Update from Idan's comment:
A_class a_instance = '{default:A_class::create()};

This uses the default syntax for filling in an array. Much nicer than the replication mechanism.

About the create function: SystemVerilog doesn't allow you to call new on a class type so I use a create function instead:

class a;
 function new();
  $display("creating a");
 static function a create();
  class a_inst;
  a_inst = new();
  return a_inst;

I believe others refer to this as a factory create function or something like that. Now creating a is as easy as calling a::create().