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