UVM Phase jumping: Discrepancy in forward jumps

I am trying to jump some of the phases in my TB in order to skip certain unnecessary checks and save some time. But I see some discrepancies.

There are two environments and two separate domains assigned to them as shown below. When domain1 is in shutdown phase, domain2 enters in main phase, this suggests that both the domains run independently of each other (as expected).

 
  // Displays are there in every phase of environment
 
  class test extends uvm_test;
    `uvm_component_utils(test)
    
    function new (string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    
    env m_env1;
    env m_env2;

    uvm_domain domain1;
    uvm_domain domain2;
    
    function void build_phase(uvm_phase phase);
      
      // This part domain1 and domain2 are running independently
      // uvm_config_db#(int)::set(this, "m_env1", "delay", 10);
      
      // Use different delays to see that domain1 and domain2 run independently
      uvm_config_db#(int)::set(this, "m_env1", "delay", 100);
      uvm_config_db#(int)::set(this, "m_env2", "delay", 100);
      
      m_env1 = env::type_id::create("m_env1", this);
      m_env2 = env::type_id::create("m_env2", this);
      
      domain1 = new("domain1");
      m_env1.set_domain(domain1);
      
      domain2 = new("domain2");
      m_env2.set_domain(domain2);
      //domain1.sync(domain2);
   
    endfunction
    
    function void start_of_simulation_phase(uvm_phase phase);
      this.set_report_verbosity_level_hier(UVM_FULL);
    endfunction
    
    task run_phase(uvm_phase phase);   
      #250;

      `ifdef EXTRACT_PH_JUMP // USE THIS SWITCH TO JUMP TO EXTRACT PHASE

      // Both domain1 and domain2 jumps to extract phase unexpectedly.
      // this is for domain2 to jump to extract phase
      domain2.jump(uvm_extract_phase::get());
      
      `else
      
      // Both domain1 and domain2 jumps to repective phases other than extract phase. I would expect only domain2 to jump and wait and domain1 to continue phase execution.
      
      // domain2 should wait till domain1 completes other phases
      // this is for domain2 to jump to final phase      
      domain2.jump(uvm_final_phase::get());
      
      `endif
  
    endtask
    
  endclass

// Output when jumping to extract phase. Extract phase display comes twice.
UVM_INFO /apps/vcsmx/etc/uvm-1.2/src/base/uvm_phase.svh(1552) @ 250: reporter [PH_JUMP] phase main (schedule uvm_sched, domain domain2) is jumping to phase extract
UVM_WARNING @ 250: main_objection [OBJTN_CLEAR] Object 'uvm_top' cleared objection counts for main_objection
UVM_INFO testbench.sv(78) @ 1040: uvm_test_top.m_env1 [uvm_test_top.m_env1] this is extract phase
UVM_INFO testbench.sv(78) @ 1040: uvm_test_top.m_env2 [uvm_test_top.m_env2] this is extract phase
UVM_INFO testbench.sv(78) @ 1040: uvm_test_top.m_env1 [uvm_test_top.m_env1] this is extract phase
UVM_INFO testbench.sv(78) @ 1040: uvm_test_top.m_env2 [uvm_test_top.m_env2] this is extract phase


  1. When I jump from run phase to any phase, both the domain1 and domain2 skips the remaining phases and jumps to the intended phase. I would expect domain2 only to skip the phases and jump forward and wait (domain1 jumps unexpectedly). Is there any way to skip phases for domain2 only?

  2. But when a jump happens from “run_phase” (or any other task phase) to “extract_phase”, then the “extract_phase” is getting called twice. This is certainly not expected. Is there any workaround for this?

Sample code: Phase jumping - EDA Playground
Referral code from Duolos.

Please provide some inputs regarding the two issues. Let me know where my understanding is lagging.

EDIT: MODIFIED THE CODE. USE “+define+EXTRACT_PH_JUMP” TO JUMP TO EXTRACT PHASE AND SEE THAT IT IS GETTING CALLED TWICE (SCENARIO-2). IF YOU DON’T USE THIS MACRO, THEN IT WILL JUMP TO FINAL PHASE (SCENARIO-1).

In reply to sharvil111:

I guess you are simulating with VCS, right?
Using Questa I see a different result:

UVM_INFO verilog_src/questa_uvm_pkg-1.2/src/questa_uvm_pkg.sv(215) @ 0: reporter [Questa UVM] QUESTA_UVM-1.2.2

UVM_INFO verilog_src/questa_uvm_pkg-1.2/src/questa_uvm_pkg.sv(217) @ 0: reporter [Questa UVM] questa_uvm::init(+struct)

UVM_INFO @ 0: reporter [RNTST] Running test test…

UVM_INFO testbench.sv(20) @ 0: uvm_test_top.m_env2 reset_phase called

UVM_INFO testbench.sv(20) @ 0: uvm_test_top.m_env1 reset_phase called

UVM_INFO testbench.sv(28) @ 100: uvm_test_top.m_env1 configure_phase called

UVM_INFO testbench.sv(28) @ 100: uvm_test_top.m_env2 configure_phase called

UVM_INFO testbench.sv(38) @ 200: uvm_test_top.m_env2 main_phase called

UVM_INFO testbench.sv(38) @ 200: uvm_test_top.m_env1 main_phase called

UVM_INFO verilog_src/uvm-1.1d/src/base/uvm_phase.svh(1314) @ 250: reporter [PH_JUMP] phase main (schedule uvm_sched, domain domain2) is jumping to phase final

UVM_WARNING @ 250: main_objection [OBJTN_CLEAR] Object ‘uvm_top’ cleared objection counts for main_objection

UVM_INFO testbench.sv(66) @ 250: uvm_test_top.m_env1 [uvm_test_top.m_env1] this is final phase

UVM_INFO testbench.sv(66) @ 250: uvm_test_top.m_env2 [uvm_test_top.m_env2] this is final phase

It does not jump th the extract phase.

In reply to chr_sue:

Pardon for the confusion. I have updated the code in my question. Refer to the comments in build and run phase of test. Uncommented the code as required.


        // ***** in build phase
       // Uncomment this to see that domain1 and domain2 are running independently
      // uvm_config_db#(int)::set(this, "m_env1", "delay", 10);
 
      // Uncomment this to see that domain1 also jumps when domain2 jumps to final phase
      uvm_config_db#(int)::set(this, "m_env1", "delay", 100);
 
      uvm_config_db#(int)::set(this, "m_env2", "delay", 100);


       // ***** in run phase;
      // Both domain1 and domain2 jumps to extract phase unexpectedly.
      // Uncomment this for domain2 to jump to extract phase
      domain2.jump(uvm_extract_phase::get());
      
      // Both domain1 and domain2 jumps to repective phases other than extract phase. I would expect only domain2 to jump and wait and domain1 to continue phase execution.
      // domain2 should wait till domain1 completes other phases
      // Uncomment this for domain2 to jump to final phase      
      //domain2.jump(uvm_final_phase::get());

I have tried with all simulators at EDAPlayground and got the same results. I believe that this should be independent of simulator.

In reply to sharvil111:

It would help greatly if you would put `ifdefs around the code instead of trying to have different sets of code to comment or uncomment.

Then you can tell us to run the code with this +define+ switch and say you get “this set of results” when in fact you were expecting “that set of results”

That will clear up all confusion.

In reply to dave_59:

Done. Please review the updated question and code.

EDIT: MODIFIED THE CODE. USE “+define+EXTRACT_PH_JUMP” TO JUMP TO EXTRACT PHASE AND SEE THAT IT IS GETTING CALLED TWICE (SCENARIO-2). IF YOU DON’T USE THIS MACRO, THEN IT WILL JUMP TO FINAL PHASE (SCENARIO-1).

Use appropriate macro to jump to extract phase or any other phase.

In reply to sharvil111:

I’m not sure what the value of this example is. I recommend my customers always to decide what they are doing, going simply with the run_phase or using the sub-phases like reset_phase etc.
You should not mix them in 1 testbench.

In reply to chr_sue:

The issue persists even if we jump from any of the sub-phases to extract phase.

This is a sample code. In the real testbench, it can be used to skip multiple phases and save the run time of simulation. It can be useful for some sanity type of tests where we don’t want thorough RTL checks.

In reply to sharvil111:

What I mean is, if you are replacing in the test the run_phase by main_phase the jumping never happens. It happens only if you use the run_phase. I believe it is not a good coding style the employ both Kinds of phasing in a testbench, using in the env the run sub-phases and in the test run_phase.

I’m not sure if you are really saving time jumping from one phase to another. Only the run_phase and the sub-phases are consuming time. All the other phases are functions.
My experience shows the real delay comes always out of the RTL.

In reply to chr_sue:

What I mean is, if you are replacing in the test the run_phase by main_phase the jumping never happens. It happens only if you use the run_phase.

Thanks for the inputs. I didn’t knew this. Is it documented somewhere? Can you please point me to some link where I can improvise my knowledge over this.

I tried using the run_phase everywhere in the current code. Then also the same issue of extract phase getting called twice, persists. Now I am using run_phase in environment and test both and jumping to extract_phase. Still I am seeing that extract phase is called twice. Moreover, there is no objection dropping when jump is called.

I have updated the code with “+define+USE_RUN_PH” switch. Refer to the same link for regenerating the issue. (Phase jumping - EDA Playground)

P.S.: I agree that the delay comes from the RTL, but still phase jumping will help in eliminating checks for several thousands of CSR-arrays in my case (these checks are in different components in top level TB).

In reply to sharvil111:

Phase jumping came with UVM-1.2. I did not see this in practice so far.A lot companies did not go with uvm-1.2 because it is not compatible with 1.1d…

In your case I’d recommend to look for another solution to switch-off this checking. A test allows you to modify your testbench. I’d go this way.