Preloading memory with UVM

Hello,

I´m new to UVM, so please excuse me if it´s a question with an obvious answer.

I have built a UVM testbench/environment for my DUT and created different UVM-tests which run different sequences. Now I´d like to initialize a memory in my design (from a hex file) based on the UVM-test I am executing. In the old SystemVerilog testbench I would just use $readmemh(“input.hex”, memory) to preload the memory. How can I do that with UVM?

I´ve searched for solutions but I´ve only seen approaches that look rather complicated. One is to write a sequence that writes the data into the memory over the memory interface at the beginning of the simulation (during actual simulation time). Is there an easy approach to that, similar to readmemh?

Thank you in advance.

In reply to Antonio:

Hi,

As UVM library is implemented with SystemVerilog language, you can use same approach you were using with SV testbench. If memory reside in DUV, in top module use $readmemh(“input.hex”, dut_instance.memory)

1 Like

In reply to mayurkubavat:

Thank you for your answer, mayurkubavat.
I have tried that, but I think I´m missing something.

In my old verification environment, I would have a separate folder for each testcase, containing a different .hex file for each testcase. So for each testcase the whole design was recompiled and the testbench would read in the specific .hex file in each folder and use it to initialize the memory.

Now with UVM I understood that I have the benefit of compiling everything only once and then selecting the specific testcase via the UVM_TESTNAME argument given to the simulator. So I need to somehow make a difference between which .hex file to read depending on the UVM_TESTNAME argument. So I tried to do the $readmemh() inside of my class “test” (extending uvm_test) and then inside of my class “environment” (extending uvm_env) but from both I get an error saying:
Hierarchical reference from package ‘rbtree_test’ into module ‘rbtree_tb_top’
is not allowed.

The only place where this works, is in the testbench (rbtree_tb_top) but there I can´t make the selection of the .hex file dependent on the UVM_TESTNAME.

In reply to Antonio:

Hello Antonio,
in my example I’m using a specific preload sequence. This sequences takes care that the memory in the DUT will be preloaded using readmemh. But I need the memory content also for comparison use in my testbench. Then the preload sequence is useful.
In your case if you want to preload only the DUT memory you can do this by changing the name of the pattern file with respect to your test.

1 Like

In reply to Antonio:

Hi Antonio, Got your point!

And error is expected in your case, because from sv class which is included in package, hierarchical reference to module is not allowed.

For time being, you can have a shell/perl script which will update/overwrite the fixed_name.hex file before running each testcases, so that you can read this fixed_name.hex file from the top module using same concept of $readmemh(“input.hex”, dut_instance.memory).

I’ll get back with what else we can do with the situation…

Thank you both for your answers.

In reply to chr_sue:

in my example I’m using a specific preload sequence. This sequences takes care that the memory in the DUT will be preloaded using readmemh …

chr_sue,
you are mentioning an example of your approach - where can I find that? Thanks.

In reply to mayurkubavat:
Ok, good :)
At the moment I´m using a makefile to execute the commands to start the simulation. It shouldn´t be a problem to add some lines to overwrite the fixed_name.hex file. Yet I have to say I´m a little surprised that there aren´t any simple solutions within UVM.

In reply to Antonio:

In my toplevel module I do the following:

logic [63:0] comp_mem00 ; //declaring a dynamic memory of 64 bit words

// preloading the design memory
always @ preloading_e begin //loading the deseign mem, when the preload sequence has been
// started
comp_mem00 = new[2MEM_ADDR_SIZE-1]; //constructing a dynamic memory of size2MEM_ADDR_SIZE
uvm_info("wideIO2_top_tb", "preloading_e triggered", UVM_HIGH) $readmemh("pattern00.hex",dut.<path to the mem>); // perfoming a sanity check foreach (addr00[i]) begin if (comp_mem00[addr00[i]] == dut.<path to the mem>.i_memArray[addr00[i]]) pass_count00++; else begin error_count00++; uvm_info(“wideIO2_top_tb”, $sformatf(“sanity check design mem :: addr = %0d,
comp_mem00 = %h :: memArray00 = %h”, addr00[i], comp_mem00[addr00[i]],
dut..i_memArray[addr00[i]]), UVM_HIGH)
end

In my preload sequence:

// pre-loading internal memory (testbench)
`uvm_info(get_type_name(),“preloding testbench memory”, UVM_MEDIUM)
$readmemh(“pattern00.hex”,mem00);

→ preloading_e; /triggers the preload in the toplevel module

The trigger is declared in a common package available for the sequence aadn the toplevel module.

In reply to chr_sue:

Thank you for your answer. I understand your implementation and I have it more or less working in my testbench now. :-)