00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 `ifdef VCS
00024 (* vmm_private_class, _vcs_vmm_class = 1 *)
00025 `endif
00026 class vmm_log_modifier;
00027 int typ;
00028 int severity;
00029 string pattern;
00030 int new_typ;
00031 int new_severity;
00032 int handling;
00033
00034 static local vmm_log log;
00035
00036 function new();
00037
00038 if (log == null) this.log = new("vmm_log_modifier", "class");
00039 endfunction: new
00040
00041 extern function string psdisplay(string prefix = "");
00042 endclass: vmm_log_modifier
00043
00044
00045 typedef class vmm_log_msg;
00046
00047 `ifdef VCS
00048 (* vmm_private_class, _vcs_vmm_class = 1 *)
00049 `endif
00050 class vmm_log_watchpoint;
00051 int typ;
00052 int severity;
00053 string pattern;
00054 logic issued;
00055
00056 event seen;
00057 vmm_log_msg msg;
00058
00059 static local vmm_log log;
00060
00061 function new();
00062
00063 if (log == null) this.log = new("vmm_log_watchpoint", "class");
00064 endfunction: new
00065
00066 extern function void display(string prefix = "");
00067 extern function string psdisplay(string prefix = "");
00068 endclass:vmm_log_watchpoint
00069
00070
00071 `ifdef VCS
00072 (* vmm_private_class, _vcs_vmm_class = 1 *)
00073 `endif
00074 class vmm_log_msg;
00075 vmm_log log;
00076
00077 bit invalid;
00078 time timestamp;
00079 int original_typ;
00080 int original_severity;
00081 int effective_typ;
00082 int effective_severity;
00083 string text[$];
00084 logic issued;
00085 int handling;
00086
00087 int flushed;
00088
00089 function new(vmm_log log);
00090 this.log = log;
00091 this.invalid = 1;
00092 endfunction: new
00093
00094 extern function void display(string prefix = "");
00095 extern function string psdisplay(string prefix = "");
00096 extern function vmm_log_msg copy();
00097 endclass: vmm_log_msg
00098
00099
00100
00101
00102
00103
00104 function string vmm_log_modifier::psdisplay(string prefix);
00105 $sformat(psdisplay, "%s%s [%s] with \"%s\" -> %s [%s] then %s",
00106 prefix, this.log.typ_image(this.typ),
00107 this.log.sev_image(this.severity),
00108 (this.pattern == "") ? "/./" : this.pattern,
00109 this.log.typ_image(this.new_typ),
00110 this.log.sev_image(this.new_severity),
00111 this.log.handling_image(this.handling));
00112 endfunction: psdisplay
00113
00114
00115
00116
00117
00118
00119 function void vmm_log_watchpoint::display(string prefix);
00120 $write("%s\n", this.psdisplay(prefix));
00121 endfunction: display
00122
00123 function string vmm_log_watchpoint::psdisplay(string prefix);
00124 $sformat(psdisplay, "%s%s [%s] with \"%s\"%s",
00125 prefix, this.log.typ_image(this.typ),
00126 this.log.sev_image(this.severity),
00127 (this.pattern == "") ? "/./" : this.pattern,
00128 (this.issued === 1'bx) ? "" : (this.issued) ? "if issued" : "if not issued");
00129 endfunction: psdisplay
00130
00131
00132 //
00133 // vmm_log_msg
00134 //
00135
00136 function void vmm_log_msg::display(string prefix);
00137 $write("%s\n", this.psdisplay(prefix));
00138 endfunction: display
00139
00140 function string vmm_log_msg::psdisplay(string prefix);
00141 $sformat(psdisplay, "%s%s [%s] at %0t", prefix,
00142 this.log.typ_image(this.effective_typ),
00143 this.log.sev_image(this.effective_severity),
00144 this.timestamp);
00145 foreach(this.text[i]) begin
00146 $sformat(psdisplay, "%s\n%s %s", psdisplay, prefix,
00147 this.text[i]);
00148 end
00149 endfunction: psdisplay
00150
00151 function vmm_log_msg vmm_log_msg::copy();
00152 copy = new(this.log);
00153
00154 copy.timestamp = this.timestamp;
00155 copy.original_typ = this.original_typ;
00156 copy.original_severity = this.original_severity;
00157 copy.effective_typ = this.effective_typ;
00158 copy.effective_severity = this.effective_severity;
00159 copy.text = this.text;
00160 copy.issued = this.issued;
00161 copy.handling = this.handling;
00162
00163 copy.flushed = this.flushed;
00164 endfunction: copy
00165
00166
00167 //
00168 // vmm_log;
00169 //
00170
00171 function void vmm_log::reset(string name,
00172 string inst,
00173 bit recurse);
00174 this.is_self = 0;
00175 this.is_all = 0;
00176
00177 this.known_idx = 0;
00178 this.recurse = recurse;
00179 this.recurse_id++;
00180 `ifdef VCS2006_06
00181 // Work-around for NYI feature in 2006.06
00182 // *NOT* IEEE compliant :-(
00183 this.recurse_stack.delete();
00184 `else
00185 // Works in VCS 2008.03
00186 this.recurse_stack = '{};
00187 `endif
00188
00189
00190 if (name == "" && inst == "") begin
00191 this.is_self = 1;
00192 return;
00193 end
00194 if (name == "/./" && inst == "/./") begin
00195 this.is_all = 1;
00196 this.recurse = 0;
00197 return;
00198 end
00199
00200 if (name == "") name = this.name;
00201 if (inst == "") inst = this.inst;
00202
00203 this.pattern[0] = name;
00204 this.is_pattern[0] = `vmm_str_match(this.pattern[0], "^/(.*)/$");
00205 if (is_pattern[0]) begin
00206 this.pattern[0] = `vmm_str_backref(this.pattern[0], 0);
00207 end
00208
00209 this.pattern[1] = inst;
00210 this.is_pattern[1] = `vmm_str_match(this.pattern[1], "^/(.*)/$");
00211 if (is_pattern[1]) begin
00212 this.pattern[1] = `vmm_str_backref(this.pattern[1], 0);
00213 end
00214 endfunction: reset
00215
00216
00217 `ifdef VCS
00218 (* vmm_private_class, _vcs_vmm_class = 1 *)
00219 `endif
00220 class vmm_log_below_iter;
00221 local vmm_log log;
00222 local int idx;
00223
00224 function new(vmm_log log);
00225 this.log = log;
00226 this.idx = 0;
00227 endfunction
00228
00229 function vmm_log data();
00230 if (this.idx >= this.log.below.size()) data = null;
00231 else data = this.log.below[idx];
00232 endfunction
00233
00234 function vmm_log start();
00235 this.idx = 0;
00236 start = this.data();
00237 endfunction
00238
00239 function vmm_log next();
00240 if (idx < this.log.below.size()) idx++;
00241 next = this.data();
00242 endfunction
00243 endclass
00244
00245
00246 function vmm_log vmm_log::for_each();
00247 if (this.is_self) begin
00248 if (this.is_self == 1) begin
00249 this.is_self = 2;
00250 if (this.recurse) begin
00251 vmm_log_below_iter j = new(this);
00252 this.visited = this.recurse_id;
00253 this.recurse_stack.push_back(j);
00254 end
00255 return this;
00256 end else if (!this.recurse) begin
00257 return null;
00258 end
00259 end
00260
00261 while (this.recurse && this.recurse_stack.size() > 0) begin
00262 vmm_log_below_iter i = recurse_stack[$];
00263
00264 while (i.data() != null) begin
00265 vmm_log that = i.data();
00266 i.next();
00267 if (that.visited != this.recurse_id) begin
00268 vmm_log_below_iter j = new(that);
00269 that.visited = this.recurse_id;
00270 this.recurse_stack.push_back(j);
00271 return that;
00272 end
00273 end
00274 this.recurse_stack.pop_back();
00275 end
00276
00277 if (this.is_self) begin
00278 return null;
00279 end
00280
00281 while (this.known_idx < this.known.size()) begin
00282 vmm_log that = this.known[this.known_idx++];
00283 bit name_ok;
00284 bit inst_ok;
00285
00286 if (this.is_all) begin
00287 return that;
00288 end
00289
00290 if (is_pattern[0]) name_ok = `vmm_str_match(that.name, this.pattern[0]);
00291 else name_ok = (that.name == this.pattern[0]);
00292
00293 if (is_pattern[1]) inst_ok = `vmm_str_match(that.inst, this.pattern[1]);
00294 else inst_ok = (that.inst == this.pattern[1]);
00295
00296 if (name_ok && inst_ok) begin
00297 if (that.visited != this.recurse_id) begin
00298 that.visited = this.recurse_id;
00299 if (this.recurse) begin
00300 vmm_log_below_iter j = new(that);
00301 this.recurse_stack.push_back(j);
00302 end
00303 return that;
00304 end
00305 end
00306 end
00307 for_each = null;
00308 endfunction: for_each
00309
00310
00311 function vmm_log::new(string name,
00312 string inst,
00313 vmm_log under);
00314 `ifdef VMM_LOG_BASE_NEW_CALL
00315 super.new(`VMM_LOG_BASE_NEW_CALL);
00316 `endif
00317
00318 this.name = name;
00319 this.inst = inst;
00320 if (under != null) under.is_above(this);
00321
00322 this.msg = new(this);
00323
00324 this.n_msg[FATAL_SEV] = 0;
00325 this.n_msg[ERROR_SEV] = 0;
00326 this.n_msg[WARNING_SEV] = 0;
00327 this.n_msg[NORMAL_SEV] = 0;
00328 this.n_msg[TRACE_SEV] = 0;
00329 this.n_msg[DEBUG_SEV] = 0;
00330 this.n_msg[VERBOSE_SEV] = 0;
00331 this.n_msg[HIDDEN_SEV] = 0;
00332 this.n_msg[IGNORE_SEV] = 0;
00333
00334 this.has_text_modifiers = 0;
00335 this.n_demoted[ERROR_SEV] = 0;
00336 this.n_demoted[WARNING_SEV] = 0;
00337
00338 this.known.push_back(this);
00339
00340 this.enabled_typs = ALL_TYPS;
00341
00342 if (this.known.size() == 1) begin
00343 this.type_list.push_back(FAILURE_TYP);
00344 this.type_list.push_back(NOTE_TYP);
00345 this.type_list.push_back(DEBUG_TYP);
00346 this.type_list.push_back(REPORT_TYP);
00347 this.type_list.push_back(NOTIFY_TYP);
00348 this.type_list.push_back(TIMING_TYP);
00349 this.type_list.push_back(XHANDLING_TYP);
00350 this.type_list.push_back(PROTOCOL_TYP);
00351 this.type_list.push_back(TRANSACTION_TYP);
00352 this.type_list.push_back(COMMAND_TYP);
00353 this.type_list.push_back(CYCLE_TYP);
00354 this.type_list.push_back(USER_TYP_0);
00355 this.type_list.push_back(USER_TYP_1);
00356 this.type_list.push_back(USER_TYP_2);
00357 this.type_list.push_back(INTERNAL_TYP);
00358
00359 this.sev_list.push_back(FATAL_SEV);
00360 this.sev_list.push_back(ERROR_SEV);
00361 this.sev_list.push_back(WARNING_SEV);
00362 this.sev_list.push_back(NORMAL_SEV);
00363 this.sev_list.push_back(TRACE_SEV);
00364 this.sev_list.push_back(DEBUG_SEV);
00365 this.sev_list.push_back(VERBOSE_SEV);
00366
00367
00368 this.type_images[FAILURE_TYP ] = "FAILURE";
00369 this.type_images[NOTE_TYP ] = "NOTE";
00370 this.type_images[DEBUG_TYP ] = "DEBUG";
00371 this.type_images[REPORT_TYP ] = "REPORT";
00372 this.type_images[NOTIFY_TYP ] = "NOTIFY";
00373 this.type_images[TIMING_TYP ] = "TIMING";
00374 this.type_images[XHANDLING_TYP ] = "XHANDLING";
00375 this.type_images[PROTOCOL_TYP ] = "PROTOCOL";
00376 this.type_images[TRANSACTION_TYP] = "XACTION";
00377 this.type_images[COMMAND_TYP ] = "COMMAND";
00378 this.type_images[CYCLE_TYP ] = "CYCLE";
00379 this.type_images[USER_TYP_0 ] = "USER_0";
00380 this.type_images[USER_TYP_1 ] = "USER_1";
00381 this.type_images[USER_TYP_2 ] = "USER_2";
00382 this.type_images[INTERNAL_TYP ] = "INTERNAL";
00383
00384 `ifdef VMM_LOG_ANSI_COLOR
00385 this.sev_images[FATAL_SEV ] = "\033[41m*FATAL*\033[0m";
00386 this.sev_images[ERROR_SEV ] = "\033[31m!ERROR!\033[0m";
00387 this.sev_images[WARNING_SEV] = "\033[33mWARNING\033[0m";
00388 `else
00389 this.sev_images[FATAL_SEV ] = "*FATAL*";
00390 this.sev_images[ERROR_SEV ] = "!ERROR!";
00391 this.sev_images[WARNING_SEV] = "WARNING";
00392 `endif
00393 this.sev_images[NORMAL_SEV ] = "Normal";
00394 this.sev_images[TRACE_SEV ] = "Trace";
00395 this.sev_images[DEBUG_SEV ] = "Debug";
00396 this.sev_images[VERBOSE_SEV] = "Verbose";
00397
00398
00399
00400 if ($test$plusargs("rvm_log_debug")) begin
00401 this.plus_debug = 1;
00402 end
00403
00404 begin
00405 bit plusarg;
00406 string arg;
00407 string level;
00408
00409 plusarg = $value$plusargs("rvm_log_default=%s", arg);
00410 if (!plusarg) begin
00411 plusarg = $value$plusargs("vmm_log_default=%s", arg);
00412 end
00413 if (plusarg) begin
00414 level = arg.substr(0, 1);
00415
00416 level = level.tolower();
00417 if (level == "er")
00418 this.dflt_lvl = ERROR_SEV;
00419 else if (level == "wa")
00420 this.dflt_lvl = WARNING_SEV;
00421 else if (level == "no")
00422 this.dflt_lvl = NORMAL_SEV;
00423 else if (level == "tr")
00424 this.dflt_lvl = TRACE_SEV;
00425 else if (level == "de")
00426 this.dflt_lvl = DEBUG_SEV;
00427 else if (level == "ve")
00428 this.dflt_lvl = VERBOSE_SEV;
00429 else if (level == "hi")
00430 this.dflt_lvl = HIDDEN_SEV;
00431 else
00432 $write("Warning: Invalid +rvm_log_default specification: \"%s\"\n",
00433 arg);
00434 end
00435
00436 else this.dflt_lvl = NORMAL_SEV;
00437
00438 plusarg = $value$plusargs("rvm_force_verbosity=%s", arg);
00439 if (!plusarg) begin
00440 plusarg = $value$plusargs("vmm_force_verbosity=%s", arg);
00441 end
00442 if (plusarg) begin
00443 level = arg.substr(0, 1);
00444
00445 level = level.tolower();
00446 if (level == "er")
00447 this.force_lvl = ERROR_SEV;
00448 else if (level == "wa")
00449 this.force_lvl = WARNING_SEV;
00450 else if (level == "no")
00451 this.force_lvl = NORMAL_SEV;
00452 else if (level == "tr")
00453 this.force_lvl = TRACE_SEV;
00454 else if (level == "de")
00455 this.force_lvl = DEBUG_SEV;
00456 else if (level == "ve")
00457 this.force_lvl = VERBOSE_SEV;
00458 else if (level == "hi")
00459 this.force_lvl = HIDDEN_SEV;
00460 else
00461 $write("Warning: Invalid +rvm_force_verbosity level: \"%s\"\n",
00462 arg);
00463 end
00464 end
00465
00466
00467
00468 end
00469
00470 this.log_lvl = this.dflt_lvl;
00471 this.log_start(STDOUT);
00472
00473
00474
00476 if (this.known.size() == 200) begin
00477 if (!$test$plusargs("vmm_log_nowarn_at_200") &&
00478 !$test$plusargs("rvm_log_nowarn_at_200")) begin
00479 if (this.start_msg(FAILURE_TYP, WARNING_SEV)) begin
00480 this.text("Over 200 vmm_log instances have been created.");
00481 this.text("Check that all vmm_data extensions use a static instance");
00482 this.text("or use +vmm_log_nowarn_at_200 to disable this warning.");
00483 this.end_msg();
00484 end
00485 end
00486 end
00487
00488 if (this.known.size() == 1000) begin
00489 if (!$test$plusargs("vmm_log_nofatal_at_1000") &&
00490 !$test$plusargs("rvm_log_nofatal_at_1000")) begin
00491 if (this.start_msg(FAILURE_TYP, FATAL_SEV)) begin
00492 this.text("Over 1000 vmm_log instances have been created.");
00493 this.text("Check that all vmm_data extensions use a static instance");
00494 this.text("or use +vmm_log_nofatal_at_1000 to disable this failure.");
00495 this.end_msg();
00496 end
00497 end
00498 end
00499
00500
00501
00502 endfunction: new
00503
00504
00505 function void vmm_log::is_above(vmm_log log);
00506 if (log == null) return;
00507 this.below.push_back(log);
00508
00509
00510 endfunction: is_above
00511
00512
00513 function vmm_log vmm_log::copy(vmm_log to);
00514 if (to == null) to = new(this.name, this.inst);
00515 else begin
00516 to.name = this.name;
00517 to.inst = this.inst;
00518 end
00519
00520 to.enabled_typs = this.enabled_typs;
00521 to.log_lvl = this.log_lvl;
00522 to.fp = this.fp;
00523
00524 copy = to;
00525 endfunction: copy
00526
00527
00528 function void vmm_log::set_name(string name);
00529 this.name = name;
00530 endfunction: set_name
00531
00532
00533 function string vmm_log::get_name();
00534 get_name = this.name;
00535 endfunction: get_name
00536
00537
00538 function void vmm_log::set_instance(string inst);
00539 this.inst = inst;
00540 endfunction: set_instance
00541
00542
00543 function string vmm_log::get_instance();
00544 get_instance = this.inst;
00545 endfunction: get_instance
00546
00547
00548 function void vmm_log::list(string name,
00549 string inst,
00550 bit recurse);
00551 this.reset(name, inst, recurse);
00552 for (vmm_log log = this.for_each(); log != null; log = this.for_each()) begin
00553 $write("%s(%s) [%s] F/E/W/e/w=%0d/%0d/%0d/%0d/%0d\n", log.name, log.inst, this.sev_image(log.log_lvl), log.n_msg[FATAL_SEV], log.n_msg[ERROR_SEV], log.n_msg[WARNING_SEV], log.n_demoted[ERROR_SEV], log.n_demoted[WARNING_SEV]);
00554 for(int i = 0; i < log.below.size(); i++) begin
00555 $write(" +--- %s(%s)\n", log.below[i].name, log.below[i].inst);
00556 end
00557 end
00558 endfunction: list
00559
00560
00561 function void vmm_log::display(string prefix);
00562 $display("%s", this.psdisplay(prefix));
00563 endfunction
00564
00565
00566 function string vmm_log::psdisplay(string prefix);
00567 $sformat(psdisplay, "%s%s(%s) [%s]", prefix, this.name, this.inst,
00568 this.sev_image(this.log_lvl));
00569 for (int i = 0; i < this.below.size(); i++) begin
00570 $sformat(psdisplay, "%s\n%s +--- %s(%s)", psdisplay, prefix,
00571 this.below[i].name, this.below[i].inst);
00572 end
00573 for (int i = 0; i < this.modifier_ids.size(); i++) begin
00574 $sformat(psdisplay, "%s\n%s", psdisplay, this.modifier_cache[this.modifier_ids[i]].psdisplay({prefix, " "}));
00575 end
00576 endfunction
00577
00578
00579 function void vmm_log::kill();
00580 foreach(this.known[i]) begin
00581 if (this.known[i] == this) this.known.delete(i);
00582 end
00583 endfunction: kill
00584
00585
00586 function vmm_log_format vmm_log::set_format(vmm_log_format fmt);
00587 if (fmt == null) begin
00588 `vmm_error(this, "Cannot use NULL formatter in vmm_log::set_format(). Unchanged");
00589 return null;
00590 end
00591
00592 set_format = this.fmt;
00593 this.fmt = fmt;
00594 endfunction: set_format
00595
00596
00597 function string vmm_log::set_typ_image(int typ,
00598 string image);
00599 if (!this.type_images.exists(typ)) begin
00600 `vmm_error(this, "Invalid message type specified to vmm_log::set_typ_image()");
00601 return "";
00602 end
00603
00604 set_typ_image = this.type_images[typ];
00605 this.type_images[typ] = image;
00606
00607
00608
00609 endfunction: set_typ_image
00610
00611
00612 function string vmm_log::typ_image(int typ);
00613 string sep = "";
00614
00615 if (this.type_images.exists(typ)) begin
00616 return this.type_images[typ];
00617 end
00618
00619
00620 if (typ == DEFAULT) begin
00621 return "(default)";
00622 end
00623 if (typ == UNCHANGED) begin
00624 return "(unchanged)";
00625 end
00626
00627
00628 typ_image = "";
00629 foreach(this.type_list[i]) begin
00630 if (typ & this.type_list[i]) begin
00631 typ_image = {typ_image, sep, this.type_images[this.type_list[i]]};
00632 sep = "/";
00633 end
00634 end
00635 if (typ_image == "") typ_image = "?MSG_TYP?";
00636 endfunction: typ_image
00637
00638
00639 function string vmm_log::set_sev_image(int severity,
00640 string image);
00641 if (!this.sev_images.exists(severity)) begin
00642 `vmm_error(this, "Invalid message severity specified to vmm_log::set_sev_image()");
00643 return "";
00644 end
00645
00646 set_sev_image = this.sev_images[severity];
00647 this.sev_images[severity] = image;
00648
00649
00650
00651 endfunction: set_sev_image
00652
00653
00654 function string vmm_log::sev_image(int severity);
00655 string sep = "";
00656
00657 if (this.sev_images.exists(severity)) begin
00658 return this.sev_images[severity];
00659 end
00660
00661
00662 if (severity == DEFAULT) begin
00663 return "(default)";
00664 end
00665 if (severity == UNCHANGED) begin
00666 return "(unchanged)";
00667 end
00668 if (severity == IGNORE_SEV) begin
00669 return "(ignored)";
00670 end
00671
00672
00673 sev_image = "";
00674 foreach(this.sev_list[i]) begin
00675 if (severity & this.sev_list[i]) begin
00676 sev_image = {sev_image, sep, this.sev_images[this.sev_list[i]]};
00677 sep = "/";
00678 end
00679 end
00680 if (sev_image == "") sev_image = "?SEV_TYP?";
00681 endfunction: sev_image
00682
00683
00684 function string vmm_log::handling_image(int handling);
00685 case (handling)
00686 ABORT_SIM : handling_image = "ABORT";
00687 COUNT_ERROR : handling_image = "ERROR";
00688 STOP_PROMPT : handling_image = "STOP";
00689 DEBUGGER : handling_image = "DEBUGGER";
00690 DUMP_STACK : handling_image = "DUMPSTACK";
00691 CONTINUE : handling_image = "CONTINUE";
00692 IGNORE : handling_image = "IGNORE";
00693 DEFAULT : handling_image = "(default)";
00694 UNCHANGED : handling_image = "(unchanged)";
00695 default : handling_image = "?HANDLING?";
00696 endcase
00697 endfunction: handling_image
00698
00699
00700 function int vmm_log::default_handling(int severity);
00701 case (severity)
00702 FATAL_SEV : default_handling = ABORT_SIM;
00703 ERROR_SEV : default_handling = COUNT_ERROR;
00704 default : default_handling = CONTINUE;
00705 endcase
00706 endfunction: default_handling
00707
00708
00709 function void vmm_log::report(string name,
00710 string inst,
00711 bit recurse);
00712 vmm_log log;
00713 int n_fatals = 0;
00714 int n_errs = 0;
00715 int n_warns = 0;
00716 int n_derrs = 0;
00717 int n_dwarns = 0;
00718 string msg;
00719
00720 this.reset(name, inst, recurse);
00721 for(log = this.for_each(); log != null; log = this.for_each()) begin
00722
00723 n_fatals += log.n_msg[FATAL_SEV];
00724 n_errs += log.n_msg[ERROR_SEV];
00725 n_warns += log.n_msg[WARNING_SEV];
00726 n_derrs += log.n_demoted[ERROR_SEV];
00727 n_dwarns += log.n_demoted[WARNING_SEV];
00728 end
00729
00730 msg = this.fmt.pass_or_fail(n_fatals == 0 && n_errs == 0,
00731 name, inst, n_fatals, n_errs, n_warns,
00732 n_derrs, n_dwarns);
00733 if (msg != "") $display("%s", msg);
00734 endfunction: report
00735
00736
00737 function bit vmm_log::start_msg(int typ,
00738 int severity);
00739
00740 if (this.msg != null && !this.msg.invalid && this.msg.issued !== 1'b0) this.end_msg();
00741
00742 // Provide a default severity if none specified
00743 if (severity < 0) begin
00744 case (typ)
00745 FAILURE_TYP : severity = ERROR_SEV;
00746 NOTE_TYP : severity = NORMAL_SEV;
00747 DEBUG_TYP : severity = DEBUG_SEV;
00748 REPORT_TYP : severity = DEBUG_SEV;
00749 NOTIFY_TYP : severity = HIDDEN_SEV;
00750 TIMING_TYP : severity = WARNING_SEV;
00751 XHANDLING_TYP : severity = WARNING_SEV;
00752 PROTOCOL_TYP : severity = DEBUG_SEV;
00753 TRANSACTION_TYP: severity = TRACE_SEV;
00754 COMMAND_TYP : severity = TRACE_SEV;
00755 CYCLE_TYP : severity = VERBOSE_SEV;
00756 default : severity = NORMAL_SEV;
00757 endcase
00758 end
00759
00760 // Perform a quick, less expensive filtering here for loggers without
00761 // promotion/demotion or watchpoints. Return immediately if the
00762 // message is not printed based on severity and enabled categories
00763 if (this.modifier_ids.size() == 0 &&
00764 this.watchpoint_ids.size() == 0) begin
00765
00766 if ((this.force_lvl != DEFAULT_SEV && severity > this.force_lvl) || // Forced?
00767 (this.force_lvl == DEFAULT_SEV && severity > this.log_lvl) || // Above?
00768 (!(typ & this.enabled_typs) && (severity >= WARNING_SEV)) // Disabled?
00769 ) begin
00770 this.msg.invalid = 1;
00771 return 0;
00772 end
00773 end
00774
00775 this.msg.invalid = 0;
00776 this.msg.original_typ = typ;
00777 this.msg.original_severity = severity;
00778 this.msg.effective_typ = typ;
00779 this.msg.effective_severity = severity;
00780 this.msg.flushed = 0;
00781 `ifdef VCS2006_06
00782 // Work-around for NYI feature in 2006.06
00783 // *NOT* IEEE compliant :-(
00784 this.msg.text.delete();
00785 `else
00786 // Works in VCS 2008.03
00787 this.msg.text = '{};
00788 `endif
00789 this.msg.handling = DEFAULT;
00790 this.msg.issued = 1'bx;
00791
00792 start_msg = 1;
00793
00794 // Do property-based promotion and filtering
00795 // if there are no text-based filters
00796 if (!this.has_text_modifiers) begin
00797 this.promote();
00798 this.filter();
00799
00800 if (this.msg.issued === 1'b0) begin
00801 start_msg = 0;
00802
00803
00804 if (this.msg.effective_severity > this.msg.original_severity) begin
00805 case (this.msg.original_severity)
00806 ERROR_SEV : this.n_demoted[ERROR_SEV]++;
00807 WARNING_SEV: this.n_demoted[WARNING_SEV]++;
00808 endcase
00809 end
00810
00811 this.msg.invalid = 1;
00812 end
00813 end
00814 endfunction: start_msg
00815
00816
00817 function bit vmm_log::text(string msg);
00818 if (this.msg.invalid)
00819 begin
00820 `vmm_error(this, "Malformed message: vmm_log::text() called before vmm_log::start_msg()");
00821 return 0;
00822 end
00823
00824 text = 1;
00825
00826 if (msg == "")
00827 begin
00828 this.flush_msg();
00829 return 1;
00830 end
00831
00832 this.msg.text.push_back(msg);
00833
00834 endfunction: text
00835
00836
00837 function void vmm_log::end_msg();
00838 int handling;
00839
00840 if (this.msg.invalid)
00841 begin
00842 `vmm_error(this, "Malformed message: vmm_log::end_msg() called before vmm_log::start_msg()");
00843 return;
00844 end
00845
00846 this.flush_msg();
00847
00848
00849
00850
00851 handling = this.msg.handling;
00852 if (handling == DEFAULT) handling = default_handling(this.msg.effective_severity);
00853
00854
00855 if (this.in_callbacks) handling = CONTINUE;
00856
00857 case (handling)
00858
00859 ABORT_SIM: begin
00860 this.in_callbacks = 1;
00861 `vmm_callback(vmm_log_callbacks, pre_abort(this));
00862 this.in_callbacks = 0;
00863 $finish;
00864 end
00865
00866 DUMP_STACK,
00867 DEBUGGER: begin
00868 this.in_callbacks = 1;
00869 `vmm_callback(vmm_log_callbacks, pre_debug(this));
00870 this.in_callbacks = 0;
00871 $stop;
00872 end
00873
00874 STOP_PROMPT: begin
00875 this.in_callbacks = 1;
00876 `vmm_callback(vmm_log_callbacks, pre_stop(this));
00877 this.in_callbacks = 0;
00878 $stop;
00879 end
00880
00881 COUNT_ERROR: begin
00882 this.error_count++;
00883 if (this.error_limit > 0 && this.error_count >= this.error_limit) begin
00884 string msg = this.fmt.abort_on_error(this.error_count,
00885 this.error_limit);
00886 if (msg != "") $display("%s", msg);
00887 this.in_callbacks = 1;
00888
00889 do for (int i = 0; i < this.callbacks.size(); i++) begin
00890 vmm_log_callbacks cb;
00891 if (!$cast(cb, this.callbacks[i])) continue;
00892 cb.pre_abort(this);
00893 end while (0);
00894 this.in_callbacks = 0;
00895 $finish;
00896 end
00897 end
00898 endcase
00899
00900 this.msg.invalid = 1;
00901 endfunction: end_msg
00902
00903
00904 function void vmm_log::flush_msg();
00905 string msg;
00906
00907 if (this.msg.flushed == 0) begin
00908
00909
00910
00911 if (this.has_text_modifiers) begin
00912 this.promote();
00913 this.filter();
00914 end
00915 this.notify();
00916
00917
00918 if (this.msg.effective_severity > this.msg.original_severity) begin
00919 case (this.msg.original_severity)
00920 ERROR_SEV : this.n_demoted[ERROR_SEV]++;
00921 WARNING_SEV: this.n_demoted[WARNING_SEV]++;
00922 endcase
00923 end
00924
00925 if (this.msg.issued === 1'b0) return;
00926
00927
00928
00929
00930 msg = this.fmt.format_msg(this.name, this.inst,
00931 this.typ_image(this.msg.effective_typ),
00932 this.sev_image(this.msg.effective_severity),
00933 this.msg.text);
00934 foreach(this.fp[i]) begin
00935 $fdisplay(this.fp[i], "%s", msg);
00936 end
00937 // Did we just send an ERROR or FATAL message to /dev/null??
00938 if (this.fp.size() == 0 && this.msg.effective_severity <= ERROR_SEV) begin
00939 // Force it to appear on STDOUT
00940 $display("%s", msg);
00941 end
00942 this.msg.flushed++;
00943 `ifdef VCS2006_06
00944 // Work-around for NYI feature in 2006.06
00945 // *NOT* IEEE compliant :-(
00946 this.msg.text.delete();
00947 `else
00948 // Works in VCS 2008.03
00949 this.msg.text = '{};
00950 `endif
00951 end
00952 else begin
00953 if (this.msg.text.size() > 0) begin
00954 msg = this.fmt.continue_msg(this.name, this.inst,
00955 this.typ_image(this.msg.effective_typ),
00956 this.sev_image(this.msg.effective_severity),
00957 this.msg.text);
00958 foreach(this.fp[i]) begin
00959 $fdisplay(this.fp[i], "%s", msg);
00960 end
00961
00962 if (this.fp.size() == 0 && this.msg.effective_severity <= ERROR_SEV) begin
00963
00964 $display("%s", msg);
00965 end
00966 this.msg.flushed++;
00967 `ifdef VCS2006_06
00968
00969
00970 this.msg.text.delete();
00971 `else
00972
00973 this.msg.text = '{};
00974 `endif
00975 end
00976 return;
00977 end
00978
00979 this.n_msg[this.msg.effective_severity]++;
00980 endfunction: flush_msg
00981
00982
00983 function void vmm_log::enable_types(int typs,
00984 string name,
00985 string inst,
00986 bit recursive);
00987 if (typs == DEFAULT_TYP ) typs = ALL_TYPS ;
00988 if (typs < 0) begin
00989 `vmm_error(this, "Invalid message type specified to vmm_log::enable_types");
00990 return;
00991 end
00992
00993 //
00994 // Enable specified types in all specified log insts
00995 //
00996 this.reset(name, inst, recursive);
00997 for(vmm_log log = this.for_each(); log != null; log = this.for_each()) begin
00998 log.enabled_typs |= typs;
00999 end
01000 endfunction: enable_types
01001
01002
01003 function void vmm_log::disable_types(int typs,
01004 string name,
01005 string inst,
01006 bit recursive);
01007 if (typs < 0) begin
01008 `vmm_error(this, "Invalid message type specified to vmm_log::disable_types");
01009 return;
01010 end
01011 // Cannot disable failure messages
01012 if (typs & FAILURE_TYP) begin
01013 `vmm_warning(this, "Cannot disable FAILURE_TYP messages");
01014 typs -= FAILURE_TYP;
01015 end
01016
01017 //
01018 // Disable specified types in all specified log insts
01019 //
01020 this.reset(name, inst, recursive);
01021 for(vmm_log log = this.for_each(); log != null; log = this.for_each()) begin
01022 log.enabled_typs &= ~(typs);
01023 end
01024 endfunction: disable_types
01025
01026
01027 function int vmm_log::modify(string name,
01028 string inst,
01029 bit recursive,
01030 int typ,
01031 int severity,
01032 string text,
01033 int new_typ,
01034 int new_severity,
01035 int handling);
01036 vmm_log_modifier modifier;
01037 int mod_id;
01038
01039 // Some severities cannot be demoted too far
01040 if (severity == FATAL_SEV &&
01041 new_severity > ERROR_SEV) begin
01042 `vmm_error(this, "Cannot demote FATAL_SEV severity to less than ERROR_SEV");
01043 return -2;
01044 end
01045 if (severity == ERROR_SEV &&
01046 new_severity > WARNING_SEV) begin
01047 `vmm_error(this, "Cannot demote ERROR severity to less than WARNING");
01048 return -2;
01049 end
01050
01051 //
01052 // Add a description of the modification to the cache
01053 //
01054 modifier = new;
01055 modifier.typ = typ;
01056 modifier.severity = severity;
01057 modifier.pattern = text;
01058 modifier.new_typ = new_typ;
01059 modifier.new_severity = new_severity;
01060 modifier.handling = handling;
01061
01062 // Remove "/" surrounding the pattern, if any
01063 if (`vmm_str_match(modifier.pattern, "^/(.*)/$")) begin
01064 modifier.pattern = `vmm_str_backref(modifier.pattern, 0);
01065 end
01066
01067 mod_id = this.modifier_cache.num();
01068 this.modifier_cache[mod_id] = modifier;
01069
01070 //
01071 // Link all affected log instances
01072 //
01073 this.reset(name, inst, recursive);
01074 for(vmm_log log = this.for_each(); log != null; log = this.for_each()) begin
01075 log.modifier_ids.push_back(mod_id);
01076 if (modifier.pattern != "") log.has_text_modifiers++;
01077 end
01078
01079 modify = mod_id;
01080 endfunction: modify
01081
01082
01083 function void vmm_log::unmodify(int modification_id,
01084 string name,
01085 string inst,
01086 bit recursive);
01087 if (modification_id < -1) begin
01088 `vmm_error(this, `vmm_sformatf("Invalid modification ID %0d specified to vmm_log::unmodify()",
01089 modification_id));
01090 return;
01091 end
01092
01093 // Does it exist?
01094 if (modification_id >= 0) begin
01095 if (!this.modifier_cache.exists(modification_id)) begin
01096 `vmm_error(this, `vmm_sformatf("Unknown modification ID %0d specified to vmm_log::unmodify()",
01097 modification_id));
01098 return;
01099 end
01100 end
01101
01102 //
01103 // Unlink all affected log instances
01104 //
01105 this.reset(name, inst, recursive);
01106 for(vmm_log log = this.for_each(); log != null; log = this.for_each()) begin
01107
01108 // Find the specified modifier...
01109 foreach(log.modifier_ids[i]) begin
01110 if (modification_id >= 0 && log.modifier_ids[i] != modification_id) continue;
01111
01112 if (this.modifier_cache[log.modifier_ids[i]].pattern != "") begin
01113 log.has_text_modifiers--;
01114 if (log.has_text_modifiers < 0) begin
01115 $write("***** vmm_log Internal ERROR: has_text_modifiers < 0\n");
01116 log.has_text_modifiers = 0;
01117 end
01118 end
01119 if (modification_id >= 0) begin
01120 log.modifier_ids.delete(i);
01121 break;
01122 end
01123 end
01124 if (modification_id < 0) begin
01125 `ifdef VCS2006_06
01126 // Work-around for NYI feature in 2006.06
01127 // *NOT* IEEE compliant :-(
01128 log.modifier_ids.delete();
01129 `else
01130 // Works in VCS 2008.03
01131 log.modifier_ids = '{};
01132 `endif
01133 end
01134 end
01135 endfunction: unmodify
01136
01137
01138 function void vmm_log::promote();
01139
01140
01141 foreach(this.modifier_ids[i]) begin
01142 vmm_log_modifier mod;
01143
01144 mod = this.modifier_cache[this.modifier_ids[i]];
01145
01146
01147
01148
01149 if (!(mod.typ & this.msg.effective_typ)) continue;
01150
01151
01152 if (!(mod.severity & this.msg.effective_severity)) continue;
01153
01154
01155 if (mod.pattern != "") begin
01156 bit matched = 0;
01157 int idx;
01158 foreach (this.msg.text[idx]) begin
01159 if (`vmm_str_match(this.msg.text[idx], mod.pattern)) begin
01160 matched = 1;
01161 break;
01162 end
01163 end
01164 if (!matched) continue;
01165 end
01166
01167
01168 if (mod.new_typ != UNCHANGED) begin
01169 if (mod.new_typ == DEFAULT) begin
01170 this.msg.effective_typ = this.msg.original_typ;
01171 end else begin
01172 this.msg.effective_typ = mod.new_typ;
01173 end
01174 end
01175
01176 if (mod.new_severity != UNCHANGED) begin
01177 if (mod.new_severity == DEFAULT) begin
01178 this.msg.effective_severity = this.msg.original_severity;
01179 end else begin
01180 this.msg.effective_severity = mod.new_severity;
01181 end
01182
01183 if (this.msg.original_severity == FATAL_SEV &&
01184 this.msg.effective_severity > ERROR_SEV) begin
01185 this.msg.effective_severity = ERROR_SEV ;
01186 end
01187 if (this.msg.original_severity == ERROR_SEV &&
01188 this.msg.effective_severity > WARNING_SEV) begin
01189 this.msg.effective_severity = WARNING_SEV;
01190 end
01191 end
01192
01193 if (mod.handling != UNCHANGED) begin
01194 this.msg.handling = mod.handling;
01195 end
01196 end
01197 endfunction: promote
01198
01199
01200 function void vmm_log::filter();
01201
01202 if (this.msg.issued === 1'b0 || // Already filtered out
01203 this.msg.effective_severity == IGNORE_SEV || // Demoted to be ignored
01204 // Cannot disable any types with severity FATAL or ERROR
01205 (!(this.msg.effective_typ & this.enabled_typs) && // Disabled
01206 (this.msg.effective_severity >= WARNING_SEV)) ||
01207 (this.force_lvl != DEFAULT_SEV && this.msg.effective_severity > this.force_lvl) ||
01208 (this.force_lvl == DEFAULT_SEV && this.log_lvl < this.msg.effective_severity)) begin
01209 this.msg.issued = 1'b0;
01210
01211 return;
01212 end
01213
01214 this.msg.issued = 1'b1;
01215 endfunction: filter
01216
01217
01218 function void vmm_log::notify();
01219 // Check notifiers in the order they were created
01220 foreach(this.watchpoint_ids[i]) begin
01221 vmm_log_watchpoint wp;
01222
01223 wp = this.watchpoint_cache[this.watchpoint_ids[i]];
01224
01225 // Does it apply to this message?
01226
01227 // Message type must be included
01228 if (!(wp.typ & this.msg.effective_typ)) continue;
01229
01230 // Message severity must be included
01231 if (!(wp.severity & this.msg.effective_severity)) continue;
01232
01233 // The message must be issued or not
01234 if (wp.issued !== 1'bx && wp.issued !== this.msg.issued) begin
01235 continue;
01236 end
01237
01238
01239 if (wp.pattern != "") begin
01240 bit matched = 0;
01241 integer idx;
01242 foreach(this.msg.text[idx]) begin
01243 if (`vmm_str_match(this.msg.text[idx], wp.pattern)) begin
01244 matched = 1;
01245 break;
01246 end
01247 end
01248 if (!matched) continue;
01249 end
01250
01251
01252 wp.msg = this.msg.copy();
01253 -> wp.seen;
01254 end
01255 endfunction: notify
01256
01257
01258 function void vmm_log::set_verbosity(int severity,
01259 string name,
01260 string inst,
01261 bit recursive);
01262 if (!this.sev_images.exists(severity) ||
01263 severity < ERROR_SEV ||
01264 severity > VERBOSE_SEV) begin
01265 `vmm_error(this, "Invalid severity specified to vmm_log::set_verbosity()");
01266 return;
01267 end
01268
01269 this.reset(name, inst, recursive);
01270 for(vmm_log log = this.for_each(); log != null; log = this.for_each()) begin
01271 log.log_lvl = severity;
01272 end
01273 endfunction: set_verbosity
01274
01275
01276 function int vmm_log::get_verbosity();
01277 get_verbosity = this.log_lvl;
01278 endfunction: get_verbosity
01279
01280
01281 function void vmm_log::log_start(int file,
01282 string name,
01283 string inst,
01284 bit recurse);
01285
01286 vmm_log log;
01287
01288 this.reset(name, inst, recurse);
01289 for(log = this.for_each(); log != null; log = this.for_each()) begin
01290
01291
01292 foreach(log.fp[i]) begin
01293 if (log.fp[i] == file) return;
01294 end
01295 log.fp.push_back(file);
01296
01297
01298 end
01299 endfunction: log_start
01300
01301
01302 function void vmm_log::log_stop(int file,
01303 string name,
01304 string inst,
01305 bit recurse);
01306
01307 vmm_log log;
01308
01309 this.reset(name, inst, recurse);
01310 for(log = this.for_each(); log != null; log = this.for_each()) begin
01311
01312
01313 foreach(log.fp[i]) begin
01314 if (log.fp[i] == file) log.fp.delete(i);
01315
01316 end
01317 end
01318 endfunction: log_stop
01319
01320
01321 function void vmm_log::stop_after_n_errors(int n);
01322 this.error_count = 0;
01323 this.error_limit = n;
01324 endfunction: stop_after_n_errors
01325
01326 function int vmm_log::get_message_count(int severity,
01327 string name,
01328 string inst,
01329 bit recurse);
01330 get_message_count = 0;
01331
01332 this.reset(name, inst, recurse);
01333 for(vmm_log log = this.for_each(); log != null; log = this.for_each()) begin
01334
01335 if (severity & FATAL_SEV) get_message_count += log.n_msg[FATAL_SEV];
01336 if (severity & ERROR_SEV) get_message_count += log.n_msg[ERROR_SEV];
01337 if (severity & WARNING_SEV) get_message_count += log.n_msg[WARNING_SEV];
01338 if (severity & NORMAL_SEV) get_message_count += log.n_msg[NORMAL_SEV];
01339 if (severity & TRACE_SEV) get_message_count += log.n_msg[TRACE_SEV];
01340 if (severity & DEBUG_SEV) get_message_count += log.n_msg[DEBUG_SEV];
01341 if (severity & VERBOSE_SEV) get_message_count += log.n_msg[VERBOSE_SEV];
01342 if (severity & HIDDEN_SEV) get_message_count += log.n_msg[HIDDEN_SEV];
01343 if (severity & IGNORE_SEV) get_message_count += log.n_msg[IGNORE_SEV];
01344 end
01345 endfunction: get_message_count
01346
01347
01348 task vmm_log::wait_for_msg(string name,
01349 string inst,
01350 bit recurse,
01351 int typs,
01352 int severity,
01353 string text,
01354 logic issued,
01355 ref vmm_log_msg msg);
01356 int wp_id;
01357
01358 wp_id = this.create_watchpoint(typs, severity, text, issued);
01359 this.add_watchpoint(wp_id, name, inst, recurse);
01360 this.wait_for_watchpoint(wp_id, msg);
01361 this.remove_watchpoint(wp_id, name, inst, recurse);
01362 endtask: wait_for_msg
01363
01364
01365 function int vmm_log::create_watchpoint(int typs,