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

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:20:12 2008
Find a documentation bug? Report bugs to: bugs.intelligentdv.com Project: DoxygenFilterSV