00001 // $Id: ovm__sequencer_8sv-source.html,v 1.1 2008/10/07 21:54:41 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 00023 `include "methodology/sequences/ovm_sequencer.svh" 00024 `include "methodology/sequences/ovm_sequence.svh" 00025 00026 00027 // new 00028 // --- 00029 00030 function ovm_seq_item_cons_if::new (string name="", 00031 ovm_component parent = null); 00032 super.new(name, parent); 00033 $cast(parent_as_seqr, parent); 00034 endfunction 00035 00036 00037 // do_print 00038 // --- 00039 00040 function void ovm_seq_item_cons_if::do_print (ovm_printer printer); 00041 super.do_print(printer); 00042 if (consumer != null) 00043 printer.print_string("item consumer", consumer.get_name()); 00044 else 00045 printer.print_string("item consumer", "NOT_CONNECTED"); 00046 endfunction 00047 00048 00049 // create 00050 // --- 00051 00052 function ovm_object ovm_seq_item_cons_if::create (string name=""); 00053 ovm_seq_item_cons_if i; i=new(name); 00054 return i; 00055 endfunction 00056 00057 00058 // get_type_name 00059 // --- 00060 00061 function string ovm_seq_item_cons_if::get_type_name(); 00062 return "ovm_seq_item_cons_if"; 00063 endfunction 00064 00065 00066 // connect_if 00067 // --- 00068 00069 function void ovm_seq_item_cons_if::connect_if( 00070 ovm_seq_item_prod_if item_prod_if); 00071 item_prod_if.seqr_ref = parent_as_seqr; 00072 consumer = item_prod_if.get_parent(); 00073 endfunction 00074 00075 00076 00077 // new 00078 // --- 00079 00080 function ovm_sequencer::new (string name, ovm_component parent); 00081 super.new(name, parent); 00082 $cast(seq_item_cons_if, create_component("ovm_seq_item_cons_if", 00083 "seq_item_cons_if")); 00084 item_done = new("item_done"); 00085 item_ready = new("item_ready"); 00086 void'(get_config_int("pull_mode", pull_mode)); 00087 void'(get_config_int("max_random_depth", max_random_depth)); 00088 void'(get_config_int("num_last_items", num_last_items)); 00089 endfunction 00090 00091 00092 // get_type_name 00093 // --- 00094 00095 function string ovm_sequencer::get_type_name(); 00096 return "ovm_sequencer"; 00097 endfunction 00098 00099 00100 // Implement data functions 00101 // ------------------------ 00102 00103 function void ovm_sequencer::do_copy (ovm_object rhs); 00104 ovm_sequencer seqr; 00105 super.do_copy(rhs); 00106 if(rhs == null) return; 00107 if(!$cast(seqr, rhs)) return; 00108 pull_mode = seqr.pull_mode; 00109 item_done = seqr.item_done; 00110 item_ready = seqr.item_ready; 00111 max_random_depth = seqr.max_random_depth; 00112 num_last_items = seqr.num_last_items; 00113 endfunction 00114 00115 function bit ovm_sequencer::do_compare (ovm_object rhs, 00116 ovm_comparer comparer); 00117 ovm_sequencer seqr; 00118 do_compare = 1; 00119 if(rhs == null) return 0; 00120 if(!$cast(seqr, rhs)) return 0; 00121 do_compare &= comparer.compare_field_int("pull_mode", pull_mode, seqr.pull_mode, 00122 $bits(pull_mode)); 00123 do_compare &= comparer.compare_object("item_done", item_done, seqr.item_done); 00124 do_compare &= comparer.compare_object("item_ready", item_ready, seqr.item_ready); 00125 do_compare &= comparer.compare_field_int("max_random_depth", max_random_depth, 00126 seqr.max_random_depth, $bits(max_random_depth), OVM_DEC); 00127 do_compare &= comparer.compare_field_int("num_last_items", num_last_items, 00128 seqr.num_last_items, $bits(num_last_items), OVM_DEC); 00129 endfunction 00130 00131 function void ovm_sequencer::do_print (ovm_printer printer); 00132 super.do_print(printer); 00133 if(sequences.size() != 0) 00134 printer.print_field("max_random_depth", max_random_depth, 00135 $bits(max_random_depth), OVM_DEC); 00136 printer.print_field("pull_mode", pull_mode, $bits(pull_mode)); 00137 printer.print_field("num_last_items", num_last_items, 00138 $bits(num_last_items), OVM_DEC); 00139 endfunction 00140 00141 function void ovm_sequencer::do_record (ovm_recorder recorder); 00142 super.do_record(recorder); 00143 recorder.record_field("pull_mode", pull_mode, $bits(pull_mode)); 00144 recorder.record_field("max_random_depth", max_random_depth, 00145 $bits(max_random_depth), OVM_DEC); 00146 recorder.record_field("num_last_items", num_last_items, 00147 $bits(num_last_items), OVM_DEC); 00148 endfunction 00149 00150 00151 // process_queue 00152 // ------------- 00153 00154 function bit ovm_sequencer::process_queue(output int index); 00155 00156 if(m_action_q.size() == 0) begin 00157 return 0; 00158 end else begin 00159 for(int i = 0; i < this.m_action_q.size() ; i ++) begin : process_queue_for 00160 if(m_grabbers.size() == 0 || 00161 m_is_current_grabber(this.m_action_q[i]) == 1) begin 00162 if(this.m_action_q[i].is_relevant()) begin : relevant_block 00163 //trigger process-specific urm_sequence::m_sync ovm_event 00164 m_action_e[i].trigger(); 00165 index = i; 00166 return 1; //process one action at a time 00167 end : relevant_block 00168 end 00169 process_queue = 0; 00170 end : process_queue_for 00171 end 00172 00173 endfunction 00174 00175 00176 // m_sync 00177 // ------ 00178 00179 task ovm_sequencer::m_sequencer_sync(input string item_name, 00180 ovm_sequence parent_seq, ovm_event ack_process); 00181 00182 this.m_action_q.push_back(parent_seq); 00183 this.m_action_e.push_back(ack_process); 00184 00185 ->m_eval_queue_e; 00186 00187 endtask 00188 00189 00190 // execute_item 00191 // ------------ 00192 00193 task ovm_sequencer::execute_item(input ovm_sequence_item item, 00194 ovm_sequence seq = null); 00195 ovm_sequence temp_seq; 00196 if (seq == null) 00197 temp_seq = new(); 00198 else 00199 temp_seq = seq; 00200 if(item.is_item()) begin 00201 ovm_event ack_process; 00202 ack_process = new({"ack_", item.get_name()}); 00203 m_sequencer_sync(item.get_name(), temp_seq, ack_process); 00204 ack_process.wait_trigger(); 00205 temp_seq.pre_do(1); 00206 #0; 00207 temp_seq.mid_do(item); 00208 m_last_push_front(item); 00209 m_item_ready_trigger(item); 00210 item_done_wait_trigger_data(item); 00211 temp_seq.post_do(item); 00212 end 00213 else begin 00214 ovm_sequence m_seq; 00215 $cast(m_seq, item); 00216 if (this.recording_detail != OVM_NONE) 00217 m_seq.tr_handle = begin_tr(m_seq, m_seq.get_name()); 00218 //temp_seq.pre_do(0); 00219 //temp_seq.mid_do(item); 00220 m_seq.set_sequencer(this); 00221 //allow users to detect started when a subsequence body() 00222 //calls ovm_do immediately 00223 #0 -> m_seq.started; 00224 m_seq.body(); 00225 -> m_seq.ended; 00226 //temp_seq.post_do(item); 00227 this.end_tr(item); 00228 end 00229 endtask 00230 00231 00232 // apply 00233 // ----- 00234 00235 task ovm_sequencer::apply(input ovm_sequence_item item, 00236 ovm_sequence seq = null); 00237 ovm_sequence temp_seq; 00238 if (seq == null) 00239 temp_seq = new(); 00240 else 00241 temp_seq = seq; 00242 if(item.is_item()) begin 00243 ovm_event ack_process; 00244 ack_process = new({"ack_", item.get_name()}); 00245 m_sequencer_sync(item.get_name(), temp_seq, ack_process); 00246 ack_process.wait_trigger(); 00247 temp_seq.pre_apply(); 00248 #0; 00249 temp_seq.mid_apply(); 00250 m_last_push_front(item); 00251 m_item_ready_trigger(item); 00252 item_done_wait_trigger_data(item); 00253 temp_seq.post_apply(); 00254 end 00255 else begin 00256 ovm_sequence m_seq; 00257 $cast(m_seq, item); 00258 if (this.recording_detail != OVM_NONE) 00259 m_seq.tr_handle = begin_tr(m_seq, m_seq.get_name()); 00260 temp_seq.pre_apply(); 00261 temp_seq.mid_apply(); 00262 m_seq.set_sequencer(this); 00263 //allow users to detect started when a subsequence body() 00264 //calls ovm_do immediately 00265 #0 -> m_seq.started; 00266 m_seq.body(); 00267 -> m_seq.ended; 00268 temp_seq.post_apply(); 00269 this.end_tr(item); 00270 end 00271 endtask 00272 00273 00274 // wait_for_activate 00275 // ----------------- 00276 00277 task ovm_sequencer::m_wait_for_activate(); 00278 if(m_action_q.size() == 0) 00279 @m_eval_queue_e; 00280 else begin // action queue is not empty (implication says process_queue 00281 // already returned a 0, which means no relevant, grab qualifier 00282 fork // isolate inner fork block so can later disable it 00283 begin 00284 fork 00285 @m_eval_queue_e; //this is a block waiting for new action entry or ungrab 00286 begin // this block is detect changes for a sequence's relevance 00287 event trigger; 00288 for(int i=0; i<m_action_q.size(); ++i) 00289 if(m_grabbers.size() == 0 || 00290 m_is_current_grabber(this.m_action_q[i]) == 1) 00291 if(!m_action_q[i].is_relevant()) begin 00292 // IUS issue work-around here... 00293 ovm_sequence s; 00294 s = m_action_q[i]; 00295 fork 00296 begin 00297 s.wait_for_relevant(); 00298 ->trigger; 00299 end 00300 join_none 00301 end 00302 @trigger; 00303 end 00304 join_any 00305 disable fork; 00306 end 00307 join 00308 end 00309 endtask 00310 00311 00312 // get_next_item 00313 // ------------- 00314 00315 task ovm_sequencer::get_next_item(output ovm_sequence_item item); 00316 int index; 00317 while (!process_queue(index)) begin // select action 00318 m_wait_for_activate(); 00319 end 00320 item_ready.wait_trigger(); // wait for pre_do, rand, mid_do to complete 00321 m_action_q.delete(index); 00322 m_action_e.delete(index); 00323 $cast(item, item_ready.get_trigger_data()); /* returns item passed into 00324 m_item_ready_trigger in 00325 ovm_sequence::m_post_sync */ 00326 endtask 00327 00328 00329 // wait_for_sequences() 00330 // ------------- 00331 00332 task ovm_sequencer::wait_for_sequences(); 00333 for (int i=0; i < 100 ; i++) 00334 #0; 00335 endtask 00336 00337 00338 // try_next_item() 00339 // ------------- 00340 00341 task ovm_sequencer::try_next_item(output ovm_sequence_item item); 00342 fork // isolate inner fork block so can later disable it 00343 begin 00344 fork : try_next_fork 00345 get_next_item(item); 00346 //items will be lost if wait_for_sequences does not delay sufficiently 00347 wait_for_sequences(); 00348 join_any 00349 disable fork; 00350 end 00351 join 00352 endtask 00353 00354 00355 // item_done_trigger 00356 // ----------------- 00357 00358 function void ovm_sequencer::item_done_trigger(ovm_sequence_item 00359 item=null); 00360 item_done.trigger(item); 00361 endfunction 00362 00363 00364 // has_do_available 00365 // ----------------- 00366 00367 function bit ovm_sequencer::has_do_available(); 00368 for(int i = 0; i < this.m_action_q.size() ; i ++) 00369 if(this.m_action_q[i].is_relevant()) 00370 return 1; 00371 return 0; 00372 endfunction 00373 00374 00375 // m_item_ready_trigger 00376 // -------------------- 00377 00378 function void ovm_sequencer::m_item_ready_trigger( 00379 input ovm_object m_item=null); 00380 item_ready.trigger(m_item); 00381 endfunction 00382 00383 00384 // item_done_wait_trigger_data 00385 // ------------------------ 00386 00387 task ovm_sequencer::item_done_wait_trigger_data(output 00388 ovm_sequence_item item); 00389 ovm_object m_object; 00390 item_done.wait_trigger_data(m_object); 00391 if (m_object != null) begin 00392 if(!$cast(item, m_object)) 00393 ovm_report_fatal("ILLCST", $psprintf("cast failure on %0s %0s", 00394 m_object.get_name(), m_object.get_type_name())); 00395 end 00396 endtask 00397 00398 00399 // grab() 00400 // ------ 00401 00402 task ovm_sequencer::grab(ovm_sequence seq); 00403 // already holds the grab 00404 if(m_grabbers[0] == seq) 00405 ovm_report_warning("DUPGRB", 00406 "Duplicate grab for this sequence. grab() ignored."); 00407 // grabbers queue is empty. requestor gets. 00408 else if(!m_grabbers.size()) begin 00409 m_grabbers[0] = seq; 00410 end 00411 else begin 00412 // is child of grabber 00413 if(m_is_current_grabber(seq)) begin 00414 m_grabbers.push_front(seq); 00415 end 00416 else begin 00417 // block grab requestor 00418 m_block_grabber(seq); 00419 m_grabbers.push_front(seq); 00420 end 00421 end 00422 endtask: grab 00423 00424 00425 // m_block_grabber() 00426 // ----------------- 00427 00428 task ovm_sequencer::m_block_grabber(ovm_sequence seq); 00429 seq.m_set_is_blocked(1); 00430 while(1) begin 00431 @ m_ungrab_e; 00432 if(m_is_current_grabber(seq) || m_grabbers.size() == 0) begin 00433 seq.m_set_is_blocked(0); 00434 return; 00435 end 00436 end 00437 endtask: m_block_grabber 00438 00439 00440 // m_is_current_grabber() 00441 // ------ 00442 00443 function bit ovm_sequencer::m_is_current_grabber(ovm_sequence seq); 00444 if(seq == m_grabbers[0]) 00445 m_is_current_grabber = 1; 00446 else begin 00447 while(seq.get_parent_seq()) begin 00448 if(seq.get_parent_seq() == m_grabbers[0]) 00449 return 1; 00450 else 00451 seq = seq.get_parent_seq(); 00452 end 00453 m_is_current_grabber = 0; 00454 end 00455 endfunction : m_is_current_grabber 00456 00457 00458 // ungrab() 00459 // ------ 00460 00461 function void ovm_sequencer::ungrab(ovm_sequence seq); 00462 if(seq == m_grabbers[0]) begin 00463 m_grabbers.delete(0); 00464 -> m_ungrab_e; 00465 -> m_eval_queue_e; 00466 end 00467 else 00468 ovm_report_error("ILNGRB", $psprintf("Illegal ungrab by %0s", 00469 seq.get_name())); 00470 endfunction : ungrab 00471 00472 00473 // current_grabber() 00474 // ------ 00475 00476 function ovm_sequence ovm_sequencer::current_grabber(); 00477 if(m_grabbers.size()) 00478 return m_grabbers[0]; 00479 else 00480 return null; 00481 endfunction :current_grabber 00482 00483 00484 // is_grabbed() 00485 // ------ 00486 00487 function bit ovm_sequencer::is_grabbed(); 00488 if(m_grabbers.size()) 00489 return 1; 00490 else 00491 return 0; 00492 endfunction :is_grabbed 00493 00494 00495 // m_last_push_front 00496 // -------------- 00497 00498 function void ovm_sequencer::m_last_push_front(ovm_sequence_item item); 00499 if(!num_last_items) 00500 return; 00501 00502 if(m_last_queue.size() == num_last_items) 00503 void'(m_last_queue.pop_back()); 00504 00505 this.m_last_queue.push_front(item); 00506 endfunction 00507 00508 00509 // set_num_last_items 00510 // ---------------- 00511 00512 function void ovm_sequencer::set_num_last_items(int unsigned max); 00513 if(max > 1024) begin 00514 ovm_report_warning("HSTOB", 00515 $psprintf("Invalid last size; 1024 is the maximum and will be used", 00516 max)); 00517 max = 1024; 00518 end 00519 00520 //shrink the buffer 00521 while((m_last_queue.size() != 0) && (m_last_queue.size() > max)) begin 00522 void'(m_last_queue.pop_back()); 00523 end 00524 00525 num_last_items = max; 00526 endfunction 00527 00528 00529 // last 00530 // ---- 00531 00532 function ovm_sequence_item ovm_sequencer::last(int unsigned n); 00533 if(n > num_last_items) begin 00534 ovm_report_warning("HSTOB", 00535 $psprintf("Invalid last access (%0d), the max history is %0d", n, 00536 num_last_items)); 00537 return null; 00538 end 00539 if(n == m_last_queue.size()) 00540 return null; 00541 00542 return m_last_queue[n]; 00543 endfunction 00544 00545
![]() 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 |