2009-05-11 19:38:43 +02:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
#include "base/misc.hh"
|
2009-05-11 19:38:45 +02:00
|
|
|
#include "mem/ruby/common/Debug.hh"
|
2010-03-23 02:43:53 +01:00
|
|
|
#include "mem/ruby/common/Global.hh"
|
2009-05-11 19:38:45 +02:00
|
|
|
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
|
2009-05-11 19:38:43 +02:00
|
|
|
|
2010-03-11 03:33:11 +01:00
|
|
|
using namespace std;
|
|
|
|
|
2009-05-11 19:38:43 +02:00
|
|
|
class Debug;
|
|
|
|
extern Debug* g_debug_ptr;
|
2010-03-11 03:33:11 +01:00
|
|
|
ostream *debug_cout_ptr;
|
2009-05-11 19:38:43 +02:00
|
|
|
|
2009-07-07 00:49:47 +02:00
|
|
|
bool Debug::m_protocol_trace = false;
|
2009-07-07 00:49:47 +02:00
|
|
|
struct DebugComponentData
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2009-07-07 00:49:47 +02:00
|
|
|
const char *desc;
|
|
|
|
const char ch;
|
2009-05-11 19:38:43 +02:00
|
|
|
};
|
|
|
|
|
2009-07-07 00:49:47 +02:00
|
|
|
// component character list
|
|
|
|
DebugComponentData debugComponents[] =
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2009-07-07 00:49:47 +02:00
|
|
|
{"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' },
|
2009-11-18 22:55:57 +01:00
|
|
|
{"Memory", 'M' },
|
2009-05-11 19:38:43 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
extern "C" void changeDebugVerbosity(VerbosityLevel vb);
|
|
|
|
extern "C" void changeDebugFilter(int filter);
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
void
|
|
|
|
changeDebugVerbosity(VerbosityLevel vb)
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-03-23 02:43:53 +01:00
|
|
|
g_debug_ptr->setVerbosity(vb);
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
void
|
|
|
|
changeDebugFilter(int filter)
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-03-23 02:43:53 +01:00
|
|
|
g_debug_ptr->setFilter(filter);
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-01-30 05:29:17 +01:00
|
|
|
Debug::Debug(const Params *p)
|
|
|
|
: SimObject(p)
|
2009-07-07 00:49:47 +02:00
|
|
|
{
|
2010-03-23 02:43:53 +01:00
|
|
|
clearFilter();
|
|
|
|
debug_cout_ptr = &cout;
|
2009-05-11 19:38:43 +02:00
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
setFilterString(p->filter_string.c_str());
|
|
|
|
setVerbosityString(p->verbosity_string.c_str());
|
|
|
|
setDebugOutputFile(p->output_filename.c_str());
|
|
|
|
m_starting_cycle = p->start_time;
|
|
|
|
m_protocol_trace = p->protocol_trace;
|
|
|
|
g_debug_ptr = this;
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
Debug::~Debug()
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
void
|
|
|
|
Debug::printVerbosity(ostream& out) const
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-03-23 02:43:53 +01:00
|
|
|
switch (getVerbosity()) {
|
2009-05-11 19:38:43 +02:00
|
|
|
case No_Verb:
|
2010-03-23 02:43:53 +01:00
|
|
|
out << "verbosity = No_Verb" << endl;
|
2009-05-11 19:38:43 +02:00
|
|
|
break;
|
|
|
|
case Low_Verb:
|
2010-03-23 02:43:53 +01:00
|
|
|
out << "verbosity = Low_Verb" << endl;
|
2009-05-11 19:38:43 +02:00
|
|
|
break;
|
|
|
|
case Med_Verb:
|
2010-03-23 02:43:53 +01:00
|
|
|
out << "verbosity = Med_Verb" << endl;
|
2009-05-11 19:38:43 +02:00
|
|
|
break;
|
|
|
|
case High_Verb:
|
2010-03-23 02:43:53 +01:00
|
|
|
out << "verbosity = High_Verb" << endl;
|
2009-05-11 19:38:43 +02:00
|
|
|
break;
|
2010-03-23 02:43:53 +01:00
|
|
|
default:
|
|
|
|
out << "verbosity = unknown" << endl;
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
bool
|
|
|
|
Debug::validDebug(int module, PriorityLevel priority)
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-03-23 02:43:53 +01:00
|
|
|
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;
|
|
|
|
case Low_Verb:
|
|
|
|
return (priority == HighPrio);
|
|
|
|
case Med_Verb:
|
|
|
|
return (priority == HighPrio || priority == MedPrio);
|
|
|
|
case High_Verb:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
void
|
|
|
|
Debug::setDebugTime(Time t)
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-03-23 02:43:53 +01:00
|
|
|
m_starting_cycle = t;
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
void
|
|
|
|
Debug::setVerbosity(VerbosityLevel vb)
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-03-23 02:43:53 +01:00
|
|
|
m_verbosityLevel = vb;
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
void
|
|
|
|
Debug::setFilter(int filter)
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-03-23 02:43:53 +01:00
|
|
|
m_filter = filter;
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
bool
|
|
|
|
Debug::setVerbosityString(const char *verb_str)
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-03-23 02:43:53 +01:00
|
|
|
string verb = verb_str ? verb_str : "";
|
|
|
|
if (verb == "none") {
|
|
|
|
setVerbosity(No_Verb);
|
|
|
|
} else if (verb == "low") {
|
|
|
|
setVerbosity(Low_Verb);
|
|
|
|
} else if (verb == "med") {
|
|
|
|
setVerbosity(Med_Verb);
|
|
|
|
} else if (verb == "high") {
|
|
|
|
setVerbosity(High_Verb);
|
|
|
|
} else {
|
|
|
|
cerr << "Error: unrecognized verbosity (use none, low, med, high): "
|
|
|
|
<< verb << endl;
|
|
|
|
return true; // error
|
|
|
|
}
|
|
|
|
return false; // no error
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
bool
|
|
|
|
Debug::checkFilter(char ch)
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-03-23 02:43:53 +01:00
|
|
|
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
|
|
|
|
}
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
2010-03-23 02:43:53 +01:00
|
|
|
return true; // error
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
bool
|
|
|
|
Debug::checkFilterString(const char *filter_str)
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-03-23 02:43:53 +01:00
|
|
|
if (filter_str == NULL) {
|
|
|
|
cerr << "Error: unrecognized component filter: NULL" << endl;
|
|
|
|
return true; // error
|
|
|
|
}
|
2009-05-11 19:38:43 +02:00
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
// check for default filter ("none") before reporting RUBY_DEBUG error
|
|
|
|
if (string(filter_str) == "none") {
|
|
|
|
return false; // no error
|
|
|
|
}
|
2009-05-11 19:38:43 +02:00
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
if (string(filter_str) == "all") {
|
|
|
|
return false; // no error
|
|
|
|
}
|
2009-05-11 19:38:43 +02:00
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
// 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
|
|
|
|
}
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
2010-03-23 02:43:53 +01:00
|
|
|
return false; // no error
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
bool
|
|
|
|
Debug::setFilterString(const char *filter_str)
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-03-23 02:43:53 +01:00
|
|
|
if (checkFilterString(filter_str)) {
|
2009-05-11 19:38:43 +02:00
|
|
|
return true; // error
|
|
|
|
}
|
2010-03-23 02:43:53 +01:00
|
|
|
|
|
|
|
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
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
bool
|
|
|
|
Debug::addFilter(char ch)
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-03-23 02:43:53 +01:00
|
|
|
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
|
|
|
|
}
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
// We didn't find the character
|
|
|
|
cerr << "Error: unrecognized component filter: " << ch << endl;
|
|
|
|
usageInstructions();
|
|
|
|
return true; // error
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
void
|
|
|
|
Debug::clearFilter()
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-03-23 02:43:53 +01:00
|
|
|
m_filter = 0;
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Debug::allFilter()
|
|
|
|
{
|
2010-03-23 02:43:53 +01:00
|
|
|
m_filter = ~0;
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
void
|
|
|
|
Debug::usageInstructions(void)
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-03-23 02:43:53 +01:00
|
|
|
cerr << "Debug components: " << endl;
|
|
|
|
for (int i = 0; i < NUMBER_OF_COMPS; i++) {
|
|
|
|
cerr << " " << debugComponents[i].ch << ": "
|
|
|
|
<< debugComponents[i].desc << endl;
|
|
|
|
}
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
void
|
|
|
|
Debug::print(ostream& out) const
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-03-23 02:43:53 +01:00
|
|
|
out << "[Debug]" << endl;
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
void
|
|
|
|
Debug::setDebugOutputFile (const char *filename)
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-03-23 02:43:53 +01:00
|
|
|
if (filename == NULL || !strcmp(filename, "none")) {
|
|
|
|
debug_cout_ptr = &cout;
|
|
|
|
return;
|
|
|
|
}
|
2009-05-11 19:38:43 +02:00
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
if (m_fout.is_open()) {
|
|
|
|
m_fout.close();
|
|
|
|
}
|
|
|
|
m_fout.open(filename, ios::out);
|
|
|
|
if (!m_fout.is_open()) {
|
|
|
|
cerr << "setDebugOutputFile: can't open file " << filename << endl;
|
|
|
|
} else {
|
|
|
|
debug_cout_ptr = &m_fout;
|
|
|
|
}
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
void
|
|
|
|
Debug::closeDebugOutputFile ()
|
2009-05-11 19:38:43 +02:00
|
|
|
{
|
2010-03-23 02:43:53 +01:00
|
|
|
if (m_fout.is_open()) {
|
|
|
|
m_fout.close ();
|
|
|
|
debug_cout_ptr = &cout;
|
|
|
|
}
|
2009-05-11 19:38:43 +02:00
|
|
|
}
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
void
|
|
|
|
Debug::debugMsg( const char *fmt, ...)
|
|
|
|
{
|
2009-05-11 19:38:43 +02:00
|
|
|
va_list args;
|
|
|
|
|
2010-03-23 02:43:53 +01:00
|
|
|
// you could check validDebug() here before printing the message
|
2009-05-11 19:38:43 +02:00
|
|
|
va_start(args, fmt);
|
|
|
|
vfprintf(stdout, fmt, args);
|
|
|
|
va_end(args);
|
|
|
|
}
|
2010-01-30 05:29:17 +01:00
|
|
|
|
|
|
|
Debug *
|
|
|
|
RubyDebugParams::create()
|
|
|
|
{
|
|
|
|
return new Debug(this);
|
|
|
|
}
|