ovm_root.svh

Go to the documentation of this file.
00001 // $Id: a00270.html,v 1.1 2009/01/07 19:30:03 alex.marin Exp $
00002 //------------------------------------------------------------------------------
00003 //   Copyright 2007-2008 Mentor Graphics Corporation
00004 //   Copyright 2007-2008 Cadence Design Systems, Inc.
00005 //   All Rights Reserved Worldwide
00006 //
00007 //   Licensed under the Apache License, Version 2.0 (the
00008 //   "License"); you may not use this file except in
00009 //   compliance with the License.  You may obtain a copy of
00010 //   the License at
00011 //
00012 //       http://www.apache.org/licenses/LICENSE-2.0
00013 //
00014 //   Unless required by applicable law or agreed to in
00015 //   writing, software distributed under the License is
00016 //   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
00017 //   CONDITIONS OF ANY KIND, either express or implied.  See
00018 //   the License for the specific language governing
00019 //   permissions and limitations under the License.
00020 //------------------------------------------------------------------------------
00021 
00022 `ifndef OVM_ROOT_SVH
00023 `define OVM_ROOT_SVH
00024 
00025 `define OVM_DEFAULT_TIMEOUT 9200s
00026 
00027 //------------------------------------------------------------------------------
00028 //
00029 // CLASS: ovm_root (phase controller)
00030 //
00031 //------------------------------------------------------------------------------
00032 // The OVM environment contains a single instance of ovm_root, called ovm_top.
00033 // The ovm_top serves as THE top-level component for all components. A component
00034 // becomes a child of ovm_top when its 'parent' constructor argument is null.
00035 //
00036 // run_test
00037 //   Phases all components through all registered phases. If the optional
00038 //   test_name argument is provided, or if a command-line plusarg, +OVM_TESTNAME,
00039 //   is found, the specified test is created prior to phasing. The test may
00040 //   contain new verification components or the entire testbench, in which case
00041 //   the test and testbench can be chosen from the command line without forcing
00042 //   recompilation. If the global (package) variable, finish_on_completion, is
00043 //   set, $finish is called after phasing completes.
00044 //   
00045 // insert_phase
00046 //   This method is used to register phases with ovm_root. The new phase (1st
00047 //   argument) is inserted _after_ the phase given by the 2nd argument. If the
00048 //   2nd argument is null, the new phase becomes the first phase.
00049 //
00050 // run_global_phase
00051 //   Note: all phasing should be started via run_test. This method is used to
00052 //   run up to and through the phase given by the 1st argument. If null, then
00053 //   all remaining phases will be run, effectively completing simulation.
00054 // 
00055 // stop_request
00056 //   Calling this function triggers the process of shutting down the currently
00057 //   running task-based phase.  This process involves calling all components'
00058 //   stop tasks for those components whose enable_stop_interrupt bit is set.
00059 //   Once all stop tasks return, or once the optional global_stop_timeout
00060 //   expires, all components' kill method is called, effectively ending the
00061 //   current phase. The ovm_top will then begin execution of the next phase,
00062 //   if any.
00063 //
00064 // find / find_all
00065 //    Returns the component handle (find) or list of components handles (find_all)
00066 //    matching a given string. The string may contain the wildcards, * and ?.
00067 //    Strings beginning with '.' are absolute path names. If optional comp arg
00068 //    provided, search begins from that component down (default=all components).
00069 //
00070 // time phase_timeout / stop_timeout
00071 //    These set watchdog timers for task-based phases and stop tasks. Their
00072 //    default value is set to the maximum time. A timeout at this value usually
00073 //    indicates a problem with your testbench. You should lower the timeout to
00074 //    prevent "never-ending" simulations. Setting the value to 0 turns off the
00075 //    timer.
00076 //
00077 // enable_print_topology
00078 //    If set, the topology is printed just after the end_of_elaboration phase.
00079 //
00080 // finish_on_completion
00081 //    If set, run_test will issue a $finish after all phases are executed.
00082 //------------------------------------------------------------------------------
00083 
00084 
00085 class ovm_root extends ovm_component;
00086 
00087   extern static function ovm_root get();
00088 
00089   extern virtual task   run_test         (string test_name="");
00090 
00091   extern task           run_global_phase (ovm_phase phase=null);      
00092 
00093   extern function void  stop_request     ();
00094 
00095   extern function void  insert_phase     (ovm_phase new_phase,
00096                                           ovm_phase exist_phase);
00097   extern function
00098           ovm_component find             (string comp_match);
00099   extern function void  find_all         (string comp_match,
00100                                           ref ovm_component comps[$],
00101                                           input ovm_component comp=null);
00102 
00103   extern function ovm_phase get_current_phase ();
00104   extern function ovm_phase get_phase_by_name (string name);
00105 
00106   virtual function string get_type_name(); return "ovm_root"; endfunction
00107 
00108   time phase_timeout = 0;
00109   time stop_timeout  = 0;
00110   bit  enable_print_topology = 0;
00111   bit  finish_on_completion  = 1;
00112 
00113 
00114   // PRIVATE members
00115 
00116   extern `_protected function new ();
00117 
00118   extern function void check_verbosity();
00119 
00120   extern local task m_do_phase_all (ovm_component comp, ovm_phase phase);
00121   extern local task m_stop_process ();
00122   extern local task m_stop_request (time timeout=0);
00123   extern local task m_do_stop_all  (ovm_component comp);
00124   extern local function void m_reset_phase(ovm_component comp,
00125                                            ovm_phase phase=null);
00126   extern local function ovm_phase m_get_phase_master(ovm_phase phase, bit set=0);
00127 
00128   local  ovm_phase  m_phase_master[ovm_phase];
00129   local  ovm_phase  m_phase_q[ovm_phase];
00130   local  ovm_phase  m_first_phase = null;
00131   local  ovm_phase  m_last_phase = null;
00132   local  event      m_stop_request_e;
00133 
00134   ovm_phase m_curr_phase = null;
00135   static local ovm_root m_inst;
00136 
00137   /*** DEPRECATED - Do not use in new code.  Convert code when appropriate ***/
00138   extern function void print_unit_list (ovm_component comp=null);
00139   extern function void print_unit      (string name, ovm_printer printer=null);
00140   extern function void print_units     (ovm_printer printer=null);
00141   extern function void print_topology  (ovm_printer printer=null);
00142 
00143 endclass
00144 
00145 class ovm_root_report_handler extends ovm_report_handler;
00146 
00147   virtual function void report(
00148       ovm_severity severity,
00149       string name,
00150       string id,
00151       string message,
00152       int verbosity_level,
00153       string filename,
00154       int line,
00155       ovm_report_object client
00156       );
00157 
00158     if(name == "")
00159       name = "reporter";
00160 
00161     super.report(severity, name, id, message, verbosity_level, filename, line, client);
00162 
00163   endfunction 
00164 
00165 endclass
00166 
00167 //------------------------------------------------------------------------------
00168 // 
00169 // Class: ovm_*_phase (predefined phases)
00170 //
00171 //------------------------------------------------------------------------------
00172 
00173 `ovm_phase_func_decl(build,1)
00174 `ovm_phase_func_decl(connect,0)
00175 `ovm_phase_func_decl(end_of_elaboration,0)
00176 `ovm_phase_func_decl(start_of_simulation,0)
00177 `ovm_phase_task_decl(run,0)
00178 `ovm_phase_func_decl(extract,0)
00179 `ovm_phase_func_decl(check,0)
00180 `ovm_phase_func_decl(report,0)
00181 
00182 build_phase               #(ovm_component) build_ph;
00183 connect_phase             #(ovm_component) connect_ph;
00184 end_of_elaboration_phase  #(ovm_component) end_of_elaboration_ph;
00185 start_of_simulation_phase #(ovm_component) start_of_simulation_ph;
00186 run_phase                 #(ovm_component) run_ph;
00187 extract_phase             #(ovm_component) extract_ph;
00188 check_phase               #(ovm_component) check_ph;
00189 report_phase              #(ovm_component) report_ph;
00190 
00191 // DEPRECATED PHASES - DO NOT USE IN NEW CODE
00192 
00193 `ovm_phase_func_decl(post_new,0)
00194 `ovm_phase_func_decl(export_connections,0)
00195 `ovm_phase_func_decl(import_connections,1)
00196 `ovm_phase_func_decl(pre_run,0)
00197 `ovm_phase_func_decl(configure,0)
00198 post_new_phase            #(ovm_component) post_new_ph;
00199 export_connections_phase  #(ovm_component) export_connections_ph;
00200 import_connections_phase  #(ovm_component) import_connections_ph;
00201 pre_run_phase             #(ovm_component) pre_run_ph;
00202 configure_phase           #(ovm_component) configure_ph;
00203 
00204 
00205 
00206 // ovm_enable_print_topology (global, deprecated)
00207 // -------------------------
00208 
00209 bit ovm_enable_print_topology = 0;
00210 
00211 // our singleton top-level; it is initialized upon first call to ovm_root::get
00212 
00213 `const ovm_root ovm_top = ovm_root::get();
00214 `const ovm_root _global_reporter = ovm_root::get();
00215 
00216 
00217 // run_test
00218 // --------
00219 
00220 task run_test (string name="");
00221   ovm_root top;
00222   top = ovm_root::get();
00223   top.run_test(name);
00224 endtask
00225 
00226 
00227 // global_stop_request 
00228 // -------------------
00229 
00230 function void global_stop_request();
00231   ovm_root top;
00232   top = ovm_root::get();
00233   top.stop_request();
00234 endfunction
00235 
00236 
00237 // set_global_timeout 
00238 // ------------------
00239 
00240 function void set_global_timeout(time timeout);
00241   ovm_root top;
00242   top = ovm_root::get();
00243   top.phase_timeout = timeout;
00244 endfunction
00245 
00246 
00247 // set_global_stop_timeout
00248 // -----------------------
00249 
00250 function void set_global_stop_timeout(time timeout);
00251   ovm_root top;
00252   top = ovm_root::get();
00253   top.stop_timeout = timeout;
00254 endfunction
00255 
00256 
00257 // ovm_find_component (deprecated)
00258 // ------------------
00259 
00260 function ovm_component ovm_find_component (string comp_name);
00261   ovm_root top;
00262   static bit issued=0;
00263   if (!issued) begin
00264     issued=1;
00265     ovm_report_warning("deprecated",
00266       {"ovm_find_component() is deprecated and replaced by ",
00267       "ovm_top.find(comp_name)"});
00268   end
00269   top = ovm_root::get();
00270   return top.find(comp_name);
00271 endfunction
00272 
00273   
00274 // ovm_print_topology (deprecated)
00275 // ------------------
00276 
00277 function void ovm_print_topology(ovm_printer printer=null);
00278   static bit issued=0;
00279   if (!issued) begin
00280     issued=1;
00281     ovm_report_warning("deprecated",
00282       {"ovm_print_topology() is deprecated and replaced by ",
00283       "ovm_top.print_topology()"});
00284   end
00285   ovm_top.print_topology(printer);
00286 endfunction
00287 
00288 
00289 
00290 //-----------------------------------------------------------------------------
00291 //
00292 // IMPLEMENTATION
00293 //
00294 //-----------------------------------------------------------------------------
00295 
00296 
00297 // get
00298 // ---
00299 
00300 function ovm_root ovm_root::get();
00301   if (m_inst == null)
00302     m_inst = new();
00303   return m_inst;
00304 endfunction
00305 
00306 
00307 // new
00308 // ---
00309 
00310 function ovm_root::new();
00311 
00312   ovm_root_report_handler rh;
00313 
00314   super.new("__top__", null);
00315 
00316   rh = new;
00317   set_report_handler(rh);
00318 
00319   check_verbosity();
00320 
00321   report_header();
00322   print_enabled=0;
00323   build_ph = new;
00324   post_new_ph = new;
00325   export_connections_ph = new;
00326   connect_ph = new;
00327   import_connections_ph = new;
00328   configure_ph = new;
00329   end_of_elaboration_ph = new;
00330   start_of_simulation_ph = new;
00331   pre_run_ph = new;
00332   run_ph = new;
00333   extract_ph = new;
00334   check_ph = new;
00335   report_ph = new;
00336   insert_phase(build_ph,              null);
00337   insert_phase(post_new_ph,           build_ph);
00338   insert_phase(export_connections_ph, post_new_ph);
00339   insert_phase(connect_ph,            export_connections_ph);
00340   insert_phase(import_connections_ph, connect_ph);
00341   insert_phase(configure_ph,          import_connections_ph);
00342   insert_phase(end_of_elaboration_ph, configure_ph);
00343   insert_phase(start_of_simulation_ph,end_of_elaboration_ph);
00344   insert_phase(pre_run_ph,            start_of_simulation_ph);
00345   insert_phase(run_ph,                pre_run_ph);
00346   insert_phase(extract_ph,            run_ph);
00347   insert_phase(check_ph,              extract_ph);
00348   insert_phase(report_ph,             check_ph);
00349 endfunction
00350 
00351 
00352 // check_verbosity
00353 // ---------------
00354 
00355 function void ovm_root::check_verbosity();
00356 
00357   string s;
00358   int plusarg;
00359   string msg;
00360   int verbosity= OVM_MEDIUM;
00361 
00362   case(1)
00363     $value$plusargs("OVM_VERBOSITY=%s", s) > 0 : plusarg = 1;
00364     $value$plusargs("ovm_verbosity=%s", s) > 0 : plusarg = 1;
00365     $value$plusargs("VERBOSITY=%s", s)     > 0 : plusarg = 1;
00366     $value$plusargs("verbosity=%s", s)     > 0 : plusarg = 1;
00367     default                                    : plusarg = 0;
00368   endcase
00369 
00370   if(plusarg == 1) begin
00371     case(s.toupper())
00372       "OVM_NONE"    : verbosity = OVM_NONE;
00373       "NONE"        : verbosity = OVM_NONE;
00374       "OVM_LOW"     : verbosity = OVM_LOW;
00375       "LOW"         : verbosity = OVM_LOW;
00376       "LO"          : verbosity = OVM_LOW;
00377       "OVM_MEDIUM"  : verbosity = OVM_MEDIUM;
00378       "OVM_MED"     : verbosity = OVM_MEDIUM;
00379       "MEDIUM"      : verbosity = OVM_MEDIUM;
00380       "MED"         : verbosity = OVM_MEDIUM;
00381       "OVM_HIGH"    : verbosity = OVM_HIGH;
00382       "OVM_HI"      : verbosity = OVM_HIGH;
00383       "HIGH"        : verbosity = OVM_HIGH;
00384       "HI"          : verbosity = OVM_HIGH;
00385       "OVM_FULL"    : verbosity = OVM_FULL;
00386       "FULL"        : verbosity = OVM_FULL;
00387       "OVM_DEBUG"   : verbosity = OVM_DEBUG;
00388       "DEBUG"       : verbosity = OVM_DEBUG;
00389       default       : begin
00390                         verbosity = s.atoi();
00391                         if(verbosity == 0) begin
00392                           verbosity = OVM_MEDIUM;
00393                           $sformat(msg, "illegal verbosity value, using default of %0d",
00394                                    OVM_MEDIUM);
00395                          ovm_report_warning("verbosity", msg);
00396                       end
00397                 end
00398     endcase
00399   end
00400 
00401   set_report_verbosity_level_hier(verbosity);
00402 
00403 endfunction
00404 
00405 
00406 //------------------------------------------------------------------------------
00407 // Primary Simulation Entry Points
00408 //------------------------------------------------------------------------------
00409 
00410 ovm_component ovm_test_top; // deprecated; do not use
00411 
00412 // run_test
00413 // --------
00414 
00415 task ovm_root::run_test(string test_name="");
00416 
00417   ovm_factory factory = ovm_factory::get();
00418   bit testname_plusarg;
00419   string msg;
00420 
00421   testname_plusarg = 0;
00422 
00423   // plusarg overrides argument
00424   if ($value$plusargs("OVM_TESTNAME=%s", test_name))
00425     testname_plusarg = 1;
00426 
00427   if ($value$plusargs("TESTNAME=%s", test_name)) begin
00428     ovm_report_warning("DPRFT",
00429           "+TESTNAME is deprecated. Use +OVM_TESTNAME instead.");
00430     testname_plusarg = 1;
00431   end
00432 
00433   // if test now defined, create it using common factory
00434   if (test_name != "") begin
00435     if(m_children.exists("ovm_test_top")) begin
00436       ovm_report_fatal("TTINST",
00437           "An ovm_test_top already exists via a previous call to run_test");
00438       #0; // forces shutdown because $finish is forked
00439     end
00440     $cast(ovm_test_top, factory.create_component_by_name(test_name,
00441           "ovm_test_top", "ovm_test_top", null));
00442 
00443     assert_test_not_found : assert(ovm_test_top != null) else begin
00444       msg = testname_plusarg ? "command line (+OVM_TESTNAME=": "call to run_test(";
00445       ovm_report_fatal("INVTST",
00446           {"Requested test from ",msg, test_name, ") not found." });
00447       $fatal;     
00448     end
00449   end
00450 
00451   if (m_children.num() == 0) begin
00452     ovm_report_fatal("NOCOMP",
00453           {"No components instantiated. You must instantiate",
00454            " at least one component before calling run_test. To run",
00455            " a test, use +OVM_TESTNAME or supply the test name in",
00456            " the argument to run_test(). Exiting simulation."});
00457     return;
00458   end
00459 
00460   ovm_report_info("RNTST", {"Running test ",test_name, "..."}, OVM_LOW);
00461 
00462   fork 
00463     // isolated from calling process
00464     run_global_phase();
00465   join
00466 
00467   report_summarize();
00468 
00469   if (finish_on_completion) begin
00470     // forking allows current delta to complete
00471     fork
00472       $finish;
00473     join_none
00474   end
00475 
00476 endtask
00477 
00478 
00479 // m_reset_phase
00480 // -------------
00481 
00482 function void ovm_root::m_reset_phase(ovm_component comp, ovm_phase phase=null);
00483   string name;
00484 
00485   if (comp.get_first_child(name))
00486     do
00487       this.m_reset_phase(comp.get_child(name));
00488     while (comp.get_next_child(name));
00489 
00490   comp.m_curr_phase=phase;
00491 
00492 endfunction
00493 
00494 
00495 // m_get_phase_master
00496 // ------------------
00497 
00498 function ovm_phase ovm_root::m_get_phase_master(ovm_phase phase, bit set=0);
00499   // Returns the master phase if one hase been initialized. Otherwise, finds
00500   // a master by name. If none is found then the master is initialized
00501   // to itself.
00502   if(phase == null) return phase;
00503   if(m_phase_master.exists(phase)) return m_phase_master[phase];
00504   foreach(m_phase_master[i])
00505     if(m_phase_master[i].get_name() == phase.get_name()) begin
00506       if(set == 1) m_phase_master[phase] = m_phase_master[i];
00507       return m_phase_master[i];
00508     end
00509 
00510   if(set == 1) m_phase_master[phase] = phase;
00511   return phase;
00512 endfunction
00513 
00514 
00515 //------------------------------------------------------------------------------
00516 // Phase control
00517 //------------------------------------------------------------------------------
00518 
00519 // run_global_phase
00520 // ----------------
00521 
00522 task ovm_root::run_global_phase(ovm_phase phase=null);
00523 
00524   time timeout;
00525   bit run_all_phases;
00526 
00527   //Get the master phase in case the input phase is an alias.
00528   phase = m_get_phase_master(phase);
00529 
00530   if (phase != null) begin
00531     if (!m_phase_q.exists(phase)) begin
00532       ovm_report_fatal("PHNTFD", {"Phase %0s not registered.",phase.get_name()}); 
00533       return;
00534     end
00535   end
00536   else begin
00537     run_all_phases = 1;
00538     phase = m_last_phase;
00539   end
00540 
00541 
00542   // MAIN LOOP: Executes all phases from the current phase
00543   // through the phase given in the argument. If 'phase' is null,
00544   // will run through all phases, even those that may have been added in
00545   // phases that have yet to run.
00546 
00547   while (m_curr_phase != phase) begin
00548 
00549     if (m_curr_phase == null)
00550       m_curr_phase = m_first_phase;
00551     else
00552       m_curr_phase = m_phase_q[m_curr_phase];
00553 
00554     // Trigger phase's in_progress event.
00555     // The #0 allows any waiting processes to resume before we continue.
00556     m_curr_phase.m_set_in_progress();
00557     #0;
00558 
00559     ovm_report_info("STARTPH",
00560       $psprintf("STARTING PHASE %0s",m_curr_phase.get_name()),int'(OVM_FULL)+1);
00561 
00562     // TASK-based phase
00563     if (m_curr_phase.is_task()) begin
00564 
00565       timeout = (phase_timeout==0) ?  `OVM_DEFAULT_TIMEOUT - $time :
00566                                       phase_timeout;
00567 
00568       `ifdef INCA
00569 
00570         // IUS does not support disabling named fork blocks, so we isolate the
00571         // inner fork block so we can kill it using disable fork
00572         fork // guard process
00573         begin
00574 
00575         fork
00576 
00577           // Start an independent process that kills the phase, else the killing
00578           // stops prematurely at the component that issued the request.
00579           m_stop_process();
00580 
00581           begin // guard process
00582             fork
00583               begin
00584                 #0; // ensures stop_process active before potential stop_request
00585                 m_do_phase_all(this,m_curr_phase);
00586                 wait fork;
00587               end
00588               begin
00589                 #timeout ovm_report_error("TIMOUT",
00590                       $psprintf("Watchdog timeout of '%0t' expired.", timeout));
00591               end
00592             join_any
00593             disable fork;
00594           end // end guard process
00595 
00596         join_any
00597         disable fork;
00598 
00599         end
00600         join // end guard process
00601 
00602       `else // QUESTA
00603 
00604         fork : task_based_phase
00605           m_stop_process();
00606           begin
00607             m_do_phase_all(this,m_curr_phase);
00608             wait fork;
00609           end
00610           #timeout ovm_report_error("TIMOUT",
00611                 $psprintf("Watchdog timeout of '%0t' expired.", timeout));
00612         join_any
00613         disable task_based_phase;
00614 
00615       `endif // INCA-QUESTA
00616 
00617     end // if (is_task)
00618 
00619     // FUNCTION-based phase
00620     else begin
00621       m_do_phase_all(this,m_curr_phase);
00622     end
00623 
00624     ovm_report_info("ENDPH",
00625       $psprintf("ENDING PHASE %0s",m_curr_phase.get_name()),int'(OVM_FULL)+1);
00626 
00627     // Trigger phase's done event.
00628     // The #0 allows any waiting processes to resume before we continue.
00629     m_curr_phase.m_set_done();
00630     #0;
00631 
00632     // If error occurred during elaboration, exit with FATAL.
00633     if (m_curr_phase == end_of_elaboration_ph) begin
00634       ovm_report_server srvr;
00635       srvr = get_report_server();
00636       if(srvr.get_severity_count(OVM_ERROR) > 0) begin
00637         ovm_report_fatal("ovm", "elaboration errors");
00638         #0; // $finish is called in a forked process in ovm_report_object::die.
00639             // this forces that process to start, preventing us from continuing
00640       end
00641 
00642       if (enable_print_topology || ovm_enable_print_topology)
00643         print_topology();
00644     end
00645 
00646     // if next phase is end_of_elab, the resolve all connections
00647     if (m_phase_q[m_curr_phase] == end_of_elaboration_ph)
00648       do_resolve_bindings();
00649 
00650     if (run_all_phases)
00651       phase = m_last_phase;
00652 
00653   end
00654 
00655 endtask
00656 
00657 
00658 // m_do_phase_all
00659 // --------------
00660 
00661 task ovm_root::m_do_phase_all (ovm_component comp, ovm_phase phase);
00662 
00663   // run_global_phase calls this private task for each phase in consecutive
00664   // order.  If the phase is a function, then all components' functions are
00665   // called sequentially in top-down or bottom-up order. If the phase is a
00666   // task, all components' do_task_phase tasks are forked and we return
00667   // with no waiting. The caller can subsequently call 'wait fork' to wait
00668   // for the forked tasks to complete.
00669 
00670   ovm_phase curr_phase;
00671   bit done[string];
00672 
00673   phase = m_get_phase_master(phase);
00674   curr_phase = comp.m_curr_phase;
00675 
00676   // This while loop is needed in case new componenents are created
00677   // several phases into a simulation.
00678 
00679   while (curr_phase != phase) begin
00680 
00681     ovm_phase ph;
00682     done.delete();
00683 
00684     if (curr_phase == null)
00685       curr_phase = m_first_phase;
00686     else
00687       curr_phase = m_phase_q[curr_phase];
00688 
00689     // bottom-up
00690     if (!curr_phase.is_top_down()) begin
00691       string name;
00692       if (comp.get_first_child(name)) begin
00693         do begin
00694           m_do_phase_all(comp.get_child(name),curr_phase);
00695           done[name] = 1;
00696         end
00697         while (comp.get_next_child(name));
00698       end
00699     end
00700 
00701     ovm_report_info("COMPPH", $psprintf("*** comp %0s (%0s) curr_phase is %0s",
00702       comp.get_full_name(),comp.get_type_name(),curr_phase.get_name()),int'(OVM_FULL)+1);
00703 
00704     if (curr_phase.is_task()) begin
00705       // We fork here to ensure that do_task_phase, a user-overridable task,
00706       // does not inadvertently block this process
00707       fork
00708         comp.do_task_phase(curr_phase);
00709       join_none
00710     end
00711     else
00712       comp.do_func_phase(curr_phase);
00713 
00714     // bottom-up 2nd pass: phase newly created components, if any
00715     if (!curr_phase.is_top_down()) begin
00716 
00717       while (comp.get_num_children() != done.num()) begin
00718         string name;
00719         if (comp.get_first_child(name)) begin
00720           do begin
00721             if (!done.exists(name)) begin
00722               m_do_phase_all(comp.get_child(name),curr_phase);
00723               done[name] = 1;
00724             end
00725           end
00726           while (comp.get_next_child(name));
00727         end
00728       end
00729     end
00730 
00731     // top-down
00732     else begin
00733       string name;
00734       if (comp.get_first_child(name))
00735         do begin
00736           m_do_phase_all(comp.get_child(name),curr_phase);
00737         end
00738         while (comp.get_next_child(name));
00739     end
00740 
00741   end
00742 endtask
00743 
00744 
00745 // get_current_phase
00746 // -----------------
00747 
00748 function ovm_phase ovm_root::get_current_phase();
00749   return m_curr_phase;
00750 endfunction
00751 
00752 
00753 //------------------------------------------------------------------------------
00754 // Stopping
00755 //------------------------------------------------------------------------------
00756 
00757 // stop_request
00758 // ------------
00759 
00760 function void ovm_root::stop_request();
00761   ->m_stop_request_e;
00762 endfunction
00763 
00764 
00765 // m_stop_process
00766 // --------------
00767 
00768 task ovm_root::m_stop_process();
00769   @m_stop_request_e;
00770   m_stop_request(stop_timeout);
00771 endtask
00772 
00773 
00774 // m_stop_request
00775 // --------------
00776 
00777 task ovm_root::m_stop_request(time timeout=0);
00778 
00779   if (timeout == 0)
00780     timeout = `OVM_DEFAULT_TIMEOUT - $time;
00781 
00782   // stop request valid for running task-based phases only
00783   if (m_curr_phase == null || !m_curr_phase.is_task()) begin
00784     ovm_report_warning("STPNA",
00785       $psprintf("Stop-request has no effect outside non-time-consuming phases",
00786                 "current phase is ",m_curr_phase==null?
00787                 "none (not started":m_curr_phase.get_name()));
00788     return;
00789   end
00790 
00791   // All stop tasks are forked from a single thread so 'wait fork'
00792   // can be used. We fork the single thread as well so that 'wait fork'
00793   // does not wait for threads previously started by the caller's thread.
00794 
00795   // IUS does not support disabling named fork blocks, so we isolate the
00796   // inner fork block so we can kill it using disable fork
00797   `ifdef INCA
00798 
00799   fork begin // guard process
00800     fork
00801       begin
00802         m_do_stop_all(this);
00803         wait fork;
00804       end
00805       begin
00806         #timeout ovm_report_warning("STPTO",
00807          $psprintf("Stop-request timeout of %0t expired. Stopping phase '%0s'",
00808                            timeout, m_curr_phase.get_name()));
00809       end
00810     join_any
00811     disable fork;
00812   end
00813   join
00814 
00815   `else // QUESTA
00816 
00817   fork : stop_tasks
00818     begin
00819       m_do_stop_all(this);
00820       wait fork;
00821     end
00822     begin
00823       #timeout ovm_report_warning("STPTO",
00824        $psprintf("Stop-request timeout of %0t expired. Stopping phase '%0s'",
00825                          timeout, m_curr_phase.get_name()));
00826     end
00827   join_any
00828   disable stop_tasks;
00829 
00830   `endif // INCA
00831 
00832   // all stop processes have completed, or a timeout has occured
00833   this.do_kill_all();
00834 
00835 endtask
00836 
00837 
00838 // m_do_stop_all
00839 // -------------
00840 
00841 task ovm_root::m_do_stop_all(ovm_component comp);
00842 
00843   string name;
00844 
00845   // we use an external traversal to ensure all forks are 
00846   // made from a single threaad.
00847   if (comp.get_first_child(name))
00848     do begin
00849       m_do_stop_all(comp.get_child(name));
00850     end
00851     while (comp.get_next_child(name));
00852 
00853   if (comp.enable_stop_interrupt) begin
00854     fork begin
00855       comp.stop(m_curr_phase.get_name());
00856     end
00857     join_none
00858   end
00859 
00860 endtask
00861 
00862 
00863 //------------------------------------------------------------------------------
00864 // Phase Insertion
00865 //------------------------------------------------------------------------------
00866 
00867 // insert_phase
00868 // ------------
00869 
00870 function void ovm_root::insert_phase(ovm_phase new_phase,
00871                                      ovm_phase exist_phase);
00872   ovm_phase exist_ph;
00873   ovm_phase master_ph;
00874   string s;
00875 
00876   // Get the phase object that is in charge of a given named phase. Since we
00877   // are inserting the phase, set the master if not set.
00878   master_ph = m_get_phase_master(new_phase, 1);
00879   exist_phase = m_get_phase_master(exist_phase);
00880 
00881   if (build_ph.is_done()) begin
00882     ovm_report_fatal("PHINST", "Phase insertion after build phase prohibited.");
00883     return;
00884   end
00885 
00886   if (exist_phase != null && exist_phase.is_done() ||
00887       exist_phase == null && m_curr_phase != null) begin 
00888     ovm_report_fatal("PHINST", {"Can not insert a phase at a point that has ",
00889       "already executed. Current phase is '", m_curr_phase.get_name(),"'."});
00890     return;
00891   end
00892 
00893   if (new_phase == null) begin
00894     ovm_report_fatal("PHNULL", "Phase argument is null.");
00895     return;
00896   end
00897 
00898   if (exist_phase != null && !m_phase_q.exists(exist_phase)) begin
00899     //could be an aliased phase. The phase may not exist in the queue, but if
00900     //the name matches one in the queue then it is a possible alias
00901     if(get_phase_by_name(exist_phase.get_name()) == null) begin
00902       ovm_report_fatal("PHNTFD", {"Phase '",exist_phase.get_name(),
00903                       "' is not registered."});
00904       return;
00905     end
00906   end
00907 
00908   // If the new phase being added is an alias object, add the alias and
00909   // return.
00910   if(master_ph != new_phase) begin
00911     master_ph.add_alias(new_phase, exist_phase);
00912     return;
00913   end
00914 
00915   if (m_phase_q.exists(new_phase)) begin
00916     if ((exist_phase == null && m_first_phase != new_phase) ||
00917         (exist_phase != null && m_phase_q[exist_phase] != new_phase)) begin
00918       ovm_report_error("PHDUPL", {"Phase '", new_phase.get_name(),
00919         "' is already registered in a different order."});
00920     end
00921     return;
00922   end
00923 
00924   new_phase.set_insertion_phase(exist_phase);
00925   if (exist_phase == null) begin
00926     m_phase_q[new_phase] = m_first_phase;
00927     m_first_phase = new_phase;
00928   end
00929   else begin
00930     m_phase_q[new_phase] = m_phase_q[exist_phase];
00931     m_phase_q[exist_phase] = new_phase;
00932   end
00933 
00934   if (m_phase_q[new_phase] == null)
00935     m_last_phase = new_phase;
00936 
00937 endfunction
00938 
00939 
00940 // get_phase_by_name
00941 // -----------------
00942 
00943 function ovm_phase ovm_root::get_phase_by_name (string name);
00944   ovm_phase m_ph;
00945   foreach (m_phase_q[ph]) begin
00946     m_ph = ph;
00947     if(m_ph.get_name() == name) 
00948       return ph;
00949   end
00950   return null;
00951 endfunction
00952 
00953 
00954 //------------------------------------------------------------------------------
00955 // Component Search & Printing
00956 //------------------------------------------------------------------------------
00957 
00958 
00959 // find_all
00960 // --------
00961 
00962 function void ovm_root::find_all(string comp_match, ref ovm_component comps[$],
00963                                  input ovm_component comp=null); 
00964   string name;
00965   `ifdef INCA
00966   static ovm_component tmp[$]; //static list to work around ius 6.2 limitation
00967   static bit s_is_child;  //starts at 0 for the root call
00968          bit is_child;    //automatic variable gets updated immediately on entry
00969   is_child = s_is_child;
00970   `endif
00971 
00972   if (comp==null)
00973     comp = this;
00974 
00975   if (comp.get_first_child(name))
00976     do begin
00977       `ifdef INCA
00978         //Indicate that a recursive call is being made. Using a static variable
00979         //since this is a temp workaround and we don't want to effect the
00980         //function prototype.
00981         s_is_child = 1;
00982         this.find_all(comp_match,tmp,comp.get_child(name));
00983         s_is_child = 0;  //reset for a future call.
00984         //Only copy to the component list if this is the top of the stack,
00985         //otherwise an infinite loop will result copying tmp to itself.
00986         if(is_child==0)
00987           while(tmp.size()) comps.push_back(tmp.pop_front());
00988       `else
00989         this.find_all(comp_match,comps,comp.get_child(name));
00990       `endif
00991     end
00992     while (comp.get_next_child(name));
00993 
00994   if (ovm_is_match(comp_match, comp.get_full_name()) &&
00995        comp.get_name() != "") /* ovm_top */
00996     comps.push_back(comp);
00997 
00998 endfunction
00999 
01000 
01001 // find
01002 // ----
01003 
01004 function ovm_component ovm_root::find (string comp_match);
01005   `ifdef INCA
01006     static ovm_component comp_list[$];
01007     comp_list.delete();
01008   `else
01009     ovm_component comp_list[$];
01010   `endif
01011 
01012   find_all(comp_match,comp_list);
01013 
01014   if (comp_list.size() > 1)
01015     ovm_report_warning("MMATCH",
01016     $psprintf("Found %0d components matching '%s'. Returning first match, %0s.",
01017               comp_list.size(),comp_match,comp_list[0].get_full_name()));
01018 
01019   if (comp_list.size() == 0)
01020     ovm_report_warning("CMPNFD",
01021       {"Component matching '",comp_match,
01022        "' was not found in the list of ovm_components"});
01023   return comp_list[0];
01024 endfunction
01025 
01026 
01027 // print_topology
01028 // --------------
01029 
01030 function void ovm_root::print_topology(ovm_printer printer=null);
01031 
01032   string s;
01033 
01034   ovm_report_info("OVMTOP", "OVM testbench topology:", OVM_LOW);
01035 
01036   if (m_children.num()==0) begin
01037     ovm_report_warning("EMTCOMP", "print_topology - No OVM components to print.");
01038     return;
01039   end
01040 
01041   if (printer==null)
01042     printer = ovm_default_printer;
01043 
01044   if (printer.knobs.sprint)
01045     s = printer.m_string;
01046 
01047   foreach (m_children[c]) begin
01048     if(m_children[c].print_enabled) begin
01049       printer.print_object("", m_children[c]);  
01050       if(printer.knobs.sprint)
01051         s = {s, printer.m_string};
01052     end
01053   end
01054 
01055   printer.m_string = s;
01056 
01057 endfunction
01058 
01059 
01060 //------------------------------------------------------------------------------
01061 //
01062 // REVIEW FOR DEPRECATION OR REMOVAL
01063 //
01064 //------------------------------------------------------------------------------
01065 
01066 // print_unit
01067 // ----------
01068 
01069 function void ovm_root::print_unit (string name, ovm_printer printer=null);
01070 
01071   ovm_component comp;
01072   static bit issued=0;
01073 
01074   if (!issued) begin
01075     issued=1;
01076     ovm_report_warning("deprecated",
01077       {"ovm_root::print_unit() is an internal method that has been deprecated.",
01078       " It is replaced by comp=ovm_top.find(name); comp.print(printer);"});
01079   end
01080   comp = find(name);
01081   if (comp)
01082     comp.print(printer);
01083 endfunction
01084 
01085 
01086 // print_units
01087 // -----------
01088 
01089 function void ovm_root::print_units (ovm_printer printer=null);
01090 
01091   string s;
01092   static bit issued=0;
01093 
01094   if (!issued) begin
01095     issued=1;
01096     ovm_report_warning("deprecated",
01097       {"ovm_root::print_units() is an internal method that ",
01098       "has been deprecated. It can be replaced by ovm_top.print(printer);"});
01099   end
01100 
01101   print_topology(printer);
01102 
01103 endfunction
01104 
01105 
01106 // print_unit_list
01107 // ---------------
01108 
01109 function void ovm_root::print_unit_list(ovm_component comp=null);
01110 
01111   string name;
01112   static bit issued=0;
01113 
01114   if (!issued) begin
01115     issued=1;
01116     ovm_report_warning("deprecated",
01117       {"ovm_root::print_unit_list() is an internal method that ",
01118       "has been deprecated."});
01119   end
01120 
01121   if (comp==null) begin
01122     comp = this;
01123     if (m_children.num()==0) begin
01124       ovm_report_warning("NOUNIT","No OVM components to print. ");
01125       return;
01126     end
01127     $display("List of ovm components");
01128   end
01129   else begin
01130     $display("%s (%s)", comp.get_full_name(), comp.get_type_name());
01131   end
01132 
01133   if (comp.get_first_child(name))
01134     do begin
01135       this.print_unit_list(comp.get_child(name));
01136     end
01137     while (comp.get_next_child(name));
01138 
01139 endfunction
01140 
01141 
01142 `endif //OVM_ROOT_SVH
01143 

Intelligent Design Verification
Intelligent Design Verification
Project: OVM, Revision: 2.0.1
Copyright (c) 2008 Intelligent Design Verification.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included here:
http://www.intelligentdv.com/licenses/fdl.txt
doxygen
Doxygen Version: 1.5.5
Wed Jan 7 19:27:18 2009
Find a documentation bug? Report bugs to: bugs.intelligentdv.com Project: DoxygenFilterSV