00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include "scv.h"
00041
00042 #include <stdarg.h>
00043 #include <string>
00044 #include <map>
00045
00046
00047
00048
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) {
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
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
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
00420
00421
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
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
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 }