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