Search code examples
system-veriloguvm

Warning when setting uvm_reg values through a task


I am creating a framework where my verification team and I can write uvm test cases with ease. The basic idea is that my base (uvm_)sequence only contains the one line in its body task:

regs.update(status);

From my individual (uvm_)tests, I can set the register values using handy helper functions. For example, my tests would contain:

class base_test extends uvm_test;
    ........
    ........
    virtual function void set_registerA(....);
        regs.registerA1.set(....);
        regs.registerA2.set(....);
        regs.registerA3.set(....);
    endfunction

    virtual function void set_registerB(....);
        regs.registerB1.set(....);
        regs.registerB2.set(....);
        regs.registerB3.set(....);
    endfunction
endclass

class test1 extends base_test;
    virtual function void end_of_elaboration_phase(uvm_phase phase);
        set_registerA(....);
        set_registerB(....);
    endfunction
endclass

class test2 extends base_test;
    virtual function void end_of_elaboration_phase(uvm_phase phase);
        set_registerA(....);
        set_registerB(....);
    endfunction
endclass

Now I realize that end_of_elaboration phase may not be the best place to set the registers. My compiler gave me warnings that said "WARNING: Calling a task "set_registerA" in task "end_of_elaboration". So I changed it to execute in my run_phase:

class test1 extends base_test;
    virtual task run_phase(uvm_phase phase);
        super.run_phase(phase);
        set_registerA(....);
        set_registerB(....);
    endfunction
endclass

class test2 extends base_test;
    virtual task run_phase(uvm_phase phase);
        super.run_phase(phase);
        set_registerA(....);
        set_registerB(....);
    endfunction
endclass

I am unsure if this is the right methodology for what I am trying to do? Does calling super.run_phase cause problems? I don't see this done anywhere else.


Solution

  • I personally don't like calling super.run_phase(...) because it can create problems if you want to implement something that was defined in a grandparent class. If you don't expect having a test inherit from a test inheriting from a test, then you shouldn't have any problems. The main idea is that the run_phase will almost always get overridden, but end_of_elaboration/start_of_simulation less so, which is why it would be a better candidate for more general things.

    W.r.t. to your compile issue, check that you didn't create tasks instead of functions for your set_register* functions. Your compiler might be more lenient and allow you to start tasks inside functions (end_of_elaboration is a function), most probably by doing the equivalent of a fork...join_none