VMM - (expanded) std_lib/vmm_log.sv

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: