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 void'(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 void'(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 function int vmm_sb_ds_iter::incr_n_pending(int delta);
00400 return 0;
00401 endfunction
00402
00403 function int vmm_sb_ds_iter::incr_n_matched(int delta);
00404 this.pkt_str.n_matched += delta;
00405 if (this.pkt_str.n_matched < 0) this.pkt_str.n_matched = 0;
00406 return this.pkt_str.n_matched;
00407 endfunction
00408
00409
00410 function int vmm_sb_ds_iter::incr_n_mismatched(int delta);
00411 this.pkt_str.n_mismatched += delta;
00412 if (this.pkt_str.n_mismatched < 0) this.pkt_str.n_mismatched = 0;
00413 return this.pkt_str.n_mismatched;
00414 endfunction
00415
00416
00417 function int vmm_sb_ds_iter::incr_n_dropped(int delta);
00418 this.pkt_str.n_dropped += delta;
00419 if (this.pkt_str.n_dropped < 0) this.pkt_str.n_dropped = 0;
00420 return this.pkt_str.n_dropped;
00421 endfunction
00422
00423
00424 function int vmm_sb_ds_iter::incr_n_not_found(int delta);
00425 this.pkt_str.n_not_found += delta;
00426 if (this.pkt_str.n_not_found < 0) this.pkt_str.n_not_found = 0;
00427 return this.pkt_str.n_not_found;
00428 endfunction
00429
00430 function int vmm_sb_ds_iter::incr_n_orphaned(int delta);
00431 return 0;
00432 endfunction
00433
00434
00435 function vmm_sb_ds_iter vmm_sb_ds_iter::copy();
00436 vmm_sb_ds_iter iter = new(this.sb, this.exp_str_id, this.inp_str_id);
00437
00438 iter.exp_str_idx = this.exp_str_idx;
00439 iter.exp_str = this.exp_str;
00440 iter.pkt_str_idx = this.pkt_str_idx;
00441 iter.pkt_str = this.pkt_str;
00442 iter.is_valid = this.is_valid;
00443 iter.stream_iter = this.stream_iter.copy();
00444
00445 return iter;
00446 endfunction: copy
00447
00448
00449 function vmm_sb_ds_stream_iter vmm_sb_ds_iter::new_stream_iter();
00450 if (!this.is_valid) begin
00451 `vmm_error(this.sb.log, "Cannot create stream iterator from invalid scoreboard iterator");
00452 return null;
00453 end
00454
00455 return this.sb.new_stream_iter(this.exp_str_idx, this.pkt_str_idx);
00456 endfunction: new_stream_iter
00457
00458
00459 function int vmm_sb_ds_iter::delete();
00460 int n = 0;
00461 int exp_idx, pkt_idx;
00462 vmm_sb_ds_exp_streams exp_str;
00463 vmm_sb_ds_pkt_stream pkt_str;
00464
00465 if (!this.is_valid) return -1;
00466
00467 n = this.pkt_str.pkts.size();
00468 exp_idx = this.exp_str_idx;
00469 exp_str = this.exp_str;
00470 pkt_idx = this.pkt_str_idx;
00471 pkt_str = this.pkt_str;
00472
00473 this.next();
00474
00475 `ifdef VCS2006_06
00476 // Work-around for NYI feature in VCS2006.06
00477 // but IEEE 1800-2009 compliant
00478 pkt_str.pkts.delete();
00479 `else
00480 // Works in VCS2008.03 or later
00481 // IEEE 1800-2005 compliant
00482 pkt_str.pkts = '{};
00483 `endif
00484 exp_str.pkt_streams.delete(pkt_idx);
00485 if (this.sb.Xinp_stream_descsX.exists(pkt_idx)) begin
00486 this.sb.Xinp_stream_descsX.delete(pkt_idx);
00487 end
00488
00489 if (exp_str.pkt_streams.num() == 0) begin
00490 this.sb.Xexp_streamsX.delete(exp_idx);
00491 if (this.sb.Xexp_stream_descsX.exists(exp_idx)) begin
00492 this.sb.Xexp_stream_descsX.delete(exp_idx);
00493 end
00494 end
00495
00496 // The entire scoreboard might be empty!
00497 if (this.sb.get_n_pending() == 0) this.sb.notify.indicate(vmm_sb_ds::EMPTY);
00498
00499 return n;
00500 endfunction: delete
00501
00502
00503 function void vmm_sb_ds_iter::display(string prefix = "");
00504 if (!this.is_valid) begin
00505 $write("%s** Iterator not on valid stream **\n", prefix);
00506 end
00507
00508 $write("%sStream: %s\n", prefix, this.describe());
00509 foreach (this.pkt_str.pkts[i]) begin
00510 this.pkt_str.pkts[i].display({prefix, " "});
00511 end
00512 endfunction: display
00513
00514
00515 function vmm_sb_ds_pkt_stream vmm_sb_ds_iter::Xget_pkt_streamX();
00516 return this.pkt_str;
00517 endfunction: Xget_pkt_streamX