VMM - sb/vmm_sb_ds.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[*];
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[*];
00063    /*local*/ string                Xinp_stream_descsX[*];
00064    /*local*/ string                Xexp_stream_descsX[*];
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    this.notify.configure(INSERTED,   vmm_notify::ONE_SHOT);
00317    this.notify.configure(EMPTY,      vmm_notify::ON_OFF);
00318    this.notify.configure(MATCHED,    vmm_notify::ONE_SHOT);
00319    this.notify.configure(MISMATCHED, vmm_notify::ONE_SHOT);
00320    this.notify.configure(DROPPED,    vmm_notify::ONE_SHOT);
00321    this.notify.configure(NOT_FOUND,  vmm_notify::ONE_SHOT);
00322    this.notify.configure(ORPHANED,   vmm_notify::ONE_SHOT);
00323 
00324    this.notify.indicate(EMPTY);
00325 endfunction: new
00326 
00327 
00328 function int vmm_sb_ds::stream_id(vmm_data          pkt,
00329                                   vmm_sb_ds::kind_e kind);
00330    return 0;
00331 endfunction: stream_id
00332 
00333 
00334 function void vmm_sb_ds::define_stream(int               stream_id,
00335                                        string            descr,
00336                                        vmm_sb_ds::kind_e kind);
00337    if (stream_id < 0) begin
00338       `vmm_error(this.log, "vmm_sb_ds::define_stream() called with negative stream_id");
00339       return;
00340    end
00341 
00342    case (kind)
00343      EITHER: begin
00344         if (this.Xdefine_stream_calledX && !this.Xparallel_streamsX) begin
00345            `vmm_error(this.log, "vmm_sb_ds::define_stream(): Attempting to define a mix of EITHER and INPUT/EXPECT streams");
00346         end
00347         else begin
00348            this.Xinp_stream_descsX[stream_id] = descr;
00349            this.Xexp_stream_descsX[stream_id] = descr;
00350            this.Xparallel_streamsX = 1;
00351         end
00352      end
00353 
00354      INPUT: begin
00355         if (this.Xdefine_stream_calledX && this.Xparallel_streamsX) begin
00356            `vmm_error(this.log, "vmm_sb_ds::define_stream(): Attempting to define a mix of EITHER and INPUT/EXPECT streams");
00357         end
00358         else begin
00359            this.Xinp_stream_descsX[stream_id] = descr;
00360         end
00361      end
00362 
00363      EXPECT: begin
00364         if (this.Xdefine_stream_calledX && this.Xparallel_streamsX) begin
00365            `vmm_error(this.log, "vmm_sb_ds::define_stream(): Attempting to define a mix of EITHER and INPUT/EXPECT streams");
00366         end
00367         else begin
00368            this.Xexp_stream_descsX[stream_id] = descr;
00369         end
00370      end
00371    endcase
00372    
00373    this.Xdefine_stream_calledX = 1;
00374    
00375 endfunction: define_stream
00376 
00377 
00378 function bit vmm_sb_ds::insert(vmm_data          pkt,
00379                                vmm_sb_ds::kind_e kind,
00380                                int               exp_stream_id,
00381                                int               inp_stream_id);
00382    vmm_sb_ds_exp_streams exp_streams;
00383    vmm_sb_ds_pkt_stream  pkt_stream;
00384    bit drop;
00385 
00386    if (kind == EITHER) begin
00387       `vmm_error(this.log, "vmm_sb_ds::insert() called with EITHER packet kind");
00388       return 0;
00389    end
00390 
00391    drop = 0;
00392    `vmm_callback(vmm_sb_ds_callbacks,
00393                  pre_insert(this, pkt, kind,
00394                             exp_stream_id, inp_stream_id, drop));
00395    if (drop) return 1;
00396 
00397    if (inp_stream_id < 0) begin
00398       inp_stream_id = this.stream_id(pkt, INPUT);
00399    end
00400    if (this.Xdefine_stream_calledX) begin
00401       if (!Xinp_stream_descsX.exists(inp_stream_id)) begin
00402          `vmm_error(this.log, $psprintf("vmm_sb_ds::insert() called with undefined input stream #%0d",
00403                                         inp_stream_id));
00404          return 0;
00405       end
00406    end
00407 
00408    if (kind == INPUT) begin
00409       vmm_data out_pkts[];
00410       
00411       `vmm_debug(this.log, $psprintf("Inserting INPUT packet in stream #%0d",
00412                                      inp_stream_id));
00413       `vmm_verbose(this.log, pkt.psdisplay("   "));
00414 
00415       this.transform(pkt, out_pkts);
00416       this.insert_recursed = 1;
00417       foreach (out_pkts[i])  begin
00418          this.insert(out_pkts[i], EXPECT, exp_stream_id, inp_stream_id);
00419       end
00420       this.insert_recursed = 0;
00421 
00422       begin
00423          vmm_sb_ds_pkts status = new(null, EXPECT, exp_stream_id, inp_stream_id);
00424          status.pkts = new [out_pkts.size()] (out_pkts);
00425          this.notify.indicate(INSERTED, status);
00426       end
00427 
00428       return 1;
00429    end
00430 
00431    // Must be an EXPECT packet
00432    if (exp_stream_id < 0) begin
00433       exp_stream_id = this.stream_id(pkt, EXPECT);
00434    end
00435    
00436    if (this.Xdefine_stream_calledX) begin
00437       if (!Xexp_stream_descsX.exists(exp_stream_id)) begin
00438          `vmm_error(this.log, $psprintf("vmm_sb_ds::insert() called with undefined expected stream #%0d",
00439                                         exp_stream_id));
00440          return 0;
00441       end
00442    end
00443    
00444    `vmm_debug(this.log, $psprintf("Inserting EXPECT packet in stream #%0d->#%0d",
00445                                   inp_stream_id, exp_stream_id));
00446    `vmm_verbose(this.log, pkt.psdisplay("   "));
00447 
00448    if (!this.Xexp_streamsX.exists(exp_stream_id)) begin
00449       exp_streams = new();
00450       this.Xexp_streamsX[exp_stream_id] = exp_streams;
00451    end
00452    else 
00453       exp_streams = this.Xexp_streamsX[exp_stream_id];
00454 
00455    if (!exp_streams.pkt_streams.exists(inp_stream_id)) begin
00456       pkt_stream = new();
00457       exp_streams.pkt_streams[inp_stream_id] = pkt_stream;
00458    end
00459    else 
00460       pkt_stream = exp_streams.pkt_streams[inp_stream_id];
00461 
00462    pkt_stream.pkts.push_back(pkt);
00463    this.notify.reset(EMPTY);
00464 
00465    pkt_stream.n_inserted++;
00466    if (!this.insert_recursed) begin
00467       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00468       this.notify.indicate(INSERTED, status);
00469    end
00470    `vmm_callback(vmm_sb_ds_callbacks,
00471                  post_insert(this, pkt, exp_stream_id, inp_stream_id));
00472 
00473    return 1;
00474 endfunction: insert
00475 
00476 
00477 function bit vmm_sb_ds::remove(vmm_data          pkt,
00478                                vmm_sb_ds::kind_e kind,
00479                                int               exp_stream_id,
00480                                int               inp_stream_id);
00481 
00482    vmm_sb_ds_exp_streams exp_streams;
00483    vmm_sb_ds_pkt_stream  pkt_stream;
00484 
00485    if (kind == EITHER) begin
00486       `vmm_error(this.log, "vmm_sb_ds::remove() called with EITHER packet kind");
00487       return 0;
00488    end
00489 
00490    if (inp_stream_id < 0) begin
00491       inp_stream_id = this.stream_id(pkt, INPUT);
00492    end
00493    if (this.Xdefine_stream_calledX) begin
00494       if (!Xinp_stream_descsX.exists(inp_stream_id)) begin
00495          `vmm_error(this.log, $psprintf("vmm_sb_ds::remove() called with undefined input stream #%0d",
00496                                         inp_stream_id));
00497          return 0;
00498       end
00499    end
00500 
00501    if (kind == INPUT) begin
00502       vmm_data out_pkts[];
00503       bit      rc = 1;
00504       
00505       `vmm_trace(this.log, $psprintf("Deleting INPUT packet from stream #%0d",
00506                                      inp_stream_id));
00507       `vmm_verbose(this.log, pkt.psdisplay("   "));
00508 
00509       this.transform(pkt, out_pkts);
00510       foreach (out_pkts[i])  begin
00511          rc |= this.remove(out_pkts[i], EXPECT, inp_stream_id, exp_stream_id);
00512       end
00513 
00514       return rc;
00515    end
00516 
00517    // Must be an EXPECT packet
00518    if (exp_stream_id < 0) begin
00519       exp_stream_id = this.stream_id(pkt, EXPECT);
00520    end
00521    
00522    if (this.Xdefine_stream_calledX) begin
00523       if (!Xexp_stream_descsX.exists(exp_stream_id)) begin
00524          `vmm_error(this.log, $psprintf("vmm_sb_ds::remove() called with undefined expected stream #%0d",
00525                                         exp_stream_id));
00526          return 0;
00527       end
00528    end
00529    
00530    `vmm_trace(this.log, $psprintf("Deleting EXPECT packet from stream #%0d->#%0d",
00531                                   inp_stream_id, exp_stream_id));
00532    `vmm_verbose(this.log, pkt.psdisplay("   "));
00533 
00534    if (!this.Xexp_streamsX.exists(exp_stream_id)) begin
00535       `vmm_error(this.log, $psprintf("vmm_sb_ds::remove(): Cannot find packet to remove: expected stream #%0d does not exist",
00536                                      exp_stream_id));
00537       return 0;
00538    end
00539    exp_streams = this.Xexp_streamsX[exp_stream_id];
00540 
00541    if (!exp_streams.pkt_streams.exists(inp_stream_id)) begin
00542       `vmm_error(this.log, $psprintf("vmm_sb_ds::remove(): Cannot find packet to remove: stream #%0d->#%0d does not exist.",
00543                                      inp_stream_id, exp_stream_id));
00544       return 0;
00545    end
00546    pkt_stream = exp_streams.pkt_streams[inp_stream_id];
00547 
00548    foreach (pkt_stream.pkts[i]) begin
00549       if (this.compare(pkt, pkt_stream.pkts[i])) begin
00550          pkt_stream.pkts.delete(i);
00551          if (pkt_stream.pkts.size() == 0) begin
00552             // The entire scoreboard might be empty!
00553             if (this.get_n_pending() == 0) this.notify.indicate(EMPTY);
00554          end
00555          return 1;
00556       end
00557    end
00558 
00559    `vmm_error(this.log, "vmm_sb_ds::remove(): Cannot find packet to remove");
00560 
00561    return 0;
00562 endfunction: remove
00563 
00564 
00565 function bit vmm_sb_ds::transform(input  vmm_data in_pkt,
00566                                   output vmm_data out_pkts[]);
00567    out_pkts    = new [1];
00568    out_pkts[0] = in_pkt;
00569    
00570    return 1;
00571 endfunction: transform
00572 
00573 
00574 function bit vmm_sb_ds::match(vmm_data actual,
00575                               vmm_data expected);
00576    return this.quick_compare(actual, expected);
00577 endfunction: match
00578 
00579 
00580 function bit vmm_sb_ds::quick_compare(vmm_data actual,
00581                                       vmm_data expected);
00582    return 1;
00583 endfunction: quick_compare
00584 
00585 
00586 function bit vmm_sb_ds::compare(vmm_data actual,
00587                                 vmm_data expected);
00588 
00589    string diff;
00590    if (this.quick_compare(actual, expected)) begin
00591       return actual.compare(expected, diff);
00592    end
00593 
00594 endfunction: compare
00595 
00596 
00597 function vmm_data vmm_sb_ds::expect_in_order(vmm_data pkt,
00598                                              int      exp_stream_id,
00599                                              int      inp_stream_id,
00600                                              bit      silent);
00601 
00602    vmm_sb_ds_exp_streams exp_streams;
00603    vmm_sb_ds_pkt_stream  pkt_stream;
00604 
00605    if (exp_stream_id < 0) begin
00606       exp_stream_id = this.stream_id(pkt, EXPECT);
00607    end
00608    if (inp_stream_id < 0) begin
00609       inp_stream_id = this.stream_id(pkt, INPUT);
00610    end
00611 
00612    `vmm_debug(this.log, $psprintf("Expecting in-order packet on stream #%0d->#%0d",
00613                                   inp_stream_id, exp_stream_id));
00614    `vmm_verbose(this.log, pkt.psdisplay("   "));
00615 
00616    if (!this.Xexp_streamsX.exists(exp_stream_id)) begin
00617       // Not found because the output stream does not exist!
00618       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00619       int n = 1;
00620 
00621       this.notify.indicate(NOT_FOUND, status);
00622       `vmm_callback(vmm_sb_ds_callbacks,
00623                     not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00624 
00625       if (!silent) begin
00626          this.n_not_found += n;
00627          `vmm_error(this.log, $psprintf("In-order packet was not found: EXPECT stream #%0d does not exist.", exp_stream_id));
00628       end
00629       return null;
00630    end
00631    exp_streams = this.Xexp_streamsX[exp_stream_id];
00632 
00633    if (!exp_streams.pkt_streams.exists(inp_stream_id)) begin
00634       // Not found because the input stream does not exist!
00635       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00636       int n = 1;
00637 
00638       this.notify.indicate(NOT_FOUND, status);
00639       `vmm_callback(vmm_sb_ds_callbacks,
00640                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00641 
00642       if (!silent) begin
00643          this.n_not_found += n;
00644          `vmm_error(this.log, $psprintf("In-order packet was not found: stream #%0d->#%0d does not exist.", inp_stream_id, exp_stream_id));
00645       end
00646       return null;
00647    end
00648    pkt_stream = exp_streams.pkt_streams[inp_stream_id];
00649 
00650    if (pkt_stream.pkts.size() == 0) begin
00651       // Not found because the packet stream is empty!
00652       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00653       int n = 1;
00654 
00655       this.notify.indicate(NOT_FOUND, status);
00656       `vmm_callback(vmm_sb_ds_callbacks,
00657                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00658 
00659       if (!silent) begin
00660          pkt_stream.n_not_found += n;
00661          `vmm_error(this.log, $psprintf("In-order packet was not found: stream %0d->%0d is empty.", inp_stream_id, exp_stream_id));
00662       end
00663       return null;
00664    end      
00665 
00666    if (!this.compare(pkt, pkt_stream.pkts[0])) begin
00667       // Not found because the packet does not match
00668       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00669       int n = 1;
00670 
00671       this.notify.indicate(NOT_FOUND, status);
00672       `vmm_callback(vmm_sb_ds_callbacks,
00673                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00674 
00675       if (!silent) begin
00676          pkt_stream.n_not_found += n;
00677          `vmm_error(this.log, $psprintf("In-order packet was not expected:\n%s\n%s.", pkt.psdisplay("   Actual: "), pkt_stream.pkts[0].psdisplay("   Expect: ")));
00678       end
00679 
00680       // Remove the packet
00681       pkt_stream.pkts.pop_front();
00682       if (pkt_stream.pkts.size() == 0) begin
00683          // The entire scoreboard might be empty!
00684          if (this.get_n_pending() == 0) this.notify.indicate(EMPTY);
00685       end
00686 
00687       return null;
00688    end      
00689 
00690    // Found!
00691    begin
00692       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00693       int n = 1;
00694 
00695       this.notify.indicate(MATCHED, status);
00696       `vmm_callback(vmm_sb_ds_callbacks,
00697                        matched(this, pkt, exp_stream_id, inp_stream_id, n));
00698       if (!silent) pkt_stream.n_matched += n;
00699    end
00700 
00701    pkt = pkt_stream.pkts.pop_front();
00702    if (pkt_stream.pkts.size() == 0) begin
00703       // The entire scoreboard might be empty!
00704       if (this.get_n_pending() == 0) this.notify.indicate(EMPTY);
00705    end
00706 
00707    return pkt;
00708 
00709 endfunction: expect_in_order
00710 
00711 
00712 function bit vmm_sb_ds::expect_with_losses(input  vmm_data pkt,
00713                                            output vmm_data matched,
00714                                            output vmm_data lost[],
00715                                            input  int      exp_stream_id,
00716                                            input  int      inp_stream_id,
00717                                            input  bit      silent);
00718 
00719    vmm_sb_ds_exp_streams exp_streams;
00720    vmm_sb_ds_pkt_stream  pkt_stream;
00721    int                   match_idx;
00722 
00723    matched = null;
00724    lost = new [0];
00725 
00726    if (inp_stream_id < 0) begin
00727       inp_stream_id = this.stream_id(pkt, INPUT);
00728    end
00729    if (exp_stream_id < 0) begin
00730       exp_stream_id = this.stream_id(pkt, EXPECT);
00731    end
00732 
00733    `vmm_debug(this.log, $psprintf("Looking for packet on stream #%0d->#%0d",
00734                                   inp_stream_id, exp_stream_id));
00735    `vmm_verbose(this.log, pkt.psdisplay("   "));
00736 
00737    if (!this.Xexp_streamsX.exists(exp_stream_id)) begin
00738       // Not found because the output stream does not exist!
00739       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00740       int n = 1;
00741 
00742       this.notify.indicate(NOT_FOUND, status);
00743       `vmm_callback(vmm_sb_ds_callbacks,
00744                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00745 
00746       if (!silent) begin
00747          this.n_not_found += n;
00748          `vmm_error(this.log, $psprintf("With-loss packet was not found: EXPECT stream #%0d does not exist.", exp_stream_id));
00749       end
00750       return 0;
00751    end
00752    exp_streams = this.Xexp_streamsX[exp_stream_id];
00753 
00754    if (!exp_streams.pkt_streams.exists(inp_stream_id)) begin
00755       // Not found because the input stream does not exist!
00756       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00757       int n = 1;
00758 
00759       this.notify.indicate(NOT_FOUND, status);
00760       `vmm_callback(vmm_sb_ds_callbacks,
00761                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00762 
00763       if (!silent) begin
00764          this.n_not_found += n;
00765          `vmm_error(this.log, $psprintf("With-loss packet was not found: Stream #%0d->%0d does not exist.", inp_stream_id, exp_stream_id));
00766       end
00767       return 0;
00768    end
00769    pkt_stream = exp_streams.pkt_streams[inp_stream_id];
00770 
00771    if (pkt_stream.pkts.size() == 0) begin
00772       // Not found because the packet stream is empty!
00773       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00774       int n = 1;
00775 
00776       this.notify.indicate(NOT_FOUND, status);
00777       `vmm_callback(vmm_sb_ds_callbacks,
00778                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00779 
00780       if (!silent) begin
00781          pkt_stream.n_not_found += n;
00782          `vmm_error(this.log, $psprintf("With-loss packet was not found: Stream #%0d->%0d is empty.", inp_stream_id, exp_stream_id));
00783       end
00784       return 0;
00785    end      
00786 
00787    foreach (pkt_stream.pkts[i]) begin
00788       if (this.match(pkt, pkt_stream.pkts[i])) begin
00789          // We have a match!
00790          matched = pkt_stream.pkts[i];
00791          match_idx = i;
00792          break;
00793       end
00794    end
00795    if (matched == null) begin
00796       // Not found because no packet matched
00797       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00798       int n = 1;
00799 
00800       this.notify.indicate(NOT_FOUND, status);
00801       `vmm_callback(vmm_sb_ds_callbacks,
00802                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00803 
00804       if (!silent) begin
00805          this.n_not_found += n;
00806          `vmm_error(this.log, {"With-loss packet was not matched:\n",
00807                                pkt.psdisplay("   ")});
00808       end
00809       return 0;
00810    end
00811 
00812 
00813    // Everything between the matching packet and the head
00814    // of the packet stream is assumed to have been lost
00815    if (match_idx > 0) begin
00816       lost = new [match_idx];
00817       foreach (lost[i]) begin
00818          lost[i] = pkt_stream.pkts[i];
00819       end
00820 
00821       begin
00822          vmm_sb_ds_pkts status = new(null, EXPECT, exp_stream_id, inp_stream_id);
00823          int n = lost.size();
00824 
00825          status.pkts = new [lost.size()] (lost);
00826          this.notify.indicate(DROPPED, status);
00827          `vmm_callback(vmm_sb_ds_callbacks,
00828                           dropped(this, status.pkts, exp_stream_id, inp_stream_id, n));
00829          if (!silent) pkt_stream.n_dropped += n;
00830       end
00831    end
00832    repeat (match_idx + 1) pkt_stream.pkts.pop_front();
00833    if (pkt_stream.pkts.size() == 0) begin
00834       // The entire scoreboard might be empty!
00835       if (this.get_n_pending() == 0) this.notify.indicate(EMPTY);
00836    end
00837 
00838    if (!this.compare(pkt, matched)) begin
00839       // Mis-match!
00840 
00841        `vmm_trace(this.log, $psprintf("packet mismatched expected packet in stream #%0d->#%0d\n%s\n%s",
00842                                   inp_stream_id, exp_stream_id,
00843                                   pkt.psdisplay("   Actual:"),
00844                                   matched.psdisplay("   Msmtch:")));
00845 
00846       begin
00847          vmm_sb_ds_pkts status = new(null, EXPECT, exp_stream_id, inp_stream_id);
00848          int n = 1;
00849 
00850          status.pkts = new [2];
00851          status.pkts[0] = pkt;
00852          status.pkts[1] = matched;
00853 
00854          this.notify.indicate(MISMATCHED, status);
00855          `vmm_callback(vmm_sb_ds_callbacks,
00856                           mismatched(this, pkt, exp_stream_id, inp_stream_id, n));
00857          if (!silent) pkt_stream.n_mismatched += n;
00858       end
00859 
00860       if (!silent) begin
00861          `vmm_error(this.log, $psprintf("With-loss packet was not found"));
00862       end
00863       return 0;
00864    end
00865 
00866    begin
00867       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00868       int n = 1;
00869 
00870       this.notify.indicate(MATCHED, status);
00871       `vmm_callback(vmm_sb_ds_callbacks,
00872                        matched(this, pkt, exp_stream_id, inp_stream_id, n));
00873       if (!silent) pkt_stream.n_matched += n;
00874    end
00875 
00876    return 1;
00877 endfunction: expect_with_losses
00878 
00879 
00880 function vmm_data vmm_sb_ds::expect_out_of_order(vmm_data pkt,
00881                                                  int      exp_stream_id,
00882                                                  int      inp_stream_id,
00883                                                  bit      silent);
00884    vmm_sb_ds_exp_streams exp_streams;
00885    vmm_sb_ds_pkt_stream  pkt_stream;
00886    int                   match_idx;
00887 
00888    if (inp_stream_id < 0) begin
00889       inp_stream_id = this.stream_id(pkt, INPUT);
00890    end
00891    if (exp_stream_id < 0) begin
00892       exp_stream_id = this.stream_id(pkt, EXPECT);
00893    end
00894 
00895    `vmm_debug(this.log, $psprintf("Looking for out-of-order packet on stream #%0d->#%0d",
00896                                   inp_stream_id, exp_stream_id));
00897    `vmm_verbose(this.log, pkt.psdisplay("   "));
00898 
00899    if (!this.Xexp_streamsX.exists(exp_stream_id)) begin
00900       // Not found because the output stream does not exist!
00901       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00902       int n = 1;
00903 
00904       this.notify.indicate(NOT_FOUND, status);
00905       `vmm_callback(vmm_sb_ds_callbacks,
00906                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00907 
00908       if (!silent) begin
00909          this.n_not_found += n;
00910          `vmm_error(this.log, $psprintf("Out-of-order packet was not found: EXPECT stream #%0d does not exist.", exp_stream_id));
00911       end
00912       return null;
00913    end
00914    exp_streams = this.Xexp_streamsX[exp_stream_id];
00915 
00916    if (!exp_streams.pkt_streams.exists(inp_stream_id)) begin
00917       // Not found because the input stream does not exist!
00918       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00919       int n = 1;
00920 
00921       this.notify.indicate(NOT_FOUND, status);
00922       `vmm_callback(vmm_sb_ds_callbacks,
00923                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00924 
00925       if (!silent) begin
00926          this.n_not_found += n;
00927          `vmm_error(this.log, $psprintf("Out-of-order packet was not found: stream %0d->%0d does not exist.", inp_stream_id, exp_stream_id));
00928       end
00929       return null;
00930    end
00931    pkt_stream = exp_streams.pkt_streams[inp_stream_id];
00932 
00933    if (pkt_stream.pkts.size() == 0) begin
00934       // Not found because the packet stream is empty!
00935       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00936       int n = 1;
00937 
00938       this.notify.indicate(NOT_FOUND, status);
00939       `vmm_callback(vmm_sb_ds_callbacks,
00940                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00941 
00942       if (!silent) begin
00943          pkt_stream.n_not_found += n;
00944          `vmm_error(this.log, $psprintf("Out-of-order packet was not found: stream %0d->%0d is empty.", inp_stream_id, exp_stream_id));
00945       end
00946       return null;
00947    end      
00948 
00949    foreach (pkt_stream.pkts[i]) begin
00950       if (this.compare(pkt, pkt_stream.pkts[i])) begin
00951          // We have a match!
00952          begin
00953             vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00954             int n = 1;
00955 
00956             this.notify.indicate(MATCHED, status);
00957             `vmm_callback(vmm_sb_ds_callbacks,
00958                              matched(this, pkt, exp_stream_id, inp_stream_id, n));
00959             if (!silent) pkt_stream.n_matched += n;
00960          end
00961 
00962          pkt = pkt_stream.pkts[i];
00963          pkt_stream.pkts.delete(i);
00964          if (pkt_stream.pkts.size() == 0) begin
00965             // The entire scoreboard might be empty!
00966             if (this.get_n_pending() == 0) this.notify.indicate(EMPTY);
00967          end
00968          return pkt;
00969       end
00970    end
00971 
00972    begin
00973       vmm_sb_ds_pkts status = new(pkt, EXPECT, exp_stream_id, inp_stream_id);
00974       int n = 1;
00975 
00976       this.notify.indicate(NOT_FOUND, status);
00977       `vmm_callback(vmm_sb_ds_callbacks,
00978                        not_found(this, pkt, exp_stream_id, inp_stream_id, n));
00979       if (!silent) pkt_stream.n_not_found += n;
00980    end
00981 
00982    if (!silent) begin
00983       `vmm_error(this.log, "Out-of-order packet was not found");
00984    end
00985    return null;
00986 endfunction: expect_out_of_order
00987 
00988 
00989 function void vmm_sb_ds::flush();
00990    this.Xinp_stream_descsX.delete();
00991    this.Xexp_stream_descsX.delete();
00992    this.Xexp_streamsX.delete();
00993    this.Xdefine_stream_calledX = 0;
00994 
00995    this.n_not_found = 0;
00996    this.orphaned = 0;
00997    this.insert_recursed = 0;
00998 
00999    this.notify.indicate(EMPTY);
01000 endfunction: flush
01001 
01002 
01003 function vmm_sb_ds_iter vmm_sb_ds::new_sb_iter(int exp_stream_id,
01004                                                int inp_stream_id);
01005 
01006    vmm_sb_ds_iter iter = new(this, exp_stream_id, inp_stream_id);
01007 
01008    return iter;
01009 endfunction: new_sb_iter
01010 
01011 function vmm_sb_ds_stream_iter vmm_sb_ds::new_stream_iter(int exp_stream_id,
01012                                                           int inp_stream_id);
01013 
01014    vmm_sb_ds_stream_iter iter = new(this, null, exp_stream_id, inp_stream_id);
01015    return iter;
01016 endfunction: new_stream_iter
01017 
01018 
01019 function void vmm_sb_ds::prepend_callback(vmm_sb_ds_callbacks cb);
01020    if (cb == null) begin
01021       `vmm_error(this.log, "Attempting to prepend a NULL callback extension");
01022       return;
01023    end
01024 
01025    foreach(this.callbacks[i]) begin
01026       if (this.callbacks[i] == cb) begin
01027          `vmm_warning(this.log, "Callback has already been registered");
01028          return;
01029       end
01030    end
01031    //Prepend new callback
01032    this.callbacks.push_front(cb);
01033 endfunction: prepend_callback
01034 
01035 
01036 function void vmm_sb_ds::append_callback(vmm_sb_ds_callbacks cb);
01037    if (cb == null) begin
01038       `vmm_error(this.log, "Attempting to append a NULL callback extension");
01039       return;
01040    end
01041 
01042    foreach(this.callbacks[i]) begin
01043       if (this.callbacks[i] == cb) begin
01044          `vmm_warning(this.log, "Callback has already been registered");
01045          return;
01046       end
01047    end
01048    //Append new callback
01049    this.callbacks.push_back(cb);
01050 endfunction: append_callback
01051 
01052 
01053 function void vmm_sb_ds::unregister_callback(vmm_sb_ds_callbacks cb);
01054    foreach(this.callbacks[i]) begin
01055       if (this.callbacks[i] == cb) begin
01056          // Unregister it
01057          this.callbacks.delete(i);
01058          return;
01059       end
01060    end
01061 
01062    `vmm_warning(this.log, "Callback was not registered");
01063 endfunction: unregister_callback
01064 
01065 
01066 function int vmm_sb_ds::get_n_inserted(int exp_stream_id,
01067                                        int inp_stream_id);
01068    int n = 0;
01069 
01070    vmm_sb_ds_iter iter;
01071    iter = new (this, exp_stream_id, inp_stream_id);
01072    while (iter.next()) begin
01073       vmm_sb_ds_pkt_stream pkt_str;
01074       pkt_str = iter.Xget_pkt_streamX();
01075       n += pkt_str.n_inserted;
01076    end
01077 
01078    return n;
01079 endfunction: get_n_inserted
01080 
01081 
01082 function int vmm_sb_ds::get_n_pending(int exp_stream_id,
01083                                       int inp_stream_id);
01084    int n = 0;
01085 
01086    vmm_sb_ds_iter iter = new (this, exp_stream_id, inp_stream_id);
01087    while (iter.next()) begin
01088       vmm_sb_ds_pkt_stream pkt_str = iter.Xget_pkt_streamX();
01089       n += pkt_str.pkts.size();
01090    end
01091 
01092    return n;
01093 endfunction: get_n_pending
01094 
01095 
01096 function int vmm_sb_ds::get_n_matched(int exp_stream_id,
01097                                       int inp_stream_id);
01098    int n = 0;
01099 
01100    vmm_sb_ds_iter iter = new (this, exp_stream_id, inp_stream_id);
01101    while (iter.next()) begin
01102       vmm_sb_ds_pkt_stream pkt_str = iter.Xget_pkt_streamX();
01103       n += pkt_str.n_matched;
01104    end
01105 
01106    return n;
01107 endfunction: get_n_matched
01108 
01109 
01110 function int vmm_sb_ds::get_n_mismatched(int exp_stream_id,
01111                                          int inp_stream_id);
01112    int n = 0;
01113 
01114    vmm_sb_ds_iter iter = new (this, exp_stream_id, inp_stream_id);
01115    while (iter.next()) begin
01116       vmm_sb_ds_pkt_stream pkt_str = iter.Xget_pkt_streamX();
01117       n += pkt_str.n_mismatched;
01118    end
01119 
01120    return n;
01121 endfunction: get_n_mismatched
01122 
01123 
01124 function int vmm_sb_ds::get_n_dropped(int exp_stream_id,
01125                                       int inp_stream_id);
01126    int n = 0;
01127 
01128    vmm_sb_ds_iter iter = new (this, exp_stream_id, inp_stream_id);
01129    while (iter.next()) begin
01130       vmm_sb_ds_pkt_stream pkt_str = iter.Xget_pkt_streamX();
01131       n += pkt_str.n_dropped;
01132    end
01133 
01134    return n;
01135 endfunction: get_n_dropped
01136 
01137 
01138 function int vmm_sb_ds::get_n_not_found(int exp_stream_id,
01139                                         int inp_stream_id);
01140    int n = 0;
01141 
01142 
01143    vmm_sb_ds_iter iter = new (this, exp_stream_id, inp_stream_id);
01144 
01145    while (iter.next()) begin
01146       vmm_sb_ds_pkt_stream pkt_str = iter.Xget_pkt_streamX();
01147       n += pkt_str.n_not_found;
01148    end
01149 
01150    if (exp_stream_id < 0 || inp_stream_id < 0) n += this.n_not_found;
01151 
01152    return n;
01153 endfunction: get_n_not_found
01154 
01155 
01156 function int vmm_sb_ds::get_n_orphaned(int exp_stream_id,
01157                                        int inp_stream_id);
01158 
01159    if (!this.orphaned) begin
01160       vmm_sb_ds_iter iter = new (this, exp_stream_id, inp_stream_id);
01161       vmm_data pkts[$];
01162       while (iter.next()) begin
01163          vmm_sb_ds_pkt_stream pkt_stream = iter.Xget_pkt_streamX();
01164 
01165          // Not yet supported in SP1
01166          // pkts = '{pkts, pkt_stream.pkts};
01167          foreach (pkt_stream.pkts[i]) pkts.push_back(pkt_stream.pkts[i]);
01168       end
01169 
01170       if (pkts.size() > 0) begin
01171          vmm_sb_ds_pkts status = new(null, EXPECT, -1, -1);
01172          int n = pkts.size();
01173 
01174          status.pkts = new [pkts.size()];
01175          foreach (pkts[i]) status.pkts[i] = pkts[i];
01176          this.notify.indicate(ORPHANED, status);
01177          `vmm_callback(vmm_sb_ds_callbacks,
01178                           orphaned(this, status.pkts,
01179                                    exp_stream_id, inp_stream_id, n));
01180          this.n_orphaned = n;
01181       end
01182 
01183       this.orphaned = 1;
01184    end
01185 
01186    return this.n_orphaned;
01187 endfunction: get_n_orphaned
01188 
01189 
01190 function void vmm_sb_ds::report(int exp_stream_id,
01191                                 int inp_stream_id);
01192    vmm_sb_ds_iter iter = new (this, exp_stream_id, inp_stream_id);
01193 
01194    string s = this.log.get_instance();
01195    if (s.len() < 30) s = {s, {(30 - s.len()){" "}}};
01196    else if (s.len() > 30) s = s.substr(0, 29);
01197           
01198    $write("+--------------------------------+------+------+------+------+------+------+\n");
01199    $write("| %s |%s|%s|%s|%s|%s|%s|\n", s,
01200           "Insert", "Matchd", "MsMtch", "Droppd", "NotFnd", "Orphan");
01201    $write("+--------------------------------+------+------+------+------+------+------+\n");
01202 
01203    while (iter.next()) begin
01204       s = iter.describe();
01205       if (s.len() < 30) s = {s, {(30 - s.len()){" "}}};
01206       else if (s.len() > 30) s = s.substr(0, 29);
01207       $write("| %s | %04d | %04d | %04d | %04d | %04d | %04d |\n", s,
01208              iter.get_n_inserted(), iter.get_n_matched(),
01209              iter.get_n_mismatched(), iter.get_n_dropped(),
01210              iter.get_n_not_found(), iter.get_n_orphaned());
01211    end
01212    $write("+--------------------------------+------+------+------+------+------+------+\n");
01213    $write("|                          TOTAL | %04d | %04d | %04d | %04d | %04d | %04d |\n",
01214           this.get_n_inserted(exp_stream_id, inp_stream_id),
01215           this.get_n_matched(exp_stream_id, inp_stream_id),
01216           this.get_n_mismatched(exp_stream_id, inp_stream_id),
01217           this.get_n_dropped(exp_stream_id, inp_stream_id),
01218           this.get_n_not_found(exp_stream_id, inp_stream_id),
01219           this.get_n_orphaned(exp_stream_id, inp_stream_id));
01220    $write("+--------------------------------+------+------+------+------+------+------+\n\n");
01221 endfunction: report
01222 
01223 
01224 function void vmm_sb_ds::describe();
01225    vmm_sb_ds_iter iter = this.new_sb_iter();
01226 
01227    $write("Streams in Data Stream Scoreboard \"%s\":\n",
01228           this.log.get_instance());
01229 
01230    while (iter.next()) begin
01231       $write("   %s\n", iter.describe());
01232    end
01233 endfunction: describe
01234 
01235 
01236 function void vmm_sb_ds::display(string prefix);
01237    $write("%sContent of Data Stream Scoreboard \"%s\":\n", prefix, 
01238           this.log.get_instance());
01239 
01240    if (this.Xparallel_streamsX) begin
01241       foreach (this.Xexp_streamsX[k]) begin
01242          vmm_sb_ds_exp_streams exp_str = this.Xexp_streamsX[k];
01243          vmm_sb_ds_pkt_stream  pkt_str = exp_str.pkt_streams[k];
01244 
01245          if (pkt_str == null) continue;
01246 
01247          $write("%s   Stream #%0d", prefix, k);
01248          if (this.Xexp_stream_descsX.exists(k)) begin
01249             $write(" (%s)", this.Xexp_stream_descsX[k]);
01250          end
01251          $write(":\n");
01252 
01253          foreach (pkt_str.pkts[i]) begin
01254             pkt_str.pkts[i].display({prefix, "      "});
01255          end
01256       end
01257 
01258       return;
01259    end
01260 
01261    foreach (this.Xexp_streamsX[k]) begin
01262       vmm_sb_ds_exp_streams exp_str = this.Xexp_streamsX[k];
01263 
01264       $write("%s   To stream #%0d", prefix, k);
01265       if (this.Xexp_stream_descsX.exists(k)) begin
01266          $write(" (%s)", this.Xexp_stream_descsX[k]);
01267       end
01268       $write(":\n");
01269       foreach (exp_str.pkt_streams[j]) begin
01270          vmm_sb_ds_pkt_stream pkt_str = exp_str.pkt_streams[j];
01271 
01272          $write("%s      From stream #%0d", prefix, j);
01273          if (this.Xinp_stream_descsX.exists(j)) begin
01274             $write(" (%s)", this.Xinp_stream_descsX[j]);
01275          end
01276          $write(":\n");
01277          foreach (pkt_str.pkts[i]) begin
01278             pkt_str.pkts[i].display({prefix, "      "});
01279          end
01280       end
01281    end
01282 endfunction: display
01283 
01284 
01285 `endif // VMM_SB_DS_SV