Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

scv_report.cpp

Go to the documentation of this file.
00001 //  -*- C++ -*- <this line is for emacs to recognize it as C++ code>
00002 /*****************************************************************************
00003 
00004   The contents of this file are subject to the restrictions and limitations
00005   set forth in the SystemC Open Source License Version 2.3 (the "License");
00006   You may not use this file except in compliance with such restrictions and
00007   limitations. You may obtain instructions on how to receive a copy of the
00008   License at http://www.systemc.org/. Software distributed by Contributors
00009   under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
00010   ANY KIND, either express or implied. See the License for the specific
00011   language governing rights and limitations under the License.
00012 
00013  *****************************************************************************/
00014 
00015 /*****************************************************************************
00016 
00017   scv_report.cpp -- A trace/debug facility for the SystemC Verification
00018   Standard library
00019 
00020   Original Authors (Cadence Design Systems, Inc):
00021   Norris Ip, Dean Shea, John Rose, Jasvinder Singh, William Paulsen,
00022   John Pierce, Rachida Kebichi, Ted Elkind, David Bailey
00023   2002-09-23
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 //
00038 // This must be included before any system headers.
00039 //
00040 #include "scv.h"
00041 
00042 #include <stdarg.h>
00043 #include <string>
00044 #include <map>
00045 
00046 
00047 //
00048 // used in implementation of scv_report
00049 //
00050 
00051 
00052 #define _SCV_DEBUG_CHECK(level) SCV_DEBUG_CHECK(scv_report_handler::get_debug(),(level))
00053 
00054 
00055 template<typename KEY, typename VAL>
00056 class xref {
00057   typedef map<KEY,VAL> map_t;
00058   typedef typename map_t::const_iterator const_iterator;
00059   typedef typename map_t::iterator iterator;
00060 public:
00061   xref(VAL val) : _default(val) {}
00062   VAL get(const KEY key) const {
00063     const_iterator _iter = _map.find(key);
00064     return ( _iter == _map.end() ) ? _default : _iter->second;
00065   }
00066   VAL incr(KEY key) { // ++_map[key]
00067     iterator _iter = _map.find(key);
00068     if ( _iter == _map.end() ) { _map[key] = 1; return 1; }
00069     else return ++(_iter->second);
00070   }
00071   VAL set(KEY key, VAL val) {
00072     VAL prv = get(key);
00073     _map[key] = val;
00074     return prv;
00075   }
00076 private:
00077   map_t _map;
00078   VAL _default;
00079 };
00080 
00081 
00082 template<typename VAL>
00083 class rules {
00084 public:
00085   rules(VAL val)
00086     : _map_sev(val), _map_msg(val), _map_com(val) {}
00087   unsigned get(scv_severity severity) const
00088     { return _map_sev.get(severity); }
00089   unsigned get(scv_msg_type msg_type) const
00090     { return _map_msg.get(msg_type); }
00091   unsigned get(scv_msg_type msg_type, scv_severity severity) const
00092     { return _map_com.get( _scv_make_unique_name(msg_type,severity) ); }
00093   unsigned incr(scv_severity severity)
00094     { return _map_sev.incr(severity); }
00095   unsigned incr(scv_msg_type msg_type)
00096     { return _map_msg.incr(msg_type); }
00097   unsigned incr(scv_msg_type msg_type, scv_severity severity)
00098     { return _map_com.incr( _scv_make_unique_name(msg_type,severity) ); }
00099   unsigned set(unsigned severity, VAL val)
00100     { return _map_sev.set(severity,val); }
00101   unsigned set(scv_msg_type msg_type, VAL val)
00102     { return _map_msg.set(msg_type,val); }
00103   unsigned set(scv_msg_type msg_type, scv_severity severity, VAL val)
00104     { return _map_com.set( _scv_make_unique_name(msg_type,severity), val ); }
00105 private:
00106   xref<unsigned,VAL> _map_sev;
00107   xref<string,VAL> _map_msg;
00108   xref<string,VAL> _map_com;
00109 };
00110 
00111 
00112 class mask {
00113 public:
00114   mask(scv_actions val) : _mask(val) {}
00115   scv_actions get() const { return _mask; }
00116   scv_actions set(scv_actions val) {
00117     scv_actions prv = _mask; _mask = val; return prv;
00118   }
00119 private:
00120   scv_actions _mask;
00121 };
00122 
00123 
00124 class scv_report_core {
00125 public:
00126   rules<scv_actions> actions;
00127   rules<int> limits;
00128   rules<int> counts;
00129   mask force;
00130   mask suppress;
00131   scv_report_core()
00132     : actions(SCV_UNSPECIFIED)
00133     , limits(-1)
00134     , counts(0)
00135     , force(0)
00136     , suppress(0)
00137     {}
00138   void initialize() {
00139     actions.set((unsigned)SCV_INFO,SCV_DEFAULT_INFO_ACTIONS);
00140     actions.set((unsigned)SCV_WARNING,SCV_DEFAULT_WARNING_ACTIONS);
00141     actions.set((unsigned)SCV_ERROR,SCV_DEFAULT_ERROR_ACTIONS);
00142     actions.set((unsigned)SCV_FATAL,SCV_DEFAULT_FATAL_ACTIONS);
00143   }
00144   static scv_report_core *get_core() {
00145     static scv_report_core *core_p = 0;
00146     if ( ! core_p ) {
00147       core_p = new scv_report_core;
00148       core_p->initialize();
00149       _scv_message::setup();
00150     }
00151     return core_p;
00152   }
00153 };
00154 
00155 
00156 #ifndef _SCV_USE_SC_REPORT
00157 
00158 
00159 static string& severity_string(scv_severity severity)
00160 {
00161   static string info = "SCV_INFO";
00162   static string warning = "SCV_WARNING";
00163   static string error = "SCV_ERROR";
00164   static string fatal = "SCV_FATAL";
00165   static string unknown = "???";
00166   switch ( severity ) {
00167     case SCV_INFO    : return info;
00168     case SCV_WARNING : return warning;
00169     case SCV_ERROR   : return error;
00170     case SCV_FATAL   : return fatal;
00171     default      : return unknown;
00172   }
00173 }
00174 
00175 
00176 static scv_report *_update_report_cache(scv_report *newp, bool replace)
00177 {
00178   typedef map<sc_process_b*,scv_report*> map_t;
00179   static map_t _map;
00180 
00181   sc_process_b *key = sc_get_curr_process_handle();
00182   map_t::const_iterator _iter = _map.find(key);
00183   scv_report *curr = ( _iter == _map.end() ) ? 0 : _iter->second;
00184 
00185   if ( replace ) {
00186     if ( curr ) delete curr;
00187     _map[key] = curr = newp;
00188   }
00189   return curr;
00190 }
00191 
00192 
00193 //
00194 // Implementation of scv_report
00195 //
00196 
00197 
00198 void scv_interrupt_here(const scv_msg_type& id) {}
00199 void scv_stop_here() {}
00200 
00201 
00202 const char *scv_report::_kind = "scv_report";
00203 
00204 scv_report::scv_report(
00205   scv_severity severity, scv_msg_type msg_type,
00206   const char *msg,
00207   const char *file_name, int line_number,
00208   sc_time time, const char *process_name
00209 )
00210 : _severity(severity), _msg_type(msg_type)
00211 , _msg(msg)
00212 , _file_name(file_name), _line_number(line_number)
00213 , _time(time), _process_name(process_name)
00214 {}
00215 
00216 scv_report::scv_report(const scv_report& src)
00217 : _severity(src._severity), _msg_type(src._msg_type)
00218 , _msg(src._msg)
00219 , _file_name(src._file_name), _line_number(src._line_number)
00220 , _time(src._time), _process_name(src._process_name)
00221 {}
00222 
00223 void scv_report::print(ostream& os, int details, int indent) const
00224 {
00225   scv_debug::indent(os,indent);
00226   os << "scv_report: severity: " << severity_string(_severity)
00227      << " msg_type: " << _msg_type
00228      << " time: " << _time << " process: " << _process_name << endl;
00229   if ( ! details ) return;
00230   scv_debug::indent(os,indent+2);
00231   os << "msg: " << _msg << endl;
00232   scv_debug::indent(os,indent+2);
00233   os << "file: " << _file_name << " line: " << _line_number << endl;
00234 }
00235 
00236 scv_report& scv_report::operator=(const scv_report& src)
00237 {
00238   _severity = src._severity;
00239   _msg_type = src._msg_type;
00240   _msg = src._msg;
00241   _file_name = src._file_name;
00242   _line_number = src._line_number;
00243   _time = src._time;
00244   _process_name = src._process_name;
00245 
00246   return *this;
00247 }
00248 
00249 scv_report::operator const char *() const
00250 {
00251   static char *buf = new char[1024];
00252   static int max = 1024;
00253   int len = 10 + 32 + 10 + _msg_type.size() + 6 + 32 + 9 + _process_name.size()
00254     + 6 + _file_name.size() + 6 + 32 + 5 + _msg.size() +1;
00255   if ( len > max ) {
00256     max = len;
00257     delete [] buf;
00258     buf = new char[max];
00259   }
00260   sprintf(
00261     buf,
00262     "severity: %s msg_type: %s time: %s process: %s file: %s line: %d msg: %s",
00263     severity_string(_severity).c_str(), _msg_type.c_str(), 
00264     (const char*)_time.to_string(), _process_name.c_str(), _file_name.c_str(), 
00265     _line_number, _msg.c_str()
00266   );
00267   return buf;
00268 }
00269 
00270 
00271 //
00272 // Implementation of scv_report_handler
00273 //
00274 
00275 
00276 int scv_report_handler::_debug = -1;
00277 
00278 static void (*_scv_report_handler)(const scv_report&, const scv_actions&)
00279   = &scv_report_handler::default_handler;
00280 
00281 static scv_actions _scv_new_action_id = 0x0100;
00282 
00283 static char *_scv_log_file_name = 0;
00284 
00285 static ofstream *_scv_log_file_stream = 0;
00286 
00287 typedef void (*cb_ptr)(const scv_report *);
00288 static list<cb_ptr> *cb_list_p = NULL;
00289 
00290 
00291 void scv_report_handler::set_handler(
00292   void (*handler)(const scv_report&, const scv_actions&)
00293 )
00294 {
00295   if ( handler ) _scv_report_handler = handler;
00296   else _scv_report_handler = &scv_report_handler::default_handler;
00297 }
00298 
00299 scv_actions scv_report_handler::set_actions(
00300   scv_severity severity, scv_actions actions
00301 )
00302 {
00303   scv_report_core *cp = scv_report_core::get_core();
00304   if ( _SCV_DEBUG_CHECK(1) ) {
00305     scv_actions old = cp->actions.get(severity);
00306     scv_out << "scv_report_handler::set_actions severity " << severity_string(severity)
00307             << " actions " << old << " --> " << actions << endl;
00308   }
00309   return cp->actions.set(severity,actions);
00310 }
00311 
00312 scv_actions scv_report_handler::set_actions(
00313   scv_msg_type msg_type, scv_actions actions
00314 )
00315 {
00316   scv_report_core *cp = scv_report_core::get_core();
00317   if ( _SCV_DEBUG_CHECK(1) ) {
00318     scv_actions old = cp->actions.get(msg_type);
00319     scv_out << "scv_report_handler::set_actions msg_type " << msg_type
00320             << " actions " << old << " --> " << actions << endl;
00321   }
00322   return cp->actions.set(msg_type,actions);
00323 }
00324 
00325 scv_actions scv_report_handler::set_actions(
00326   scv_msg_type msg_type, scv_severity severity,
00327   scv_actions actions
00328 )
00329 {
00330   scv_report_core *cp = scv_report_core::get_core();
00331   if ( _SCV_DEBUG_CHECK(1) ) {
00332     scv_actions old = cp->actions.get(msg_type,severity);
00333     scv_out << "scv_report_handler::set_actions msg_type " << msg_type
00334             << " severity " << severity_string(severity)
00335             << " actions " << old << " --> " << actions << endl;
00336   }
00337   return cp->actions.set(msg_type,severity,actions);
00338 }
00339 
00340 int scv_report_handler::stop_after(
00341   scv_severity severity, int limit
00342 )
00343 {
00344   scv_report_core *cp = scv_report_core::get_core();
00345   if ( _SCV_DEBUG_CHECK(1) ) {
00346     int old = cp->limits.get(severity);
00347     scv_out << "scv_report_handler::stop_after severity " << severity_string(severity)
00348             << " limit " << old << " --> " << limit << endl;
00349   }
00350   return cp->limits.set(severity,limit);
00351 }
00352 
00353 int scv_report_handler::stop_after(
00354   scv_msg_type msg_type, int limit
00355 )
00356 {
00357   scv_report_core *cp = scv_report_core::get_core();
00358   if ( _SCV_DEBUG_CHECK(1) ) {
00359     int old = cp->limits.get(msg_type);
00360     scv_out << "scv_report_handler::stop_after msg_type " << msg_type
00361             << " limit " << old << " --> " << limit << endl;
00362   }
00363   return cp->limits.set(msg_type,limit);
00364 }
00365 
00366 int scv_report_handler::stop_after(
00367   scv_msg_type msg_type, scv_severity severity,
00368   int limit
00369 )
00370 {
00371   scv_report_core *cp = scv_report_core::get_core();
00372   if ( _SCV_DEBUG_CHECK(1) ) {
00373     int old = cp->actions.get(msg_type,severity);
00374     scv_out << "scv_report_handler::stop_after msg_type " << msg_type
00375             << " severity " << severity_string(severity)
00376             << " limit " << old << " --> " << limit << endl;
00377   }
00378   return cp->limits.set(msg_type,severity,limit);
00379 }
00380 
00381 void scv_report_handler::initialize()
00382 {
00383   scv_report_core *cp = scv_report_core::get_core();
00384   if ( _SCV_DEBUG_CHECK(1) ) {
00385     scv_out << "scv_report_handler::initialize" << endl;
00386   }
00387   cp->initialize();
00388 }
00389 
00390 scv_actions scv_report_handler::suppress(scv_actions actions)
00391 {
00392   scv_report_core *cp = scv_report_core::get_core();
00393   if ( _SCV_DEBUG_CHECK(1) ) {
00394     scv_actions old = cp->suppress.get();
00395     scv_out << "scv_report_handler::suppress actions " << old << " --> " << actions << endl;
00396   }
00397   return cp->suppress.set(actions);
00398 }
00399 
00400 scv_actions scv_report_handler::force(scv_actions actions)
00401 {
00402   scv_report_core *cp = scv_report_core::get_core();
00403   if ( _SCV_DEBUG_CHECK(1) ) {
00404     scv_actions old = cp->force.get();
00405     scv_out << "scv_report_handler::force actions " << old << " --> " << actions << endl;
00406   }
00407   return cp->force.set(actions);
00408 }
00409 
00410 void scv_report_handler::register_cb(cb_ptr f)
00411 {
00412   if ( ! cb_list_p ) cb_list_p = new list<cb_ptr>();
00413   cb_list_p->push_front(f);
00414 }
00415 
00416 
00417 scv_actions scv_report_handler::get_new_action_id()
00418 {
00419   // _scv_new_action_id initially set to new action
00420   // after predefined ones; once we're out of bits
00421   // it'll roll over to 0, and stay 0.
00422   scv_actions new_action_id = _scv_new_action_id;
00423   _scv_new_action_id <<= 1;
00424   return new_action_id;
00425 }
00426 
00427 const char *scv_report_handler::get_log_file_name()
00428 { return _scv_log_file_name; }
00429 
00430 void scv_report_handler::set_log_file_name(const char *name)
00431 { 
00432   assert(name);
00433   if ( _scv_log_file_stream ) return;
00434   if ( _scv_log_file_name ) delete [] _scv_log_file_name;
00435   _scv_log_file_name = new char[ strlen(name) +1 ];
00436   strcpy(_scv_log_file_name,name);
00437 }
00438 
00439 
00440 void scv_report_handler::default_handler(
00441   const scv_report& report, const scv_actions& actions
00442 )
00443 {
00444   scv_severity severity = report.get_severity();
00445   scv_msg_type msg_type = report.get_msg_type();
00446   const char *msg = report.get_msg();
00447   sc_time time = report.get_time();
00448   const char *process = report.get_process_name();
00449   const char *file_name = report.get_file_name();
00450   int line_number = report.get_line_number();
00451 
00452   scv_report_core *cp = scv_report_core::get_core();
00453 
00454   int sev_count = cp->counts.incr(severity);
00455   int msg_count = cp->counts.incr(msg_type);
00456   int com_count = cp->counts.incr(msg_type,severity);
00457 
00458   bool stop_flag = false;
00459   int limit = cp->limits.get(msg_type,severity);
00460   if ( limit == -1 ) {
00461     limit = cp->limits.get(msg_type);
00462     if ( limit == -1 ) {
00463       limit = cp->limits.get(severity);
00464       if ( limit == -1 ) {
00465   if ( severity == SCV_FATAL ) { limit = 1; stop_flag = true; }
00466       }
00467       else if ( limit == 0 ) ;
00468       else if ( sev_count >= limit ) stop_flag = true;
00469     }
00470     else if ( limit == 0 ) ;
00471     else if ( msg_count >= limit ) stop_flag = true;
00472   }
00473   else if ( limit == 0 ) ;
00474   else if ( com_count >= limit ) stop_flag = true;
00475 
00476   string label = severity_string(severity);
00477 
00478   if ( actions & SCV_LOG ) {
00479     if ( _scv_log_file_name && ! _scv_log_file_stream ) {
00480       _scv_log_file_stream = new ofstream(_scv_log_file_name);
00481       if ( ! *_scv_log_file_stream ) {
00482   char image[1024];
00483   sprintf(image,"Cannot open log file \"%s\"",_scv_log_file_name);
00484   delete [] _scv_log_file_name;
00485   _scv_log_file_name = 0;
00486   SCV_REPORT_ERROR("LOG_FILE_ERROR",image);
00487   delete _scv_log_file_stream;
00488   _scv_log_file_stream = 0;
00489       }
00490     }
00491     if ( _scv_log_file_stream ) {
00492       *_scv_log_file_stream << endl
00493         << "*** " << label << ": " << msg_type
00494         << " at time " << time << " in process " << process << endl 
00495         << "    " << msg << endl;
00496     }
00497   }
00498 
00499   if ( actions & SCV_DISPLAY ) {
00500     scv_out << endl
00501             << "*** " << label << ": " << msg_type
00502             << " at time " << time << " in process " << process << endl 
00503             << "    " << msg << endl;
00504   }
00505 
00506   if ( cb_list_p ) {
00507     scv_report report(severity,msg_type,msg,file_name,line_number,time,process);
00508     list<cb_ptr>::iterator i;
00509     for ( i = cb_list_p->begin(); i != cb_list_p->end(); i++ ) {
00510       (**i)(&report);
00511     }
00512   }
00513 
00514   if ( actions & SCV_ABORT ) {
00515     scv_out << endl
00516             << "*** " << severity_string(SCV_FATAL) << ": SCV_ABORT" << endl
00517             << "    Simulation is now ending." << endl;
00518     abort();
00519   }
00520 
00521   if ( stop_flag ) {
00522     scv_out << endl
00523             << "*** " << severity_string(SCV_FATAL) << ": " << "SCV_MESSAGE_LIMIT"
00524             << " at time " << time << " in process " << process << endl 
00525             << "    You have reached the " << label << " message limit of "
00526             << limit << "." << endl
00527             << "    Simulation is now ending." << endl;
00528     sc_stop();
00529   }
00530 
00531   if ( actions & SCV_STOP ) {
00532     scv_out << endl
00533             << "*** " << severity_string(SCV_FATAL) << ": SCV_STOP" << endl
00534             << "    Simulation is now ending." << endl;
00535     sc_stop();
00536   }
00537 
00538   if ( actions & SCV_CACHE_REPORT ) {
00539     _update_report_cache( new scv_report(report), true );
00540   }
00541 
00542   if ( actions & SCV_THROW ) throw scv_report(report);
00543 
00544   if ( actions & SCV_INTERRUPT ) scv_interrupt_here(msg_type);
00545 }
00546 
00547 void scv_report_handler::report(
00548   scv_severity severity, scv_msg_type msg_type,
00549   const char *msg,
00550   const char *file_name, int line_number
00551 )
00552 {
00553   scv_stop_here();
00554 
00555   scv_report_core *cp = scv_report_core::get_core();
00556 
00557   scv_actions actions = cp->actions.get(msg_type,severity);
00558   if ( actions == SCV_UNSPECIFIED ) actions = cp->actions.get(msg_type);
00559   if ( actions == SCV_UNSPECIFIED ) actions = cp->actions.get(severity);
00560 
00561   scv_actions hold;
00562   hold = cp->suppress.get();
00563   actions &= ~hold;
00564   hold = cp->force.get();
00565   actions |= hold;
00566 
00567   sc_time time = sc_time_stamp();
00568   const char *process = scv_get_process_name( sc_get_curr_process_handle() );
00569 
00570   scv_report report(
00571     severity, msg_type, msg,
00572     file_name, line_number, time, process
00573   );
00574 
00575   _scv_report_handler(report,actions);
00576 }
00577 
00578 const scv_report *scv_report_handler::get_cached_report()
00579 { return _update_report_cache(0,false); }
00580 
00581 void scv_report_handler::clear_cached_report()
00582 { _update_report_cache(0,true); }
00583 
00584 
00585 #endif // ! _SCV_USE_SC_REPORT
00586 
00587 
00588 //
00589 // Implementation of _scv_message
00590 //
00591 
00592 
00593 #define _SCV_DEFERR(code, number, string, severity, stack_action) \
00594   _scv_message_desc *_scv_message::code##_base = 0; \
00595   _scv_message_desc **_scv_message::code = &_scv_message::code##_base;
00596 #include "scv/scv_messages.h"
00597 #undef _SCV_DEFERR
00598 
00599 
00600 void _scv_message::message(_scv_message_desc **desc_pp, ...)
00601 {
00602   // make sure desc is defined
00603   scv_report_core::get_core();
00604 
00605   _scv_message_desc *desc_p = *desc_pp;
00606 
00607   const char *tag = desc_p->get_tag();
00608   const char *format = desc_p->get_format();
00609   scv_severity severity = desc_p->get_severity();
00610   scv_actions actions = desc_p->get_actions();
00611 
00612   scv_actions hold = scv_report_handler::force(0);
00613   scv_report_handler::force(hold|actions);
00614 
00615   static char formattedMessageString[20000];
00616   va_list ap;
00617   va_start(ap,desc_pp);
00618   vsprintf(formattedMessageString,format,ap);
00619   va_end(ap);
00620 
00621   scv_report_handler::report(severity,tag,formattedMessageString,"unknown",0);
00622 
00623   scv_report_handler::force(hold);
00624 }
00625 
00626 void _scv_message::setup()
00627 {
00628   static bool first_time = true;
00629   if ( first_time ) first_time = false;
00630   else return;
00631 #define _SCV_DEFERR(code, number, string, severity, stack_action) \
00632   code##_base = new _scv_message_desc(#code,string,xlat_severity(severity),SCV_DO_NOTHING);
00633 #include "scv/scv_messages.h"
00634 #undef _SCV_DEFERR
00635   scv_report_handler::set_actions(SCV_ERROR,SCV_LOG|SCV_DISPLAY|SCV_CACHE_REPORT);
00636   scv_report_handler::set_actions(SCV_FATAL,SCV_LOG|SCV_DISPLAY|SCV_CACHE_REPORT);
00637 }
00638 
00639 scv_severity _scv_message::xlat_severity(severity_level severity)
00640 {
00641   switch ( severity ) {
00642     case INFO    : return SCV_INFO;
00643     case WARNING : return SCV_WARNING;
00644     case ERROR   : return SCV_ERROR;
00645     default  : return SCV_FATAL;
00646   }
00647 }

Generated on Fri Jan 14 08:29:11 2005 for SystemC2.1beta11(excludingMSLib)(IncludingSCV)\nProvidedby:www.openverificationfoundation.org by doxygen1.2.18