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