/* * 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); } */