00001 // 00002 // ------------------------------------------------------------- 00003 // Copyright 2004-2008 Synopsys, Inc. 00004 // All Rights Reserved Worldwide 00005 // 00006 // Licensed under the Apache License, Version 2.0 (the 00007 // "License"); you may not use this file except in 00008 // compliance with the License. You may obtain a copy of 00009 // the License at 00010 // 00011 // http://www.apache.org/licenses/LICENSE-2.0 00012 // 00013 // Unless required by applicable law or agreed to in 00014 // writing, software distributed under the License is 00015 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 00016 // CONDITIONS OF ANY KIND, either express or implied. See 00017 // the License for the specific language governing 00018 // permissions and limitations under the License. 00019 // ------------------------------------------------------------- 00020 // 00021 00022 00023 function vmm_sb_ds_iter::new(vmm_sb_ds sb, 00024 int exp_stream_id, 00025 int inp_stream_id); 00026 this.sb = sb; 00027 this.inp_str_id = inp_stream_id; 00028 this.exp_str_id = exp_stream_id; 00029 this.exp_str = null; 00030 this.pkt_str = null; 00031 this.is_valid = 0; 00032 endfunction: new 00033 00034 00035 function bit vmm_sb_ds_iter::first(); 00036 this.is_valid = 0; 00037 return this.next(); 00038 endfunction: first 00039 00040 00041 function bit vmm_sb_ds_iter::is_ok(); 00042 return is_valid; 00043 endfunction: is_ok 00044 00045 00046 function bit vmm_sb_ds_iter::next(); 00047 if (!this.is_valid) begin 00048 if (!this.next_exp_str()) begin 00049 // There is no applicable expected stream group 00050 return 0; 00051 end 00052 this.pkt_str = null; 00053 end 00054 00055 do begin 00056 this.next_pkt_str(); 00057 if (this.pkt_str == null) begin 00058 if (!this.next_exp_str()) begin 00059 // Looks like we ran out of applicable expected stream groups 00060 this.is_valid = 0; 00061 return 0; 00062 end 00063 end 00064 end while (this.pkt_str == null || this.exp_str == null); 00065 00066 this.is_valid = 1; 00067 return 1; 00068 endfunction: next 00069 00070 00071 function bit vmm_sb_ds_iter::next_exp_str(); 00072 if (this.exp_str_id >= 0) begin 00073 // Iterator over a specific stream 00074 if (this.exp_str != null) begin 00075 // Looks like the end of the line! 00076 this.exp_str = null; 00077 return 0; 00078 end 00079 00080 // This is the first iteration - go to specific streams 00081 if (!this.sb.Xexp_streamsX.exists(this.exp_str_id)) begin 00082 // Can't go to streams coz expected streams do not exist 00083 return 0; 00084 end 00085 00086 this.exp_str_idx = this.exp_str_id; 00087 this.exp_str = this.sb.Xexp_streamsX[this.exp_str_id]; 00088 return 1; 00089 end 00090 00091 // Iterator over all streams 00092 if (this.exp_str == null) begin 00093 // This is the first iteration - go to first set of streams 00094 if (!this.sb.Xexp_streamsX.first(this.exp_str_idx)) begin 00095 // There are no expected streams to iterate over 00096 return 0; 00097 end 00098 this.exp_str = this.sb.Xexp_streamsX[this.exp_str_idx]; 00099 return 1; 00100 end 00101 00102 // Move on to the next set of streams 00103 if (!this.sb.Xexp_streamsX.next(this.exp_str_idx)) begin 00104 // Looks like the end of the line! 00105 this.exp_str = null; 00106 return 0; 00107 end 00108 this.exp_str = this.sb.Xexp_streamsX[this.exp_str_idx]; 00109 return 1; 00110 endfunction: next_exp_str 00111 00112 00113 function bit vmm_sb_ds_iter::next_pkt_str(); 00114 00115 if (this.exp_str == null) begin 00116 `vmm_fatal(this.sb.log, "Internal Error: next_inp_str() called with no selected expected streams"); 00117 return 0; 00118 end 00119 00120 if (this.inp_str_id >= 0) begin 00121 // Iterator over a specific stream 00122 if (this.pkt_str != null) begin 00123 // Looks like the end of the line! 00124 this.pkt_str = null; 00125 return 0; 00126 end 00127 00128 // This is the first iteration - go to specific streams 00129 if (!this.exp_str.pkt_streams.exists(this.inp_str_id)) begin 00130 // Can't go to stream coz input stream do not exist 00131 return 0; 00132 end 00133 00134 this.pkt_str_idx = this.inp_str_id; 00135 this.pkt_str = this.exp_str.pkt_streams[this.inp_str_id]; 00136 return 1; 00137 end 00138 00139 // Iterator over all streams 00140 if (this.pkt_str == null) begin 00141 // This is the first iteration - go to first set of streams 00142 if (!this.exp_str.pkt_streams.first(this.pkt_str_idx)) begin 00143 // There are no input streams to iterate over 00144 return 0; 00145 end 00146 this.pkt_str = this.exp_str.pkt_streams[this.pkt_str_idx]; 00147 return 1; 00148 end 00149 00150 // Move on to the input stream 00151 if (!this.exp_str.pkt_streams.next(this.pkt_str_idx)) begin 00152 // Looks like the end of the line! 00153 this.pkt_str = null; 00154 return 0; 00155 end 00156 this.pkt_str = this.exp_str.pkt_streams[this.pkt_str_idx]; 00157 return 1; 00158 endfunction: next_pkt_str 00159 00160 00161 function bit vmm_sb_ds_iter::last(); 00162 this.is_valid = 0; 00163 return this.prev(); 00164 endfunction: last 00165 00166 00167 function bit vmm_sb_ds_iter::prev(); 00168 if (!this.is_valid) begin 00169 if (!this.prev_exp_str()) begin 00170 // There is no applicable expected stream group 00171 return 0; 00172 end 00173 this.pkt_str = null; 00174 end 00175 00176 do begin 00177 this.prev_pkt_str(); 00178 if (this.pkt_str == null) begin 00179 if (!this.prev_exp_str()) begin 00180 // Looks like we ran out of applicable expected stream groups 00181 this.is_valid = 0; 00182 return 0; 00183 end 00184 end 00185 end while (this.pkt_str == null || this.exp_str == null); 00186 00187 this.is_valid = 1; 00188 return 1; 00189 endfunction: prev 00190 00191 00192 function bit vmm_sb_ds_iter::prev_exp_str(); 00193 if (this.exp_str_id >= 0) begin 00194 // Iterator over a specific stream 00195 00196 if (this.exp_str != null) begin 00197 // Looks like the end of the line! 00198 this.exp_str = null; 00199 return 0; 00200 end 00201 00202 // This is the first iteration - go to specific streams 00203 if (!this.sb.Xexp_streamsX.exists(this.exp_str_id)) begin 00204 // Can't go to streams coz expected streams do not exist 00205 return 0; 00206 end 00207 00208 this.exp_str = this.sb.Xexp_streamsX[this.exp_str_id]; 00209 return 1; 00210 end 00211 00212 // Iterator over all streams 00213 if (this.exp_str == null) begin 00214 // This is the first iteration - go to first set of streams 00215 if (!this.sb.Xexp_streamsX.last(this.exp_str_idx)) begin 00216 // There are no expected streams to iterate over 00217 return 0; 00218 end 00219 this.exp_str = this.sb.Xexp_streamsX[this.exp_str_idx]; 00220 return 1; 00221 end 00222 00223 // Move on to the prev set of streams 00224 if (!this.sb.Xexp_streamsX.prev(this.exp_str_idx)) begin 00225 // Looks like the end of the line! 00226 this.exp_str = null; 00227 return 0; 00228 end 00229 this.exp_str = this.sb.Xexp_streamsX[this.exp_str_idx]; 00230 return 1; 00231 endfunction: prev_exp_str 00232 00233 00234 function bit vmm_sb_ds_iter::prev_pkt_str(); 00235 00236 if (this.exp_str == null) begin 00237 `vmm_fatal(this.sb.log, "Internal Error: prev_inp_str() called with no selected expected streams"); 00238 return 0; 00239 end 00240 00241 if (this.inp_str_id >= 0) begin 00242 // Iterator over a specific stream 00243 00244 if (this.pkt_str != null) begin 00245 // Looks like the end of the line! 00246 this.pkt_str = null; 00247 return 0; 00248 end 00249 00250 // This is the first iteration - go to specific streams 00251 if (!this.exp_str.pkt_streams.exists(this.inp_str_id)) begin 00252 // Can't go to stream coz input stream do not exist 00253 return 0; 00254 end 00255 00256 this.pkt_str = this.exp_str.pkt_streams[this.inp_str_id]; 00257 return 1; 00258 end 00259 00260 // Iterator over all streams 00261 if (this.pkt_str == null) begin 00262 // This is the first iteration - go to first set of streams 00263 if (!this.exp_str.pkt_streams.last(this.pkt_str_idx)) begin 00264 // There are no input streams to iterate over 00265 return 0; 00266 end 00267 this.pkt_str = this.exp_str.pkt_streams[this.pkt_str_idx]; 00268 return 1; 00269 end 00270 00271 // Move on to the input stream 00272 if (!this.exp_str.pkt_streams.prev(this.pkt_str_idx)) begin 00273 // Looks like the end of the line! 00274 this.pkt_str = null; 00275 return 0; 00276 end 00277 this.pkt_str = this.exp_str.pkt_streams[this.pkt_str_idx]; 00278 return 1; 00279 endfunction: prev_pkt_str 00280 00281 00282 function int vmm_sb_ds_iter::length(); 00283 int n = 0; 00284 00285 foreach (this.sb.Xexp_streamsX[i]) begin 00286 n += this.sb.Xexp_streamsX[i].pkt_streams.num(); 00287 end 00288 00289 return n; 00290 endfunction: length 00291 00292 00293 function int vmm_sb_ds_iter::pos(); 00294 int n = 0; 00295 00296 if (!this.is_valid) return -1; 00297 00298 foreach (this.sb.Xexp_streamsX[i]) begin 00299 if (i == this.exp_str_idx) begin 00300 vmm_sb_ds_exp_streams exp_str = this.sb.Xexp_streamsX[i]; 00301 foreach (exp_str.pkt_streams[j]) begin 00302 if (j == this.pkt_str_idx) return n; 00303 n++; 00304 end 00305 00306 this.is_valid = 0; 00307 return -1; 00308 end 00309 n += this.sb.Xexp_streamsX[i].pkt_streams.num(); 00310 end 00311 00312 this.is_valid = 0; 00313 return -1; 00314 endfunction: pos 00315 00316 00317 function int vmm_sb_ds_iter::inp_stream_id(); 00318 return (this.is_valid) ? this.pkt_str_idx : -1; 00319 endfunction: inp_stream_id 00320 00321 00322 function int vmm_sb_ds_iter::exp_stream_id(); 00323 return (this.is_valid) ? this.exp_str_idx : -1; 00324 endfunction: exp_stream_id 00325 00326 00327 function string vmm_sb_ds_iter::describe(); 00328 bit [1:0] s; 00329 00330 if (!this.is_valid) begin 00331 return "Iterator on invalid stream"; 00332 end 00333 00334 if (this.sb.Xparallel_streamsX) begin 00335 return this.sb.Xinp_stream_descsX[this.pkt_str_idx]; 00336 end 00337 00338 s[1] = this.sb.Xinp_stream_descsX.exists(this.pkt_str_idx); 00339 s[0] = this.sb.Xexp_stream_descsX.exists(this.exp_str_idx); 00340 00341 case (s) 00342 2'b00: return $psprintf("Stream #%0d->#%0d", this.pkt_str_idx, 00343 this.exp_str_idx); 00344 2'b10: return this.sb.Xinp_stream_descsX[this.pkt_str_idx]; 00345 2'b01: return this.sb.Xexp_stream_descsX[this.exp_str_idx]; 00346 2'b11: if (this.sb.Xinp_stream_descsX[this.pkt_str_idx] == 00347 this.sb.Xexp_stream_descsX[this.exp_str_idx]) begin 00348 return this.sb.Xexp_stream_descsX[this.exp_str_idx]; 00349 end 00350 else begin 00351 return {this.sb.Xinp_stream_descsX[this.pkt_str_idx], "->", 00352 this.sb.Xexp_stream_descsX[this.exp_str_idx]}; 00353 end 00354 endcase 00355 endfunction: describe 00356 00357 00358 function int vmm_sb_ds_iter::get_n_inserted(); 00359 return this.pkt_str.n_inserted; 00360 endfunction: get_n_inserted 00361 00362 00363 function int vmm_sb_ds_iter::get_n_pending(); 00364 return this.pkt_str.pkts.size(); 00365 endfunction: get_n_pending 00366 00367 00368 function int vmm_sb_ds_iter::get_n_matched(); 00369 return this.pkt_str.n_matched; 00370 endfunction: get_n_matched 00371 00372 00373 function int vmm_sb_ds_iter::get_n_mismatched(); 00374 return this.pkt_str.n_mismatched; 00375 endfunction: get_n_mismatched 00376 00377 00378 function int vmm_sb_ds_iter::get_n_dropped(); 00379 return this.pkt_str.n_dropped; 00380 endfunction: get_n_dropped 00381 00382 00383 function int vmm_sb_ds_iter::get_n_not_found(); 00384 return this.pkt_str.n_not_found; 00385 endfunction: get_n_not_found 00386 00387 00388 function int vmm_sb_ds_iter::get_n_orphaned(); 00389 return this.pkt_str.pkts.size(); 00390 endfunction: get_n_orphaned 00391 00392 00393 function int vmm_sb_ds_iter::incr_n_inserted(int delta); 00394 this.pkt_str.n_inserted += delta; 00395 if (this.pkt_str.n_inserted < 0) this.pkt_str.n_inserted = 0; 00396 return this.pkt_str.n_inserted; 00397 endfunction 00398 00399 00400 function int vmm_sb_ds_iter::incr_n_matched(int delta); 00401 this.pkt_str.n_matched += delta; 00402 if (this.pkt_str.n_matched < 0) this.pkt_str.n_matched = 0; 00403 return this.pkt_str.n_matched; 00404 endfunction 00405 00406 00407 function int vmm_sb_ds_iter::incr_n_mismatched(int delta); 00408 this.pkt_str.n_mismatched += delta; 00409 if (this.pkt_str.n_mismatched < 0) this.pkt_str.n_mismatched = 0; 00410 return this.pkt_str.n_mismatched; 00411 endfunction 00412 00413 00414 function int vmm_sb_ds_iter::incr_n_dropped(int delta); 00415 this.pkt_str.n_dropped += delta; 00416 if (this.pkt_str.n_dropped < 0) this.pkt_str.n_dropped = 0; 00417 return this.pkt_str.n_dropped; 00418 endfunction 00419 00420 00421 function int vmm_sb_ds_iter::incr_n_not_found(int delta); 00422 this.pkt_str.n_not_found += delta; 00423 if (this.pkt_str.n_not_found < 0) this.pkt_str.n_not_found = 0; 00424 return this.pkt_str.n_not_found; 00425 endfunction 00426 00427 00428 function vmm_sb_ds_iter vmm_sb_ds_iter::copy(); 00429 vmm_sb_ds_iter iter = new(this.sb, this.exp_str_id, this.inp_str_id); 00430 00431 iter.exp_str_idx = this.exp_str_idx; 00432 iter.exp_str = this.exp_str; 00433 iter.pkt_str_idx = this.pkt_str_idx; 00434 iter.pkt_str = this.pkt_str; 00435 iter.is_valid = this.is_valid; 00436 iter.stream_iter = this.stream_iter.copy(); 00437 00438 return iter; 00439 endfunction: copy 00440 00441 00442 function vmm_sb_ds_stream_iter vmm_sb_ds_iter::new_stream_iter(); 00443 if (!this.is_valid) begin 00444 `vmm_error(this.sb.log, "Cannot create stream iterator from invalid scoreboard iterator"); 00445 return null; 00446 end 00447 00448 return this.sb.new_stream_iter(this.exp_str_idx, this.pkt_str_idx); 00449 endfunction: new_stream_iter 00450 00451 00452 function int vmm_sb_ds_iter::delete(); 00453 int n = 0; 00454 int exp_idx, pkt_idx; 00455 vmm_sb_ds_exp_streams exp_str; 00456 vmm_sb_ds_pkt_stream pkt_str; 00457 00458 if (!this.is_valid) return -1; 00459 00460 n = this.pkt_str.pkts.size(); 00461 exp_idx = this.exp_str_idx; 00462 exp_str = this.exp_str; 00463 pkt_idx = this.pkt_str_idx; 00464 pkt_str = this.pkt_str; 00465 00466 this.next(); 00467 00468 `ifdef VCS2006_06 00469 // Work-around for NYI feature in VCS2006.06 00470 // *NOT* IEEE compliant :-( 00471 pkt_str.pkts.delete(); 00472 `else 00473 // Works in VCS2008.03 00474 pkt_str.pkts = '{}; 00475 `endif 00476 exp_str.pkt_streams.delete(pkt_idx); 00477 if (this.sb.Xinp_stream_descsX.exists(pkt_idx)) begin 00478 this.sb.Xinp_stream_descsX.delete(pkt_idx); 00479 end 00480 00481 if (exp_str.pkt_streams.num() == 0) begin 00482 this.sb.Xexp_streamsX.delete(exp_idx); 00483 if (this.sb.Xexp_stream_descsX.exists(exp_idx)) begin 00484 this.sb.Xexp_stream_descsX.delete(exp_idx); 00485 end 00486 end 00487 00488 // The entire scoreboard might be empty! 00489 if (this.sb.get_n_pending() == 0) this.sb.notify.indicate(vmm_sb_ds::EMPTY); 00490 00491 return n; 00492 endfunction: delete 00493 00494 00495 function void vmm_sb_ds_iter::display(string prefix); 00496 if (!this.is_valid) begin 00497 $write("%s** Iterator not on valid stream **\n", prefix); 00498 end 00499 00500 $write("%sStream: %s\n", prefix, this.describe()); 00501 foreach (this.pkt_str.pkts[i]) begin 00502 this.pkt_str.pkts[i].display({prefix, " "}); 00503 end 00504 endfunction: display 00505 00506 00507 function vmm_sb_ds_pkt_stream vmm_sb_ds_iter::Xget_pkt_streamX(); 00508 return this.pkt_str; 00509 endfunction: Xget_pkt_streamX