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
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
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
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 )
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
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());
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
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
00213
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
00228 sc_actions sc_report_handler::execute(sc_msg_def* md, sc_severity severity_)
00229 {
00230 sc_actions actions = md->sev_actions[severity_];
00231
00232 if ( SC_UNSPECIFIED == actions )
00233 actions = md->actions;
00234
00235 if ( SC_UNSPECIFIED == actions )
00236 actions = sev_actions[severity_];
00237
00238 actions &= ~suppress_mask;
00239 actions |= force_mask;
00240
00241 unsigned * limit = 0;
00242 unsigned * call_count = 0;
00243
00244
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
00270 }
00271 else if ( *limit != UINT_MAX )
00272 {
00273 if ( *call_count >= *limit )
00274 actions |= 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
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
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
00342
00343
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;
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) )
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
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
00624
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 SC_DEFAULT_INFO_ACTIONS,
00633 SC_DEFAULT_WARNING_ACTIONS,
00634 SC_DEFAULT_ERROR_ACTIONS,
00635 SC_DEFAULT_FATAL_ACTIONS
00636 };
00637
00638
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
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}, \
00682 0u, {0u}, 0u, \
00683 0u, {0u}, NULL, \
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 }
00706
00707