VMM OpenSource - sv/sb/vmm_sb_ds_iter.sv

sv/sb/vmm_sb_ds_iter.sv expanded source

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