Jump to content

instantiate an array of classes inside a class of UVM


Recommended Posts

Inside a uvm_env class, I try to create an array of another uvm_env class. I need to pass parameters to each element of this array. I can't use a generate loop inside the class and I couldn't find out a way to use a for loop to pass the individual parameters.

My last attempt was to declare an array of class inside my uvm_env class like:

class_type1 class_array [9:0];

and then to pass the parameters at the module where this class is, by using 'defparam' inside a generate:

module ...

...

genvar i;

generate

for (i=0 ; i<=9 ; i++) begin

defparam class_instance.class_array.param = my_params;

end

endgenerate

...

endmodule

But the compiler then complains that I use the class (already with parameters) in the build phase. I'm using a for loop in the build function to loop through all elements.

Is there a way to create an array of parameterized classes inside a class in systemverilog?

Link to comment
Share on other sites

First of all, this is not a UVM issue but a generic SystemVerilog issue.

Second,you should not use the defparam statement as it is subject to ordering 'race' conditions. And only the positional (#()) notation can be used to specify class parameters.

So you probably need something like this:

class_type1#(my_params) class array [10];

No need for the generate statement.

Link to comment
Share on other sites

Not yet.. I have put the 'foreach' loop inside the new function. My code (without all the UVM stuff) now is:

class_base array[9:0];
function new();
  foreach (array[i]) begin
     class_type#(my_params[i]) o = new();
     array[i] = o;
  end
endfunction

I have a compilation error pointing that 'i' is a illegal operand for constant expression (perhaps it is treated as a variable?).

Link to comment
Share on other sites

My DUV has a series of memory wrappers. I have developed a parameterized uvm_env with UVCs for the memory wrappers and I wish to instantiate them with individual parameters in my testbench environment. The approach I have so far is to unroll the loop of memory environments using a perl script I wrote. It works fine but I wonder if it is possible to do it in SV or not.

Link to comment
Share on other sites

You are right that you would need a generate to create the compile-time parameterizations from a my_params array compile-time constant.

However, you might use this approach instead:

uvm_factory factory = uvm_factory::get();

initial begin

factory.set_inst_override_by_type( base::get_type(), param#(<subenv_param>)::get_type(), "env.<subenv_name>" );

...

end

This code can be part of tb_top module.

Your "env" would then just need to create the right number of "base" type components with the appropriate <subenv_name>s.

Link to comment
Share on other sites

Hi,

now I have:

inside my testbench top module:

uvm_factory factory = uvm_factory::get();
  initial begin
    for (int i=0 ; i < 10; i++) begin
      string env_path;
      $sformat(env_path,"my_tb.env_instance[%0d]",i);
      factory.set_inst_override_by_type(env_type::get_type(),
        env_type#(PARAM[i])::get_type(),env_path);
    end
  end

inside my uvm testbench class:

env_type env_instance[9:0];
  function void build();
    super.build();
    for (int i=0 ; i < 10; i++) begin
      string env_element;
      $sformat(env_element,"env_instance[%0d]",i);
      env_instance[i] = env_type::type_id::create(env_element,this);
    end
  end

I added the '$sformat' functions in order to pass a different string on each loop iteration.

I still have compilation errors pointing to the 'i' inside the factory function call:

Illegal operand for constant expression

Link to comment
Share on other sites

  • 2 weeks later...

hi,

the point is that:

env_type#(PARAM)::get_type(),env_path);

especially the PARAM is not "constant". the part "#(..)" are parameters and have to be constant at elab time BUT for you they are runtime selected. this does not work that way - you have to make a generate loop around your initial (+the genvar 'i'). that way 'i' is a elab time constant and it should work.

Link to comment
Share on other sites

Hi

You may probably use the following code:

my_class obj[];

obj = new[10];

for(int i=0;i<10;i++)

begin

$sformat(str,"obj_%0d",i);

obj = my_class::type_id::create(str, this);

end

The above code will create the obj_0, obj_1, obj_2, obj_3 ..... obj_9.

I hope this is what you required. This code was working without any error.

Regards

Peer Mohammed

Edited by mpeer
Link to comment
Share on other sites

Parameterization is a two-edged sword... it makes code highly reusable but difficult to instantiate in generic contexts.

You mentionned earlier that what you are trying to instantiate are memory environments. Those parameters wouldn't be the size of the memory data path by any chance?? If so, you might want to rely in SV's automatic data value extension and truncation instead of parameters.

See http://www.vmmcentral.org/vmartialarts/2008/07/size-does-matter

Link to comment
Share on other sites

Hi all,

Thank you for the expertise support. My code now passes that compilation error. The fix jadec and uwes proposed looks like:

uvm_factory factory = uvm_factory::get();
[SIZE="4"]genvar i;
generate
for (int i=0 ; i < 10; i++) begin[/SIZE]
  initial begin
      string env_path;
      $sformat(env_path,"my_tb.env_instance[%0d]",i);
      factory.set_inst_override_by_type(env_type::get_type(),
        env_type#(PARAM[i])::get_type(),env_path);
    end
  end

But the compilation still doesn't finish.

The error I have now is because I have parameterized interfaces connected to the testbench environment. Well, the interfaces are parameterized at their declaration (therefore, at compilation) while the environment is now parameterized only with the factory functions, at runtime.

This creates an error message, during compilation, stating that they aren't compatible in my assign_vi function, inside the connect function.

Going into more details, my parameters are data width, address width and an address id for each memory wrapper environment. These values are known at the start of the compilation and they are used to create the mirror memories and interfaces buses. There is a good number of instances (64) which are probing each memory wrapper inside the duv. I may have to use janick's last suggestion and create a big defined value and then truncate it during runtime according to each implementation.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...