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