sc_report_handler.cpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   The following code is derived, directly or indirectly, from the SystemC
00004   source code Copyright (c) 1996-2006 by all Contributors.
00005   All Rights reserved.
00006 
00007   The contents of this file are subject to the restrictions and limitations
00008   set forth in the SystemC Open Source License Version 2.4 (the "License");
00009   You may not use this file except in compliance with such restrictions and
00010   limitations. You may obtain instructions on how to receive a copy of the
00011   License at http://www.systemc.org/. Software distributed by Contributors
00012   under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
00013   ANY KIND, either express or implied. See the License for the specific
00014   language governing rights and limitations under the License.
00015 
00016  *****************************************************************************/
00017 
00018 /*****************************************************************************
00019 
00020   sc_report_handler.cpp - 
00021 
00022   Original Author: Alex Riesen, Synopsys, Inc.
00023   see also sc_report.cpp
00024 
00025  *****************************************************************************/
00026 
00027 /*****************************************************************************
00028 
00029   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
00030   changes you are making here.
00031 
00032       Name, Affiliation, Date:
00033   Description of Modification:
00034 
00035  *****************************************************************************/
00036 
00037 // $Log: sc_report_handler.cpp,v $
00038 // Revision 1.1.1.1  2006/12/15 20:31:39  acg
00039 // SystemC 2.2
00040 //
00041 // Revision 1.6  2006/03/21 00:00:37  acg
00042 //   Andy Goodrich: changed name of sc_get_current_process_base() to be
00043 //   sc_get_current_process_b() since its returning an sc_process_b instance.
00044 //
00045 // Revision 1.5  2006/01/31 21:42:07  acg
00046 //  Andy Goodrich: Added checks for SC_DEPRECATED_WARNINGS being defined as
00047 //  DISABLED. If so, we turn off the /IEEE_Std_1666/deprecated message group.
00048 //
00049 // Revision 1.4  2006/01/26 21:08:17  acg
00050 //  Andy Goodrich: conversion to use sc_is_running instead of deprecated
00051 //  sc_simcontext::is_running()
00052 //
00053 // Revision 1.3  2006/01/13 18:53:11  acg
00054 // Andy Goodrich: Added $Log command so that CVS comments are reproduced in
00055 // the source.
00056 //
00057 
00058 #include "sysc/utils/sc_iostream.h"
00059 #include "sysc/kernel/sc_process.h"
00060 #include "sysc/kernel/sc_simcontext_int.h"
00061 #include "sysc/utils/sc_stop_here.h"
00062 #include "sysc/utils/sc_report_handler.h"
00063 #include "sysc/utils/sc_report.h"
00064 
00065 namespace std {}
00066 
00067 namespace sc_core {
00068 
00069 // not documented, but available
00070 const std::string sc_report_compose_message(const sc_report& rep)
00071 {
00072     static const char * severity_names[] = {
00073     "Info", "Warning", "Error", "Fatal"
00074     };
00075     std::string str;
00076 
00077     str += severity_names[rep.get_severity()];
00078     str += ": ";
00079 
00080     if ( rep.get_id() >= 0 ) // backward compatibility with 2.0+
00081     {
00082     char idstr[64];
00083     std::sprintf(idstr, "(%c%d) ",
00084         "IWEF"[rep.get_severity()], rep.get_id());
00085     str += idstr;
00086     }
00087     str += rep.get_msg_type();
00088 
00089     if( *rep.get_msg() )
00090     {
00091     str += ": ";
00092     str += rep.get_msg();
00093     }
00094     if( rep.get_severity() > SC_INFO )
00095     {
00096         char line_number_str[16];
00097     str += "\nIn file: ";
00098     str += rep.get_file_name();
00099     str += ":";
00100     std::sprintf(line_number_str, "%d", rep.get_line_number());
00101     str += line_number_str;
00102     sc_simcontext* simc = sc_get_curr_simcontext();
00103 
00104     if( simc && sc_is_running() )
00105     {
00106         const char* proc_name = rep.get_process_name();
00107 
00108         if( proc_name )
00109         {
00110         str += "\nIn process: ";
00111         str += proc_name;
00112         str += " @ ";
00113         str += rep.get_time().to_string();
00114         }
00115     }
00116     }
00117 
00118     return str;
00119 }
00120 bool sc_report_close_default_log();
00121 
00122 static ::std::ofstream* log_stream = 0;
00123 static
00124 struct auto_close_log
00125 {
00126     ~auto_close_log()
00127     {
00128     sc_report_close_default_log();
00129     }
00130 } auto_close;
00131 
00132 const char* sc_report::get_process_name() const
00133 {
00134     return process ? process->name() : 0;
00135 }
00136 
00137 
00138 //
00139 // The official handler of the exception reporting
00140 //
00141 
00142 void sc_report_handler::default_handler(const sc_report& rep,
00143                     const sc_actions& actions)
00144 {
00145     if ( actions & SC_DISPLAY )
00146     ::std::cout << ::std::endl << sc_report_compose_message(rep) << 
00147         ::std::endl;
00148 
00149     if ( (actions & SC_LOG) && get_log_file_name() )
00150     {
00151     if ( !log_stream )
00152         log_stream = new ::std::ofstream(get_log_file_name()); // ios::trunc
00153 
00154     *log_stream << rep.get_time() << ": "
00155         << sc_report_compose_message(rep) << ::std::endl;
00156     }
00157     if ( actions & SC_STOP )
00158     {
00159     sc_stop_here(rep.get_msg_type(), rep.get_severity());
00160     sc_stop();
00161     }
00162     if ( actions & SC_INTERRUPT )
00163     sc_interrupt_here(rep.get_msg_type(), rep.get_severity());
00164 
00165     if ( actions & SC_ABORT )
00166     abort();
00167 
00168     if ( actions & SC_THROW )
00169     throw rep; 
00170 }
00171 
00172 // not documented, but available
00173 bool sc_report_close_default_log()
00174 {
00175     delete log_stream;
00176     sc_report_handler::set_log_file_name(NULL);
00177 
00178     if ( !log_stream )
00179     return false;
00180 
00181     log_stream = 0;
00182     return true;
00183 }
00184 
00185 int sc_report_handler::get_count(sc_severity severity_) 
00186 { 
00187    return sev_call_count[severity_]; 
00188 } 
00189 
00190 int sc_report_handler::get_count(const char* msg_type_) 
00191 { 
00192     sc_msg_def * md = mdlookup(msg_type_); 
00193 
00194     if ( !md ) 
00195         md = add_msg_type(msg_type_); 
00196 
00197     return md->call_count; 
00198 } 
00199 
00200 int sc_report_handler::get_count(const char* msg_type_, sc_severity severity_) 
00201 { 
00202     sc_msg_def * md = mdlookup(msg_type_); 
00203 
00204     if ( !md ) 
00205         md = add_msg_type(msg_type_); 
00206 
00207     return md->sev_call_count[severity_]; 
00208 } 
00209 
00210 
00211 //
00212 // CLASS: sc_report_handler
00213 // implementation
00214 //
00215 
00216 sc_msg_def * sc_report_handler::mdlookup(const char * msg_type_)
00217 {
00218     for ( msg_def_items * item = messages; item; item = item->next )
00219     {
00220     for ( int i = 0; i < item->count; ++i )
00221         if ( !strcmp(msg_type_, item->md[i].msg_type) )
00222         return item->md + i;
00223     }
00224     return 0;
00225 }
00226 
00227 // The calculation of actions to be executed
00228 sc_actions sc_report_handler::execute(sc_msg_def* md, sc_severity severity_)
00229 {
00230     sc_actions actions = md->sev_actions[severity_]; // high prio
00231 
00232     if ( SC_UNSPECIFIED == actions ) // middle prio
00233     actions = md->actions;
00234 
00235     if ( SC_UNSPECIFIED == actions ) // the lowest prio
00236     actions = sev_actions[severity_];
00237 
00238     actions &= ~suppress_mask; // higher than the high prio
00239     actions |= force_mask; // higher than above, and the limit is the highest
00240 
00241     unsigned * limit = 0;
00242     unsigned * call_count = 0;
00243 
00244     // just increment counters and check for overflow
00245     if ( md->sev_call_count[severity_] < UINT_MAX )
00246     md->sev_call_count[severity_]++;
00247     if ( md->call_count < UINT_MAX )
00248     md->call_count++;
00249     if ( sev_call_count[severity_] < UINT_MAX )
00250     sev_call_count[severity_]++;
00251 
00252     if ( md->limit_mask & (1 << (severity_ + 1)) )
00253     {
00254     limit = md->sev_limit + severity_;
00255     call_count = md->sev_call_count + severity_;
00256     }
00257     if ( !limit && (md->limit_mask & 1) )
00258     {
00259     limit = &md->limit;
00260     call_count = &md->call_count;
00261     }
00262     if ( !limit )
00263     {
00264     limit = sev_limit + severity_;
00265     call_count = sev_call_count + severity_;
00266     }
00267     if ( *limit == 0 )
00268     {
00269     // stop limit disabled
00270     }
00271     else if ( *limit != UINT_MAX )
00272     {
00273     if ( *call_count >= *limit )
00274         actions |= SC_STOP; // force sc_stop()
00275     }
00276     return actions;
00277 }
00278 
00279 void sc_report_handler::report(sc_severity severity_,
00280                    const char * msg_type_,
00281                    const char * msg_,
00282                    const char * file_,
00283                    int line_)
00284 {
00285     sc_msg_def * md = mdlookup(msg_type_);
00286 
00287     if ( !md )
00288     md = add_msg_type(msg_type_);
00289 
00290     sc_actions actions = execute(md, severity_);
00291     sc_report rep(severity_, md, msg_, file_, line_);
00292 
00293     if ( actions & SC_CACHE_REPORT )
00294     cache_report(rep);
00295 
00296     handler(rep, actions);
00297 }
00298 
00299 // The following method is never called by the simulator.
00300 
00301 void sc_report_handler::initialize()
00302 {
00303 #if 0 // actually, i do not know whether we have to reset these.
00304     suppress();
00305     force();
00306     set_actions(SC_INFO,    SC_DEFAULT_INFO_ACTIONS);
00307     set_actions(SC_WARNING, SC_DEFAULT_WARNING_ACTIONS);
00308     set_actions(SC_ERROR,   SC_DEFAULT_ERROR_ACTIONS);
00309     set_actions(SC_FATAL,   SC_DEFAULT_FATAL_ACTIONS);
00310 #endif
00311 
00312     sev_call_count[SC_INFO]    = 0;
00313     sev_call_count[SC_WARNING] = 0;
00314     sev_call_count[SC_ERROR]   = 0;
00315     sev_call_count[SC_FATAL]   = 0;
00316 
00317     msg_def_items * items = messages;
00318 
00319     while ( items != &msg_terminator )
00320     {
00321     for ( int i = 0; i < items->count; ++i )
00322     {
00323         items->md[i].call_count = 0;
00324         items->md[i].sev_call_count[SC_INFO]    = 0;
00325         items->md[i].sev_call_count[SC_WARNING] = 0;
00326         items->md[i].sev_call_count[SC_ERROR]   = 0;
00327         items->md[i].sev_call_count[SC_FATAL]   = 0;
00328     }
00329     items = items->next;
00330     }
00331 
00332     // PROCESS ANY ENVIRONMENTAL OVERRIDES:
00333 
00334     const char* deprecation_warn = std::getenv("SC_DEPRECATION_WARNINGS");
00335     if ( (deprecation_warn!=0) && !strcmp(deprecation_warn,"DISABLE") )
00336     {
00337         set_actions("/IEEE_Std_1666/deprecated", SC_DO_NOTHING);
00338     }
00339 }
00340 
00341 // free the sc_msg_def's allocated by add_msg_type
00342 // (or implicit msg_type registration: set_actions, abort_after)
00343 // clear last_global_report.
00344 void sc_report_handler::release()
00345 {
00346     if ( last_global_report )
00347     delete last_global_report;
00348     last_global_report = 0;
00349     sc_report_close_default_log();
00350 
00351     msg_def_items * items = messages, * newitems = &msg_terminator;
00352     messages = &msg_terminator;
00353 
00354     while ( items != &msg_terminator )
00355     {
00356     for ( int i = 0; i < items->count; ++i )
00357         if ( items->md[i].msg_type == items->md[i].msg_type_data )
00358         free(items->md[i].msg_type_data);
00359 
00360     msg_def_items * prev = items;
00361     items = items->next;
00362 
00363     if ( prev->allocated )
00364     {
00365         delete [] prev->md;
00366         delete prev;
00367     }
00368     else
00369     {
00370         prev->next = newitems;
00371         newitems = prev;
00372     }
00373     }
00374     messages = newitems;
00375 }
00376 
00377 sc_msg_def * sc_report_handler::add_msg_type(const char * msg_type_)
00378 {
00379     sc_msg_def * md = mdlookup(msg_type_);
00380 
00381     if ( md )
00382     return md;
00383 
00384     msg_def_items * items = new msg_def_items;
00385 
00386     if ( !items )
00387     return 0;
00388 
00389     items->count = 1;
00390     items->md = new sc_msg_def[items->count];
00391 
00392     if ( !items->md )
00393     {
00394     delete items;
00395     return 0;
00396     }
00397     memset(items->md, 0, sizeof(sc_msg_def) * items->count);
00398     items->md->msg_type_data = strdup(msg_type_);
00399     items->md->id = -1; // backward compatibility with 2.0+
00400 
00401     if ( !items->md->msg_type_data )
00402     {
00403     delete items->md;
00404     delete items;
00405     return 0;
00406     }
00407     items->md->msg_type = items->md->msg_type_data;
00408     add_static_msg_types(items);
00409     items->allocated = true;
00410 
00411     return items->md;
00412 }
00413 
00414 void sc_report_handler::add_static_msg_types(msg_def_items * items)
00415 {
00416     items->allocated = false;
00417     items->next = messages;
00418     messages = items;
00419 }
00420 
00421 sc_actions sc_report_handler::set_actions(sc_severity severity_,
00422                       sc_actions actions_)
00423 {
00424     sc_actions old = sev_actions[severity_];
00425     sev_actions[severity_] = actions_;
00426     return old;
00427 }
00428 
00429 sc_actions sc_report_handler::set_actions(const char * msg_type_,
00430                       sc_actions actions_)
00431 {
00432     sc_msg_def * md = mdlookup(msg_type_);
00433 
00434     if ( !md )
00435     md = add_msg_type(msg_type_);
00436 
00437     sc_actions old = md->actions;
00438     md->actions = actions_;
00439 
00440     return old;
00441 }
00442 
00443 sc_actions sc_report_handler::set_actions(const char * msg_type_,
00444                       sc_severity severity_,
00445                       sc_actions actions_)
00446 {
00447     sc_msg_def * md = mdlookup(msg_type_);
00448 
00449     if ( !md )
00450     md = add_msg_type(msg_type_);
00451 
00452     sc_actions old = md->sev_actions[severity_];
00453     md->sev_actions[severity_] = actions_;
00454 
00455     return old;
00456 }
00457 
00458 int sc_report_handler::stop_after(sc_severity severity_, int limit)
00459 {
00460     int old = sev_limit[severity_];
00461 
00462     sev_limit[severity_] = limit < 0 ? UINT_MAX: limit;
00463 
00464     return old;
00465 }
00466 
00467 int sc_report_handler::stop_after(const char * msg_type_, int limit)
00468 {
00469     sc_msg_def * md = mdlookup(msg_type_);
00470 
00471     if ( !md )
00472     md = add_msg_type(msg_type_);
00473 
00474     int old = md->limit_mask & 1 ? md->limit: UINT_MAX;
00475 
00476     if ( limit < 0 )
00477     md->limit_mask &= ~1;
00478     else
00479     {
00480     md->limit_mask |= 1;
00481     md->limit = limit;
00482     }
00483     return old;
00484 }
00485 
00486 int sc_report_handler::stop_after(const char * msg_type_,
00487                   sc_severity severity_,
00488                   int limit)
00489 {
00490     sc_msg_def * md = mdlookup(msg_type_);
00491 
00492     if ( !md )
00493     md = add_msg_type(msg_type_);
00494 
00495     int mask = 1 << (severity_ + 1);
00496     int old = md->limit_mask & mask ?  md->sev_limit[severity_]: UINT_MAX;
00497 
00498     if ( limit < 0 )
00499     md->limit_mask &= ~mask;
00500     else
00501     {
00502     md->limit_mask |= mask;
00503     md->sev_limit[severity_] = limit;
00504     }
00505     return old;
00506 }
00507 
00508 sc_actions sc_report_handler::suppress(sc_actions mask)
00509 {
00510     sc_actions old = suppress_mask;
00511     suppress_mask = mask;
00512     return old;
00513 }
00514 
00515 sc_actions sc_report_handler::suppress()
00516 {
00517     return suppress(0);
00518 }
00519 
00520 sc_actions sc_report_handler::force(sc_actions mask)
00521 {
00522     sc_actions old = force_mask;
00523     force_mask = mask;
00524     return old;
00525 }
00526 
00527 sc_actions sc_report_handler::force()
00528 {
00529     return force(0);
00530 }
00531 
00532 void sc_report_handler::set_handler(sc_report_handler_proc handler_)
00533 {
00534     handler = handler_ ? handler_: &sc_report_handler::default_handler;
00535 }
00536 
00537 sc_report* sc_report_handler::get_cached_report()
00538 {
00539     sc_process_b * proc = sc_get_current_process_b();
00540 
00541     if ( proc )
00542     return proc->get_last_report();
00543 
00544     return last_global_report;
00545 }
00546 
00547 void sc_report_handler::clear_cached_report()
00548 {
00549     sc_process_b * proc = sc_get_current_process_b();
00550 
00551     if ( proc )
00552     proc->set_last_report(0);
00553     else
00554     {
00555     if ( last_global_report )
00556         delete last_global_report;
00557     last_global_report = 0;
00558     }
00559 }
00560 
00561 sc_actions sc_report_handler::get_new_action_id()
00562 {
00563     for ( sc_actions p = 1; p; p <<= 1 )
00564     {
00565     if ( !(p & available_actions) ) // free
00566     {
00567         available_actions |= p;
00568         return p;
00569     }
00570     }
00571     return SC_UNSPECIFIED;
00572 }
00573 
00574 bool sc_report_handler::set_log_file_name(const char* name_)
00575 {
00576     if ( !name_ )
00577     {
00578     free(log_file_name);
00579     log_file_name = 0;
00580     return false;
00581     }
00582     if ( log_file_name )
00583     return false;
00584 
00585     log_file_name = strdup(name_);
00586     return true;
00587 }
00588 
00589 const char * sc_report_handler::get_log_file_name()
00590 {
00591     return log_file_name;
00592 }
00593 
00594 void sc_report_handler::cache_report(const sc_report& rep)
00595 {
00596     sc_process_b * proc = sc_get_current_process_b();
00597     if ( proc )
00598     proc->set_last_report(new sc_report(rep));
00599     else
00600     {
00601     if ( last_global_report )
00602         delete last_global_report;
00603     last_global_report = new sc_report(rep);
00604     }
00605 }
00606 
00607 //
00608 // backward compatibility with 2.0+
00609 //
00610 
00611 sc_msg_def * sc_report_handler::mdlookup(int id)
00612 {
00613     for ( msg_def_items * item = messages; item; item = item->next )
00614     {
00615     for ( int i = 0; i < item->count; ++i )
00616         if ( id == item->md[i].id )
00617         return item->md + i;
00618     }
00619     return 0;
00620 }
00621 
00622 //
00623 // CLASS: sc_report_handler
00624 // static variables
00625 //
00626 
00627 sc_actions sc_report_handler::suppress_mask = 0;
00628 sc_actions sc_report_handler::force_mask = 0;
00629 
00630 sc_actions sc_report_handler::sev_actions[SC_MAX_SEVERITY] =
00631 {
00632     /* info  */ SC_DEFAULT_INFO_ACTIONS,
00633     /* warn  */ SC_DEFAULT_WARNING_ACTIONS,
00634     /* error */ SC_DEFAULT_ERROR_ACTIONS,
00635     /* fatal */ SC_DEFAULT_FATAL_ACTIONS
00636 };
00637 
00638 // Note that SC_FATAL has a limit of 1 by default
00639 
00640 sc_actions sc_report_handler::sev_limit[SC_MAX_SEVERITY] =
00641 {
00642     UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX
00643 };
00644 sc_actions sc_report_handler::sev_call_count[SC_MAX_SEVERITY] = { 0, 0, 0, 0 };
00645 
00646 sc_report* sc_report_handler::last_global_report = NULL;
00647 sc_actions sc_report_handler::available_actions =
00648     SC_DO_NOTHING |
00649     SC_THROW |
00650     SC_LOG |
00651     SC_DISPLAY |
00652     SC_CACHE_REPORT |
00653     SC_INTERRUPT |
00654     SC_STOP |
00655     SC_ABORT;
00656 
00657 sc_report_handler_proc sc_report_handler::handler =
00658     &sc_report_handler::default_handler;
00659 
00660 char * sc_report_handler::log_file_name = 0;
00661 
00662 sc_report_handler::msg_def_items * sc_report_handler::messages =
00663     &sc_report_handler::msg_terminator;
00664 
00665 
00666 //
00667 // predefined messages
00668 //
00669 
00670 const char SC_ID_REGISTER_ID_FAILED_[] = "register_id failed";
00671 const char SC_ID_UNKNOWN_ERROR_[]      = "unknown error";
00672 const char SC_ID_WITHOUT_MESSAGE_[]    = "";
00673 const char SC_ID_NOT_IMPLEMENTED_[]    = "not implemented";
00674 const char SC_ID_INTERNAL_ERROR_[]     = "internal error";
00675 const char SC_ID_ASSERTION_FAILED_[]   = "assertion failed";
00676 const char SC_ID_OUT_OF_BOUNDS_[]      = "out of bounds";
00677 
00678 #define DEFINE_MSG(id,n)                                                     \
00679     {                                                                        \
00680     (id),                                                                \
00681     0u, {0u}, /* actions */                                              \
00682     0u, {0u}, 0u, /* limits */                                           \
00683     0u, {0u}, NULL, /* call counters */                                  \
00684     n                                                                    \
00685     }
00686 
00687 static sc_msg_def default_msgs[] = {
00688     DEFINE_MSG(SC_ID_REGISTER_ID_FAILED_, 800),
00689     DEFINE_MSG(SC_ID_UNKNOWN_ERROR_, 0),
00690     DEFINE_MSG(SC_ID_WITHOUT_MESSAGE_, 1),
00691     DEFINE_MSG(SC_ID_NOT_IMPLEMENTED_, 2),
00692     DEFINE_MSG(SC_ID_INTERNAL_ERROR_, 3),
00693     DEFINE_MSG(SC_ID_ASSERTION_FAILED_, 4),
00694     DEFINE_MSG(SC_ID_OUT_OF_BOUNDS_, 5)
00695 };
00696 
00697 sc_report_handler::msg_def_items sc_report_handler::msg_terminator =
00698 {
00699     default_msgs,
00700     sizeof(default_msgs)/sizeof(*default_msgs),
00701     false,
00702     NULL
00703 };
00704 
00705 } // namespace sc_core
00706 
00707 // Taf!

Generated on Wed Jan 21 15:32:10 2009 for SystemC by  doxygen 1.5.5