blob: 1115152f44917cfb7f168a5b59a3c8624d9309d2 [file] [log] [blame]
/*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* $Id$
*
*/
#include <fstream>
#include <stdarg.h>
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/Debug.hh"
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
#include "mem/gems_common/util.hh"
class Debug;
extern Debug* g_debug_ptr;
std::ostream * debug_cout_ptr;
bool Debug::m_protocol_trace = false;
struct DebugComponentData
{
const char *desc;
const char ch;
};
// component character list
DebugComponentData debugComponents[] =
{
{"System", 's' },
{"Node", 'N' },
{"Queue", 'q' },
{"Event Queue", 'e' },
{"Network", 'n' },
{"Sequencer", 'S' },
{"Tester", 't' },
{"Generated", 'g' },
{"SLICC", 'l' },
{"Network Queues", 'Q' },
{"Time", 'T' },
{"Network Internals", 'i' },
{"Store Buffer", 'b' },
{"Cache", 'c' },
{"Predictor", 'p' },
{"Allocator", 'a' },
};
extern "C" void changeDebugVerbosity(VerbosityLevel vb);
extern "C" void changeDebugFilter(int filter);
void changeDebugVerbosity(VerbosityLevel vb)
{
g_debug_ptr->setVerbosity(vb);
}
void changeDebugFilter(int filter)
{
g_debug_ptr->setFilter(filter);
}
Debug::Debug()
{
m_verbosityLevel = No_Verb;
m_starting_cycle = ~0;
clearFilter();
debug_cout_ptr = &cout;
}
Debug::Debug( const string & name, const vector<string> & argv )
{
for (size_t i=0;i<argv.size();i+=2){
if (argv[i] == "filter_string")
setFilterString( argv[i+1].c_str() );
else if (argv[i] == "verbosity_string")
setVerbosityString( argv[i+1].c_str() );
else if (argv[i] == "start_time")
m_starting_cycle = atoi( argv[i+1].c_str() );
else if (argv[i] == "output_filename")
setDebugOutputFile( argv[i+1].c_str() );
else if (argv[i] == "protocol_trace")
m_protocol_trace = string_to_bool(argv[i+1]);
else
assert(0);
}
}
Debug::Debug( const char *filterString, const char *verboseString,
Time filterStartTime, const char *filename )
{
m_verbosityLevel = No_Verb;
clearFilter();
debug_cout_ptr = &cout;
m_starting_cycle = filterStartTime;
setFilterString( filterString );
setVerbosityString( verboseString );
setDebugOutputFile( filename );
}
Debug::~Debug()
{
}
void Debug::printVerbosity(ostream& out) const
{
switch (getVerbosity()) {
case No_Verb:
out << "verbosity = No_Verb" << endl;
break;
case Low_Verb:
out << "verbosity = Low_Verb" << endl;
break;
case Med_Verb:
out << "verbosity = Med_Verb" << endl;
break;
case High_Verb:
out << "verbosity = High_Verb" << endl;
break;
default:
out << "verbosity = unknown" << endl;
}
}
bool Debug::validDebug(int module, PriorityLevel priority)
{
int local_module = (1 << module);
if(m_filter & local_module) {
if (g_eventQueue_ptr == NULL ||
g_eventQueue_ptr->getTime() >= m_starting_cycle) {
switch(m_verbosityLevel) {
case No_Verb:
return false;
break;
case Low_Verb:
if(priority == HighPrio) {
return true;
}else{
return false;
}
break;
case Med_Verb:
if(priority == HighPrio || priority == MedPrio ) {
return true;
}else{
return false;
}
break;
case High_Verb:
return true;
break;
}
}
}
return false;
}
void Debug::setDebugTime(Time t)
{
m_starting_cycle = t;
}
void Debug::setVerbosity(VerbosityLevel vb)
{
m_verbosityLevel = vb;
}
void Debug::setFilter(int filter)
{
m_filter = filter;
}
bool Debug::checkVerbosityString(const char *verb_str)
{
if (verb_str == NULL) {
cerr << "Error: unrecognized verbosity (use none, low, med, high): NULL" << endl;
return true; // error
} else if ( (string(verb_str) == "none") ||
(string(verb_str) == "low") ||
(string(verb_str) == "med") ||
(string(verb_str) == "high") ) {
return false;
}
cerr << "Error: unrecognized verbosity (use none, low, med, high): NULL" << endl;
return true; // error
}
bool Debug::setVerbosityString(const char *verb_str)
{
bool check_fails = checkVerbosityString(verb_str);
if (check_fails) {
return true; // error
}
if (string(verb_str) == "none") {
setVerbosity(No_Verb);
} else if (string(verb_str) == "low") {
setVerbosity(Low_Verb);
} else if (string(verb_str) == "med") {
setVerbosity(Med_Verb);
} else if (string(verb_str) == "high") {
setVerbosity(High_Verb);
} else {
cerr << "Error: unrecognized verbosity (use none, low, med, high): " << verb_str << endl;
return true; // error
}
return false; // no error
}
bool Debug::checkFilter(char ch)
{
for (int i=0; i<NUMBER_OF_COMPS; i++) {
// Look at all components to find a character match
if (debugComponents[i].ch == ch) {
// We found a match - return no error
return false; // no error
}
}
return true; // error
}
bool Debug::checkFilterString(const char *filter_str)
{
if (filter_str == NULL) {
cerr << "Error: unrecognized component filter: NULL" << endl;
return true; // error
}
// check for default filter ("none") before reporting RUBY_DEBUG error
if ( (string(filter_str) == "none") ) {
return false; // no error
}
if (RUBY_DEBUG == false) {
cerr << "Error: User specified set of debug components, but the RUBY_DEBUG compile-time flag is false." << endl;
cerr << "Solution: Re-compile with RUBY_DEBUG set to true." << endl;
return true; // error
}
if ( (string(filter_str) == "all") ) {
return false; // no error
}
// scan string checking each character
for (unsigned int i = 0; i < strlen(filter_str); i++) {
bool unrecognized = checkFilter( filter_str[i] );
if (unrecognized == true) {
return true; // error
}
}
return false; // no error
}
bool Debug::setFilterString(const char *filter_str)
{
if (checkFilterString(filter_str)) {
return true; // error
}
if (string(filter_str) == "all" ) {
allFilter();
} else if (string(filter_str) == "none") {
clearFilter();
} else {
// scan string adding to bit mask for each component which is present
for (unsigned int i = 0; i < strlen(filter_str); i++) {
bool error = addFilter( filter_str[i] );
if (error) {
return true; // error
}
}
}
return false; // no error
}
bool Debug::addFilter(char ch)
{
for (int i=0; i<NUMBER_OF_COMPS; i++) {
// Look at all components to find a character match
if (debugComponents[i].ch == ch) {
// We found a match - update the filter bit mask
cout << " Debug: Adding to filter: '" << ch << "' (" << debugComponents[i].desc << ")" << endl;
m_filter |= (1 << i);
return false; // no error
}
}
// We didn't find the character
cerr << "Error: unrecognized component filter: " << ch << endl;
usageInstructions();
return true; // error
}
void Debug::clearFilter()
{
m_filter = 0;
}
void Debug::allFilter()
{
m_filter = ~0;
}
void Debug::usageInstructions(void)
{
cerr << "Debug components: " << endl;
for (int i=0; i<NUMBER_OF_COMPS; i++) {
cerr << " " << debugComponents[i].ch << ": " << debugComponents[i].desc << endl;
}
}
void Debug::print(ostream& out) const
{
out << "[Debug]" << endl;
}
void Debug::setDebugOutputFile (const char * filename)
{
if ( (filename == NULL) ||
(!strcmp(filename, "none")) ) {
debug_cout_ptr = &cout;
return;
}
if (m_fout.is_open() ) {
m_fout.close ();
}
m_fout.open (filename, std::ios::out);
if (! m_fout.is_open() ) {
cerr << "setDebugOutputFile: can't open file " << filename << endl;
}
else {
debug_cout_ptr = &m_fout;
}
}
void Debug::closeDebugOutputFile ()
{
if (m_fout.is_open() ) {
m_fout.close ();
debug_cout_ptr = &cout;
}
}
void Debug::debugMsg( const char *fmt, ... )
{
va_list args;
// you could check validDebug() here before printing the message
va_start(args, fmt);
vfprintf(stdout, fmt, args);
va_end(args);
}
/*
void DEBUG_OUT( const char* fmt, ...) {
if (RUBY_DEBUG) {
cout << "Debug: in fn "
<< __PRETTY_FUNCTION__
<< " in " << __FILE__ << ":"
<< __LINE__ << ": ";
va_list args;
va_start(args, fmt);
vfprintf(stdout, fmt, args);
va_end(args);
}
}
void ERROR_OUT( const char* fmt, ... ) {
if (ERROR_MESSAGE_FLAG) {
cout << "error: in fn "
<< __PRETTY_FUNCTION__ << " in "
<< __FILE__ << ":"
<< __LINE__ << ": ";
va_list args;
va_start(args, fmt);
vfprintf(stdout, fmt, args);
va_end(args);
}
assert(0);
}
*/