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