Timestep and objections

When all objections are dropped in the run_phase, is the current timestep still completed before going to the next phase?
Or asked otherwise, the checking if all objections are dropped, and going to the next phase happens only at the end of a timestep?

In reply to NiLu:

No. There is no time advancement between ending one phase and starting the next.

I actually meant when does the uvm ‘kernel’ look if there are objections left and is there a chance to go to the next phase?

For example when all components just enter the run_phase, none of them have any objections raised to start with, but still the run_phase doesn’t end (luckily). It seems the phases run at least long enough to run being able to raise an objection. So when are objections being observed? My main interest is to know if the CURRENT timestep is finished when the objection count reaches 0?

Basically my setup uses only 1 objection in the test. When my sequence ends, the objection is dropped. In the same timestep the scoreboard will get its last value. So I am wondering if it could happen that the run_phase ends before the scoreboard saw the last transaction in its run_phase?

edit: reading the reference manual, I am starting to suspect that it is when the objection count goes from a non zero number to zero, explaining why run_phase doesn’t end immediately?
But it seems it means the phase could change in the middle of a timestep?

In reply to NiLu:
Essentially, you have the default drain time (#0) to raise an objection before the phase ends. Then, dropping the objection count to 0 causes an event to end the phase.

I still do not fully get this matching with what I see. E.g. if my test’s run_phase contains only:

    $display("start of test");
    for(int i=0;i<10000;i++) begin
        #0;
    end
    $display("after 10000 x #0 (%0t)",$realtime);
    #1ns
    $display("after #1ns (%0t)",$realtime);

returns:

start of test

after 10000 x #0 (0.0 ns)

Hence the phase doesn’t end after the first #0, but only when time needs to be advanced.

EDIT: raising and dropping an objection prior to the above code has the same effect.

In reply to NiLu:

Be careful using #0, because it makes only 1 step froward in the SV scheduler of a time step.
In my code I never use #0.
10000 x #0 is useless, because there are not 10000 steps in one time step.
Regarding your first question: the actual timestep will be completed when dropping an objection.
But completing this does not mean any step forward in time. The actual time is still the same.

I also do not use #0 in my code, this was just an experiment to see if the phase could end before completing the actual timestep.

the actual timestep will be completed when dropping an objection.

This was actually the info I was looking for.

In reply to NiLu:
After further investigation, it seams the UVM scheduler is using wait_for_nba_region to wait for any objects top be raised before continuing on to the next phase. This means if you are using time-consuming sub-phases, each phase consumes one iteration of NBA cycles.

Thanks for the update. Let me try to summarize (assume I only use run_phase, not its sub-phases):

In a condition where all objections were dropped and no new ones get raised, the current time slot is NOT always finished before a move from run_phase to extract_phase happens. It only guarantees that the current active/inactive/NBA is finished before such a move of phase.
In particular when the current NBA update would trigger a new loop of active/inactive/NBA this new loop will not finish before we move to the extract_phase. Correct?

In reply to NiLu:
Your first sentence is correct. Unfortunately, even if your code does not use the sub-phases, the uvm_component base class has them and the phase scheduler will execute them. Each one of these sub phases consumes one NBA loop in parallel with the run_phase. This example run with +UVM_PHASE_TRACE will show exactly what is going on.

module top;
import uvm_pkg::*;
`include "uvm_macros.svh"

   event e;
   
class test extends uvm_test;
   `uvm_component_utils(test);
   function new(string name, uvm_component parent);
      super.new(name,parent);
   endfunction
   
   task run_phase(uvm_phase phase);
      for(int i=0;i<100;i++)  begin // each loop is one NBA delta cycle   
	 ->>e;
	 $display("%0d before ->> (%0t)",i, $realtime);
	 @e $display("%0d after ->> (%0t)",i, $realtime);
      end
   endtask : run_phase
endclass : test
   initial run_test("test");
endmodule : top

In reply to dave_59:

Thanks!