UVM Phase Synchronization

As suggested by chr_sue, the usage of mixed-phases is not recommended practice. Still if you have constraints of multiple phase usage, then you can make use of wait_for_state API of UVM phase.

The uvm_phase class provides the “wait_for_state” task to wait till a particular state of phase is reached. All you need to do is get a handle of implementation of a phase and call the API.

In the build_phase of monitor, get the handle of main_phase implementation. Thereafter, in the run phase, call the wait task to wait till driver reaches main phase.

// Get handle of main phase in monitor
uvm_phase p;
p = phase.find_by_name("main",0);
// find_by_name prototype
// extern function uvm_phase find_by_name(string name, bit stay_in_scope=1);

// Call wait task in monitor run phase
p.wait_for_state(UVM_PHASE_STARTED);
// wait_for_state prototype
// extern task wait_for_state(uvm_phase_state state, uvm_wait_op op=UVM_EQ);

Note that this works in a single phase domain, I have not tested it across multiple domains. Following is an example of how the wait task is invoked to block the monitor.

  class driver extends uvm_component;
    `uvm_component_utils(driver)
    function new(string name = "driver",uvm_component parent = null);
      super.new(name,parent);
    endfunction
    
    task reset_phase(uvm_phase phase);
      phase.raise_objection(this);
      #5;
      $display($time,"\tdriver: reset phase ended");
      phase.drop_objection(this);
    endtask
      
    task main_phase(uvm_phase phase);
      phase.raise_objection(this);
      phase.drop_objection(this);
    endtask
    
  endclass
      
  class monitor extends uvm_component;
    uvm_phase p;
    
    `uvm_component_utils(monitor)
    function new(string name = "monitor",uvm_component parent = null);
      super.new(name,parent);
    endfunction
      
    function void build_phase(uvm_phase phase);
      p = phase.find_by_name("main",0);
      if(p == null) $display("P found null");
    endfunction
    
    task run_phase(uvm_phase phase);
      phase.raise_objection(this);
      p.wait_for_state(UVM_PHASE_STARTED);
      $display($time,"\tMonitor unblocked");
      phase.drop_objection(this);
    endtask
  endclass

  // Output
  UVM_INFO @ 0: reporter [RNTST] Running test test...
                     5	driver: reset phase ended
                     5	Monitor unblocked
  UVM_INFO /apps/vcsmx/etc/uvm-1.1/src/base/uvm_objection.svh(1267) @ 5: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase

For more information refer to uvm_phase.svh and uvm_phase singletons question. This blog post might also be useful.