Expanded versions of source files are the output of the preprocessor. Lines subject to conditional compilation are not shown and all compiler pragmas have been stripped. Macros have been completely expanded.
std_lib/vmm_log.sv unexpanded source
00001: // 00002: // ------------------------------------------------------------- 00003: // Copyright 2004-2008 Synopsys, Inc. 00004: // All Rights Reserved Worldwide 00005: // 00006: // Licensed under the Apache License, Version 2.0 (the 00007: // "License"); you may not use this file except in 00008: // compliance with the License. You may obtain a copy of 00009: // the License at 00010: // 00011: // http://www.apache.org/licenses/LICENSE-2.0 00012: // 00013: // Unless required by applicable law or agreed to in 00014: // writing, software distributed under the License is 00015: // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 00016: // CONDITIONS OF ANY KIND, either express or implied. See 00017: // the License for the specific language governing 00018: // permissions and limitations under the License. 00019: // ------------------------------------------------------------- 00020: // 00021: 00022: 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: // Initialize all static properties 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: 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: // Initialize all static properties 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: 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: /*local*/ 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: // vmm_log_modifier 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: // vmm_log_watchpoint 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++; 00185: // Works in VCS 2008.03 00186: this.recurse_stack = '{}; 00188: 00189: // Trivial iterators? 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; // No point in recursion 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(0+1); 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(0+1); 00213: end 00214: endfunction: reset 00215: 00216: 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); 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: // Define default images 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: 00389: this.sev_images[FATAL_SEV ] = "*FATAL*"; 00390: this.sev_images[ERROR_SEV ] = "!ERROR!"; 00391: this.sev_images[WARNING_SEV] = "WARNING"; 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: // Process command-line options 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); // Only look at the 1st 2 chars 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: // Sometimes, VCS screws up static initialization order 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); // Only look at the 1st 2 chars 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: // Catch a common usage error 00475: /// 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: : do : if (this.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.text("Cannot use NULL formatter in vmm_log::set_format(). Unchanged")); : this.end_msg(); : end : while (0); 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: : do : if (this.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.text("Invalid message type specified to vmm_log::set_typ_image()")); : this.end_msg(); : end : while (0); 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: // Special types 00620: if (typ == DEFAULT) begin 00621: return "(default)"; 00622: end 00623: if (typ == UNCHANGED) begin 00624: return "(unchanged)"; 00625: end 00626: 00627: // Composite type? 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: : do : if (this.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.text("Invalid message severity specified to vmm_log::set_sev_image()")); : this.end_msg(); : end : while (0); 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: // Special severities 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: // Composite severity? 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; 00786: // Works in VCS 2008.03 00787: this.msg.text = '{}; 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: // Record risky demotions 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: : do : if (this.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.text("Malformed message: vmm_log::text() called before vmm_log::start_msg()")); : this.end_msg(); : end : while (0); 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: : do : if (this.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.text("Malformed message: vmm_log::end_msg() called before vmm_log::start_msg()")); : this.end_msg(); : end : while (0); 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: // Avoid recursive handling in callbacks 00855: if (this.in_callbacks) handling = CONTINUE; 00856: 00857: case (handling) 00858: 00859: ABORT_SIM: begin 00860: this.in_callbacks = 1; 00861: : : do foreach (this.callbacks[vmm_i]) begin : vmm_log_callbacks cb; : if (!$cast(cb, this.callbacks[vmm_i])) continue; : : cb.pre_abort(this); : end while (0); 00862: this.in_callbacks = 0; 00863: $finish; 00864: end 00865: 00866: DUMP_STACK, 00867: DEBUGGER: begin 00868: this.in_callbacks = 1; 00869: : : do foreach (this.callbacks[vmm_i]) begin : vmm_log_callbacks cb; : if (!$cast(cb, this.callbacks[vmm_i])) continue; : : cb.pre_debug(this); : end while (0); 00870: this.in_callbacks = 0; 00871: $stop; 00872: end 00873: 00874: STOP_PROMPT: begin 00875: this.in_callbacks = 1; 00876: : : do foreach (this.callbacks[vmm_i]) begin : vmm_log_callbacks cb; : if (!$cast(cb, this.callbacks[vmm_i])) continue; : : cb.pre_stop(this); : end while (0); 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: //`vmm_callback(vmm_log_callbacks, pre_abort(this)); 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: // Perform promotion/demotion if there are text filters 00910: // (it will have been done in start_msg() if there were none) 00911: if (this.has_text_modifiers) begin 00912: this.promote(); 00913: this.filter(); 00914: end 00915: this.notify(); 00916: 00917: // Record risky demotions 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++; 00948: // Works in VCS 2008.03 00949: this.msg.text = '{}; 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: // Did we just send an ERROR or FATAL message to /dev/null?? 00962: if (this.fp.size() == 0 && this.msg.effective_severity <= ERROR_SEV) begin 00963: // Force it to appear on STDOUT 00964: $display("%s", msg); 00965: end 00966: this.msg.flushed++; 00972: // Works in VCS 2008.03 00973: this.msg.text = '{}; 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: : do : if (this.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.text("Invalid message type specified to vmm_log::enable_types")); : this.end_msg(); : end : while (0); 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: : do : if (this.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.text("Invalid message type specified to vmm_log::disable_types")); : this.end_msg(); : end : while (0); 01009: return; 01010: end 01011: // Cannot disable failure messages 01012: if (typs & FAILURE_TYP) begin 01013: : do : if (this.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin : void'(this.text("Cannot disable FAILURE_TYP messages")); : this.end_msg(); : end : while(0); 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: : do : if (this.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.text("Cannot demote FATAL_SEV severity to less than ERROR_SEV")); : this.end_msg(); : end : while (0); 01043: return -2; 01044: end 01045: if (severity == ERROR_SEV && 01046: new_severity > WARNING_SEV) begin 01047: : do : if (this.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.text("Cannot demote ERROR severity to less than WARNING")); : this.end_msg(); : end : while (0); 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(0+1); 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 01089: : do : if (this.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.text($psprintf("Invalid modification ID %0d specified to vmm_log::unmodify()", : modification_id))); : this.end_msg(); : end : while (0); 01090: return; 01091: end 01092: 01093: // Does it exist? 01094: if (modification_id >= 0) begin 01095: if (!this.modifier_cache.exists(modification_id)) begin 01097: : do : if (this.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.text($psprintf("Unknown modification ID %0d specified to vmm_log::unmodify()", : modification_id))); : this.end_msg(); : end : while (0); 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 01130: // Works in VCS 2008.03 01131: log.modifier_ids = '{}; 01133: end 01134: end 01135: endfunction: unmodify 01136: 01137: 01138: function void vmm_log::promote(); 01139: 01140: // Apply modifiers in the order they were created 01141: foreach(this.modifier_ids[i]) begin 01142: vmm_log_modifier mod; 01143: 01144: mod = this.modifier_cache[this.modifier_ids[i]]; 01145: 01146: // Does it apply to this message? 01147: 01148: // Message type must be included 01149: if (!(mod.typ & this.msg.effective_typ)) continue; 01150: 01151: // Message severity must be included 01152: if (!(mod.severity & this.msg.effective_severity)) continue; 01153: 01154: // If specified, the text pattern must match 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: // Promote message! 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: // Some severities cannot be demoted too far 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: // If specified, the text pattern must match 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; // to the next watchpt 01249: end 01250: 01251: // This is a watched message 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: : do : if (this.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.text("Invalid severity specified to vmm_log::set_verbosity()")); : this.end_msg(); : end : while (0); 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: // Find the loggers in question 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: // Check that we are not already logging to this file 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: // Find the loggers in question 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: // Check that we are indeed logging to this file 01313: foreach(log.fp[i]) begin 01314: if (log.fp[i] == file) log.fp.delete(i); 01315: // Cannot close this file because it may still be used by other loggers 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, 01366: int severity, 01367: string text, 01368: logic issued); 01369: vmm_log_watchpoint wp = new; 01370: int wp_id; 01371: 01372: // 01373: // Add a description of the watchpoint to the cache 01374: // 01375: wp.typ = typs; 01376: wp.severity = severity; 01377: wp.pattern = text; 01378: wp.issued = issued; 01379: 01380: // Remove "/" surrounding the pattern, if any 01381: if (vmm_str_match(wp.pattern, "^/(.*)/$")) begin 01382: wp.pattern = vmm_str_backref(0+1); 01383: end 01384: 01385: wp_id = this.watchpoint_cache.num(); 01386: this.watchpoint_cache[wp_id] = wp; 01387: 01388: create_watchpoint = wp_id; 01389: endfunction: create_watchpoint 01390: 01391: 01392: function void vmm_log::add_watchpoint(int watchpoint_id, 01393: string name, 01394: string inst, 01395: bit recurse); 01396: vmm_log log; 01397: vmm_log_watchpoint wp; 01398: 01399: if (!this.watchpoint_cache.exists(watchpoint_id)) begin 01400: : do : if (this.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin : void'(this.text($psprintf("Watchpoint #%0d does not exist", watchpoint_id))); : this.end_msg(); : end : while(0); 01401: return; 01402: end 01403: wp = this.watchpoint_cache[watchpoint_id]; 01404: 01405: // 01406: // Link all affected log insts 01407: // 01408: this.reset(name, inst, recurse); 01409: for(log = this.for_each(); log != null; log = this.for_each()) begin 01410: log.watchpoint_ids.push_back(watchpoint_id); 01411: if (wp.pattern != "") log.has_text_modifiers++; 01412: end 01413: endfunction: add_watchpoint 01414: 01415: 01416: function void vmm_log::remove_watchpoint(int watchpoint_id, 01417: string name, 01418: string inst, 01419: bit recurse); 01420: vmm_log log; 01421: 01422: // 01423: // Unlink all affected log insts 01424: // 01425: this.reset(name, inst, recurse); 01426: for(log = this.for_each(); log != null; log = this.for_each()) begin 01427: 01428: // Find the specified watchpoint... 01429: foreach(log.watchpoint_ids[i]) begin 01430: if (watchpoint_id < 0 || log.watchpoint_ids[i] == watchpoint_id) begin 01431: if (this.watchpoint_cache[log.watchpoint_ids[i]].pattern != "") begin 01432: log.has_text_modifiers--; 01433: if (log.has_text_modifiers < 0) begin 01434: $write("***** vmm_log Internal ERROR: has_text_modifiers < 0\n"); 01435: log.has_text_modifiers = 0; 01436: end 01437: end 01438: log.watchpoint_ids.delete(i); 01439: if (watchpoint_id >= 0) break; 01440: end 01441: end 01442: end 01443: endfunction: remove_watchpoint 01444: 01445: 01446: task vmm_log::wait_for_watchpoint(int watchpoint_id, 01447: ref vmm_log_msg msg); 01448: vmm_log_watchpoint wp; 01449: 01450: if (!this.watchpoint_cache.exists(watchpoint_id)) begin 01451: : do : if (this.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin : void'(this.text($psprintf("Watchpoint #%0d does not exist", watchpoint_id))); : this.end_msg(); : end : while(0); 01452: msg = null; 01453: end 01454: else begin 01455: // 01456: // Wait for a triggering of the watchpoint 01457: // 01458: wp = this.watchpoint_cache[watchpoint_id]; 01459: @wp.seen; 01460: msg = wp.msg; 01461: end 01462: endtask: wait_for_watchpoint 01463: 01464: function void vmm_log::prepend_callback(vmm_log_callbacks cb); 01465: // Check if callback has already been registered... 01466: foreach (this.callbacks[i]) begin 01467: if (this.callbacks[i] == cb) begin 01468: if (this.start_msg(FAILURE_TYP, WARNING_SEV)) begin 01469: this.text("Callback has already been registered"); 01470: this.end_msg(); 01471: end 01472: return; 01473: end 01474: end 01475: 01476: // Register new callback 01477: this.callbacks.push_front(cb); 01478: endfunction: prepend_callback 01479: 01480: 01481: function void vmm_log::append_callback(vmm_log_callbacks cb); 01482: // Check if callback has already been registered... 01483: foreach (this.callbacks[i]) begin 01484: if (this.callbacks[i] == cb) begin 01485: if (this.start_msg(FAILURE_TYP, WARNING_SEV)) begin 01486: this.text("Callback has already been registered"); 01487: this.end_msg(); 01488: end 01489: return; 01490: end 01491: end 01492: 01493: // Register new callback 01494: this.callbacks.push_back(cb); 01495: endfunction: append_callback 01496: 01497: 01498: function void vmm_log::unregister_callback(vmm_log_callbacks cb); 01499: // Look for callback 01500: foreach (this.callbacks[i]) begin 01501: if (this.callbacks[i] == cb) begin 01502: // Unregister it 01503: this.callbacks.delete(i); 01504: return; 01505: end 01506: end 01507: 01508: if (this.start_msg(FAILURE_TYP, WARNING_SEV)) begin 01509: this.text("Callback was not registered"); 01510: this.end_msg(); 01511: end 01512: endfunction: unregister_callback 01513: 01514: 01515: // 01516: // vmm_log_format 01517: // 01518: 01519: function string vmm_log_format::format_msg(string name, 01520: string inst, 01521: string msg_typ, 01522: string severity, 01523: ref string lines[$]); 01524: $sformat(format_msg, "%s[%s] on %s(%s) at %t:", 01525: severity, msg_typ, name, inst, $realtime()); 01526: foreach(lines[i]) begin 01527: string line = lines[i]; 01528: string t; 01529: 01530: format_msg = {format_msg, "\n "}; 01531: 01532: while (1) begin 01533: string pre; 01534: if (!vmm_str_match(line, "\n")) begin 01535: format_msg = {format_msg, line}; 01536: break; 01537: end 01538: 01539: pre = vmm_str_prematch(); 01540: format_msg = {format_msg, pre, "\n "}; 01541: line = vmm_str_postmatch(); 01542: end 01543: end 01544: endfunction: format_msg 01545: 01546: 01547: function string vmm_log_format::continue_msg(string name, 01548: string inst, 01549: string msg_typ, 01550: string severity, 01551: ref string lines[$]); 01552: continue_msg = ""; 01553: foreach(lines[i]) begin 01554: if (i > 0) continue_msg = {continue_msg, "\n"}; 01555: $sformat(continue_msg, "%s %s", continue_msg, lines[i]); 01556: end 01557: endfunction: continue_msg 01558: 01559: 01560: function string vmm_log_format::abort_on_error(int count, 01561: int limit); 01562: abort_on_error = "Maximum number of error messages exceeded. Aborting\nUse method stop_after_n_errors() of vmm_log to increase threshold."; 01563: endfunction: abort_on_error 01564: 01565: 01566: function string vmm_log_format::pass_or_fail(bit pass, 01567: string name, 01568: string inst, 01569: int fatals, 01570: int errors, 01571: int warnings, 01572: int dem_errs, 01573: int dem_warns); 01574: if (pass) begin 01575: $sformat(pass_or_fail, "Simulation PASSED on %s (%s) at %t (%0d warnings, %0d demoted errors & %0d demoted warnings)", 01576: name, inst, $realtime(), warnings, dem_errs, dem_warns); 01577: end else begin 01578: $sformat(pass_or_fail, "Simulation *FAILED* on %s (%s) at %t: %0d errors, %0d warnings", 01579: name, inst, $realtime(), fatals + errors, warnings); 01580: end 01581: endfunction: pass_or_fail 01582: 01583: 01584: 01585: