ovm_root.svh

Go to the documentation of this file.
00001 // $Id: ovm__root_8svh-source.html,v 1.1 2008/10/07 21:54:19 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 local task m_do_phase_all (ovm_component comp, ovm_phase phase);
00119   extern local task m_stop_process ();
00120   extern local task m_stop_request (time timeout=0);
00121   extern local task m_do_stop_all  (ovm_component comp);
00122   extern local function void m_reset_phase(ovm_component comp,
00123                                            ovm_phase phase=null);
00124 
00125   local  ovm_phase  m_phase_q[ovm_phase];
00126   local  ovm_phase  m_first_phase = null;
00127   local  ovm_phase  m_last_phase = null;
00128   local  event      m_stop_request_e;
00129 
00130   ovm_phase m_curr_phase = null;
00131   static local ovm_root m_inst;
00132 
00133   /*** DEPRECATED - Do not use in new code.  Convert code when appropriate ***/
00134   extern function void print_unit_list (ovm_component comp=null);
00135   extern function void print_unit      (string name, ovm_printer printer=null);
00136   extern function void print_units     (ovm_printer printer=null);
00137   extern function void print_topology  (ovm_printer printer=null);
00138 
00139 endclass
00140 
00141 // ovm_enable_print_topology (global, deprecated)
00142 // -------------------------
00143 
00144 bit ovm_enable_print_topology = 0;
00145 
00146 // our singleton top-level; it is initialized upon first call to ovm_root::get
00147 
00148 `const ovm_root ovm_top = ovm_root::get();
00149 
00150 
00151 // run_test
00152 // --------
00153 
00154 task run_test (string test_name="");
00155   ovm_root top;
00156   top = ovm_root::get();
00157   top.run_test(test_name);
00158 endtask
00159 
00160 
00161 // global_stop_request 
00162 // -------------------
00163 
00164 function void global_stop_request();
00165   ovm_root top;
00166   top = ovm_root::get();
00167   top.stop_request();
00168 endfunction
00169 
00170 
00171 // set_global_timeout 
00172 // ------------------
00173 
00174 function void set_global_timeout(time timeout);
00175   ovm_root top;
00176   top = ovm_root::get();
00177   top.phase_timeout = timeout;
00178 endfunction
00179 
00180 
00181 // set_global_stop_timeout
00182 // -----------------------
00183 
00184 function void set_global_stop_timeout(time timeout);
00185   ovm_root top;
00186   top = ovm_root::get();
00187   top.stop_timeout = timeout;
00188 endfunction
00189 
00190 
00191 // ovm_find_component (deprecated)
00192 // ------------------
00193 
00194 function ovm_component ovm_find_component (string comp_name);
00195   ovm_root top;
00196   top = ovm_root::get();
00197   return top.find(comp_name);
00198 endfunction
00199 
00200   
00201 // ovm_print_topology (deprecated)
00202 // ------------------
00203 
00204 function void ovm_print_topology(ovm_printer printer=null);
00205   ovm_report_handler::ovm_report_deprecated("ovm_print_topology()");
00206   ovm_top.print_topology(printer);
00207 endfunction
00208 
00209 
00210 
00211 //-----------------------------------------------------------------------------
00212 //
00213 // IMPLEMENTATION
00214 //
00215 //-----------------------------------------------------------------------------
00216 
00217 // get
00218 // ---
00219 
00220 function ovm_root ovm_root::get();
00221   if (m_inst == null)
00222     m_inst = new();
00223   return m_inst;
00224 endfunction
00225 
00226 
00227 // new
00228 // ---
00229 
00230 function ovm_root::new();
00231   super.new("__top__", null);
00232   report_header();
00233   print_enabled=0;
00234 endfunction
00235 
00236 
00237 
00238 //------------------------------------------------------------------------------
00239 // Primary Simulation Entry Points
00240 //------------------------------------------------------------------------------
00241 
00242 ovm_component ovm_test_top; // deprecated; do not use
00243 
00244 // run_test
00245 // --------
00246 
00247 task ovm_root::run_test(string test_name="");
00248 
00249   ovm_factory factory = ovm_factory::get();
00250   bit testname_plusarg;
00251   string msg;
00252 
00253   testname_plusarg = 0;
00254 
00255   // plusarg overrides argument
00256   if ($value$plusargs("OVM_TESTNAME=%s", test_name))
00257     testname_plusarg = 1;
00258 
00259   if ($value$plusargs("TESTNAME=%s", test_name)) begin
00260     ovm_report_warning("DPRFT",
00261           "+TESTNAME is deprecated. Use +OVM_TESTNAME instead.");
00262     testname_plusarg = 1;
00263   end
00264 
00265   // if test now defined, create it using common factory
00266   if (test_name != "") begin
00267     if(m_children.exists("ovm_test_top")) begin
00268       ovm_report_fatal("TTINST",
00269           "An ovm_test_top already exists via a previous call to run_test");
00270       #0; // forces shutdown because $finish is forked
00271     end
00272     $cast(ovm_test_top, factory.create_component_by_name(test_name,
00273           "ovm_test_top", "ovm_test_top", null));
00274 
00275     assert_test_not_found : assert(ovm_test_top != null) else begin
00276       msg = testname_plusarg ? "command line (+OVM_TESTNAME=": "call to run_test(";
00277       ovm_report_fatal("INVTST",
00278           {"Requested test from ",msg, test_name, ") not found." });
00279       $fatal;     
00280     end
00281   end
00282 
00283   if (m_children.num() == 0) begin
00284     ovm_report_fatal("NOCOMP",
00285           {"No components instantiated. You must instantiate",
00286            " at least one component before calling run_test. To run",
00287            " a test, use +OVM_TESTNAME or supply the test name in",
00288            " the argument to run_test(). Exiting simulation."});
00289     return;
00290   end
00291 
00292   ovm_report_info("RNTST", {"Running test ",test_name, "..."}, OVM_LOW);
00293 
00294   fork 
00295     // isolated from calling process
00296     run_global_phase();
00297   join
00298 
00299   report_summarize();
00300 
00301   if (finish_on_completion) begin
00302     // forking allows current delta to complete
00303     fork
00304       $finish;
00305     join_none
00306   end
00307 
00308 endtask
00309 
00310 
00311 // m_reset_phase
00312 // -------------
00313 
00314 function void ovm_root::m_reset_phase(ovm_component comp, ovm_phase phase=null);
00315   string name;
00316 
00317   if (comp.get_first_child(name))
00318     do
00319       this.m_reset_phase(comp.get_child(name));
00320     while (comp.get_next_child(name));
00321 
00322   comp.m_curr_phase=phase;
00323 
00324 endfunction
00325 
00326 //------------------------------------------------------------------------------
00327 // Phase control
00328 //------------------------------------------------------------------------------
00329 
00330 // run_global_phase
00331 // ----------------
00332 
00333 task ovm_root::run_global_phase(ovm_phase phase=null);
00334 
00335   time timeout;
00336 
00337   if (m_curr_phase != null) begin
00338     ovm_report_fatal("PHSSTR", "Global phasing has already started."); 
00339     #0; // forces shutdown because $finish is forked
00340     return;     
00341   end
00342 
00343   // If we weren't given a specific phase, run through them all.
00344 
00345   if (phase == null) begin
00346     phase = m_last_phase;
00347   end
00348 
00349   if (!m_phase_q.exists(phase)) begin
00350     ovm_report_fatal("PHNTFD", {"Phase %0s not registered.",phase.get_name()}); 
00351     return;
00352   end
00353 
00354   if (m_curr_phase == phase || phase.is_done()) begin
00355     ovm_report_warning("PHDONE", $psprintf(
00356        "Phase '%0s' already executed. Current phase is '%0s'.",
00357        phase.get_name(), m_curr_phase.get_name()));
00358     return;
00359   end
00360 
00361   // MAIN LOOP: Executes all phases from the current phase
00362   // through the phase given in the argument.
00363   while (m_curr_phase != phase) begin
00364 
00365     if (m_curr_phase == null)
00366       m_curr_phase = m_first_phase;
00367     else
00368       m_curr_phase = m_phase_q[m_curr_phase];
00369 
00370     // Trigger phase's in_progress event.
00371     // The #0 allows any waiting processes to resume before we continue.
00372     m_curr_phase.m_set_in_progress();
00373     #0;
00374 
00375     ovm_report_info("STARTPH",
00376       $psprintf("STARTING PHASE %0s",m_curr_phase.get_name()),int'(OVM_FULL)+1);
00377 
00378     // TASK-based phase
00379     if (m_curr_phase.is_task()) begin
00380 
00381       event wait_forever;
00382 
00383       timeout = (phase_timeout==0) ?  `OVM_DEFAULT_TIMEOUT - $time :
00384                                       phase_timeout;
00385 
00386       `ifdef INCA
00387 
00388         // IUS does not support disabling named fork blocks, so we isolate the
00389         // inner fork block so we can kill it using disable fork
00390         fork // guard process
00391         begin
00392 
00393         fork
00394 
00395           // Start an independent process that kills the phase, else the killing
00396           // stops prematurely at the component that issued the request.
00397           m_stop_process();
00398 
00399           begin // guard process
00400             fork
00401               begin
00402                 #0; // ensures stop_process active before potential stop_request
00403                 m_do_phase_all(this,m_curr_phase);
00404                 @wait_forever; // wait for stop or timeout
00405               end
00406               begin
00407                 #timeout ovm_report_error("TIMOUT",
00408                       $psprintf("Watchdog timeout of '%0t' expired.", timeout));
00409               end
00410             join_any
00411             disable fork;
00412           end // end guard process
00413 
00414         join_any
00415         disable fork;
00416 
00417         end
00418         join // end guard process
00419 
00420       `else // QUESTA
00421 
00422         fork : task_based_phase
00423           m_stop_process();
00424           begin
00425             m_do_phase_all(this,m_curr_phase);
00426             wait fork;
00427           end
00428           #timeout ovm_report_error("TIMOUT",
00429                 $psprintf("Watchdog timeout of '%0x' expired.", timeout));
00430         join_any
00431         disable task_based_phase;
00432 
00433       `endif // INCA-QUESTA
00434 
00435     end // if (is_task)
00436 
00437     // FUNCTION-based phase
00438     else begin
00439       m_do_phase_all(this,m_curr_phase);
00440     end
00441 
00442     ovm_report_info("ENDPH",
00443       $psprintf("ENDING PHASE %0s",m_curr_phase.get_name()),int'(OVM_FULL)+1);
00444 
00445     // Trigger phase's done event.
00446     // The #0 allows any waiting processes to resume before we continue.
00447     m_curr_phase.m_set_done();
00448     #0;
00449 
00450     // If error occurred during elaboration, exit with FATAL.
00451     if (m_curr_phase == end_of_elaboration_ph) begin
00452       ovm_report_server srvr;
00453       srvr = get_report_server();
00454       if(srvr.get_severity_count(OVM_ERROR) > 0) begin
00455         ovm_report_fatal("ovm", "elaboration errors");
00456         #0; // $finish is called in a forked process in ovm_report_object::die.
00457             // this forces that process to start, preventing us from continuing
00458       end
00459 
00460       if (enable_print_topology || ovm_enable_print_topology)
00461         print_topology();
00462     end
00463 
00464     // if next phase is end_of_elab, the resolve all connections
00465     if (m_phase_q[m_curr_phase] == end_of_elaboration_ph)
00466       do_resolve_bindings();
00467 
00468   end
00469 
00470 endtask
00471 
00472 
00473 // m_do_phase_all
00474 // --------------
00475 
00476 task ovm_root::m_do_phase_all (ovm_component comp, ovm_phase phase);
00477 
00478   // run_global_phase calls this private task for each phase in consecutive
00479   // order.  If the phase is a function, then all components' functions are
00480   // called sequentially in top-down or bottom-up order. If the phase is a
00481   // task, all components' do_task_phase tasks are forked and we return
00482   // with no waiting. The caller can subsequently call 'wait fork' to wait
00483   // for the forked tasks to complete.
00484 
00485   ovm_phase curr_phase;
00486   bit done[string];
00487 
00488   curr_phase = comp.m_curr_phase;
00489 
00490   // This while loop is needed in case new componenents are created
00491   // several phases into a simulation.
00492 
00493   while (curr_phase != phase) begin
00494 
00495     ovm_phase ph;
00496     done.delete();
00497 
00498     if (curr_phase == null)
00499       curr_phase = m_first_phase;
00500     else
00501       curr_phase = m_phase_q[curr_phase];
00502 
00503     // bottom-up
00504     if (!curr_phase.is_top_down()) begin
00505       string name;
00506       if (comp.get_first_child(name)) begin
00507         do begin
00508           m_do_phase_all(comp.get_child(name),curr_phase);
00509           done[name] = 1;
00510         end
00511         while (comp.get_next_child(name));
00512       end
00513     end
00514 
00515     ovm_report_info("COMPPH", $psprintf("*** comp %0s (%0s) curr_phase is %0s",
00516       comp.get_full_name(),comp.get_type_name(),curr_phase.get_name()),int'(OVM_FULL)+1);
00517 
00518     if (curr_phase.is_task()) begin
00519       // We fork here to ensure that do_task_phase, a user-overridable task,
00520       // does not inadvertently block this process
00521       fork
00522         comp.do_task_phase(curr_phase);
00523       join_none
00524     end
00525     else
00526       comp.do_func_phase(curr_phase);
00527 
00528     // bottom-up 2nd pass: phase newly created components, if any
00529     if (!curr_phase.is_top_down()) begin
00530 
00531       while (comp.get_num_children() != done.num()) begin
00532         string name;
00533         if (comp.get_first_child(name)) begin
00534           do begin
00535             if (!done.exists(name)) begin
00536               m_do_phase_all(comp.get_child(name),curr_phase);
00537               done[name] = 1;
00538             end
00539           end
00540           while (comp.get_next_child(name));
00541         end
00542       end
00543     end
00544 
00545     // top-down
00546     else begin
00547       string name;
00548       if (comp.get_first_child(name))
00549         do begin
00550           m_do_phase_all(comp.get_child(name),curr_phase);
00551         end
00552         while (comp.get_next_child(name));
00553     end
00554 
00555   end
00556 endtask
00557 
00558 
00559 // get_current_phase
00560 // -----------------
00561 
00562 function ovm_phase ovm_root::get_current_phase();
00563   return m_curr_phase;
00564 endfunction
00565 
00566 
00567 //------------------------------------------------------------------------------
00568 // Stopping
00569 //------------------------------------------------------------------------------
00570 
00571 // stop_request
00572 // ------------
00573 
00574 function void ovm_root::stop_request();
00575   ->m_stop_request_e;
00576 endfunction
00577 
00578 
00579 // m_stop_process
00580 // --------------
00581 
00582 task ovm_root::m_stop_process();
00583   @m_stop_request_e;
00584   m_stop_request(stop_timeout);
00585 endtask
00586 
00587 
00588 // m_stop_request
00589 // --------------
00590 
00591 task ovm_root::m_stop_request(time timeout=0);
00592 
00593   if (timeout == 0)
00594     timeout = `OVM_DEFAULT_TIMEOUT - $time;
00595 
00596   // stop request valid for running task-based phases only
00597   if (m_curr_phase == null || !m_curr_phase.is_task()) begin
00598     ovm_report_warning("STPNA",
00599       $psprintf("Stop-request has no effect outside non-time-consuming phases",
00600                 "current phase is ",m_curr_phase==null?
00601                 "none (not started":m_curr_phase.get_name()));
00602     return;
00603   end
00604 
00605   // All stop tasks are forked from a single thread so 'wait fork'
00606   // can be used. We fork the single thread as well so that 'wait fork'
00607   // does not wait for threads previously started by the caller's thread.
00608 
00609   // IUS does not support disabling named fork blocks, so we isolate the
00610   // inner fork block so we can kill it using disable fork
00611   `ifdef INCA
00612 
00613   fork begin // guard process
00614     fork
00615       begin
00616         m_do_stop_all(this);
00617         wait fork;
00618       end
00619       begin
00620         #timeout ovm_report_warning("STPTO",
00621          $psprintf("Stop-request timeout of %0t expired. Stopping phase '%0s'",
00622                            timeout, m_curr_phase.get_name()));
00623       end
00624     join_any
00625     disable fork;
00626   end
00627   join
00628 
00629   `else // QUESTA
00630 
00631   fork : stop_tasks
00632     begin
00633       m_do_stop_all(this);
00634       wait fork;
00635     end
00636     begin
00637       #timeout ovm_report_warning("STPTO",
00638        $psprintf("Stop-request timeout of %0t expired. Stopping phase '%0s'",
00639                          timeout, m_curr_phase.get_name()));
00640     end
00641   join_any
00642   disable stop_tasks;
00643 
00644   `endif // INCA
00645 
00646   // all stop processes have completed, or a timeout has occured
00647   this.do_kill_all();
00648 
00649 endtask
00650 
00651 
00652 // m_do_stop_all
00653 // -------------
00654 
00655 task ovm_root::m_do_stop_all(ovm_component comp);
00656 
00657   string name;
00658 
00659   // we use an external traversal to ensure all forks are 
00660   // made from a single threaad.
00661   if (comp.get_first_child(name))
00662     do begin
00663       m_do_stop_all(comp.get_child(name));
00664     end
00665     while (comp.get_next_child(name));
00666 
00667   if (comp.enable_stop_interrupt) begin
00668     fork begin
00669       comp.stop(m_curr_phase.get_name());
00670     end
00671     join_none
00672   end
00673 
00674 endtask
00675 
00676 
00677 //------------------------------------------------------------------------------
00678 // Phase Insertion
00679 //------------------------------------------------------------------------------
00680 
00681 // insert_phase
00682 // ------------
00683 
00684 function void ovm_root::insert_phase(ovm_phase new_phase,
00685                                      ovm_phase exist_phase);
00686   ovm_phase exist_ph;
00687   string s;
00688 
00689   if (build_ph.is_done()) begin
00690     ovm_report_fatal("PHINST", "Phase insertion after build phase prohibited.");
00691     return;
00692   end
00693 
00694   if (exist_phase != null && exist_phase.is_done() ||
00695       exist_phase == null && m_curr_phase != null) begin 
00696     ovm_report_fatal("PHINST", {"Can not insert a phase at a point that has ",
00697       "already executed. Current phase is '", m_curr_phase.get_name(),"'."});
00698     return;
00699   end
00700 
00701   if (new_phase == null) begin
00702     ovm_report_fatal("PHNULL", "Phase argument is null.");
00703     return;
00704   end
00705 
00706   if (exist_phase != null && !m_phase_q.exists(exist_phase)) begin
00707     ovm_report_fatal("PHNTFD", {"Phase '",exist_phase.get_name(),
00708                       "' is not registered."});
00709     return;
00710   end
00711 
00712   if (m_phase_q.exists(new_phase)) begin
00713     if ((exist_phase == null && m_first_phase != new_phase) ||
00714         (exist_phase != null && m_phase_q[exist_phase] != new_phase)) begin
00715       ovm_report_error("PHDUPL", {"Phase '", new_phase.get_name(),
00716         "' is already registered in a different order."});
00717     end
00718     return;
00719   end
00720 
00721   if (exist_phase == null) begin
00722     m_phase_q[new_phase] = m_first_phase;
00723     m_first_phase = new_phase;
00724   end
00725   else begin
00726     m_phase_q[new_phase] = m_phase_q[exist_phase];
00727     m_phase_q[exist_phase] = new_phase;
00728   end
00729 
00730   if (m_phase_q[new_phase] == null)
00731     m_last_phase = new_phase;
00732 
00733 endfunction
00734 
00735 
00736 // get_phase_by_name
00737 // -----------------
00738 
00739 function ovm_phase ovm_root::get_phase_by_name (string name);
00740   ovm_phase m_ph;
00741   foreach (m_phase_q[ph]) begin
00742     m_ph = ph;
00743     if(m_ph.get_name() == name) 
00744       return ph;
00745   end
00746   return null;
00747 endfunction
00748 
00749 
00750 //------------------------------------------------------------------------------
00751 // Component Search & Printing
00752 //------------------------------------------------------------------------------
00753 
00754 
00755 // find_all
00756 // --------
00757 
00758 function void ovm_root::find_all(string comp_match, ref ovm_component comps[$],
00759                                  input ovm_component comp=null); 
00760   string name;
00761   `ifdef INCA
00762   static ovm_component tmp[$]; //static list to work around ius 6.2 limitation
00763   static bit s_is_child;  //starts at 0 for the root call
00764          bit is_child;    //automatic variable gets updated immediately on entry
00765   is_child = s_is_child;
00766   `endif
00767 
00768   if (comp==null)
00769     comp = this;
00770 
00771   if (comp.get_first_child(name))
00772     do begin
00773       `ifdef INCA
00774         //Indicate that a recursive call is being made. Using a static variable
00775         //since this is a temp workaround and we don't want to effect the
00776         //function prototype.
00777         s_is_child = 1;
00778         this.find_all(comp_match,tmp,comp.get_child(name));
00779         s_is_child = 0;  //reset for a future call.
00780         //Only copy to the component list if this is the top of the stack,
00781         //otherwise an infinite loop will result copying tmp to itself.
00782         if(is_child==0)
00783           while(tmp.size()) comps.push_back(tmp.pop_front());
00784       `else
00785         this.find_all(comp_match,comps,comp.get_child(name));
00786       `endif
00787     end
00788     while (comp.get_next_child(name));
00789 
00790   if (ovm_is_match(comp_match, comp.get_full_name()) &&
00791        comp.get_name() != "") /* ovm_top */
00792     comps.push_back(comp);
00793 
00794 endfunction
00795 
00796 
00797 // find
00798 // ----
00799 
00800 function ovm_component ovm_root::find (string comp_match);
00801   `ifdef INCA
00802     static ovm_component comp_list[$];
00803     comp_list.delete();
00804   `else
00805     ovm_component comp_list[$];
00806   `endif
00807 
00808   find_all(comp_match,comp_list);
00809 
00810   if (comp_list.size() > 1)
00811     ovm_report_warning("MMATCH",
00812     $psprintf("Found %0d components matching '%s'. Returning first match, %0s.",
00813               comp_list.size(),comp_match,comp_list[0].get_full_name()));
00814 
00815   if (comp_list.size() == 0)
00816     ovm_report_warning("CMPNFD",
00817       {"Component matching '",comp_match,"' was not found in the list of ovm_components"});
00818   return comp_list[0];
00819 endfunction
00820 
00821 
00822 //------------------------------------------------------------------------------
00823 //
00824 // REVIEW FOR DEPRECATION OR REMOVAL
00825 //
00826 //------------------------------------------------------------------------------
00827 
00828 // print_unit
00829 // ----------
00830 
00831 function void ovm_root::print_unit (string name, ovm_printer printer=null);
00832 
00833   ovm_component comp;
00834   comp = find(name);
00835   if (comp)
00836     comp.print(printer);
00837 endfunction
00838 
00839 
00840 // print_units
00841 // -----------
00842 
00843 function void ovm_root::print_units (ovm_printer printer=null);
00844 
00845   // Can replace implementation with one line, which will produce single table
00846   //   this.print(printer);
00847 
00848   string s;
00849 
00850   if (m_children.num()==0) begin
00851     ovm_report_warning("EMTCOMP", "No OVM components to print.");
00852     return;
00853   end
00854 
00855   if (printer==null)
00856     printer = ovm_default_printer;
00857 
00858   if (printer.knobs.sprint)
00859     s = printer.m_string;
00860 
00861   foreach (m_children[c]) begin
00862     if(m_children[c].print_enabled) begin
00863       printer.print_object("", m_children[c]);  
00864       if(printer.knobs.sprint)
00865         s = {s, printer.m_string};
00866     end
00867   end
00868 
00869   printer.m_string = s;
00870 
00871 
00872 endfunction
00873 
00874 
00875 // print_unit_list
00876 // ---------------
00877 
00878 function void ovm_root::print_unit_list(ovm_component comp=null);
00879 
00880   string name;
00881 
00882   if (comp==null) begin
00883     comp = this;
00884     if (m_children.num()==0) begin
00885       ovm_report_warning("NOUNIT","No OVM components to print. ");
00886       return;
00887     end
00888     $display("List of ovm components");
00889   end
00890   else begin
00891     $display("%s (%s)", comp.get_full_name(), comp.get_type_name());
00892   end
00893 
00894   if (comp.get_first_child(name))
00895     do begin
00896       this.print_unit_list(comp.get_child(name));
00897     end
00898     while (comp.get_next_child(name));
00899 
00900 endfunction
00901 
00902 
00903 // print_topology
00904 // --------------
00905 
00906 function void ovm_root::print_topology(ovm_printer printer=null);
00907   ovm_report_info("OVMTOP", "OVM testbench topology:", OVM_LOW);
00908   print_units(printer);
00909 endfunction
00910 
00911 
00912 `endif //OVM_ROOT_SVH

Intelligent Design Verification
Intelligent Design Verification
Project: OVM, Revision: 1.1.0
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.4.6
Mon Sep 29 14:23:30 2008
Find a documentation bug? Report bugs to: bugs.intelligentdv.com Project: DoxygenFilterSV