//------------------------------------------------------------------------------
//    Copyright 2009 Mentor Graphics Corporation
//    Copyright 2009 Synopsys, Inc.
//    All Rights Reserved Worldwide
//
//    Licensed under the Apache License, Version 2.0 (the
//    "License"); you may not use this file except in
//    compliance with the License.  You may obtain a copy of
//    the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in
//    writing, software distributed under the License is
//    distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
//    CONDITIONS OF ANY KIND, either express or implied.  See
//    the License for the specific language governing
//    permissions and limitations under the License.
//------------------------------------------------------------------------------


//------------------------------------------------------------------------------
//
// Title: Integrated Phase Control - VMM-on-top
//
//------------------------------------------------------------------------------
//
// This class is used to ensure OVM components (i.e. all subtypes of
// ovm_component), when instantiated in VMM environments and/or components, have
// their phase methods called at the correct time relative to the execution of
// the top-level VMM environment phase methods.
//
// With VMM_OVM_INTEROP defined, OVM phasing is controlled by the ~avt_vmm_ovm_env~
// as follows:
//
//|             VMM                 OVM
//|             |                    
//|           gen_cfg                
//|             |                    
//|            build________________build
//|                   ovm_build       |
//|                                 connect
//|              _____________________/     
//|             |                      
//|             |_____________end_of_elaboration
//|                                   |
//|                           start_of_simulation
//|              _____________________/     
//|             |          
//|             |            
//|             |\__FORK run phase__ 
//|             |                    \
//|           reset_dut              run
//|             |                     |
//|           cfg_dut                 | 
//|             |                     |
//|           start                   |
//|             |                     |
//|        wait_for_end               |
//|             |                     |
//|             |_ stop  --> FORK     |
//|             | request        \    |
//|             |               stop  |
//|             |                 |   |    
//|             |                 |-->X    
//|             |__ WAIT -------> *
//|                 for run
//|              ___/  complete
//|           stop                   
//|             |                    
//|          cleanup                 
//|             |                    
//|             |
//|           report
//|             |___________________extract
//|                 ovm_report        |
//|                                  check
//|                                   |
//|                                 report 
//|                                   |
//|                                 <user>
//|                                   |
//|              _____________________*
//|             |
//|        <final report>
//|             |
//|             *
//
//------------------------------------------------------------------------------

`ifdef VMM_ON_TOP

// Replace the OVM message server with one that re-routes
// OVM messages to a vmm_log instance.

function bit avt_override_ovm_report_server();
  avt_vmm_ovm_report_server svr;
  ovm_report_global_server glob;
  svr = avt_vmm_ovm_report_server::get();
  glob = new();
  glob.set_server(svr);
  return 1;
endfunction

bit _avt_ovm_server = avt_override_ovm_report_server();

`endif

//------------------------------------------------------------------------------
//
// CLASS: avt_vmm_ovm_env
//
// This class is used to automatically integrate OVM phasing with VMM phasing
// in a VMM-on-top environment.
//------------------------------------------------------------------------------

class avt_vmm_ovm_env extends `AVT_VMM_OVM_ENV_BASE;

   bit disable_ovm = 0;
   protected int build_level;

   // Function: new
   // 
   // Creates a new instance of an ~avt_vmm_ovm_env~.

   function new(string name = "Verif Env"
                `VMM_ENV_BASE_NEW_EXTERN_ARGS);
     super.new(name
     `ifdef VMM_ENV_BASE_NEW_CALL
      `VMM_ENV_BASE_NEW_CALL
     `endif
     );

   endfunction


   // Function: ovm_build
   // 
   // Calls into the OVM's phasing mechanism to complete OVM's
   // ~build~, ~connect~, and any other user-defined phases
   // up to ~end_of_elaboration~.

   virtual function void ovm_build();
     if (disable_ovm)
       return;
     if (--build_level <= 0)
       ovm_top.run_global_func_phase(configure_ph,1);
   endfunction


   // Function: ovm_report
   // 
   // Calls into the OVM's phasing mechanism to complete OVM's
   // ~extract~, ~check~, and ~report~ phases.

   virtual task ovm_report();
     if (!disable_ovm) begin
       repeat(2) #0;
       ovm_top.run_global_phase(report_ph);
     end
   endtask


   // Task: reset_dut
   //
   // Syncs the start of VMM reset_dut with the start of OVM run phase,
   // then forks OVM run phase to run in parallel with reset_dut,
   // config_dut, start, and wait_for_end.

   virtual task reset_dut();
      if (this.step < BUILD)
        this.build();
      if (!disable_ovm) begin
        if (!connect_ph.is_done()) begin
         `vmm_fatal(this.log, {"The build() method did not call ",
                    "avt_vmm_ovm_env::ovm_build() before returning"});
        end
        ovm_top.run_global_phase(run_ph,1);
        fork
	   ovm_top.run_global_phase(run_ph);
        join_none
      end
      super.reset_dut();
   endtask


   // Function: stop
   // 
   // Requests the OVM run phase to stop if it is still running,
   // then waits for the OVM run phase to finish.

   virtual task stop();
      super.stop();
      if (!disable_ovm) begin
        if (!run_ph.is_done()) begin
           repeat (2) #0;
           ovm_top.global_stop_request();
           run_ph.wait_done();
        end
      end
   endtask


   // Task: report
   //
   // Calls into the OVM's phasing mechanism to execute user-defined
   // OVM phases inserted after ~report_ph~, if any.

   virtual task report();
      if (!disable_ovm) begin
        repeat (2) #0;
        ovm_top.run_global_phase();
      end
      super.report();
   endtask

endclass


// MACRO: `ovm_build
//
// Overrides the avt_vmm_ovm_env's <ovm_build> method such that the
// call to advance OVM phasing up to ~end_of_elaboration~ is
// performed only once in the most derived env-subtype of a
// a potentially deep vmm_env-inheritance hierarchy.

`define ovm_build \
   local int _ovm_build_level = ++build_level; \
   virtual function void ovm_build(); \
     if (disable_ovm) \
       return; \
     if (--build_level <= 0) \
       ovm_top.run_global_func_phase(configure_ph,1); \
   endfunction





