rafael.shirakawa Posted March 7, 2011 Report Share Posted March 7, 2011 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? Quote Link to comment Share on other sites More sharing options...
janick Posted March 7, 2011 Report Share Posted March 7, 2011 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. Quote Link to comment Share on other sites More sharing options...
rafael.shirakawa Posted March 8, 2011 Author Report Share Posted March 8, 2011 Hi Janik, The suggestion you gave was my first approach for the problem. But I wish to pass an unique parameter for each instance of the class. There are compilations errors when I put it inside a for loop, as: for (int i=0 ; i<=10;i++) begin class_type1#(my_params[i]) class array [i]; end Quote Link to comment Share on other sites More sharing options...
janick Posted March 8, 2011 Report Share Posted March 8, 2011 You must then make the array type the non-parameterizable class type, allocate a parameterized instance, then add if to the array as a base class. class_base array[10]; foreach (array[i]) begin class_type#(my_params[i]) o = new(); array[i] = o; end Quote Link to comment Share on other sites More sharing options...
rafael.shirakawa Posted March 8, 2011 Author Report Share Posted March 8, 2011 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?). Quote Link to comment Share on other sites More sharing options...
janick Posted March 8, 2011 Report Share Posted March 8, 2011 Sorry -- my bad. Class parameters must be compile-time constants. You'll need to show more of what you want to do because your approach seems to be the wrong one. Quote Link to comment Share on other sites More sharing options...
rafael.shirakawa Posted March 8, 2011 Author Report Share Posted March 8, 2011 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. Quote Link to comment Share on other sites More sharing options...
jadec Posted March 10, 2011 Report Share Posted March 10, 2011 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. Quote Link to comment Share on other sites More sharing options...
rafael.shirakawa Posted March 14, 2011 Author Report Share Posted March 14, 2011 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 Quote Link to comment Share on other sites More sharing options...
jadec Posted March 23, 2011 Report Share Posted March 23, 2011 You'll need a generate for the initial block and genvar i. Assuming that PARAM is a parameter array. Quote Link to comment Share on other sites More sharing options...
uwes Posted March 24, 2011 Report Share Posted March 24, 2011 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. Quote Link to comment Share on other sites More sharing options...
mpeer Posted March 24, 2011 Report Share Posted March 24, 2011 (edited) 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 March 24, 2011 by mpeer Quote Link to comment Share on other sites More sharing options...
janick Posted March 24, 2011 Report Share Posted March 24, 2011 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 Quote Link to comment Share on other sites More sharing options...
rafael.shirakawa Posted March 24, 2011 Author Report Share Posted March 24, 2011 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. Quote Link to comment Share on other sites More sharing options...
janick Posted March 24, 2011 Report Share Posted March 24, 2011 Definitely go for a "MAX_BITS" approach for data and address. For the memory ID, that does not need to be a compile-time constant. Why not make it a configuration parameter using uvm_config_db? Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.