Accessing task of generate block using hierarchy path

I have generated memory model instance as below mentioned way.
How many number of model instance get generate will be define by `WIDTH define.

module temp();
.
.
.
.

generate
genvar i;
begin : GEN_MEM_MODEL
for(i = 0; i < `WIDTH; i = i+1) begin : MEM_MODEL_INST
.
.
.
endmodule

Now how can I access method / task of memory model which I have generated using “generate” keyword.

While generation it showing name as below :

ddr_tb_top.dram_model.GEN_MEM_MODEL.MEM_MODEL_INST[0].i_dram0.
ddr_tb_top.dram_model.GEN_MEM_MODEL.MEM_MODEL_INST[1].i_dram0.
ddr_tb_top.dram_model.GEN_MEM_MODEL.MEM_MODEL_INST[2].i_dram0.
ddr_tb_top.dram_model.GEN_MEM_MODEL.MEM_MODEL_INST[3].i_dram0.

I want to access some memory part of these models so I am trying by below mentioned way

// Write randome data from backdoor of memory
for(int i= 0 ; i < `WIDTH ; i++) begin
top.dram_model.GEN_MEM_MODEL.MEM_MODEL_INST[i].i_dram0.task_name;
end

It’s not allow to use me ‘i’ variable.
It will give me error as

** Error: (vsim-3745) /home/niyati/projects/DRACO/sv_ve/verif/scripts/…/…/…//sv_ve/tests/sib_ddr3_base_test.sv(472): A variable index into the generate block ‘ddr_tb_top.dram_model.GEN_MEM_MODEL.MEM_MODEL_INST’ is illegal.

verror 3745 :
vsim Message # 3745:
A variable index was detected in a reference to the specified generate
hierarchy. The index must be an integer literal, a parameter, a localparam,
or an expression made up of them (constant expression).

It allow to use as
top.dram_model.GEN_MEM_MODEL.MEM_MODEL_INST[0].i_dram0.task_name;
top.dram_model.GEN_MEM_MODEL.MEM_MODEL_INST[1].i_dram0.task_name;
top.dram_model.GEN_MEM_MODEL.MEM_MODEL_INST[2].i_dram0.task_name;

Can you please suggest me some way by which I can use or call it in for loop inplace of writing / calling one by one

Thanks in advance

The index created by a generate loop or array if instances cannot be accessed via a dynamic variable. This restriction is mainly because of Verilog parametrization and a few other features that has the potential to make each instance unique. In a regular array, every element is the exact same type and has the exact same sub-components. The compiler must check at elaboration, not at run-time if the full path is valid.

There are several ways to get around this limitation. If you need to call all instances at once, you can create a generated loop of always blocks that wait for a trigger when you want to call all the tasks

event call_task1_name;
event call_function2_name;
genvar index;
for(index = 0; i < `WIDTH; i++) begin
always @call_task1_name
 top.dram_model.GEN_MEM_MODEL.MEM_MODEL_INST[ index].i_dram0.task1_name;
always @call_function2_name
 top.dram_model.GEN_MEM_MODEL.MEM_MODEL_INST[ index].i_dram0.function2_name;
end

When you trigger call_task_name, all the tasks will be called in parallel.

If you need to selectively call the tasks, then the best thing to do is wrap the calls in methods of a class

virtual class mem_model_array_c;
  pure virtual task task1_name;
  pure virtual function void function2_name;
endclass

mem_model_array_c mem_model_array_h[`WIDTH];
genvar index;
for(index = 0; i < `WIDTH; i++) begin :class_decl_loop
class mem_model_element_c extends mem_model_array_c;
task task1_name;
  top.dram_model.GEN_MEM_MODEL.MEM_MODEL_INST[ index].i_dram0.task1_name;
endtask
function void function2_name;
 top.dram_model.GEN_MEM_MODEL.MEM_MODEL_INST[ index].i_dram0.function2_name;
endfunction
endclass

mem_model_element_C mem_model_element_h = new();
initial mem_model_array_h[ index] = mem_model_element_h;

end : class_decl_loop

Now you can individually call the task or function with

mem_model_array_h[ expr].function2_name;

P.S. Please try to use parameters in packages instead of `defines for WIDTH

Please use function void for routines that do not consume time. Tasks can call other functions, but functions cannot call other tasks.

In reply to dave_59:

This genvar / generate we can use in module only.

By this syntax I want to go for back door write. So I need to define one task in base test(base test is call extended from uvm_test) [I am using SV + UVM environment]. So How can use this in task or suggest me some another way.

In reply to Niyati:

The generate loop is to define and construct the concrete class. Instead of storing the class handle in an array, use uvm_config_db to pass it to your UVM classes

mem_model_element_C mem_model_element_h = new();
initial uvm_config_db#(mem_model_array_c)::set(null,"",$sformatf("elementname_%0d",index),mem_model_element_h;

The abstract class mem_model_array_c from my original post should be defined in a package, and you will call uvm_config_db#(mem_model_array_c)::get from your UVM class. (You might want to change its name to mem_model_abstract_c)

In the same manner you would have passed a interface instance to a virtual interface variable, you are now passing a concrete class handle to an abstract class variable. That object can now be used inside your class-based UVM testbench, but because that was constructed in your module-based testbench, it will call the task/function inside the module.