gem5/base/trace.cc
Kevin Lim f58d85128d Fixes so m5 compiles on gcc 3.4, which has much stricter syntax. Most changes come from templated code,
which is evaluated slightly differently than in previous versions of gcc.

arch/alpha/alpha_linux_process.cc:
    Alphabetize includes.
arch/alpha/vptr.hh:
    Change the constants that are being used for alpha pagebytes to come from the ISA.
base/random.hh:
cpu/static_inst.cc:
sim/param.cc:
    Fix up template syntax.
base/range.hh:
    Include iostream for << operator.
base/res_list.hh:
base/statistics.hh:
cpu/simple_cpu/simple_cpu.hh:
cpu/static_inst.hh:
sim/eventq.hh:
sim/param.hh:
    Fixup for templated code to resolve different scope lookup in gcc 3.4.  This defers the lookup of the
    function/variable until actual instantiation time by making it dependent on the templated class/function.
base/trace.cc:
    Fix call to new.
base/trace.hh:
    Fix up #define to have full path.
cpu/base_cpu.cc:
    Fix up call to new.
dev/etherlink.hh:
dev/ns_gige.hh:
dev/sinic.hh:
    Fixup for friend class/function declaration.  g++ 3.4 no longer allows typedefs to be declared as
    a friend class.
dev/pcidev.hh:
    Fix up re-definition of access level to params.
kern/linux/linux_syscalls.hh:
kern/tru64/tru64_syscalls.hh:
    Fix up header.  Fix up template syntax.
sim/serialize.cc:
    Include errno.h.
sim/startup.cc:
    Change startupq.  queue was getting destructed before all things had called ~StartupCallback(), which lead
    to a segfault.  This puts startupq in global space, and we allocate it ourselves.  Other code may be similar
    to this and may need changing in the future.
sim/syscall_emul.hh:
    Include cpu/exec_context.hh and sim/process.hh, as forward declarations are no longer sufficient.
sim/universe.cc:
    Include errno.h

--HG--
extra : convert_revision : e49d08ee89eb06a28351f02bafc028ca6652d5af
2005-01-14 18:34:56 -05:00

349 lines
7.7 KiB
C++

/*
* Copyright (c) 2001-2004 The Regents of The University of Michigan
* 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 <ctype.h>
#include <fstream>
#include <iostream>
#include <list>
#include <string>
#include <vector>
#include "base/misc.hh"
#include "base/trace.hh"
#include "base/str.hh"
using namespace std;
namespace Trace {
const string DefaultName("global");
FlagVec flags(NumFlags, false);
//
// This variable holds the output stream for debug information. Other
// than setting up/redirecting this stream, do *NOT* reference this
// directly; use DebugOut() (see below) to access this stream for
// output.
//
ostream *dprintf_stream = &cerr;
ObjectMatch ignore;
Log theLog;
Log::Log()
{
size = 0;
buffer = NULL;
}
void
Log::init(int _size)
{
if (buffer != NULL) {
fatal("Trace::Log::init called twice!");
}
size = _size;
buffer = new Record *[size];
for (int i = 0; i < size; ++i) {
buffer[i] = NULL;
}
nextRecPtr = &buffer[0];
wrapRecPtr = &buffer[size];
}
Log::~Log()
{
for (int i = 0; i < size; ++i) {
delete buffer[i];
}
delete [] buffer;
}
void
Log::append(Record *rec)
{
// dump record to output stream if there's one open
if (dprintf_stream != NULL) {
rec->dump(*dprintf_stream);
}
// no buffering: justget rid of it now
if (buffer == NULL) {
delete rec;
return;
}
Record *oldRec = *nextRecPtr;
if (oldRec != NULL) {
// log has wrapped: overwrite
delete oldRec;
}
*nextRecPtr = rec;
if (++nextRecPtr == wrapRecPtr) {
nextRecPtr = &buffer[0];
}
}
void
Log::dump(ostream &os)
{
if (buffer == NULL) {
return;
}
Record **bufPtr = nextRecPtr;
if (*bufPtr == NULL) {
// next record slot is empty: log must not be full yet.
// start dumping from beginning of buffer
bufPtr = buffer;
}
do {
Record *rec = *bufPtr;
rec->dump(os);
if (++bufPtr == wrapRecPtr) {
bufPtr = &buffer[0];
}
} while (bufPtr != nextRecPtr);
}
PrintfRecord::~PrintfRecord()
{
delete &args;
}
void
PrintfRecord::dump(ostream &os)
{
string fmt = "";
if (!name.empty()) {
fmt = "%s: " + fmt;
args.prepend(name);
}
if (cycle != (Tick)-1) {
fmt = "%7d: " + fmt;
args.prepend(cycle);
}
fmt += format;
args.dump(os, fmt);
os.flush();
}
DataRecord::DataRecord(Tick _cycle, const string &_name,
const void *_data, int _len)
: Record(_cycle), name(_name), len(_len)
{
data = new uint8_t[len];
memcpy(data, _data, len);
}
DataRecord::~DataRecord()
{
delete [] data;
}
void
DataRecord::dump(ostream &os)
{
int c, i, j;
for (i = 0; i < len; i += 16) {
ccprintf(os, "%d: %s: %08x ", cycle, name, i);
c = len - i;
if (c > 16) c = 16;
for (j = 0; j < c; j++) {
ccprintf(os, "%02x ", data[i + j] & 0xff);
if ((j & 0xf) == 7 && j > 0)
ccprintf(os, " ");
}
for (; j < 16; j++)
ccprintf(os, " ");
ccprintf(os, " ");
for (j = 0; j < c; j++) {
int ch = data[i + j] & 0x7f;
ccprintf(os,
"%c", (char)(isprint(ch) ? ch : ' '));
}
ccprintf(os, "\n");
if (c < 16)
break;
}
}
} // namespace Trace
//
// Returns the current output stream for debug information. As a
// wrapper around Trace::dprintf_stream, this handles cases where debug
// information is generated in the process of parsing .ini options,
// before we process the option that sets up the debug output stream
// itself.
//
std::ostream &
DebugOut()
{
return *Trace::dprintf_stream;
}
/////////////////////////////////////////////
//
// C-linkage functions for invoking from gdb
//
/////////////////////////////////////////////
//
// Dump trace buffer to specified file (cout if NULL)
//
extern "C"
void
dumpTrace(const char *filename)
{
if (filename != NULL) {
ofstream out(filename);
Trace::theLog.dump(out);
out.close();
}
else {
Trace::theLog.dump(cout);
}
}
//
// Turn on/off trace output to cerr. Typically used when trace output
// is only going to circular buffer, but you want to see what's being
// sent there as you step through some code in gdb. This uses the
// same facility as the "trace to file" feature, and will print error
// messages rather than clobbering an existing ostream pointer.
//
extern "C"
void
echoTrace(bool on)
{
if (on) {
if (Trace::dprintf_stream != NULL) {
cerr << "Already echoing trace to a file... go do a 'tail -f'"
<< " on that file instead." << endl;
} else {
Trace::dprintf_stream = &cerr;
}
} else {
if (Trace::dprintf_stream != &cerr) {
cerr << "Not echoing trace to cerr." << endl;
} else {
Trace::dprintf_stream = NULL;
}
}
}
extern "C"
void
printTraceFlags()
{
using namespace Trace;
for (int i = 0; i < numFlagStrings; ++i)
if (flags[i])
cprintf("%s\n", flagStrings[i]);
}
void
tweakTraceFlag(const char *string, bool value)
{
using namespace Trace;
std::string str(string);
for (int i = 0; i < numFlagStrings; ++i) {
if (str != flagStrings[i])
continue;
int idx = i;
if (idx < NumFlags) {
flags[idx] = value;
} else {
idx -= NumFlags;
if (idx >= NumCompoundFlags) {
ccprintf(cerr, "Invalid compound flag");
return;
}
const Flags *flagVec = compoundFlags[idx];
for (int j = 0; flagVec[j] != -1; ++j) {
if (flagVec[j] >= NumFlags) {
ccprintf(cerr, "Invalid compound flag");
return;
}
flags[flagVec[j]] = value;
}
}
cprintf("flag %s was %s\n", string, value ? "set" : "cleared");
return;
}
cprintf("could not find flag %s\n", string);
}
extern "C"
void
setTraceFlag(const char *string)
{
tweakTraceFlag(string, true);
}
extern "C"
void
clearTraceFlag(const char *string)
{
tweakTraceFlag(string, false);
}