// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: cReport.cc
// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// For the avoidance of doubt, and except that if any non-GPL license
// choice is available it will apply instead, Sun elects to use only
// the General Public License version 2 (GPLv2) at this time for any
// software where a choice of GPL license versions is made
// available with the language indicating that GPLv2 or any later version
// may be used, or where a choice of which version of the GPL is applied is
// otherwise unspecified.
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// ========== Copyright Header End ============================================
#include "report_msg_format.h"
extern "C" int g_cycle_count
, g_death_cycle_count
, g_exit_on_error
;
////////////////////////////////////////////////////////////////////////////////
// Class variable definitions
PrintLevel
ReportClass::global_print_threshold
= REPORT_DEFAULT_PRINT_THRESHOLD
;
int ReportClass::max_error_count
= REPORT_DEFAULT_MAX_ERROR_COUNT
;
int ReportClass::global_error_count
= 0;
int ReportClass::global_warning_count
= 0;
int ReportClass::use_short_pathnames
= 0;
const char* ReportClass::path_prefix
= "";
int ReportClass::num_remaining_nonfatal_cycles
= 0;
int ReportClass::show_simulation_time
= 0;
int ReportClass::global_print_threshold_locked_by
= REPORT_LOCKED_BY_NO_ONE
;
int ReportClass::report_type_display_locked_by
[R_NUM_REPORT_TYPES
];
////////////////////////////////////////////////////////////////////////////////
// Message display functions
// Display a message of the given type. The message will use
// the current print level and error level for this report type.
// Accepts a printf-like format string and arg list.
void ReportClass::report(ReportType report_type
,
const char* time_str
, const char* location_str
, const char* format_str
, ...)
void* varargs
[REPORT_MAX_NUM_VARARGS
];
PrintLevel my_print_level
= get_print_level(report_type
);
ErrorLevel my_error_level
= get_error_level(report_type
);
// Actually do the output, if the print level is appropriate.
if (my_print_level
>= global_print_threshold
) {
// review: 1. Support output redirection here!!!
// - if fatal errors are disabled, make errors into warnings.
if (num_remaining_nonfatal_cycles
> 0 && my_error_level
== RERR_ERROR
)
prefix_str
= get_prefix(report_type
, RERR_MESSAGE
);
prefix_str
= get_prefix(report_type
, my_error_level
);
if (!get_table_mode(report_type
)) {
fprintf(stdout
, REPORT_MSG_FORMAT_STRING
, prefix_str
, time_str
, location_str
);
// If fatal error, output the error type.
if (my_error_level
== RERR_ERROR
) {
fprintf(stdout
, "%s: ", report_type_to_str(report_type
));
// Print message string, extracting any arguments from the varargs list.
// Use the format string to find out how many arguments we should expect.
const char *fp
= format_str
;
for (i
= 0; i
< REPORT_MAX_NUM_VARARGS
; i
++)
va_start(ap
, format_str
);
while (fp
= strchr(fp
, '%'))
// Found another '%' in the formatting string.
// If it's actually associated with a vararg, grab the next one.
varargs
[j
++] = va_arg(ap
, void*);
// This is it. This is where the message is finally printed.
fprintf(stdout
, format_str
,
varargs
[0], varargs
[1], varargs
[2], varargs
[3], varargs
[4],
varargs
[5], varargs
[6], varargs
[7], varargs
[8], varargs
[9]);
// Print newline (if not in table mode)
if (!get_table_mode(report_type
)) {
// If this report produced a fatal error or a warning, deal with the situation.
if (my_error_level
== RERR_ERROR
) {
if (get_num_remaining_nonfatal_cycles() == 0) {
// Increase the ReportClass's global error count,
// but only if fatal errors are not currently disabled!
inc_global_error_count();
// If this error pushed us over the maximum number of allowable errors,
// schedule a cycle soon in which the sim will be killed.
if(get_global_error_count() >= get_max_error_count()
g_death_cycle_count
= g_cycle_count
+ REPORT_DEATH_CYCLE_DELAY
;
fprintf(stdout
, "Report:(%0d) [PLI] Scheduling $finish for cycle %0d\n", g_cycle_count
, g_death_cycle_count
);
} else if (my_error_level
== RERR_WARNING
) {
// Increase the ReportClass's global warning count.
inc_global_warning_count();
} // ReportClass::report(...)
// ReportClass:report_test_complete
void ReportClass::report_test_complete(int finish_cycle
)
fprintf(stdout
, REPORT_TEST_DONE_FORMAT_STRING
, finish_cycle
, get_global_error_count(), get_global_warning_count());
// ReportClass::will_this_print
// Return true if the report_type will print, false otherwise
int ReportClass::this_will_print(ReportType report_type
)
//fprintf(stdout,"ReportClass::this_will_print: report_type: %d(%d), global_print_threshold: %d\n",
//report_type, get_print_level(report_type), global_print_threshold);
return( get_print_level(report_type
) >= global_print_threshold
);
////////////////////////////////////////////////////////////////////////////////
// Accessors for class variables
// ReportClass::set_global_print_threshold
// This accessor may be called with a "lock" variable to prevent further changes.
// This can be used to lock in changes from the command line, for example.
// NOTE! The lock variable can only be set once; further changes are ignored.
void ReportClass::set_global_print_threshold(PrintLevel new_print_threshold
, int locked_by
)
if (ReportClass::global_print_threshold_locked_by
== REPORT_LOCKED_BY_NO_ONE
)
// No lock currently set for the print threshold.
if (locked_by
!= REPORT_LOCKED_BY_NO_ONE
)
temp_report
.report(RTYP_REPORT_MSG
, REPORT_CPP_DEFAULT_TIME_STR
, REPORT_CPP_DEFAULT_LOCATION_STR
,
"Locked global print threshold to %s -- further changes will be ignored",
print_level_to_str(new_print_threshold
));
ReportClass::global_print_threshold_locked_by
= locked_by
;
// No new lock specified -- just change the thing.
temp_report
.report(RTYP_REPORT_MSG
, REPORT_CPP_DEFAULT_TIME_STR
, REPORT_CPP_DEFAULT_LOCATION_STR
,
"Changing global print threshold from %s to %s",
print_level_to_str(ReportClass::global_print_threshold
),
print_level_to_str(new_print_threshold
));
ReportClass::global_print_threshold
= new_print_threshold
;
// Print threshold has already been locked.
// Only allow changes if 'locked_by' matches the lock.
if (locked_by
== ReportClass::global_print_threshold_locked_by
)
temp_report
.report(RTYP_REPORT_MSG
, REPORT_CPP_DEFAULT_TIME_STR
, REPORT_CPP_DEFAULT_LOCATION_STR
,
"Changing global print threshold from %s to %s",
print_level_to_str(ReportClass::global_print_threshold
),
print_level_to_str(new_print_threshold
));
ReportClass::global_print_threshold
= new_print_threshold
;
temp_report
.report(RTYP_REPORT_MSG
, REPORT_CPP_DEFAULT_TIME_STR
, REPORT_CPP_DEFAULT_LOCATION_STR
,
"Can't change global print threshold to %s -- it's locked!",
print_level_to_str(new_print_threshold
));
// ReportClass::get_global_print_threshold
PrintLevel
ReportClass::get_global_print_threshold()
return global_print_threshold
;
// ReportClass::set_max_error_count
void ReportClass::set_max_error_count(int error_count
)
temp_report
.report(RTYP_REPORT_MSG
, REPORT_CPP_DEFAULT_TIME_STR
, REPORT_CPP_DEFAULT_LOCATION_STR
,
"Changing maximum error count from %d to %d", max_error_count
, error_count
);
max_error_count
= error_count
;
// ReportClass::get_max_error_count
int ReportClass::get_max_error_count()
// ReportClass::get_global_error_count
int ReportClass::get_global_error_count()
return global_error_count
;
// ReportClass::inc_global_error_count
// Increase the global error count and generate a "fatal error" report
// which should cause a test to be marked as failing.
// NOTE: The simulation itself should be killed by the calling code!
void ReportClass::inc_global_error_count()
if (++global_error_count
== max_error_count
)
temp_report
.report(RTYP_REPORT_MSG
, REPORT_CPP_DEFAULT_TIME_STR
, REPORT_CPP_DEFAULT_LOCATION_STR
,
"Maximum error count of %d has been reached!", max_error_count
);
// ReportClass::get_global_warning_count
int ReportClass::get_global_warning_count()
return global_warning_count
;
// ReportClass::inc_global_warning_count
void ReportClass::inc_global_warning_count()
// ReportClass::set_short_pathnames
void ReportClass::set_short_pathnames(int use_short
)
temp_report
.report(RTYP_REPORT_MSG
, REPORT_CPP_DEFAULT_TIME_STR
, REPORT_CPP_DEFAULT_LOCATION_STR
, "Using short pathnames.");
temp_report
.report(RTYP_REPORT_MSG
, REPORT_CPP_DEFAULT_TIME_STR
, REPORT_CPP_DEFAULT_LOCATION_STR
, "Using long pathnames.");
use_short_pathnames
= use_short
;
// ReportClass::get_short_pathnames
int ReportClass::get_short_pathnames()
return use_short_pathnames
;
void ReportClass::set_path_prefix(const char* prefix
)
temp_report
.report(RTYP_REPORT_MSG
, REPORT_CPP_DEFAULT_TIME_STR
, REPORT_CPP_DEFAULT_LOCATION_STR
,
"Setting path prefix to %s", prefix
);
const char* ReportClass::get_path_prefix()
// ReportClass::disable_fatal_errors
void ReportClass::disable_fatal_errors(int num_cycles
)
temp_report
.report(RTYP_REPORT_MSG
, REPORT_CPP_DEFAULT_TIME_STR
, REPORT_CPP_DEFAULT_LOCATION_STR
,
"Disabling fatal errors for %0d cycles.", num_cycles
);
num_remaining_nonfatal_cycles
= num_cycles
;
// ReportClass::get_num_remaining_nonfatal_cycles
int ReportClass::get_num_remaining_nonfatal_cycles()
return num_remaining_nonfatal_cycles
;
// ReportClass::dec_num_remaining_nonfatal_cycles
void ReportClass::dec_num_remaining_nonfatal_cycles()
if (get_num_remaining_nonfatal_cycles() == 0)
temp_report
.report(RTYP_WARNING
, REPORT_CPP_DEFAULT_TIME_STR
, REPORT_CPP_DEFAULT_LOCATION_STR
,
"Attempting to decrement a num_remaining_nonfatal_cycles of zero!");
num_remaining_nonfatal_cycles
--;
// ReportClass::set_show_simulation_time
void ReportClass::set_show_simulation_time(int sim_time
)
temp_report
.report(RTYP_REPORT_MSG
, REPORT_CPP_DEFAULT_TIME_STR
, REPORT_CPP_DEFAULT_LOCATION_STR
,
"Not displaying simulation time.");
temp_report
.report(RTYP_REPORT_MSG
, REPORT_CPP_DEFAULT_TIME_STR
, REPORT_CPP_DEFAULT_LOCATION_STR
,
"Displaying simulation time.");
show_simulation_time
= sim_time
;
// ReportClass::get_show_simulation_time
int ReportClass::get_show_simulation_time()
return show_simulation_time
;
////////////////////////////////////////////////////////////////////////////////
// Accessors for instance variables
// ReportClass::set_default_print_level
// Changes the print level of all messages which have not thus far been
// overridden by set_print_level.
void ReportClass::set_default_print_level(ReportType report_type
, PrintLevel new_print_level
) {
report(RTYP_REPORT_MSG
, REPORT_CPP_DEFAULT_TIME_STR
,
REPORT_CPP_DEFAULT_LOCATION_STR
, "Setting *default* print level for type %s to %s",
report_type_to_str(report_type
),
print_level_to_str(new_print_level
));
// If the type is "ALL_REPORTS", set everything. Otherwise, just set the desired type.
if (report_type
== RTYP_ALL_REPORTS
) {
for (int type
= __RTYP_FIRST_TYPE
; type
<= __RTYP_LAST_TYPE
; type
++) {
default_print_level_by_type
[type
] = new_print_level
;
default_print_level_by_type
[report_type
] = new_print_level
;
// ReportClass::set_default_error_level
// Changes the error level of all messages which have not thus far been
// overridden by set_error_level.
void ReportClass::set_default_error_level(ReportType report_type
, ErrorLevel new_error_level
) {
report(RTYP_REPORT_MSG
, REPORT_CPP_DEFAULT_TIME_STR
,
REPORT_CPP_DEFAULT_LOCATION_STR
, "Setting *default* error level for type %s to %s",
report_type_to_str(report_type
),
error_level_to_str(new_error_level
));
// If the type is "ALL_REPORTS", set everything. Otherwise, just set the desired type.
if (report_type
== RTYP_ALL_REPORTS
) {
for (int type
= __RTYP_FIRST_TYPE
; type
<= __RTYP_LAST_TYPE
; type
++) {
default_error_level_by_type
[type
] = new_error_level
;
default_error_level_by_type
[report_type
] = new_error_level
;
// ReportClass::set_default_table_mode
// Changes the table_mode of all messages which have not thus far been
// overridden by set_table_mode.
void ReportClass::set_default_table_mode(ReportType report_type
, int mode
) {
report(RTYP_REPORT_MSG
, REPORT_CPP_DEFAULT_TIME_STR
,
REPORT_CPP_DEFAULT_LOCATION_STR
, "Setting *default* print level for type %s to %s",
report_type_to_str(report_type
),
// If the type is "ALL_REPORTS", set everything. Otherwise, just set the desired type.
if (report_type
== RTYP_ALL_REPORTS
) {
for (int type
= __RTYP_FIRST_TYPE
; type
<= __RTYP_LAST_TYPE
; type
++) {
default_table_mode_by_type
[type
] = mode
;
default_table_mode_by_type
[report_type
] = mode
;
//////////////////////////////////////////////////////////////////
// ReportClass::set_print_level
// Changes the print level of this message type only, on this
// ReportClass instance only.
void ReportClass::set_print_level(ReportType report_type
, PrintLevel new_print_level
, int silent
) {
report(RTYP_REPORT_MSG
, REPORT_CPP_DEFAULT_TIME_STR
,
REPORT_CPP_DEFAULT_LOCATION_STR
, "Setting print level for type %s to %s",
report_type_to_str(report_type
),
print_level_to_str(new_print_level
));
if (localized_print_level_by_type
== NULL
) {
// copy the default array.
localized_print_level_by_type
= new PrintLevel
[R_NUM_REPORT_TYPES
];
for (int type
= __RTYP_FIRST_TYPE
; type
<= __RTYP_LAST_TYPE
; type
++) {
localized_print_level_by_type
[type
] = default_print_level_by_type
[type
];
// If the type is "ALL_REPORTS", set everything. Otherwise, just set the desired type.
if (report_type
== RTYP_ALL_REPORTS
) {
for (int type
= __RTYP_FIRST_TYPE
; type
<= __RTYP_LAST_TYPE
; type
++) {
localized_print_level_by_type
[type
] = new_print_level
;
localized_print_level_by_type
[report_type
] = new_print_level
;
// ReportClass::get_print_level
PrintLevel
ReportClass::get_print_level(ReportType report_type
) {
return localized_print_level_by_type
== NULL
? default_print_level_by_type
[report_type
] : localized_print_level_by_type
[report_type
];
// ReportClass::set_error_level
// Changes the error level of this message type only, on this
// ReportClass instance only.
void ReportClass::set_error_level(ReportType report_type
, ErrorLevel new_error_level
, int silent
) {
report(RTYP_REPORT_MSG
, REPORT_CPP_DEFAULT_TIME_STR
,
REPORT_CPP_DEFAULT_LOCATION_STR
, "Setting error level for type %s to %s",
report_type_to_str(report_type
),
error_level_to_str(new_error_level
));
if (localized_error_level_by_type
== NULL
) {
// copy the default array.
localized_error_level_by_type
= new ErrorLevel
[R_NUM_REPORT_TYPES
];
for (int type
= __RTYP_FIRST_TYPE
; type
<= __RTYP_LAST_TYPE
; type
++) {
localized_error_level_by_type
[type
] = default_error_level_by_type
[type
];
// If the type is "ALL_REPORTS", set everything. Otherwise, just set the desired type.
if (report_type
== RTYP_ALL_REPORTS
) {
for (int type
= __RTYP_FIRST_TYPE
; type
<= __RTYP_LAST_TYPE
; type
++) {
localized_error_level_by_type
[type
] = new_error_level
;
localized_error_level_by_type
[report_type
] = new_error_level
;
// ReportClass::get_error_level
ErrorLevel
ReportClass::get_error_level(ReportType report_type
) {
return localized_error_level_by_type
== NULL
? default_error_level_by_type
[report_type
] : localized_error_level_by_type
[report_type
];
// ReportClass::set_table_mode
void ReportClass::set_table_mode(ReportType report_type
, int mode
, int silent
) {
report(RTYP_REPORT_MSG
, REPORT_CPP_DEFAULT_TIME_STR
,
REPORT_CPP_DEFAULT_LOCATION_STR
, "Set table mode for type %s to %s.",
report_type_to_str(report_type
),
if (localized_table_mode_by_type
== NULL
) {
// copy the default array.
localized_table_mode_by_type
= new int[R_NUM_REPORT_TYPES
];
for (int type
= __RTYP_FIRST_TYPE
; type
<= __RTYP_LAST_TYPE
; type
++) {
localized_table_mode_by_type
[type
] = default_table_mode_by_type
[type
];
// If the type is "ALL_REPORTS", set everything. Otherwise, just set the desired type.
if (report_type
== RTYP_ALL_REPORTS
) {
for (int type
= __RTYP_FIRST_TYPE
; type
<= __RTYP_LAST_TYPE
; type
++) {
localized_table_mode_by_type
[type
] = mode
;
localized_table_mode_by_type
[report_type
] = mode
;
// ReportClass::get_table_mode
int ReportClass::get_table_mode(ReportType report_type
) {
return localized_table_mode_by_type
== NULL
? default_table_mode_by_type
[report_type
] : localized_table_mode_by_type
[report_type
];
////////////////////////////////////////////////////////////////////////////////