VMM - (expanded) sb/vmm_sb_ds.sv

Expanded versions of source files are the output of the preprocessor. Lines subject to conditional compilation are not shown and all compiler pragmas have been stripped. Macros have been completely expanded.

sb/vmm_sb_ds.sv unexpanded 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: 
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:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text("vmm_sb_ds::define_stream() called with negative stream_id")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00339:       return;
00340:    end
00341: 
00342:    case (kind)
00343:      EITHER: begin
00344:         if (this.Xdefine_stream_calledX && !this.Xparallel_streamsX) begin
00345:            
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text("vmm_sb_ds::define_stream(): Attempting to define a mix of EITHER and INPUT/EXPECT streams")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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:            
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text("vmm_sb_ds::define_stream(): Attempting to define a mix of EITHER and INPUT/EXPECT streams")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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:            
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text("vmm_sb_ds::define_stream(): Attempting to define a mix of EITHER and INPUT/EXPECT streams")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text("vmm_sb_ds::insert() called with EITHER packet kind")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00388:       return 0;
00389:    end
00390: 
00391:    drop = 0;
00394: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.pre_insert(this, pkt, kind,
     :                             exp_stream_id, inp_stream_id, drop); 
     : end while (0);
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
00403: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("vmm_sb_ds::insert() called with undefined input stream #%0d",
     :                                         inp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00404:          return 0;
00405:       end
00406:    end
00407: 
00408:    if (kind == INPUT) begin
00409:       vmm_data out_pkts[];
00410:       
00412: 
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::DEBUG_SEV)) begin 
     :       void'(this.log.text($psprintf("Inserting INPUT packet in stream #%0d",
     :                                      inp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00413:       
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::VERBOSE_SEV)) begin 
     :       void'(this.log.text(pkt.psdisplay("   "))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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
00439: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("vmm_sb_ds::insert() called with undefined expected stream #%0d",
     :                                         exp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00440:          return 0;
00441:       end
00442:    end
00443:    
00445: 
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::DEBUG_SEV)) begin 
     :       void'(this.log.text($psprintf("Inserting EXPECT packet in stream #%0d->#%0d",
     :                                   inp_stream_id, exp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00446:    
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::VERBOSE_SEV)) begin 
     :       void'(this.log.text(pkt.psdisplay("   "))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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
00471: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.post_insert(this, pkt, exp_stream_id, inp_stream_id); 
     : end while (0);
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:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text("vmm_sb_ds::remove() called with EITHER packet kind")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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
00496: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("vmm_sb_ds::remove() called with undefined input stream #%0d",
     :                                         inp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00497:          return 0;
00498:       end
00499:    end
00500: 
00501:    if (kind == INPUT) begin
00502:       vmm_data out_pkts[];
00503:       bit      rc = 1;
00504:       
00506: 
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin 
     :       void'(this.log.text($psprintf("Deleting INPUT packet from stream #%0d",
     :                                      inp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00507:       
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::VERBOSE_SEV)) begin 
     :       void'(this.log.text(pkt.psdisplay("   "))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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
00525: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("vmm_sb_ds::remove() called with undefined expected stream #%0d",
     :                                         exp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00526:          return 0;
00527:       end
00528:    end
00529:    
00531: 
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin 
     :       void'(this.log.text($psprintf("Deleting EXPECT packet from stream #%0d->#%0d",
     :                                   inp_stream_id, exp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00532:    
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::VERBOSE_SEV)) begin 
     :       void'(this.log.text(pkt.psdisplay("   "))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00533: 
00534:    if (!this.Xexp_streamsX.exists(exp_stream_id)) begin
00536: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("vmm_sb_ds::remove(): Cannot find packet to remove: expected stream #%0d does not exist",
     :                                      exp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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
00543: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("vmm_sb_ds::remove(): Cannot find packet to remove: stream #%0d->#%0d does not exist.",
     :                                      inp_stream_id, exp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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:    
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text("vmm_sb_ds::remove(): Cannot find packet to remove")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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: 
00613: 
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::DEBUG_SEV)) begin 
     :       void'(this.log.text($psprintf("Expecting in-order packet on stream #%0d->#%0d",
     :                                   inp_stream_id, exp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00614:    
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::VERBOSE_SEV)) begin 
     :       void'(this.log.text(pkt.psdisplay("   "))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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);
00623: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.not_found(this, pkt, exp_stream_id, inp_stream_id, n); 
     : end while (0);
00624: 
00625:       if (!silent) begin
00626:          this.n_not_found += n;
00627:          
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("In-order packet was not found: EXPECT stream #%0d does not exist.", exp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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);
00640: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.not_found(this, pkt, exp_stream_id, inp_stream_id, n); 
     : end while (0);
00641: 
00642:       if (!silent) begin
00643:          this.n_not_found += n;
00644:          
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("In-order packet was not found: stream #%0d->#%0d does not exist.", inp_stream_id, exp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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);
00657: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.not_found(this, pkt, exp_stream_id, inp_stream_id, n); 
     : end while (0);
00658: 
00659:       if (!silent) begin
00660:          pkt_stream.n_not_found += n;
00661:          
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("In-order packet was not found: stream %0d->%0d is empty.", inp_stream_id, exp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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);
00673: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.not_found(this, pkt, exp_stream_id, inp_stream_id, n); 
     : end while (0);
00674: 
00675:       if (!silent) begin
00676:          pkt_stream.n_not_found += n;
00677:          
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("In-order packet was not expected:\n%s\n%s.", pkt.psdisplay("   Actual: "), pkt_stream.pkts[0].psdisplay("   Expect: ")))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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);
00697: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.matched(this, pkt, exp_stream_id, inp_stream_id, n); 
     : end while (0);
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: 
00734: 
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::DEBUG_SEV)) begin 
     :       void'(this.log.text($psprintf("Looking for packet on stream #%0d->#%0d",
     :                                   inp_stream_id, exp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00735:    
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::VERBOSE_SEV)) begin 
     :       void'(this.log.text(pkt.psdisplay("   "))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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);
00744: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.not_found(this, pkt, exp_stream_id, inp_stream_id, n); 
     : end while (0);
00745: 
00746:       if (!silent) begin
00747:          this.n_not_found += n;
00748:          
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("With-loss packet was not found: EXPECT stream #%0d does not exist.", exp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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);
00761: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.not_found(this, pkt, exp_stream_id, inp_stream_id, n); 
     : end while (0);
00762: 
00763:       if (!silent) begin
00764:          this.n_not_found += n;
00765:          
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("With-loss packet was not found: Stream #%0d->%0d does not exist.", inp_stream_id, exp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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);
00778: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.not_found(this, pkt, exp_stream_id, inp_stream_id, n); 
     : end while (0);
00779: 
00780:       if (!silent) begin
00781:          pkt_stream.n_not_found += n;
00782:          
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("With-loss packet was not found: Stream #%0d->%0d is empty.", inp_stream_id, exp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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);
00802: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.not_found(this, pkt, exp_stream_id, inp_stream_id, n); 
     : end while (0);
00803: 
00804:       if (!silent) begin
00805:          this.n_not_found += n;
00807: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text({"With-loss packet was not matched:\n",
     :                                pkt.psdisplay("   ")})); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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);
00828: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.dropped(this, status.pkts, exp_stream_id, inp_stream_id, n); 
     : end while (0);
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: 
00844: 
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin 
     :       void'(this.log.text($psprintf("packet mismatched expected packet in stream #%0d->#%0d\n%s\n%s",
     :                                   inp_stream_id, exp_stream_id,
     :                                   pkt.psdisplay("   Actual:"),
     :                                   matched.psdisplay("   Msmtch:")))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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);
00856: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.mismatched(this, pkt, exp_stream_id, inp_stream_id, n); 
     : end while (0);
00857:          if (!silent) pkt_stream.n_mismatched += n;
00858:       end
00859: 
00860:       if (!silent) begin
00861:          
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("With-loss packet was not found"))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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);
00872: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.matched(this, pkt, exp_stream_id, inp_stream_id, n); 
     : end while (0);
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: 
00896: 
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::DEBUG_SEV)) begin 
     :       void'(this.log.text($psprintf("Looking for out-of-order packet on stream #%0d->#%0d",
     :                                   inp_stream_id, exp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00897:    
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::VERBOSE_SEV)) begin 
     :       void'(this.log.text(pkt.psdisplay("   "))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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);
00906: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.not_found(this, pkt, exp_stream_id, inp_stream_id, n); 
     : end while (0);
00907: 
00908:       if (!silent) begin
00909:          this.n_not_found += n;
00910:          
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Out-of-order packet was not found: EXPECT stream #%0d does not exist.", exp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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);
00923: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.not_found(this, pkt, exp_stream_id, inp_stream_id, n); 
     : end while (0);
00924: 
00925:       if (!silent) begin
00926:          this.n_not_found += n;
00927:          
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Out-of-order packet was not found: stream %0d->%0d does not exist.", inp_stream_id, exp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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);
00940: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.not_found(this, pkt, exp_stream_id, inp_stream_id, n); 
     : end while (0);
00941: 
00942:       if (!silent) begin
00943:          pkt_stream.n_not_found += n;
00944:          
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Out-of-order packet was not found: stream %0d->%0d is empty.", inp_stream_id, exp_stream_id))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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);
00958: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.matched(this, pkt, exp_stream_id, inp_stream_id, n); 
     : end while (0);
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);
00978: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.not_found(this, pkt, exp_stream_id, inp_stream_id, n); 
     : end while (0);
00979:       if (!silent) pkt_stream.n_not_found += n;
00980:    end
00981: 
00982:    if (!silent) begin
00983:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text("Out-of-order packet was not found")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text("Attempting to prepend a NULL callback extension")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
01022:       return;
01023:    end
01024: 
01025:    foreach(this.callbacks[i]) begin
01026:       if (this.callbacks[i] == cb) begin
01027:          
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text("Callback has already been registered")); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
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:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text("Attempting to append a NULL callback extension")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
01039:       return;
01040:    end
01041: 
01042:    foreach(this.callbacks[i]) begin
01043:       if (this.callbacks[i] == cb) begin
01044:          
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text("Callback has already been registered")); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
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:    
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text("Callback was not registered")); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
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);
01179: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_sb_ds_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.orphaned(this, status.pkts,
     :                                    exp_stream_id, inp_stream_id, n); 
     : end while (0);
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: