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 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 Version: 1.4.6 Mon Sep 29 14:20:12 2008 |