VMM OpenSource - sv/sb/vmm_sb_ds.sv

sv/sb/vmm_sb_ds.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 `ifndef VMM_SB_DS_SV
00024 `define VMM_SB_DS_SV
00025 
00026 typedef class vmm_sb_ds_iter;
00027 typedef class vmm_sb_ds_stream_iter;
00028 
00029 
00030 //
00031 // The packet queues, one for each inp->exp stream pair
00032 //
00033 // (Undocumented)
00034 //
00035 class vmm_sb_ds_pkt_stream;
00036    vmm_data pkts[$];
00037 
00038    int n_inserted   = 0;
00039    int n_matched    = 0;
00040    int n_mismatched = 0;
00041    int n_dropped    = 0;
00042    int n_not_found  = 0;
00043 endclass
00044 
00045 
00046 //
00047 // Packet queues for one expected stream, one per input stream
00048 //
00049 // (Undocumented)
00050 //
00051 class vmm_sb_ds_exp_streams;
00052    vmm_sb_ds_pkt_stream  pkt_streams[`VMM_AA_INT];
00053 endclass
00054 
00055 
00056 //
00057 // Top-Level Data-stream scoreboard class
00058 //
00059 typedef class vmm_sb_ds_callbacks;
00060 class vmm_sb_ds;
00061 
00062    /*local*/ vmm_sb_ds_exp_streams Xexp_streamsX[`VMM_AA_INT];
00063    /*local*/ string                Xinp_stream_descsX[`VMM_AA_INT];
00064    /*local*/ string                Xexp_stream_descsX[`VMM_AA_INT];
00065    /*local*/ bit                   Xdefine_stream_calledX = 0;
00066    /*local*/ bit                   Xparallel_streamsX     = 0;
00067 
00068    local int n_not_found     = 0;
00069    local bit orphaned        = 0;
00070    local int n_orphaned      = 0;
00071    local bit insert_recursed = 0;
00072 
00073    local vmm_sb_ds_callbacks callbacks[$];
00074 
00075    vmm_log    log;
00076    vmm_notify notify;
00077 
00078    typedef enum {EITHER, INPUT, EXPECT} kind_e;
00079 
00080    typedef enum {INSERTED = 999_000, EMPTY, MATCHED, MISMATCHED,
00081                  DROPPED, NOT_FOUND, ORPHANED} notifications_e;
00082 
00083    extern function new(string name);
00084 
00085    extern virtual function int stream_id(vmm_data          pkt,
00086                                          vmm_sb_ds::kind_e kind = EITHER);
00087 
00088    extern function void define_stream(int               stream_id,
00089                                       string            descr = "",
00090                                       vmm_sb_ds::kind_e kind = EITHER);
00091 
00092    extern virtual function bit insert(vmm_data          pkt,
00093                                       vmm_sb_ds::kind_e kind          = INPUT,
00094                                       int               exp_stream_id = -1,
00095                                       int               inp_stream_id = -1);
00096    extern virtual function bit remove(vmm_data          pkt,
00097                                       vmm_sb_ds::kind_e kind          = INPUT,
00098                                       int               exp_stream_id = -1,
00099                                       int               inp_stream_id = -1);
00100 
00101    extern virtual function bit transform(input  vmm_data in_pkt,
00102                                          output vmm_data out_pkts[]);
00103 
00104    extern virtual function bit match(vmm_data actual,
00105                                      vmm_data expected);
00106    extern virtual function bit quick_compare(vmm_data actual,
00107                                              vmm_data expected);
00108    extern virtual function bit compare(vmm_data actual,
00109                                        vmm_data expected);
00110 
00111 
00112    typedef enum {IN_ORDER, WITH_LOSSES, OUT_ORDER} ordering_e;
00113 
00114    extern virtual function vmm_data expect_in_order(vmm_data pkt,
00115                                                     int      exp_stream_id = -1,
00116                                                     int      inp_stream_id = -1,
00117                                                     bit      silent        = 0);
00118    extern virtual function bit expect_with_losses(input  vmm_data pkt,
00119                                                   output vmm_data matched,
00120                                                   output vmm_data lost[],
00121                                                   input  int      exp_stream_id = -1,
00122                                                   input  int      inp_stream_id = -1,
00123                                                   input  bit      silent        = 0);
00124    extern virtual function vmm_data expect_out_of_order(vmm_data pkt,
00125                                                         int      exp_stream_id = -1,
00126                                                         int      inp_stream_id = -1,
00127                                                         bit      silent        = 0);
00128 
00129    extern virtual function void flush();
00130 
00131    extern function vmm_sb_ds_iter new_sb_iter(int exp_stream_id = -1,
00132                                               int inp_stream_id = -1);
00133    extern function vmm_sb_ds_stream_iter new_stream_iter(int exp_stream_id = -1,
00134                                                          int inp_stream_id = -1);
00135 
00136    extern function void prepend_callback(vmm_sb_ds_callbacks cb);
00137    extern function void append_callback(vmm_sb_ds_callbacks cb);
00138    extern function void unregister_callback(vmm_sb_ds_callbacks cb);
00139 
00140    extern function int get_n_inserted(int exp_stream_id = -1,
00141                                       int inp_stream_id = -1);
00142    extern function int get_n_pending(int exp_stream_id = -1,
00143                                      int inp_stream_id = -1);
00144    extern function int get_n_matched(int exp_stream_id = -1,
00145                                      int inp_stream_id = -1);
00146    extern function int get_n_mismatched(int exp_stream_id = -1,
00147                                         int inp_stream_id = -1);
00148    extern function int get_n_dropped(int exp_stream_id = -1,
00149                                      int inp_stream_id = -1);
00150    extern function int get_n_not_found(int exp_stream_id = -1,
00151                                        int inp_stream_id = -1);
00152    extern function int get_n_orphaned(int exp_stream_id = -1,
00153                                       int inp_stream_id = -1);
00154 
00155    extern virtual function void report(int exp_stream_id = -1,
00156                                        int inp_stream_id = -1);
00157    extern virtual function void describe();
00158    extern virtual function void display(string prefix = "");
00159 
00160 endclass
00161 
00162 
00163 //
00164 // Callback facade class
00165 //
00166 class vmm_sb_ds_callbacks;
00167 
00168    virtual function void pre_insert(input vmm_sb_ds         sb,
00169                                     input vmm_data          pkt,
00170                                     input vmm_sb_ds::kind_e kind,
00171                                     ref   int               exp_stream_id,
00172                                     ref   int               inp_stream_id,
00173                                     ref   bit               drop);
00174    endfunction: pre_insert
00175 
00176    virtual function void post_insert(vmm_sb_ds sb,
00177                                      vmm_data  pkt,
00178                                      int       exp_stream_id,
00179                                      int       inp_stream_id);
00180    endfunction: post_insert
00181 
00182    virtual function void matched(input vmm_sb_ds sb,
00183                                  input vmm_data  pkt,
00184                                  input int       exp_stream_id,
00185                                  input int       inp_stream_id,
00186                                  ref   int       count);
00187    endfunction: matched
00188 
00189    virtual function void mismatched(input vmm_sb_ds sb,
00190                                     input vmm_data  pkt,
00191                                     input int       exp_stream_id,
00192                                     input int       inp_stream_id,
00193                                     ref   int       count);
00194    endfunction: mismatched
00195 
00196    virtual function void dropped(input vmm_sb_ds sb,
00197                                  input vmm_data  pkts[],
00198                                  input int       exp_stream_id,
00199                                  input int       inp_stream_id,
00200                                  ref   int       count);
00201    endfunction: dropped
00202 
00203    virtual function void not_found(input vmm_sb_ds sb,
00204                                    input vmm_data  pkt,
00205                                    input int       exp_stream_id,
00206                                    input int       inp_stream_id,
00207                                    ref   int       count);
00208    endfunction: not_found
00209 
00210    virtual function void orphaned(input vmm_sb_ds sb,
00211                                   input vmm_data  pkts[],
00212                                   input int       exp_stream_id,
00213                                   input int       inp_stream_id,
00214                                   ref   int       count);
00215    endfunction: orphaned
00216 
00217 endclass
00218 
00219 
00220 //
00221 // Status descriptor for notifications
00222 //
00223 class vmm_sb_ds_pkts extends vmm_data;
00224    vmm_data          pkts[];
00225    vmm_sb_ds::kind_e kind;
00226    int               inp_stream_id;
00227    int               exp_stream_id;
00228 
00229    /*local*/ function new(vmm_data          pkt,
00230                           vmm_sb_ds::kind_e kind,
00231                           int               exp_stream_id,
00232                           int               inp_stream_id);
00233       super.new(null);
00234 
00235       if (pkt != null) begin
00236          this.pkts = new [1];
00237          this.pkts[0] = pkt;
00238       end
00239       this.kind = kind;
00240       this.inp_stream_id = inp_stream_id;
00241       this.exp_stream_id = exp_stream_id;
00242    endfunction
00243 endclass
00244 
00245 
00246 //
00247 // Scoreboard iterator
00248 //
00249 class vmm_sb_ds_iter;
00250 
00251    local vmm_sb_ds sb;
00252    local int       exp_str_id;
00253    local int       inp_str_id;
00254 
00255    local int                   exp_str_idx;
00256    local vmm_sb_ds_exp_streams exp_str;
00257    local int                   pkt_str_idx;
00258    local vmm_sb_ds_pkt_stream  pkt_str;
00259 
00260    local bit is_valid;
00261 
00262    vmm_sb_ds_stream_iter stream_iter;
00263 
00264    /*local*/ extern function new(vmm_sb_ds sb,
00265                                  int       exp_stream_id,
00266                                  int       inp_stream_id);
00267    
00268    extern function bit first();
00269    extern function bit is_ok();
00270    extern function bit next();
00271    extern function bit last();
00272    extern function bit prev();
00273    extern function int length();
00274    extern function int pos();
00275 
00276    extern function int inp_stream_id();
00277    extern function int exp_stream_id();
00278    extern function string describe();
00279 
00280    extern function int get_n_inserted();
00281    extern function int get_n_pending();
00282    extern function int get_n_matched();
00283    extern function int get_n_mismatched();
00284    extern function int get_n_dropped();
00285    extern function int get_n_not_found();
00286    extern function int get_n_orphaned();
00287 
00288    extern function int incr_n_inserted(int delta);
00289    extern function int incr_n_pending(int delta);
00290    extern function int incr_n_matched(int delta);
00291    extern function int incr_n_mismatched(int delta);
00292    extern function int incr_n_dropped(int delta);
00293    extern function int incr_n_not_found(int delta);
00294    extern function int incr_n_orphaned(int delta);
00295 
00296    extern function vmm_sb_ds_iter copy();
00297    extern function vmm_sb_ds_stream_iter new_stream_iter();
00298 
00299    extern function int delete();
00300 
00301    extern function void display(string prefix = "");
00302 
00303    /*local*/ extern function vmm_sb_ds_pkt_stream Xget_pkt_streamX();
00304 
00305    extern local function bit next_exp_str();
00306    extern local function bit next_pkt_str();
00307    extern local function bit prev_exp_str();
00308    extern local function bit prev_pkt_str();
00309 endclass: vmm_sb_ds_iter
00310 
00311 
00312 function vmm_sb_ds::new(string name);
00313    this.log    = new("Data Stream Scoreboard", name);
00314    this.notify = new(this.log);
00315 
00316    void'(this.notify.configure(INSERTED,   vmm_notify::ONE_SHOT));
00317    void'(this.notify.configure(EMPTY,      vmm_notify::ON_OFF));
00318    void'(this.notify.configure(MATCHED,    vmm_notify::ONE_SHOT));
00319    void'(this.notify.configure(MISMATCHED, vmm_notify::ONE_SHOT));
00320    void'(this.notify.configure(DROPPED,    vmm_notify::ONE_SHOT));
00321    void'(this.notify.configure(NOT_FOUND,  vmm_notify::ONE_SHOT));
00322    void'(this.notify.configure(ORPHANED,   vmm_notify::ONE_SHOT));
00323 
00324    this.notify.indicate(EMPTY);
00325 
00326    begin
00327       vmm_opts opts = new;
00328       if (opts.get_bit("sb_trace", "VMM Scoreboard trace ON")) begin
00329          this.log.set_verbosity(vmm_log::TRACE_SEV);
00330       end
00331       if (opts.get_bit("sb_debug", "VMM Scoreboard debug ON")) begin
00332          this.log.set_verbosity(vmm_log::DEBUG_SEV);
00333       end
00334    end
00335 endfunction: new
00336 
00337 
00338 function int vmm_sb_ds::stream_id(vmm_data          pkt,
00339                                   vmm_sb_ds::kind_e kind = EITHER);
00340    return 0;
00341 endfunction: stream_id
00342 
00343 
00344 function void vmm_sb_ds::define_stream(int               stream_id,
00345                                        string            descr = "",
00346                                        vmm_sb_ds::kind_e kind = EITHER);
00347    if (stream_id < 0) begin
00348       `vmm_error(this.log, "vmm_sb_ds::define_stream() called with negative stream_id");
00349       return;
00350    end
00351 
00352    case (kind)
00353      EITHER: begin
00354         if (this.Xdefine_stream_calledX && !this.Xparallel_streamsX) begin
00355            `vmm_error(this.log, "vmm_sb_ds::define_stream(): Attempting to define a mix of EITHER and INPUT/EXPECT streams");
00356         end
00357         else begin
00358            this.Xinp_stream_descsX[stream_id] = descr;
00359            this.Xexp_stream_descsX[stream_id] = descr;
00360            this.Xparallel_streamsX = 1;
00361         end
00362      end
00363 
00364      INPUT: begin
00365         if (this.Xdefine_stream_calledX && this.Xparallel_streamsX) begin
00366            `vmm_error(this.log, "vmm_sb_ds::define_stream(): Attempting to define a mix of EITHER and INPUT/EXPECT streams");
00367         end
00368         else begin
00369            this.Xinp_stream_descsX[stream_id] = descr;
00370         end
00371      end
00372 
00373      EXPECT: begin
00374         if (this.Xdefine_stream_calledX && this.Xparallel_streamsX) begin
00375            `vmm_error(this.log, "vmm_sb_ds::define_stream(): Attempting to define a mix of EITHER and INPUT/EXPECT streams");
00376         end
00377         else begin
00378            this.Xexp_stream_descsX[stream_id] = descr;
00379         end
00380      end
00381    endcase
00382    
00383    this.Xdefine_stream_calledX = 1;
00384    
00385 endfunction: define_stream
00386 
00387 
00388 function bit vmm_sb_ds::insert(vmm_data          pkt,
00389                                vmm_sb_ds::kind_e kind = INPUT,
00390                                int               exp_stream_id = -1,
00391                                int               inp_stream_id = -1);
00392    vmm_sb_ds_exp_streams exp_streams;
00393    vmm_sb_ds_pkt_stream  pkt_stream;
00394    bit drop;
00395 
00396    if (kind == EITHER) begin
00397       `vmm_error(this.log, "vmm_sb_ds::insert() called with EITHER packet kind");
00398       return 0;
00399    end
00400 
00401    drop = 0;
00402    `vmm_callback(vmm_sb_ds_callbacks,
00403                  pre_insert(this, pkt, kind,
00404                             exp_stream_id, inp_stream_id, drop));
00405    if (drop) return 1;
00406 
00407    if (inp_stream_id < 0) begin
00408       inp_stream_id = this.stream_id(pkt, INPUT);
00409    end
00410    if (this.Xdefine_stream_calledX) begin
00411       if (!Xinp_stream_descsX.exists(inp_stream_id)) begin
00412          `vmm_error(this.log, $psprintf("vmm_sb_ds::insert() called with undefined input stream #%0d",
00413                                         inp_stream_id));
00414          return 0;
00415       end
00416    end
00417 
00418    if (kind == INPUT) begin
00419       vmm_data out_pkts[];
00420       
00421       `vmm_debug(this.log, $psprintf("Inserting INPUT packet in stream #%0d",
00422                                      inp_stream_id));
00423       `vmm_verbose(this.log, pkt.psdisplay("   "));
00424 
00425       void'(this.transform(pkt, out_pkts));
00426       this.insert_recursed = 1;
00427       foreach (out_pkts[i])  begin
00428          void'(this.insert(out_pkts[i], EXPECT, exp_stream_id, inp_stream_id));
00429       end
00430       this.insert_recursed = 0;
00431 
00432       begin
00433          vmm_sb_ds_pkts status = new(null, EXPECT, exp_stream_id, inp_stream_id);
00434          status.pkts = new [out_pkts.size()] (out_pkts);
00435          this.notify.indicate(INSERTED, status);
00436       end
00437 
00438       return 1;
00439    end
00440 
00441    // Must be an EXPECT packet
00442    if (exp_stream_id < 0) begin
00443       exp_stream_id = this.stream_id(pkt, EXPECT);
00444    end
00445    
00446    if (this.Xdefine_stream_calledX) begin
00447       if (!Xexp_stream_descsX.exists(exp_stream_id)) begin
00448          `vmm_error(this.log, $psprintf("vmm_sb_ds::insert() called with undefined expected stream #%0d",
00449                                         exp_stream_id));
00450          return 0;
00451       end
00452    end
00453    
00454    `vmm_debug(this.log, $psprintf("Inserting EXPECT packet in stream #%0d->#%0d",
00455                                   inp_stream_id, exp_stream_id));
00456    `vmm_verbose(this.log, pkt.psdisplay("   "));
00457 
00458    if (!this.Xexp_streamsX.exists(exp_stream_id)) begin
00459       exp_streams = new();
00460       this.Xexp_streamsX[exp_stream_id] = exp_streams;
00461    end
00462    else 
00463       exp_streams = this.Xexp_streamsX[exp_stream_id];
00464 
00465    if (!exp_streams.pkt_streams.exists(inp_stream_id)) begin
00466       pkt_stream = new();
00467       exp_streams.pkt_streams[inp_stream_id] = pkt_stream;
00468    end
00469    else 
00470       pkt_stream = exp_streams.pkt_streams[inp_stream_id];
00471 
00472    pkt_stream.pkts.push_back(pkt);
00473    this.notify.reset(EMPTY);
00474 
00475    pkt_stream.n_inserted++;
00476    if (!this.insert_recursed) begin
00477       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00478       this.notify.indicate(INSERTED, status);
00479    end
00480    `vmm_callback(vmm_sb_ds_callbacks,
00481                  post_insert(this, pkt, exp_stream_id, inp_stream_id));
00482 
00483    return 1;
00484 endfunction: insert
00485 
00486 
00487 function bit vmm_sb_ds::remove(vmm_data          pkt,
00488                                vmm_sb_ds::kind_e kind = INPUT,
00489                                int               exp_stream_id = -1,
00490                                int               inp_stream_id = -1);
00491 
00492    vmm_sb_ds_exp_streams exp_streams;
00493    vmm_sb_ds_pkt_stream  pkt_stream;
00494 
00495    if (kind == EITHER) begin
00496       `vmm_error(this.log, "vmm_sb_ds::remove() called with EITHER packet kind");
00497       return 0;
00498    end
00499 
00500    if (inp_stream_id < 0) begin
00501       inp_stream_id = this.stream_id(pkt, INPUT);
00502    end
00503    if (this.Xdefine_stream_calledX) begin
00504       if (!Xinp_stream_descsX.exists(inp_stream_id)) begin
00505          `vmm_error(this.log, $psprintf("vmm_sb_ds::remove() called with undefined input stream #%0d",
00506                                         inp_stream_id));
00507          return 0;
00508       end
00509    end
00510 
00511    if (kind == INPUT) begin
00512       vmm_data out_pkts[];
00513       bit      rc = 1;
00514       
00515       `vmm_trace(this.log, $psprintf("Deleting INPUT packet from stream #%0d",
00516                                      inp_stream_id));
00517       `vmm_verbose(this.log, pkt.psdisplay("   "));
00518 
00519       void'(this.transform(pkt, out_pkts));
00520       foreach (out_pkts[i])  begin
00521          rc |= this.remove(out_pkts[i], EXPECT, inp_stream_id, exp_stream_id);
00522       end
00523 
00524       return rc;
00525    end
00526 
00527    // Must be an EXPECT packet
00528    if (exp_stream_id < 0) begin
00529       exp_stream_id = this.stream_id(pkt, EXPECT);
00530    end
00531    
00532    if (this.Xdefine_stream_calledX) begin
00533       if (!Xexp_stream_descsX.exists(exp_stream_id)) begin
00534          `vmm_error(this.log, $psprintf("vmm_sb_ds::remove() called with undefined expected stream #%0d",
00535                                         exp_stream_id));
00536          return 0;
00537       end
00538    end
00539    
00540    `vmm_trace(this.log, $psprintf("Deleting EXPECT packet from stream #%0d->#%0d",
00541                                   inp_stream_id, exp_stream_id));
00542    `vmm_verbose(this.log, pkt.psdisplay("   "));
00543 
00544    if (!this.Xexp_streamsX.exists(exp_stream_id)) begin
00545       `vmm_error(this.log, $psprintf("vmm_sb_ds::remove(): Cannot find packet to remove: expected stream #%0d does not exist",
00546                                      exp_stream_id));
00547       return 0;
00548    end
00549    exp_streams = this.Xexp_streamsX[exp_stream_id];
00550 
00551    if (!exp_streams.pkt_streams.exists(inp_stream_id)) begin
00552       `vmm_error(this.log, $psprintf("vmm_sb_ds::remove(): Cannot find packet to remove: stream #%0d->#%0d does not exist.",
00553                                      inp_stream_id, exp_stream_id));
00554       return 0;
00555    end
00556    pkt_stream = exp_streams.pkt_streams[inp_stream_id];
00557 
00558    foreach (pkt_stream.pkts[i]) begin
00559       if (this.compare(pkt, pkt_stream.pkts[i])) begin
00560          pkt_stream.pkts.delete(i);
00561          if (pkt_stream.pkts.size() == 0) begin
00562             // The entire scoreboard might be empty!
00563             if (this.get_n_pending() == 0) this.notify.indicate(EMPTY);
00564          end
00565          return 1;
00566       end
00567    end
00568 
00569    `vmm_error(this.log, "vmm_sb_ds::remove(): Cannot find packet to remove");
00570 
00571    return 0;
00572 endfunction: remove
00573 
00574 
00575 function bit vmm_sb_ds::transform(input  vmm_data in_pkt,
00576                                   output vmm_data out_pkts[]);
00577    out_pkts    = new [1];
00578    out_pkts[0] = in_pkt;
00579    
00580    return 1;
00581 endfunction: transform
00582 
00583 
00584 function bit vmm_sb_ds::match(vmm_data actual,
00585                               vmm_data expected);
00586    return this.quick_compare(actual, expected);
00587 endfunction: match
00588 
00589 
00590 function bit vmm_sb_ds::quick_compare(vmm_data actual,
00591                                       vmm_data expected);
00592    return 1;
00593 endfunction: quick_compare
00594 
00595 
00596 function bit vmm_sb_ds::compare(vmm_data actual,
00597                                 vmm_data expected);
00598 
00599    string diff;
00600    if (this.quick_compare(actual, expected)) begin
00601       return actual.compare(expected, diff);
00602    end
00603 
00604 endfunction: compare
00605 
00606 
00607 function vmm_data vmm_sb_ds::expect_in_order(vmm_data pkt,
00608                                              int      exp_stream_id = -1,
00609                                              int      inp_stream_id = -1,
00610                                              bit      silent = 0);
00611 
00612    vmm_sb_ds_exp_streams exp_streams;
00613    vmm_sb_ds_pkt_stream  pkt_stream;
00614 
00615    if (exp_stream_id < 0) begin
00616       exp_stream_id = this.stream_id(pkt, EXPECT);
00617    end
00618    if (inp_stream_id < 0) begin
00619       inp_stream_id = this.stream_id(pkt, INPUT);
00620    end
00621 
00622    `vmm_debug(this.log, $psprintf("Expecting in-order packet on stream #%0d->#%0d",
00623                                   inp_stream_id, exp_stream_id));
00624    `vmm_verbose(this.log, pkt.psdisplay("   "));
00625 
00626    if (!this.Xexp_streamsX.exists(exp_stream_id)) begin
00627       // Not found because the output stream does not exist!
00628       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00629       int n = 1;
00630 
00631       this.notify.indicate(NOT_FOUND, status);
00632       `vmm_callback(vmm_sb_ds_callbacks,
00633                     not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00634 
00635       if (!silent) begin
00636          this.n_not_found += n;
00637          `vmm_error(this.log, $psprintf("In-order packet was not found: EXPECT stream #%0d does not exist.", exp_stream_id));
00638       end
00639       return null;
00640    end
00641    exp_streams = this.Xexp_streamsX[exp_stream_id];
00642 
00643    if (!exp_streams.pkt_streams.exists(inp_stream_id)) begin
00644       // Not found because the input stream does not exist!
00645       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00646       int n = 1;
00647 
00648       this.notify.indicate(NOT_FOUND, status);
00649       `vmm_callback(vmm_sb_ds_callbacks,
00650                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00651 
00652       if (!silent) begin
00653          this.n_not_found += n;
00654          `vmm_error(this.log, $psprintf("In-order packet was not found: stream #%0d->#%0d does not exist.", inp_stream_id, exp_stream_id));
00655       end
00656       return null;
00657    end
00658    pkt_stream = exp_streams.pkt_streams[inp_stream_id];
00659 
00660    if (pkt_stream.pkts.size() == 0) begin
00661       // Not found because the packet stream is empty!
00662       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00663       int n = 1;
00664 
00665       this.notify.indicate(NOT_FOUND, status);
00666       `vmm_callback(vmm_sb_ds_callbacks,
00667                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00668 
00669       if (!silent) begin
00670          pkt_stream.n_not_found += n;
00671          `vmm_error(this.log, $psprintf("In-order packet was not found: stream %0d->%0d is empty.", inp_stream_id, exp_stream_id));
00672       end
00673       return null;
00674    end      
00675 
00676    if (!this.compare(pkt, pkt_stream.pkts[0])) begin
00677       // Not found because the packet does not match
00678       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00679       int n = 1;
00680 
00681       this.notify.indicate(NOT_FOUND, status);
00682       `vmm_callback(vmm_sb_ds_callbacks,
00683                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00684 
00685       if (!silent) begin
00686          pkt_stream.n_not_found += n;
00687          `vmm_error(this.log, $psprintf("In-order packet was not expected:\n%s\n%s.", pkt.psdisplay("   Actual: "), pkt_stream.pkts[0].psdisplay("   Expect: ")));
00688       end
00689 
00690       // Remove the packet
00691       void'(pkt_stream.pkts.pop_front());
00692       if (pkt_stream.pkts.size() == 0) begin
00693          // The entire scoreboard might be empty!
00694          if (this.get_n_pending() == 0) this.notify.indicate(EMPTY);
00695       end
00696 
00697       return null;
00698    end      
00699 
00700    // Found!
00701    begin
00702       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00703       int n = 1;
00704 
00705       this.notify.indicate(MATCHED, status);
00706       `vmm_callback(vmm_sb_ds_callbacks,
00707                        matched(this, pkt, exp_stream_id, inp_stream_id, n));
00708       if (!silent) pkt_stream.n_matched += n;
00709    end
00710 
00711    pkt = pkt_stream.pkts.pop_front();
00712    if (pkt_stream.pkts.size() == 0) begin
00713       // The entire scoreboard might be empty!
00714       if (this.get_n_pending() == 0) this.notify.indicate(EMPTY);
00715    end
00716 
00717    return pkt;
00718 
00719 endfunction: expect_in_order
00720 
00721 
00722 function bit vmm_sb_ds::expect_with_losses(input  vmm_data pkt,
00723                                            output vmm_data matched,
00724                                            output vmm_data lost[],
00725                                            input  int      exp_stream_id = -1,
00726                                            input  int      inp_stream_id = -1,
00727                                            input  bit      silent = 0);
00728 
00729    vmm_sb_ds_exp_streams exp_streams;
00730    vmm_sb_ds_pkt_stream  pkt_stream;
00731    int                   match_idx;
00732 
00733    matched = null;
00734    lost = new [0];
00735 
00736    if (inp_stream_id < 0) begin
00737       inp_stream_id = this.stream_id(pkt, INPUT);
00738    end
00739    if (exp_stream_id < 0) begin
00740       exp_stream_id = this.stream_id(pkt, EXPECT);
00741    end
00742 
00743    `vmm_debug(this.log, $psprintf("Looking for packet on stream #%0d->#%0d",
00744                                   inp_stream_id, exp_stream_id));
00745    `vmm_verbose(this.log, pkt.psdisplay("   "));
00746 
00747    if (!this.Xexp_streamsX.exists(exp_stream_id)) begin
00748       // Not found because the output stream does not exist!
00749       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00750       int n = 1;
00751 
00752       this.notify.indicate(NOT_FOUND, status);
00753       `vmm_callback(vmm_sb_ds_callbacks,
00754                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00755 
00756       if (!silent) begin
00757          this.n_not_found += n;
00758          `vmm_error(this.log, $psprintf("With-loss packet was not found: EXPECT stream #%0d does not exist.", exp_stream_id));
00759       end
00760       return 0;
00761    end
00762    exp_streams = this.Xexp_streamsX[exp_stream_id];
00763 
00764    if (!exp_streams.pkt_streams.exists(inp_stream_id)) begin
00765       // Not found because the input stream does not exist!
00766       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00767       int n = 1;
00768 
00769       this.notify.indicate(NOT_FOUND, status);
00770       `vmm_callback(vmm_sb_ds_callbacks,
00771                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00772 
00773       if (!silent) begin
00774          this.n_not_found += n;
00775          `vmm_error(this.log, $psprintf("With-loss packet was not found: Stream #%0d->%0d does not exist.", inp_stream_id, exp_stream_id));
00776       end
00777       return 0;
00778    end
00779    pkt_stream = exp_streams.pkt_streams[inp_stream_id];
00780 
00781    if (pkt_stream.pkts.size() == 0) begin
00782       // Not found because the packet stream is empty!
00783       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00784       int n = 1;
00785 
00786       this.notify.indicate(NOT_FOUND, status);
00787       `vmm_callback(vmm_sb_ds_callbacks,
00788                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00789 
00790       if (!silent) begin
00791          pkt_stream.n_not_found += n;
00792          `vmm_error(this.log, $psprintf("With-loss packet was not found: Stream #%0d->%0d is empty.", inp_stream_id, exp_stream_id));
00793       end
00794       return 0;
00795    end      
00796 
00797    foreach (pkt_stream.pkts[i]) begin
00798       if (this.match(pkt, pkt_stream.pkts[i])) begin
00799          // We have a match!
00800          matched = pkt_stream.pkts[i];
00801          match_idx = i;
00802          break;
00803       end
00804    end
00805    if (matched == null) begin
00806       // Not found because no packet matched
00807       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00808       int n = 1;
00809 
00810       this.notify.indicate(NOT_FOUND, status);
00811       `vmm_callback(vmm_sb_ds_callbacks,
00812                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00813 
00814       if (!silent) begin
00815          this.n_not_found += n;
00816          `vmm_error(this.log, {"With-loss packet was not matched:\n",
00817                                pkt.psdisplay("   ")});
00818       end
00819       return 0;
00820    end
00821 
00822 
00823    // Everything between the matching packet and the head
00824    // of the packet stream is assumed to have been lost
00825    if (match_idx > 0) begin
00826       lost = new [match_idx];
00827       foreach (lost[i]) begin
00828          lost[i] = pkt_stream.pkts[i];
00829       end
00830 
00831       begin
00832          vmm_sb_ds_pkts status = new(null, EXPECT, exp_stream_id, inp_stream_id);
00833          int n = lost.size();
00834 
00835          status.pkts = new [lost.size()] (lost);
00836          this.notify.indicate(DROPPED, status);
00837          `vmm_callback(vmm_sb_ds_callbacks,
00838                           dropped(this, status.pkts, exp_stream_id, inp_stream_id, n));
00839          if (!silent) pkt_stream.n_dropped += n;
00840       end
00841    end
00842    repeat (match_idx + 1) void'(pkt_stream.pkts.pop_front());
00843    if (pkt_stream.pkts.size() == 0) begin
00844       // The entire scoreboard might be empty!
00845       if (this.get_n_pending() == 0) this.notify.indicate(EMPTY);
00846    end
00847 
00848    if (!this.compare(pkt, matched)) begin
00849       // Mis-match!
00850 
00851        `vmm_trace(this.log, $psprintf("packet mismatched expected packet in stream #%0d->#%0d\n%s\n%s",
00852                                   inp_stream_id, exp_stream_id,
00853                                   pkt.psdisplay("   Actual:"),
00854                                   matched.psdisplay("   Msmtch:")));
00855 
00856       begin
00857          vmm_sb_ds_pkts status = new(null, EXPECT, exp_stream_id, inp_stream_id);
00858          int n = 1;
00859 
00860          status.pkts = new [2];
00861          status.pkts[0] = pkt;
00862          status.pkts[1] = matched;
00863 
00864          this.notify.indicate(MISMATCHED, status);
00865          `vmm_callback(vmm_sb_ds_callbacks,
00866                           mismatched(this, pkt, exp_stream_id, inp_stream_id, n));
00867          if (!silent) pkt_stream.n_mismatched += n;
00868       end
00869 
00870       if (!silent) begin
00871          `vmm_error(this.log, $psprintf("With-loss packet was not found"));
00872       end
00873       return 0;
00874    end
00875 
00876    begin
00877       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00878       int n = 1;
00879 
00880       this.notify.indicate(MATCHED, status);
00881       `vmm_callback(vmm_sb_ds_callbacks,
00882                        matched(this, pkt, exp_stream_id, inp_stream_id, n));
00883       if (!silent) pkt_stream.n_matched += n;
00884    end
00885 
00886    return 1;
00887 endfunction: expect_with_losses
00888 
00889 
00890 function vmm_data vmm_sb_ds::expect_out_of_order(vmm_data pkt,
00891                                                  int      exp_stream_id = -1,
00892                                                  int      inp_stream_id = -1,
00893                                                  bit      silent = 0);
00894    vmm_sb_ds_exp_streams exp_streams;
00895    vmm_sb_ds_pkt_stream  pkt_stream;
00896    int                   match_idx;
00897 
00898    if (inp_stream_id < 0) begin
00899       inp_stream_id = this.stream_id(pkt, INPUT);
00900    end
00901    if (exp_stream_id < 0) begin
00902       exp_stream_id = this.stream_id(pkt, EXPECT);
00903    end
00904 
00905    `vmm_debug(this.log, $psprintf("Looking for out-of-order packet on stream #%0d->#%0d",
00906                                   inp_stream_id, exp_stream_id));
00907    `vmm_verbose(this.log, pkt.psdisplay("   "));
00908 
00909    if (!this.Xexp_streamsX.exists(exp_stream_id)) begin
00910       // Not found because the output stream does not exist!
00911       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00912       int n = 1;
00913 
00914       this.notify.indicate(NOT_FOUND, status);
00915       `vmm_callback(vmm_sb_ds_callbacks,
00916                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00917 
00918       if (!silent) begin
00919          this.n_not_found += n;
00920          `vmm_error(this.log, $psprintf("Out-of-order packet was not found: EXPECT stream #%0d does not exist.", exp_stream_id));
00921       end
00922       return null;
00923    end
00924    exp_streams = this.Xexp_streamsX[exp_stream_id];
00925 
00926    if (!exp_streams.pkt_streams.exists(inp_stream_id)) begin
00927       // Not found because the input stream does not exist!
00928       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00929       int n = 1;
00930 
00931       this.notify.indicate(NOT_FOUND, status);
00932       `vmm_callback(vmm_sb_ds_callbacks,
00933                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00934 
00935       if (!silent) begin
00936          this.n_not_found += n;
00937          `vmm_error(this.log, $psprintf("Out-of-order packet was not found: stream %0d->%0d does not exist.", inp_stream_id, exp_stream_id));
00938       end
00939       return null;
00940    end
00941    pkt_stream = exp_streams.pkt_streams[inp_stream_id];
00942 
00943    if (pkt_stream.pkts.size() == 0) begin
00944       // Not found because the packet stream is empty!
00945       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00946       int n = 1;
00947 
00948       this.notify.indicate(NOT_FOUND, status);
00949       `vmm_callback(vmm_sb_ds_callbacks,
00950                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00951 
00952       if (!silent) begin
00953          pkt_stream.n_not_found += n;
00954          `vmm_error(this.log, $psprintf("Out-of-order packet was not found: stream %0d->%0d is empty.", inp_stream_id, exp_stream_id));
00955       end
00956       return null;
00957    end      
00958 
00959    foreach (pkt_stream.pkts[i]) begin
00960       if (this.compare(pkt, pkt_stream.pkts[i])) begin
00961          // We have a match!
00962          begin
00963             vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00964             int n = 1;
00965 
00966             this.notify.indicate(MATCHED, status);
00967             `vmm_callback(vmm_sb_ds_callbacks,
00968                              matched(this, pkt, exp_stream_id, inp_stream_id, n));
00969             if (!silent) pkt_stream.n_matched += n;
00970          end
00971 
00972          pkt = pkt_stream.pkts[i];
00973          pkt_stream.pkts.delete(i);
00974          if (pkt_stream.pkts.size() == 0) begin
00975             // The entire scoreboard might be empty!
00976             if (this.get_n_pending() == 0) this.notify.indicate(EMPTY);
00977          end
00978          return pkt;
00979       end
00980    end
00981 
00982    begin
00983       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00984       int n = 1;
00985 
00986       this.notify.indicate(NOT_FOUND, status);
00987       `vmm_callback(vmm_sb_ds_callbacks,
00988                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00989       if (!silent) pkt_stream.n_not_found += n;
00990    end
00991 
00992    if (!silent) begin
00993       `vmm_error(this.log, "Out-of-order packet was not found");
00994    end
00995    return null;
00996 endfunction: expect_out_of_order
00997 
00998 
00999 function void vmm_sb_ds::flush();
01000    this.Xinp_stream_descsX.delete();
01001    this.Xexp_stream_descsX.delete();
01002    this.Xexp_streamsX.delete();
01003    this.Xdefine_stream_calledX = 0;
01004 
01005    this.n_not_found = 0;
01006    this.orphaned = 0;
01007    this.insert_recursed = 0;
01008 
01009    this.notify.indicate(EMPTY);
01010 endfunction: flush
01011 
01012 
01013 function vmm_sb_ds_iter vmm_sb_ds::new_sb_iter(int exp_stream_id = -1,
01014                                                int inp_stream_id = -1);
01015 
01016    vmm_sb_ds_iter iter = new(this, exp_stream_id, inp_stream_id);
01017 
01018    return iter;
01019 endfunction: new_sb_iter
01020 
01021 function vmm_sb_ds_stream_iter vmm_sb_ds::new_stream_iter(int exp_stream_id = -1,
01022                                                           int inp_stream_id = -1);
01023 
01024    vmm_sb_ds_stream_iter iter = new(this, null, exp_stream_id, inp_stream_id);
01025    return iter;
01026 endfunction: new_stream_iter
01027 
01028 
01029 function void vmm_sb_ds::prepend_callback(vmm_sb_ds_callbacks cb);
01030    if (cb == null) begin
01031       `vmm_error(this.log, "Attempting to prepend a NULL callback extension");
01032       return;
01033    end
01034 
01035    foreach(this.callbacks[i]) begin
01036       if (this.callbacks[i] == cb) begin
01037          `vmm_warning(this.log, "Callback has already been registered");
01038          return;
01039       end
01040    end
01041    //Prepend new callback
01042    this.callbacks.push_front(cb);
01043 endfunction: prepend_callback
01044 
01045 
01046 function void vmm_sb_ds::append_callback(vmm_sb_ds_callbacks cb);
01047    if (cb == null) begin
01048       `vmm_error(this.log, "Attempting to append a NULL callback extension");
01049       return;
01050    end
01051 
01052    foreach(this.callbacks[i]) begin
01053       if (this.callbacks[i] == cb) begin
01054          `vmm_warning(this.log, "Callback has already been registered");
01055          return;
01056       end
01057    end
01058    //Append new callback
01059    this.callbacks.push_back(cb);
01060 endfunction: append_callback
01061 
01062 
01063 function void vmm_sb_ds::unregister_callback(vmm_sb_ds_callbacks cb);
01064    foreach(this.callbacks[i]) begin
01065       if (this.callbacks[i] == cb) begin
01066          // Unregister it
01067          this.callbacks.delete(i);
01068          return;
01069       end
01070    end
01071 
01072    `vmm_warning(this.log, "Callback was not registered");
01073 endfunction: unregister_callback
01074 
01075 
01076 function int vmm_sb_ds::get_n_inserted(int exp_stream_id = -1,
01077                                        int inp_stream_id = -1);
01078    int n = 0;
01079 
01080    vmm_sb_ds_iter iter;
01081    iter = new (this, exp_stream_id, inp_stream_id);
01082    while (iter.next()) begin
01083       vmm_sb_ds_pkt_stream pkt_str;
01084       pkt_str = iter.Xget_pkt_streamX();
01085       n += pkt_str.n_inserted;
01086    end
01087 
01088    return n;
01089 endfunction: get_n_inserted
01090 
01091 
01092 function int vmm_sb_ds::get_n_pending(int exp_stream_id = -1,
01093                                       int inp_stream_id = -1);
01094    int n = 0;
01095 
01096    vmm_sb_ds_iter iter = new (this, exp_stream_id, inp_stream_id);
01097    while (iter.next()) begin
01098       vmm_sb_ds_pkt_stream pkt_str = iter.Xget_pkt_streamX();
01099       n += pkt_str.pkts.size();
01100    end
01101 
01102    return n;
01103 endfunction: get_n_pending
01104 
01105 
01106 function int vmm_sb_ds::get_n_matched(int exp_stream_id = -1,
01107                                       int inp_stream_id = -1);
01108    int n = 0;
01109 
01110    vmm_sb_ds_iter iter = new (this, exp_stream_id, inp_stream_id);
01111    while (iter.next()) begin
01112       vmm_sb_ds_pkt_stream pkt_str = iter.Xget_pkt_streamX();
01113       n += pkt_str.n_matched;
01114    end
01115 
01116    return n;
01117 endfunction: get_n_matched
01118 
01119 
01120 function int vmm_sb_ds::get_n_mismatched(int exp_stream_id = -1,
01121                                          int inp_stream_id = -1);
01122    int n = 0;
01123 
01124    vmm_sb_ds_iter iter = new (this, exp_stream_id, inp_stream_id);
01125    while (iter.next()) begin
01126       vmm_sb_ds_pkt_stream pkt_str = iter.Xget_pkt_streamX();
01127       n += pkt_str.n_mismatched;
01128    end
01129 
01130    return n;
01131 endfunction: get_n_mismatched
01132 
01133 
01134 function int vmm_sb_ds::get_n_dropped(int exp_stream_id = -1,
01135                                       int inp_stream_id = -1);
01136    int n = 0;
01137 
01138    vmm_sb_ds_iter iter = new (this, exp_stream_id, inp_stream_id);
01139    while (iter.next()) begin
01140       vmm_sb_ds_pkt_stream pkt_str = iter.Xget_pkt_streamX();
01141       n += pkt_str.n_dropped;
01142    end
01143 
01144    return n;
01145 endfunction: get_n_dropped
01146 
01147 
01148 function int vmm_sb_ds::get_n_not_found(int exp_stream_id = -1,
01149                                         int inp_stream_id = -1);
01150    int n = 0;
01151 
01152 
01153    vmm_sb_ds_iter iter = new (this, exp_stream_id, inp_stream_id);
01154 
01155    while (iter.next()) begin
01156       vmm_sb_ds_pkt_stream pkt_str = iter.Xget_pkt_streamX();
01157       n += pkt_str.n_not_found;
01158    end
01159 
01160    if (exp_stream_id < 0 || inp_stream_id < 0) n += this.n_not_found;
01161 
01162    return n;
01163 endfunction: get_n_not_found
01164 
01165 
01166 function int vmm_sb_ds::get_n_orphaned(int exp_stream_id = -1,
01167                                        int inp_stream_id = -1);
01168 
01169    if (!this.orphaned) begin
01170       vmm_sb_ds_iter iter = new (this, exp_stream_id, inp_stream_id);
01171       vmm_data pkts[$];
01172       while (iter.next()) begin
01173          vmm_sb_ds_pkt_stream pkt_stream = iter.Xget_pkt_streamX();
01174 
01175          // Not yet supported in SP1
01176          // pkts = '{pkts, pkt_stream.pkts};
01177          foreach (pkt_stream.pkts[i]) pkts.push_back(pkt_stream.pkts[i]);
01178       end
01179 
01180       if (pkts.size() > 0) begin
01181          vmm_sb_ds_pkts status = new(null, EXPECT, -1, -1);
01182          int n = pkts.size();
01183 
01184          status.pkts = new [pkts.size()];
01185          foreach (pkts[i]) status.pkts[i] = pkts[i];
01186          this.notify.indicate(ORPHANED, status);
01187          `vmm_callback(vmm_sb_ds_callbacks,
01188                           orphaned(this, status.pkts,
01189                                    exp_stream_id, inp_stream_id, n));
01190          this.n_orphaned = n;
01191       end
01192 
01193       this.orphaned = 1;
01194    end
01195 
01196    return this.n_orphaned;
01197 endfunction: get_n_orphaned
01198 
01199 
01200 function void vmm_sb_ds::report(int exp_stream_id = -1,
01201                                 int inp_stream_id = -1);
01202    vmm_sb_ds_iter iter = new (this, exp_stream_id, inp_stream_id);
01203 
01204    string s = this.log.get_instance();
01205    if (s.len() < 30) s = {s, {(30 - s.len()){" "}}};
01206    else if (s.len() > 30) s = s.substr(0, 29);
01207           
01208    $write("+--------------------------------+------+------+------+------+------+------+\n");
01209    $write("| %s |%s|%s|%s|%s|%s|%s|\n", s,
01210           "Insert", "Matchd", "MsMtch", "Droppd", "NotFnd", "Orphan");
01211    $write("+--------------------------------+------+------+------+------+------+------+\n");
01212 
01213    while (iter.next()) begin
01214       s = iter.describe();
01215       if (s.len() < 30) s = {s, {(30 - s.len()){" "}}};
01216       else if (s.len() > 30) s = s.substr(0, 29);
01217       $write("| %s | %04d | %04d | %04d | %04d | %04d | %04d |\n", s,
01218              iter.get_n_inserted(), iter.get_n_matched(),
01219              iter.get_n_mismatched(), iter.get_n_dropped(),
01220              iter.get_n_not_found(), iter.get_n_orphaned());
01221    end
01222    $write("+--------------------------------+------+------+------+------+------+------+\n");
01223    $write("|                          TOTAL | %04d | %04d | %04d | %04d | %04d | %04d |\n",
01224           this.get_n_inserted(exp_stream_id, inp_stream_id),
01225           this.get_n_matched(exp_stream_id, inp_stream_id),
01226           this.get_n_mismatched(exp_stream_id, inp_stream_id),
01227           this.get_n_dropped(exp_stream_id, inp_stream_id),
01228           this.get_n_not_found(exp_stream_id, inp_stream_id),
01229           this.get_n_orphaned(exp_stream_id, inp_stream_id));
01230    $write("+--------------------------------+------+------+------+------+------+------+\n\n");
01231 endfunction: report
01232 
01233 
01234 function void vmm_sb_ds::describe();
01235    vmm_sb_ds_iter iter = this.new_sb_iter();
01236 
01237    $write("Streams in Data Stream Scoreboard \"%s\":\n",
01238           this.log.get_instance());
01239 
01240    while (iter.next()) begin
01241       $write("   %s\n", iter.describe());
01242    end
01243 endfunction: describe
01244 
01245 
01246 function void vmm_sb_ds::display(string prefix = "");
01247    $write("%sContent of Data Stream Scoreboard \"%s\":\n", prefix, 
01248           this.log.get_instance());
01249 
01250    if (this.Xparallel_streamsX) begin
01251       foreach (this.Xexp_streamsX[k]) begin
01252          vmm_sb_ds_exp_streams exp_str = this.Xexp_streamsX[k];
01253          vmm_sb_ds_pkt_stream  pkt_str = exp_str.pkt_streams[k];
01254 
01255          if (pkt_str == null) continue;
01256 
01257          $write("%s   Stream #%0d", prefix, k);
01258          if (this.Xexp_stream_descsX.exists(k)) begin
01259             $write(" (%s)", this.Xexp_stream_descsX[k]);
01260          end
01261          $write(":\n");
01262 
01263          foreach (pkt_str.pkts[i]) begin
01264             pkt_str.pkts[i].display({prefix, "      "});
01265          end
01266       end
01267 
01268       return;
01269    end
01270 
01271    foreach (this.Xexp_streamsX[k]) begin
01272       vmm_sb_ds_exp_streams exp_str = this.Xexp_streamsX[k];
01273 
01274       $write("%s   To stream #%0d", prefix, k);
01275       if (this.Xexp_stream_descsX.exists(k)) begin
01276          $write(" (%s)", this.Xexp_stream_descsX[k]);
01277       end
01278       $write(":\n");
01279       foreach (exp_str.pkt_streams[j]) begin
01280          vmm_sb_ds_pkt_stream pkt_str = exp_str.pkt_streams[j];
01281 
01282          $write("%s      From stream #%0d", prefix, j);
01283          if (this.Xinp_stream_descsX.exists(j)) begin
01284             $write(" (%s)", this.Xinp_stream_descsX[j]);
01285          end
01286          $write(":\n");
01287          foreach (pkt_str.pkts[i]) begin
01288             pkt_str.pkts[i].display({prefix, "      "});
01289          end
01290       end
01291    end
01292 endfunction: display
01293 
01294 
01295 `endif // VMM_SB_DS_SV