Turn the instruction tracing code into pluggable sim objects.
authorGabe Black <gblack@eecs.umich.edu>
Sun, 29 Jul 2007 03:30:43 +0000 (20:30 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Sun, 29 Jul 2007 03:30:43 +0000 (20:30 -0700)
These need to be refined a little still and given parameters.

--HG--
extra : convert_revision : 9a8f5a7bd9dacbebbbd2c235cd890c49a81040d7

23 files changed:
src/cpu/BaseCPU.py
src/cpu/ExeTracer.py [new file with mode: 0644]
src/cpu/IntelTrace.py [new file with mode: 0644]
src/cpu/LegionTrace.py [new file with mode: 0644]
src/cpu/NativeTrace.py [new file with mode: 0644]
src/cpu/SConscript
src/cpu/base.cc
src/cpu/base.hh
src/cpu/exetrace.cc
src/cpu/exetrace.hh
src/cpu/inteltrace.cc [new file with mode: 0644]
src/cpu/inteltrace.hh [new file with mode: 0644]
src/cpu/legiontrace.cc [new file with mode: 0644]
src/cpu/legiontrace.hh [new file with mode: 0644]
src/cpu/nativetrace.cc [new file with mode: 0644]
src/cpu/nativetrace.hh [new file with mode: 0644]
src/cpu/o3/fetch_impl.hh
src/cpu/simple/atomic.cc
src/cpu/simple/base.cc
src/cpu/simple/timing.cc
src/sim/InstTracer.py [new file with mode: 0644]
src/sim/SConscript
src/sim/insttracer.hh [new file with mode: 0644]

index 6c2aace5153aec13ef700d678f71ab43afb9c010..8be84392dd39159f23799251f07f67ae2ee012b5 100644 (file)
@@ -31,8 +31,12 @@ from m5.params import *
 from m5.proxy import *
 from m5 import build_env
 from Bus import Bus
+from InstTracer import InstTracer
+from ExeTracer import ExeTracer
 import sys
 
+default_tracer = ExeTracer()
+
 if build_env['FULL_SYSTEM']:
     if build_env['TARGET_ISA'] == 'alpha':
         from AlphaTLB import AlphaDTB, AlphaITB
@@ -83,6 +87,8 @@ class BaseCPU(SimObject):
     clock = Param.Clock('1t', "clock speed")
     phase = Param.Latency('0ns', "clock phase")
 
+    tracer = Param.InstTracer(default_tracer, "Instruction tracer")
+
     _mem_ports = []
 
     def connectMemPorts(self, bus):
diff --git a/src/cpu/ExeTracer.py b/src/cpu/ExeTracer.py
new file mode 100644 (file)
index 0000000..e904f9e
--- /dev/null
@@ -0,0 +1,36 @@
+# Copyright (c) 2007 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.
+#
+# Authors: Gabe Black
+
+from m5.SimObject import SimObject
+from m5.params import *
+from InstTracer import InstTracer
+
+class ExeTracer(InstTracer):
+    type = 'ExeTracer'
+    cxx_namespace = 'Trace'
+    cxx_class = 'ExeTracer'
diff --git a/src/cpu/IntelTrace.py b/src/cpu/IntelTrace.py
new file mode 100644 (file)
index 0000000..6e8f567
--- /dev/null
@@ -0,0 +1,36 @@
+# Copyright (c) 2007 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.
+#
+# Authors: Gabe Black
+
+from m5.SimObject import SimObject
+from m5.params import *
+from InstTracer import InstTracer
+
+class IntelTrace(InstTracer):
+    type = 'IntelTrace'
+    cxx_namespace = 'Trace'
+    cxx_class = 'IntelTrace'
diff --git a/src/cpu/LegionTrace.py b/src/cpu/LegionTrace.py
new file mode 100644 (file)
index 0000000..f9b6470
--- /dev/null
@@ -0,0 +1,36 @@
+# Copyright (c) 2007 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.
+#
+# Authors: Gabe Black
+
+from m5.SimObject import SimObject
+from m5.params import *
+from InstTracer import InstTracer
+
+class LegionTrace(InstTracer):
+    type = 'LegionTrace'
+    cxx_namespace = 'Trace'
+    cxx_class = 'LegionTrace'
diff --git a/src/cpu/NativeTrace.py b/src/cpu/NativeTrace.py
new file mode 100644 (file)
index 0000000..96b4e99
--- /dev/null
@@ -0,0 +1,36 @@
+# Copyright (c) 2007 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.
+#
+# Authors: Gabe Black
+
+from m5.SimObject import SimObject
+from m5.params import *
+from InstTracer import InstTracer
+
+class NativeTrace(InstTracer):
+    type = 'NativeTrace'
+    cxx_namespace = 'Trace'
+    cxx_class = 'NativeTrace'
index adf47fa4dd2d05b7e46d4836e177a81f7ba350a7..b686c0d95a9c9c844f9d0085b3c15a5feed42d28 100644 (file)
@@ -105,12 +105,15 @@ CheckerSupportedCPUList = ['O3CPU', 'OzoneCPU']
 
 SimObject('BaseCPU.py')
 SimObject('FuncUnit.py')
+SimObject('ExeTracer.py')
+SimObject('IntelTrace.py')
 
 Source('activity.cc')
 Source('base.cc')
 Source('cpuevent.cc')
 Source('exetrace.cc')
 Source('func_unit.cc')
+Source('inteltrace.cc')
 Source('pc_event.cc')
 Source('quiesce_event.cc')
 Source('static_inst.cc')
@@ -123,6 +126,14 @@ if env['FULL_SYSTEM']:
     Source('intr_control.cc')
     Source('profile.cc')
 
+    if env['TARGET_ISA'] == 'sparc':
+        SimObject('LegionTrace.py')
+        Source('legiontrace.cc')
+
+if env['TARGET_ISA'] == 'x86':
+    SimObject('NativeTrace.py')
+    Source('nativetrace.cc')
+
 if env['USE_CHECKER']:
     Source('checker/cpu.cc')
     checker_supports = False
index 17c04907a91b3edbd7404f73f09c435a7e043474..0fc3b4ceadbc25c49fe8a067603b6751c9d02f3c 100644 (file)
@@ -188,6 +188,7 @@ BaseCPU::BaseCPU(Params *p)
     if (params->profile)
         profileEvent = new ProfileEvent(this, params->profile);
 #endif
+    tracer = params->tracer;
 }
 
 BaseCPU::Params::Params()
@@ -196,6 +197,7 @@ BaseCPU::Params::Params()
     profile = false;
 #endif
     checker = NULL;
+    tracer = NULL;
 }
 
 void
index 4d8300186ceb0c48e615f1ca2c706d585e50abb0..76f6e46849961c65991c691b4349d1d1f723ed0e 100644 (file)
@@ -38,6 +38,7 @@
 #include "base/statistics.hh"
 #include "config/full_system.hh"
 #include "sim/eventq.hh"
+#include "sim/insttracer.hh"
 #include "mem/mem_object.hh"
 
 #if FULL_SYSTEM
@@ -132,8 +133,13 @@ class BaseCPU : public MemObject
     std::vector<ThreadContext *> threadContexts;
     std::vector<TheISA::Predecoder *> predecoders;
 
+    Trace::InstTracer * tracer;
+
   public:
 
+    /// Provide access to the tracer pointer
+    Trace::InstTracer * getTracer() { return tracer; }
+
     /// Notify the CPU that the indicated context is now active.  The
     /// delay parameter indicates the number of ticks to wait before
     /// executing (typically 0 or 1).
@@ -169,6 +175,8 @@ class BaseCPU : public MemObject
         Tick functionTraceStart;
         System *system;
         int cpu_id;
+        Trace::InstTracer * tracer;
+
         Tick phase;
 #if FULL_SYSTEM
         Tick profile;
index 25d41811e26d7f104aed54bb9c9cd5b3eb0a8543..38c22da9471a5396d921622f0b10de5bca79b6d1 100644 (file)
  *          Steve Raasch
  */
 
-#include <errno.h>
-#include <fstream>
 #include <iomanip>
-#include <sys/ipc.h>
-#include <sys/shm.h>
 
-#include "arch/predecoder.hh"
-#include "arch/regfile.hh"
-#include "arch/utility.hh"
 #include "base/loader/symtab.hh"
-#include "base/socket.hh"
-#include "config/full_system.hh"
 #include "cpu/base.hh"
 #include "cpu/exetrace.hh"
 #include "cpu/static_inst.hh"
+#include "cpu/thread_context.hh"
 #include "enums/OpClass.hh"
-#include "sim/system.hh"
-
-#if FULL_SYSTEM
-#include "arch/tlb.hh"
-#endif
-
-//XXX This is temporary
-#include "arch/isa_specific.hh"
-#include "cpu/m5legion_interface.h"
+#include "params/ExeTracer.hh"
 
 using namespace std;
 using namespace TheISA;
 
-#if THE_ISA == SPARC_ISA && FULL_SYSTEM
-static int diffcount = 0;
-static bool wasMicro = false;
-#endif
-
 namespace Trace {
-SharedData *shared_data = NULL;
-ListenSocket *cosim_listener = NULL;
 
 void
-setupSharedData()
-{
-    int shmfd = shmget('M' << 24 | getuid(), sizeof(SharedData), 0777);
-    if (shmfd < 0)
-        fatal("Couldn't get shared memory fd. Is Legion running?");
-
-    shared_data = (SharedData*)shmat(shmfd, NULL, SHM_RND);
-    if (shared_data == (SharedData*)-1)
-        fatal("Couldn't allocate shared memory");
-
-    if (shared_data->flags != OWN_M5)
-        fatal("Shared memory has invalid owner");
-
-    if (shared_data->version != VERSION)
-        fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION,
-              shared_data->version);
-
-    // step legion forward one cycle so we can get register values
-    shared_data->flags = OWN_LEGION;
-}
-
-////////////////////////////////////////////////////////////////////////
-//
-//  Methods for the InstRecord object
-//
-
-#if THE_ISA == SPARC_ISA
-
-inline char * genCenteredLabel(int length, char * buffer, char * label)
-{
-    int labelLength = strlen(label);
-    assert(labelLength <= length);
-    int leftPad = (length - labelLength) / 2;
-    int rightPad = length - leftPad - labelLength;
-    char format[64];
-    sprintf(format, "%%%ds%%s%%%ds", leftPad, rightPad);
-    sprintf(buffer, format, "", label, "");
-    return buffer;
-}
-
-inline void printRegPair(ostream & os, char const * title, uint64_t a, uint64_t b)
-{
-    ccprintf(os, "  %16s  |  %#018x   %s   %#-018x  \n",
-            title, a, (a == b) ? "|" : "X", b);
-}
-
-inline void printColumnLabels(ostream & os)
-{
-    static char * regLabel = genCenteredLabel(16, new char[17], "Register");
-    static char * m5Label = genCenteredLabel(18, new char[18], "M5");
-    static char * legionLabel = genCenteredLabel(18, new char[18], "Legion");
-    ccprintf(os, "  %s  |  %s   |   %s  \n", regLabel, m5Label, legionLabel);
-    ccprintf(os, "--------------------+-----------------------+-----------------------\n");
-}
-
-inline void printSectionHeader(ostream & os, char * name)
-{
-    char sectionString[70];
-    genCenteredLabel(69, sectionString, name);
-    ccprintf(os, "====================================================================\n");
-    ccprintf(os, "%69s\n", sectionString);
-    ccprintf(os, "====================================================================\n");
-}
-
-inline void printLevelHeader(ostream & os, int level)
-{
-    char sectionString[70];
-    char levelName[70];
-    sprintf(levelName, "Trap stack level %d", level);
-    genCenteredLabel(69, sectionString, levelName);
-    ccprintf(os, "====================================================================\n");
-    ccprintf(os, "%69s\n", sectionString);
-    ccprintf(os, "====================================================================\n");
-}
-
-#endif
-
-void
-Trace::InstRecord::dump()
+Trace::ExeTracerRecord::dump()
 {
     ostream &outs = Trace::output();
 
-    DPRINTF(Sparc, "Instruction: %#X\n", staticInst->machInst);
-    bool diff = true;
-    if (IsOn(ExecRegDelta))
-    {
-        diff = false;
-#ifndef NDEBUG
-#if THE_ISA == SPARC_ISA
-        static int fd = 0;
-        //Don't print what happens for each micro-op, just print out
-        //once at the last op, and for regular instructions.
-        if(!staticInst->isMicroop() || staticInst->isLastMicroop())
-        {
-            if(!cosim_listener)
-            {
-                int port = 8000;
-                cosim_listener = new ListenSocket();
-                while(!cosim_listener->listen(port, true))
-                {
-                    DPRINTF(GDBMisc, "Can't bind port %d\n", port);
-                    port++;
-                }
-                ccprintf(cerr, "Listening for cosimulator on port %d\n", port);
-                fd = cosim_listener->accept();
-            }
-            char prefix[] = "goli";
-            for(int p = 0; p < 4; p++)
-            {
-                for(int i = 0; i < 8; i++)
-                {
-                    uint64_t regVal;
-                    int res = read(fd, &regVal, sizeof(regVal));
-                    if(res < 0)
-                        panic("First read call failed! %s\n", strerror(errno));
-                    regVal = TheISA::gtoh(regVal);
-                    uint64_t realRegVal = thread->readIntReg(p * 8 + i);
-                    if((regVal & 0xffffffffULL) != (realRegVal & 0xffffffffULL))
-                    {
-                        DPRINTF(ExecRegDelta, "Register %s%d should be %#x but is %#x.\n", prefix[p], i, regVal, realRegVal);
-                        diff = true;
-                    }
-                    //ccprintf(outs, "%s%d m5 = %#x statetrace = %#x\n", prefix[p], i, realRegVal, regVal);
-                }
-            }
-            /*for(int f = 0; f <= 62; f+=2)
-            {
-                uint64_t regVal;
-                int res = read(fd, &regVal, sizeof(regVal));
-                if(res < 0)
-                    panic("First read call failed! %s\n", strerror(errno));
-                regVal = TheISA::gtoh(regVal);
-                uint64_t realRegVal = thread->readFloatRegBits(f, 64);
-                if(regVal != realRegVal)
-                {
-                    DPRINTF(ExecRegDelta, "Register f%d should be %#x but is %#x.\n", f, regVal, realRegVal);
-                }
-            }*/
-            uint64_t regVal;
-            int res = read(fd, &regVal, sizeof(regVal));
-            if(res < 0)
-                panic("First read call failed! %s\n", strerror(errno));
-            regVal = TheISA::gtoh(regVal);
-            uint64_t realRegVal = thread->readNextPC();
-            if(regVal != realRegVal)
-            {
-                DPRINTF(ExecRegDelta, "Register pc should be %#x but is %#x.\n", regVal, realRegVal);
-                diff = true;
-            }
-            res = read(fd, &regVal, sizeof(regVal));
-            if(res < 0)
-                panic("First read call failed! %s\n", strerror(errno));
-            regVal = TheISA::gtoh(regVal);
-            realRegVal = thread->readNextNPC();
-            if(regVal != realRegVal)
-            {
-                DPRINTF(ExecRegDelta, "Register npc should be %#x but is %#x.\n", regVal, realRegVal);
-                diff = true;
-            }
-            res = read(fd, &regVal, sizeof(regVal));
-            if(res < 0)
-                panic("First read call failed! %s\n", strerror(errno));
-            regVal = TheISA::gtoh(regVal);
-            realRegVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2);
-            if((regVal & 0xF) != (realRegVal & 0xF))
-            {
-                DPRINTF(ExecRegDelta, "Register ccr should be %#x but is %#x.\n", regVal, realRegVal);
-                diff = true;
-            }
-        }
-#endif
-#endif
-#if 0 //THE_ISA == SPARC_ISA
-        //Don't print what happens for each micro-op, just print out
-        //once at the last op, and for regular instructions.
-        if(!staticInst->isMicroop() || staticInst->isLastMicroop())
-        {
-            static uint64_t regs[32] = {
-                0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0};
-            static uint64_t ccr = 0;
-            static uint64_t y = 0;
-            static uint64_t floats[32];
-            uint64_t newVal;
-            static const char * prefixes[4] = {"G", "O", "L", "I"};
-
-            outs << hex;
-            outs << "PC = " << thread->readNextPC();
-            outs << " NPC = " << thread->readNextNPC();
-            newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2);
-            //newVal = thread->readMiscRegNoEffect(SparcISA::MISCREG_CCR);
-            if(newVal != ccr)
-            {
-                outs << " CCR = " << newVal;
-                ccr = newVal;
-            }
-            newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 1);
-            //newVal = thread->readMiscRegNoEffect(SparcISA::MISCREG_Y);
-            if(newVal != y)
-            {
-                outs << " Y = " << newVal;
-                y = newVal;
-            }
-            for(int y = 0; y < 4; y++)
-            {
-                for(int x = 0; x < 8; x++)
-                {
-                    int index = x + 8 * y;
-                    newVal = thread->readIntReg(index);
-                    if(regs[index] != newVal)
-                    {
-                        outs << " " << prefixes[y] << dec << x << " = " << hex << newVal;
-                        regs[index] = newVal;
-                    }
-                }
-            }
-            for(int y = 0; y < 32; y++)
-            {
-                newVal = thread->readFloatRegBits(2 * y, 64);
-                if(floats[y] != newVal)
-                {
-                    outs << " F" << dec << (2 * y) << " = " << hex << newVal;
-                    floats[y] = newVal;
-                }
-            }
-            outs << dec << endl;
-        }
-#endif
-    }
-    if(!diff) {
-    } else if (IsOn(ExecIntel)) {
-        ccprintf(outs, "%7d ) ", when);
-        outs << "0x" << hex << PC << ":\t";
-        if (staticInst->isLoad()) {
-            ccprintf(outs, "<RD %#x>", addr);
-        } else if (staticInst->isStore()) {
-            ccprintf(outs, "<WR %#x>", addr);
-        }
-        outs << endl;
-    } else {
-        if (IsOn(ExecTicks))
-            ccprintf(outs, "%7d: ", when);
-
-        outs << thread->getCpuPtr()->name() << " ";
-
-        if (IsOn(ExecSpeculative))
-            outs << (misspeculating ? "-" : "+") << " ";
-
-        if (IsOn(ExecThread))
-            outs << "T" << thread->getThreadNum() << " : ";
-
-
-        std::string sym_str;
-        Addr sym_addr;
-        if (debugSymbolTable
-            && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr)
-            && IsOn(ExecSymbol)) {
-            if (PC != sym_addr)
-                sym_str += csprintf("+%d", PC - sym_addr);
-            outs << "@" << sym_str << " : ";
-        }
-        else {
-            outs << "0x" << hex << PC << " : ";
-        }
-
-        //
-        //  Print decoded instruction
-        //
-
-#if defined(__GNUC__) && (__GNUC__ < 3)
-        // There's a bug in gcc 2.x library that prevents setw()
-        // from working properly on strings
-        string mc(staticInst->disassemble(PC, debugSymbolTable));
-        while (mc.length() < 26)
-            mc += " ";
-        outs << mc;
-#else
-        outs << setw(26) << left << staticInst->disassemble(PC, debugSymbolTable);
-#endif
-
-        outs << " : ";
+    if (IsOn(ExecTicks))
+        ccprintf(outs, "%7d: ", when);
 
-        if (IsOn(ExecOpClass)) {
-            outs << Enums::OpClassStrings[staticInst->opClass()] << " : ";
-        }
+    outs << thread->getCpuPtr()->name() << " ";
 
-        if (IsOn(ExecResult) && data_status != DataInvalid) {
-            outs << " D=";
-#if 0
-            if (data_status == DataDouble)
-                ccprintf(outs, "%f", data.as_double);
-            else
-                ccprintf(outs, "%#018x", data.as_int);
-#else
-            ccprintf(outs, "%#018x", data.as_int);
-#endif
-        }
+    if (IsOn(ExecSpeculative))
+        outs << (misspeculating ? "-" : "+") << " ";
 
-        if (IsOn(ExecEffAddr) && addr_valid)
-            outs << " A=0x" << hex << addr;
+    if (IsOn(ExecThread))
+        outs << "T" << thread->getThreadNum() << " : ";
 
-        if (IsOn(ExecIntRegs) && regs_valid) {
-            for (int i = 0; i < TheISA::NumIntRegs;)
-                for (int j = i + 1; i <= j; i++)
-                    ccprintf(outs, "r%02d = %#018x%s", i,
-                            iregs->regs.readReg(i),
-                            ((i == j) ? "\n" : "    "));
-            outs << "\n";
-        }
 
-        if (IsOn(ExecFetchSeq) && fetch_seq_valid)
-            outs << "  FetchSeq=" << dec << fetch_seq;
-
-        if (IsOn(ExecCPSeq) && cp_seq_valid)
-            outs << "  CPSeq=" << dec << cp_seq;
-
-        //
-        //  End of line...
-        //
-        outs << endl;
+    std::string sym_str;
+    Addr sym_addr;
+    if (debugSymbolTable
+        && IsOn(ExecSymbol)
+        && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr)) {
+        if (PC != sym_addr)
+            sym_str += csprintf("+%d", PC - sym_addr);
+        outs << "@" << sym_str << " : ";
+    }
+    else {
+        outs << "0x" << hex << PC << " : ";
     }
-#if THE_ISA == SPARC_ISA && FULL_SYSTEM
-    static TheISA::Predecoder predecoder(NULL);
-    // Compare
-    if (IsOn(ExecLegion))
-    {
-        bool compared = false;
-        bool diffPC   = false;
-        bool diffCC   = false;
-        bool diffInst = false;
-        bool diffIntRegs = false;
-        bool diffFpRegs = false;
-        bool diffTpc = false;
-        bool diffTnpc = false;
-        bool diffTstate = false;
-        bool diffTt = false;
-        bool diffTba = false;
-        bool diffHpstate = false;
-        bool diffHtstate = false;
-        bool diffHtba = false;
-        bool diffPstate = false;
-        bool diffY = false;
-        bool diffFsr = false;
-        bool diffCcr = false;
-        bool diffTl = false;
-        bool diffGl = false;
-        bool diffAsi = false;
-        bool diffPil = false;
-        bool diffCwp = false;
-        bool diffCansave = false;
-        bool diffCanrestore = false;
-        bool diffOtherwin = false;
-        bool diffCleanwin = false;
-        bool diffTlb = false;
-        Addr m5Pc, lgnPc;
-
-        if (!shared_data)
-            setupSharedData();
-
-        // We took a trap on a micro-op...
-        if (wasMicro && !staticInst->isMicroop())
-        {
-            // let's skip comparing this tick
-            while (!compared)
-                if (shared_data->flags == OWN_M5) {
-                    shared_data->flags = OWN_LEGION;
-                    compared = true;
-                }
-            compared = false;
-            wasMicro = false;
-        }
-
-        if (staticInst->isLastMicroop())
-            wasMicro = false;
-        else if (staticInst->isMicroop())
-            wasMicro = true;
-
-
-        if(!staticInst->isMicroop() || staticInst->isLastMicroop()) {
-            while (!compared) {
-                if (shared_data->flags == OWN_M5) {
-                    m5Pc = PC & TheISA::PAddrImplMask;
-                    if (bits(shared_data->pstate,3,3)) {
-                        m5Pc &= mask(32);
-                    }
-                    lgnPc = shared_data->pc & TheISA::PAddrImplMask;
-                    if (lgnPc != m5Pc)
-                       diffPC = true;
-
-                    if (shared_data->cycle_count !=
-                            thread->getCpuPtr()->instCount())
-                        diffCC = true;
-
-                    if (shared_data->instruction !=
-                            (SparcISA::MachInst)staticInst->machInst) {
-                        diffInst = true;
-                    }
-                    // assume we have %g0 working correctly
-                    for (int i = 1; i < TheISA::NumIntArchRegs; i++) {
-                        if (thread->readIntReg(i) != shared_data->intregs[i]) {
-                            diffIntRegs = true;
-                        }
-                    }
-                    for (int i = 0; i < TheISA::NumFloatRegs/2; i++) {
-                        if (thread->readFloatRegBits(i*2,FloatRegFile::DoubleWidth) != shared_data->fpregs[i]) {
-                            diffFpRegs = true;
-                        }
-                    }
-                            uint64_t oldTl = thread->readMiscRegNoEffect(MISCREG_TL);
-                    if (oldTl != shared_data->tl)
-                        diffTl = true;
-                    for (int i = 1; i <= MaxTL; i++) {
-                        thread->setMiscRegNoEffect(MISCREG_TL, i);
-                        if (thread->readMiscRegNoEffect(MISCREG_TPC) !=
-                                shared_data->tpc[i-1])
-                            diffTpc = true;
-                        if (thread->readMiscRegNoEffect(MISCREG_TNPC) !=
-                                shared_data->tnpc[i-1])
-                            diffTnpc = true;
-                        if (thread->readMiscRegNoEffect(MISCREG_TSTATE) !=
-                                shared_data->tstate[i-1])
-                            diffTstate = true;
-                        if (thread->readMiscRegNoEffect(MISCREG_TT) !=
-                                shared_data->tt[i-1])
-                            diffTt = true;
-                        if (thread->readMiscRegNoEffect(MISCREG_HTSTATE) !=
-                                shared_data->htstate[i-1])
-                            diffHtstate = true;
-                    }
-                    thread->setMiscRegNoEffect(MISCREG_TL, oldTl);
-
-                    if(shared_data->tba != thread->readMiscRegNoEffect(MISCREG_TBA))
-                        diffTba = true;
-                    //When the hpstate register is read by an instruction,
-                    //legion has bit 11 set. When it's in storage, it doesn't.
-                    //Since we don't directly support seperate interpretations
-                    //of the registers like that, the bit is always set to 1 and
-                    //we just don't compare it. It's not supposed to matter
-                    //anyway.
-                    if((shared_data->hpstate | (1 << 11)) != thread->readMiscRegNoEffect(MISCREG_HPSTATE))
-                        diffHpstate = true;
-                    if(shared_data->htba != thread->readMiscRegNoEffect(MISCREG_HTBA))
-                        diffHtba = true;
-                    if(shared_data->pstate != thread->readMiscRegNoEffect(MISCREG_PSTATE))
-                        diffPstate = true;
-                    //if(shared_data->y != thread->readMiscRegNoEffect(MISCREG_Y))
-                    if(shared_data->y !=
-                            thread->readIntReg(NumIntArchRegs + 1))
-                        diffY = true;
-                    if(shared_data->fsr != thread->readMiscRegNoEffect(MISCREG_FSR)) {
-                        diffFsr = true;
-                        if (mbits(shared_data->fsr, 63,10) ==
-                                mbits(thread->readMiscRegNoEffect(MISCREG_FSR), 63,10)) {
-                            thread->setMiscRegNoEffect(MISCREG_FSR, shared_data->fsr);
-                            diffFsr = false;
-                        }
-                    }
-                    //if(shared_data->ccr != thread->readMiscRegNoEffect(MISCREG_CCR))
-                    if(shared_data->ccr !=
-                            thread->readIntReg(NumIntArchRegs + 2))
-                        diffCcr = true;
-                    if(shared_data->gl != thread->readMiscRegNoEffect(MISCREG_GL))
-                        diffGl = true;
-                    if(shared_data->asi != thread->readMiscRegNoEffect(MISCREG_ASI))
-                        diffAsi = true;
-                    if(shared_data->pil != thread->readMiscRegNoEffect(MISCREG_PIL))
-                        diffPil = true;
-                    if(shared_data->cwp != thread->readMiscRegNoEffect(MISCREG_CWP))
-                        diffCwp = true;
-                    //if(shared_data->cansave != thread->readMiscRegNoEffect(MISCREG_CANSAVE))
-                    if(shared_data->cansave !=
-                            thread->readIntReg(NumIntArchRegs + 3))
-                        diffCansave = true;
-                    //if(shared_data->canrestore !=
-                    //     thread->readMiscRegNoEffect(MISCREG_CANRESTORE))
-                    if(shared_data->canrestore !=
-                            thread->readIntReg(NumIntArchRegs + 4))
-                        diffCanrestore = true;
-                    //if(shared_data->otherwin != thread->readMiscRegNoEffect(MISCREG_OTHERWIN))
-                    if(shared_data->otherwin !=
-                            thread->readIntReg(NumIntArchRegs + 6))
-                        diffOtherwin = true;
-                    //if(shared_data->cleanwin != thread->readMiscRegNoEffect(MISCREG_CLEANWIN))
-                    if(shared_data->cleanwin !=
-                            thread->readIntReg(NumIntArchRegs + 5))
-                        diffCleanwin = true;
-
-                    for (int i = 0; i < 64; i++) {
-                        if (shared_data->itb[i] !=  thread->getITBPtr()->TteRead(i))
-                                diffTlb = true;
-                        if (shared_data->dtb[i] !=  thread->getDTBPtr()->TteRead(i))
-                                diffTlb = true;
-                    }
-
-                    if (diffPC || diffCC || diffInst || diffIntRegs ||
-                         diffFpRegs || diffTpc || diffTnpc || diffTstate ||
-                         diffTt || diffHpstate || diffHtstate || diffHtba ||
-                         diffPstate || diffY || diffCcr || diffTl || diffFsr ||
-                         diffGl || diffAsi || diffPil || diffCwp || diffCansave ||
-                         diffCanrestore || diffOtherwin || diffCleanwin || diffTlb)
-                       {
-
-                        outs << "Differences found between M5 and Legion:";
-                        if (diffPC)
-                            outs << " [PC]";
-                        if (diffCC)
-                            outs << " [CC]";
-                        if (diffInst)
-                            outs << " [Instruction]";
-                        if (diffIntRegs)
-                            outs << " [IntRegs]";
-                        if (diffFpRegs)
-                            outs << " [FpRegs]";
-                        if (diffTpc)
-                            outs << " [Tpc]";
-                        if (diffTnpc)
-                            outs << " [Tnpc]";
-                        if (diffTstate)
-                            outs << " [Tstate]";
-                        if (diffTt)
-                            outs << " [Tt]";
-                        if (diffHpstate)
-                            outs << " [Hpstate]";
-                        if (diffHtstate)
-                            outs << " [Htstate]";
-                        if (diffHtba)
-                            outs << " [Htba]";
-                        if (diffPstate)
-                            outs << " [Pstate]";
-                        if (diffY)
-                            outs << " [Y]";
-                        if (diffFsr)
-                            outs << " [FSR]";
-                        if (diffCcr)
-                            outs << " [Ccr]";
-                        if (diffTl)
-                            outs << " [Tl]";
-                        if (diffGl)
-                            outs << " [Gl]";
-                        if (diffAsi)
-                            outs << " [Asi]";
-                        if (diffPil)
-                            outs << " [Pil]";
-                        if (diffCwp)
-                            outs << " [Cwp]";
-                        if (diffCansave)
-                            outs << " [Cansave]";
-                        if (diffCanrestore)
-                            outs << " [Canrestore]";
-                        if (diffOtherwin)
-                            outs << " [Otherwin]";
-                        if (diffCleanwin)
-                            outs << " [Cleanwin]";
-                        if (diffTlb)
-                            outs << " [Tlb]";
-                        outs << endl << endl;
-
-                        outs << right << setfill(' ') << setw(15)
-                             << "M5 PC: " << "0x"<< setw(16) << setfill('0')
-                             << hex << m5Pc << endl;
-                        outs << setfill(' ') << setw(15)
-                             << "Legion PC: " << "0x"<< setw(16) << setfill('0') << hex
-                             << lgnPc << endl << endl;
-
-                        outs << right << setfill(' ') << setw(15)
-                             << "M5 CC: " << "0x"<< setw(16) << setfill('0')
-                             << hex << thread->getCpuPtr()->instCount() << endl;
-                        outs << setfill(' ') << setw(15)
-                             << "Legion CC: " << "0x"<< setw(16) << setfill('0') << hex
-                             << shared_data->cycle_count << endl << endl;
 
-                        outs << setfill(' ') << setw(15)
-                             << "M5 Inst: "  << "0x"<< setw(8)
-                             << setfill('0') << hex << staticInst->machInst
-                             << staticInst->disassemble(m5Pc, debugSymbolTable)
-                             << endl;
+    //
+    //  Print decoded instruction
+    //
 
-                        predecoder.setTC(thread);
-                        predecoder.moreBytes(m5Pc, m5Pc,
-                                shared_data->instruction);
+    outs << setw(26) << left;
+    outs << staticInst->disassemble(PC, debugSymbolTable);
+    outs << " : ";
 
-                        assert(predecoder.extMachInstReady());
+    if (IsOn(ExecOpClass)) {
+        outs << Enums::OpClassStrings[staticInst->opClass()] << " : ";
+    }
 
-                        StaticInstPtr legionInst =
-                            StaticInst::decode(predecoder.getExtMachInst(), lgnPc);
-                        outs << setfill(' ') << setw(15)
-                             << " Legion Inst: "
-                             << "0x" << setw(8) << setfill('0') << hex
-                             << shared_data->instruction
-                             << legionInst->disassemble(lgnPc, debugSymbolTable)
-                             << endl << endl;
+    if (IsOn(ExecResult) && data_status != DataInvalid) {
+        ccprintf(outs, " D=%#018x", data.as_int);
+    }
 
-                        printSectionHeader(outs, "General State");
-                        printColumnLabels(outs);
-                        printRegPair(outs, "HPstate",
-                                thread->readMiscRegNoEffect(MISCREG_HPSTATE),
-                                shared_data->hpstate | (1 << 11));
-                        printRegPair(outs, "Htba",
-                                thread->readMiscRegNoEffect(MISCREG_HTBA),
-                                shared_data->htba);
-                        printRegPair(outs, "Pstate",
-                                thread->readMiscRegNoEffect(MISCREG_PSTATE),
-                                shared_data->pstate);
-                        printRegPair(outs, "Y",
-                                //thread->readMiscRegNoEffect(MISCREG_Y),
-                                thread->readIntReg(NumIntArchRegs + 1),
-                                shared_data->y);
-                        printRegPair(outs, "FSR",
-                                thread->readMiscRegNoEffect(MISCREG_FSR),
-                                shared_data->fsr);
-                        printRegPair(outs, "Ccr",
-                                //thread->readMiscRegNoEffect(MISCREG_CCR),
-                                thread->readIntReg(NumIntArchRegs + 2),
-                                shared_data->ccr);
-                        printRegPair(outs, "Tl",
-                                thread->readMiscRegNoEffect(MISCREG_TL),
-                                shared_data->tl);
-                        printRegPair(outs, "Gl",
-                                thread->readMiscRegNoEffect(MISCREG_GL),
-                                shared_data->gl);
-                        printRegPair(outs, "Asi",
-                                thread->readMiscRegNoEffect(MISCREG_ASI),
-                                shared_data->asi);
-                        printRegPair(outs, "Pil",
-                                thread->readMiscRegNoEffect(MISCREG_PIL),
-                                shared_data->pil);
-                        printRegPair(outs, "Cwp",
-                                thread->readMiscRegNoEffect(MISCREG_CWP),
-                                shared_data->cwp);
-                        printRegPair(outs, "Cansave",
-                                //thread->readMiscRegNoEffect(MISCREG_CANSAVE),
-                                thread->readIntReg(NumIntArchRegs + 3),
-                                shared_data->cansave);
-                        printRegPair(outs, "Canrestore",
-                                //thread->readMiscRegNoEffect(MISCREG_CANRESTORE),
-                                thread->readIntReg(NumIntArchRegs + 4),
-                                shared_data->canrestore);
-                        printRegPair(outs, "Otherwin",
-                                //thread->readMiscRegNoEffect(MISCREG_OTHERWIN),
-                                thread->readIntReg(NumIntArchRegs + 6),
-                                shared_data->otherwin);
-                        printRegPair(outs, "Cleanwin",
-                                //thread->readMiscRegNoEffect(MISCREG_CLEANWIN),
-                                thread->readIntReg(NumIntArchRegs + 5),
-                                shared_data->cleanwin);
-                        outs << endl;
-                        for (int i = 1; i <= MaxTL; i++) {
-                            printLevelHeader(outs, i);
-                            printColumnLabels(outs);
-                            thread->setMiscRegNoEffect(MISCREG_TL, i);
-                            printRegPair(outs, "Tpc",
-                                    thread->readMiscRegNoEffect(MISCREG_TPC),
-                                    shared_data->tpc[i-1]);
-                            printRegPair(outs, "Tnpc",
-                                    thread->readMiscRegNoEffect(MISCREG_TNPC),
-                                    shared_data->tnpc[i-1]);
-                            printRegPair(outs, "Tstate",
-                                    thread->readMiscRegNoEffect(MISCREG_TSTATE),
-                                    shared_data->tstate[i-1]);
-                            printRegPair(outs, "Tt",
-                                    thread->readMiscRegNoEffect(MISCREG_TT),
-                                    shared_data->tt[i-1]);
-                            printRegPair(outs, "Htstate",
-                                    thread->readMiscRegNoEffect(MISCREG_HTSTATE),
-                                    shared_data->htstate[i-1]);
-                        }
-                        thread->setMiscRegNoEffect(MISCREG_TL, oldTl);
-                        outs << endl;
+    if (IsOn(ExecEffAddr) && addr_valid)
+        outs << " A=0x" << hex << addr;
 
-                        printSectionHeader(outs, "General Purpose Registers");
-                        static const char * regtypes[4] = {"%g", "%o", "%l", "%i"};
-                        for(int y = 0; y < 4; y++) {
-                            for(int x = 0; x < 8; x++) {
-                                char label[8];
-                                sprintf(label, "%s%d", regtypes[y], x);
-                                printRegPair(outs, label,
-                                        thread->readIntReg(y*8+x),
-                                        shared_data->intregs[y*8+x]);
-                            }
-                        }
-                        if (diffFpRegs) {
-                            for (int x = 0; x < 32; x++) {
-                                char label[8];
-                                sprintf(label, "%%f%d", x);
-                                printRegPair(outs, label,
-                                 thread->readFloatRegBits(x*2,FloatRegFile::DoubleWidth),
-                                 shared_data->fpregs[x]);
-                            }
-                        }
-                        if (diffTlb) {
-                            printColumnLabels(outs);
-                            char label[8];
-                            for (int x = 0; x < 64; x++) {
-                                if (shared_data->itb[x] !=  ULL(0xFFFFFFFFFFFFFFFF) ||
-                                    thread->getITBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF))  {
-                                        sprintf(label, "I-TLB:%02d", x);
-                                        printRegPair(outs, label, thread->getITBPtr()->TteRead(x),
-                                                shared_data->itb[x]);
-                                }
-                            }
-                            for (int x = 0; x < 64; x++) {
-                                if (shared_data->dtb[x] !=  ULL(0xFFFFFFFFFFFFFFFF) ||
-                                    thread->getDTBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF))  {
-                                        sprintf(label, "D-TLB:%02d", x);
-                                        printRegPair(outs, label, thread->getDTBPtr()->TteRead(x),
-                                                shared_data->dtb[x]);
-                                }
-                            }
-                            thread->getITBPtr()->dumpAll();
-                            thread->getDTBPtr()->dumpAll();
-                        }
+    if (IsOn(ExecFetchSeq) && fetch_seq_valid)
+        outs << "  FetchSeq=" << dec << fetch_seq;
 
-                        diffcount++;
-                        if (diffcount > 3)
-                            fatal("Differences found between Legion and M5\n");
-                    } else
-                        diffcount = 0;
+    if (IsOn(ExecCPSeq) && cp_seq_valid)
+        outs << "  CPSeq=" << dec << cp_seq;
 
-                    compared = true;
-                    shared_data->flags = OWN_LEGION;
-                }
-            } // while
-        } // if not microop
-    }
-#endif
+    //
+    //  End of line...
+    //
+    outs << endl;
 }
 
 /* namespace Trace */ }
+
+////////////////////////////////////////////////////////////////////////
+//
+//  ExeTracer Simulation Object
+//
+Trace::ExeTracer *
+ExeTracerParams::create()
+{
+    return new Trace::ExeTracer(name);
+};
index 8c0fa22cb401aa825d6697d04c8245064e5d2c5f..76907d955a6f712e5e707666f29cd11047a53f8d 100644 (file)
 #ifndef __EXETRACE_HH__
 #define __EXETRACE_HH__
 
-#include <cstring>
-#include <fstream>
-#include <vector>
-
 #include "base/trace.hh"
-#include "cpu/inst_seq.hh"     // for InstSeqNum
 #include "cpu/static_inst.hh"
-#include "cpu/thread_context.hh"
 #include "sim/host.hh"
+#include "sim/insttracer.hh"
 
 class ThreadContext;
 
 
 namespace Trace {
 
-class InstRecord
+class ExeTracerRecord : public InstRecord
 {
-  protected:
-    typedef TheISA::IntRegFile IntRegFile;
-
-    Tick when;
-
-    // The following fields are initialized by the constructor and
-    // thus guaranteed to be valid.
-    ThreadContext *thread;
-    // need to make this ref-counted so it doesn't go away before we
-    // dump the record
-    StaticInstPtr staticInst;
-    Addr PC;
-    bool misspeculating;
-
-    // The remaining fields are only valid for particular instruction
-    // types (e.g, addresses for memory ops) or when particular
-    // options are enabled (e.g., tracing full register contents).
-    // Each data field has an associated valid flag to indicate
-    // whether the data field is valid.
-    Addr addr;
-    bool addr_valid;
-
-    union {
-        uint64_t as_int;
-        double as_double;
-    } data;
-    enum {
-        DataInvalid = 0,
-        DataInt8 = 1,  // set to equal number of bytes
-        DataInt16 = 2,
-        DataInt32 = 4,
-        DataInt64 = 8,
-        DataDouble = 3
-    } data_status;
-
-    InstSeqNum fetch_seq;
-    bool fetch_seq_valid;
-
-    InstSeqNum cp_seq;
-    bool cp_seq_valid;
-
-    struct iRegFile {
-        IntRegFile regs;
-    };
-    iRegFile *iregs;
-    bool regs_valid;
-
   public:
-    InstRecord(Tick _when, ThreadContext *_thread,
-               const StaticInstPtr &_staticInst,
-               Addr _pc, bool spec)
-        : when(_when), thread(_thread),
-          staticInst(_staticInst), PC(_pc),
-          misspeculating(spec)
+    ExeTracerRecord(Tick _when, ThreadContext *_thread,
+               const StaticInstPtr &_staticInst, Addr _pc, bool spec)
+        : InstRecord(_when, _thread, _staticInst, _pc, spec)
     {
-        data_status = DataInvalid;
-        addr_valid = false;
-        regs_valid = false;
-
-        fetch_seq_valid = false;
-        cp_seq_valid = false;
     }
 
-    ~InstRecord() { }
-
-    void setAddr(Addr a) { addr = a; addr_valid = true; }
-
-    void setData(Twin64_t d) { data.as_int = d.a; data_status = DataInt64; }
-    void setData(Twin32_t d) { data.as_int = d.a; data_status = DataInt32; }
-    void setData(uint64_t d) { data.as_int = d; data_status = DataInt64; }
-    void setData(uint32_t d) { data.as_int = d; data_status = DataInt32; }
-    void setData(uint16_t d) { data.as_int = d; data_status = DataInt16; }
-    void setData(uint8_t d) { data.as_int = d; data_status = DataInt8; }
-
-    void setData(int64_t d) { setData((uint64_t)d); }
-    void setData(int32_t d) { setData((uint32_t)d); }
-    void setData(int16_t d) { setData((uint16_t)d); }
-    void setData(int8_t d)  { setData((uint8_t)d); }
-
-    void setData(double d) { data.as_double = d; data_status = DataDouble; }
-
-    void setFetchSeq(InstSeqNum seq)
-    { fetch_seq = seq; fetch_seq_valid = true; }
-
-    void setCPSeq(InstSeqNum seq)
-    { cp_seq = seq; cp_seq_valid = true; }
-
-    void setRegs(const IntRegFile &regs);
-
     void dump();
 };
 
-
-inline void
-InstRecord::setRegs(const IntRegFile &regs)
+class ExeTracer : public InstTracer
 {
-    if (!iregs)
-      iregs = new iRegFile;
+  public:
 
-    std::memcpy(&iregs->regs, &regs, sizeof(IntRegFile));
-    regs_valid = true;
-}
+    ExeTracer(const std::string & name) : InstTracer(name)
+    {}
 
-inline InstRecord *
-getInstRecord(Tick when, ThreadContext *tc, const StaticInstPtr staticInst,
-              Addr pc)
-{
-    if (!IsOn(ExecEnable))
-        return NULL;
+    InstRecord *
+    getInstRecord(Tick when, ThreadContext *tc,
+            const StaticInstPtr staticInst, Addr pc)
+    {
+        if (!IsOn(ExecEnable))
+            return NULL;
 
-    if (!Trace::enabled)
-        return NULL;
+        if (!Trace::enabled)
+            return NULL;
 
-    if (!IsOn(ExecSpeculative) && tc->misspeculating())
-        return NULL;
+        if (!IsOn(ExecSpeculative) && tc->misspeculating())
+            return NULL;
 
-    return new InstRecord(when, tc, staticInst, pc, tc->misspeculating());
-}
+        return new ExeTracerRecord(when, tc,
+                staticInst, pc, tc->misspeculating());
+    }
+};
 
 /* namespace Trace */ }
 
diff --git a/src/cpu/inteltrace.cc b/src/cpu/inteltrace.cc
new file mode 100644 (file)
index 0000000..afa51b5
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2001-2005 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.
+ *
+ * Authors: Steve Reinhardt
+ *          Lisa Hsu
+ *          Nathan Binkert
+ *          Steve Raasch
+ */
+
+#include <iomanip>
+
+#include "cpu/exetrace.hh"
+#include "cpu/inteltrace.hh"
+#include "cpu/static_inst.hh"
+#include "params/IntelTrace.hh"
+
+using namespace std;
+using namespace TheISA;
+
+namespace Trace {
+
+void
+Trace::IntelTraceRecord::dump()
+{
+    ostream &outs = Trace::output();
+    ccprintf(outs, "%7d ) ", when);
+    outs << "0x" << hex << PC << ":\t";
+    if (staticInst->isLoad()) {
+        ccprintf(outs, "<RD %#x>", addr);
+    } else if (staticInst->isStore()) {
+        ccprintf(outs, "<WR %#x>", addr);
+    }
+    outs << endl;
+}
+
+/* namespace Trace */ }
+
+////////////////////////////////////////////////////////////////////////
+//
+//  ExeTracer Simulation Object
+//
+Trace::IntelTrace *
+IntelTraceParams::create()
+{
+    return new Trace::IntelTrace(name);
+};
diff --git a/src/cpu/inteltrace.hh b/src/cpu/inteltrace.hh
new file mode 100644 (file)
index 0000000..21afe0f
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2001-2005 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.
+ *
+ * Authors: Steve Reinhardt
+ *          Nathan Binkert
+ */
+
+#ifndef __INTELTRACE_HH__
+#define __INTELTRACE_HH__
+
+#include "base/trace.hh"
+#include "cpu/static_inst.hh"
+#include "sim/host.hh"
+#include "sim/insttracer.hh"
+
+class ThreadContext;
+
+
+namespace Trace {
+
+class IntelTraceRecord : public InstRecord
+{
+  public:
+    IntelTraceRecord(Tick _when, ThreadContext *_thread,
+               const StaticInstPtr &_staticInst, Addr _pc, bool spec)
+        : InstRecord(_when, _thread, _staticInst, _pc, spec)
+    {
+    }
+
+    void dump();
+};
+
+class IntelTrace : public InstTracer
+{
+  public:
+
+    IntelTrace(const std::string & name) : InstTracer(name)
+    {}
+
+    IntelTraceRecord *
+    getInstRecord(Tick when, ThreadContext *tc,
+            const StaticInstPtr staticInst, Addr pc)
+    {
+        if (!IsOn(ExecEnable))
+            return NULL;
+
+        if (!Trace::enabled)
+            return NULL;
+
+        if (!IsOn(ExecSpeculative) && tc->misspeculating())
+            return NULL;
+
+        return new IntelTraceRecord(when, tc,
+                staticInst, pc, tc->misspeculating());
+    }
+};
+
+/* namespace Trace */ }
+
+#endif // __EXETRACE_HH__
diff --git a/src/cpu/legiontrace.cc b/src/cpu/legiontrace.cc
new file mode 100644 (file)
index 0000000..58181cb
--- /dev/null
@@ -0,0 +1,600 @@
+/*
+ * Copyright (c) 2001-2005 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.
+ *
+ * Authors: Steve Reinhardt
+ *          Lisa Hsu
+ *          Nathan Binkert
+ *          Steve Raasch
+ */
+
+#include "arch/isa_specific.hh"
+#if THE_ISA != SPARC_ISA
+    #error Legion tracing only works with SPARC simulations!
+#endif
+
+#include "config/full_system.hh"
+#if !FULL_SYSTEM
+    #error Legion tracing only works in full system!
+#endif
+
+#include <iomanip>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#include "arch/sparc/predecoder.hh"
+#include "arch/sparc/regfile.hh"
+#include "arch/sparc/utility.hh"
+#include "base/socket.hh"
+#include "cpu/base.hh"
+#include "cpu/legiontrace.hh"
+#include "cpu/static_inst.hh"
+#include "cpu/thread_context.hh"
+#include "params/LegionTrace.hh"
+#include "sim/system.hh"
+
+#if FULL_SYSTEM
+#include "arch/tlb.hh"
+#endif
+
+//XXX This is temporary
+#include "cpu/m5legion_interface.h"
+
+using namespace std;
+using namespace TheISA;
+
+#if FULL_SYSTEM
+static int diffcount = 0;
+static bool wasMicro = false;
+#endif
+
+namespace Trace {
+SharedData *shared_data = NULL;
+
+void
+setupSharedData()
+{
+    int shmfd = shmget('M' << 24 | getuid(), sizeof(SharedData), 0777);
+    if (shmfd < 0)
+        fatal("Couldn't get shared memory fd. Is Legion running?");
+
+    shared_data = (SharedData*)shmat(shmfd, NULL, SHM_RND);
+    if (shared_data == (SharedData*)-1)
+        fatal("Couldn't allocate shared memory");
+
+    if (shared_data->flags != OWN_M5)
+        fatal("Shared memory has invalid owner");
+
+    if (shared_data->version != VERSION)
+        fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION,
+              shared_data->version);
+
+    // step legion forward one cycle so we can get register values
+    shared_data->flags = OWN_LEGION;
+}
+
+////////////////////////////////////////////////////////////////////////
+//
+//  Utility methods for pretty printing a report about a difference
+//
+
+inline char * genCenteredLabel(int length, char * buffer, char * label)
+{
+    int labelLength = strlen(label);
+    assert(labelLength <= length);
+    int leftPad = (length - labelLength) / 2;
+    int rightPad = length - leftPad - labelLength;
+    char format[64];
+    sprintf(format, "%%%ds%%s%%%ds", leftPad, rightPad);
+    sprintf(buffer, format, "", label, "");
+    return buffer;
+}
+
+inline void printRegPair(ostream & os, char const * title, uint64_t a, uint64_t b)
+{
+    ccprintf(os, "  %16s  |  %#018x   %s   %#-018x  \n",
+            title, a, (a == b) ? "|" : "X", b);
+}
+
+inline void printColumnLabels(ostream & os)
+{
+    static char * regLabel = genCenteredLabel(16, new char[17], "Register");
+    static char * m5Label = genCenteredLabel(18, new char[18], "M5");
+    static char * legionLabel = genCenteredLabel(18, new char[18], "Legion");
+    ccprintf(os, "  %s  |  %s   |   %s  \n", regLabel, m5Label, legionLabel);
+    ccprintf(os, "--------------------+-----------------------+-----------------------\n");
+}
+
+inline void printSectionHeader(ostream & os, char * name)
+{
+    char sectionString[70];
+    genCenteredLabel(69, sectionString, name);
+    ccprintf(os, "====================================================================\n");
+    ccprintf(os, "%69s\n", sectionString);
+    ccprintf(os, "====================================================================\n");
+}
+
+inline void printLevelHeader(ostream & os, int level)
+{
+    char sectionString[70];
+    char levelName[70];
+    sprintf(levelName, "Trap stack level %d", level);
+    genCenteredLabel(69, sectionString, levelName);
+    ccprintf(os, "====================================================================\n");
+    ccprintf(os, "%69s\n", sectionString);
+    ccprintf(os, "====================================================================\n");
+}
+
+void
+Trace::LegionTraceRecord::dump()
+{
+    ostream &outs = Trace::output();
+
+    static TheISA::Predecoder predecoder(NULL);
+    // Compare
+    bool compared = false;
+    bool diffPC   = false;
+    bool diffCC   = false;
+    bool diffInst = false;
+    bool diffIntRegs = false;
+    bool diffFpRegs = false;
+    bool diffTpc = false;
+    bool diffTnpc = false;
+    bool diffTstate = false;
+    bool diffTt = false;
+    bool diffTba = false;
+    bool diffHpstate = false;
+    bool diffHtstate = false;
+    bool diffHtba = false;
+    bool diffPstate = false;
+    bool diffY = false;
+    bool diffFsr = false;
+    bool diffCcr = false;
+    bool diffTl = false;
+    bool diffGl = false;
+    bool diffAsi = false;
+    bool diffPil = false;
+    bool diffCwp = false;
+    bool diffCansave = false;
+    bool diffCanrestore = false;
+    bool diffOtherwin = false;
+    bool diffCleanwin = false;
+    bool diffTlb = false;
+    Addr m5Pc, lgnPc;
+
+    if (!shared_data)
+        setupSharedData();
+
+    // We took a trap on a micro-op...
+    if (wasMicro && !staticInst->isMicroop())
+    {
+        // let's skip comparing this tick
+        while (!compared)
+            if (shared_data->flags == OWN_M5) {
+                shared_data->flags = OWN_LEGION;
+                compared = true;
+            }
+        compared = false;
+        wasMicro = false;
+    }
+
+    if (staticInst->isLastMicroop())
+        wasMicro = false;
+    else if (staticInst->isMicroop())
+        wasMicro = true;
+
+
+    if(!staticInst->isMicroop() || staticInst->isLastMicroop()) {
+        while (!compared) {
+            if (shared_data->flags == OWN_M5) {
+                m5Pc = PC & SparcISA::PAddrImplMask;
+                if (bits(shared_data->pstate,3,3)) {
+                    m5Pc &= mask(32);
+                }
+                lgnPc = shared_data->pc & SparcISA::PAddrImplMask;
+                if (lgnPc != m5Pc)
+                   diffPC = true;
+
+                if (shared_data->cycle_count !=
+                        thread->getCpuPtr()->instCount())
+                    diffCC = true;
+
+                if (shared_data->instruction !=
+                        (SparcISA::MachInst)staticInst->machInst) {
+                    diffInst = true;
+                }
+                // assume we have %g0 working correctly
+                for (int i = 1; i < TheISA::NumIntArchRegs; i++) {
+                    if (thread->readIntReg(i) != shared_data->intregs[i]) {
+                        diffIntRegs = true;
+                    }
+                }
+                for (int i = 0; i < TheISA::NumFloatRegs/2; i++) {
+                    if (thread->readFloatRegBits(i*2,
+                                FloatRegFile::DoubleWidth) !=
+                            shared_data->fpregs[i]) {
+                        diffFpRegs = true;
+                    }
+                }
+                        uint64_t oldTl =
+                            thread->readMiscRegNoEffect(MISCREG_TL);
+                if (oldTl != shared_data->tl)
+                    diffTl = true;
+                for (int i = 1; i <= MaxTL; i++) {
+                    thread->setMiscRegNoEffect(MISCREG_TL, i);
+                    if (thread->readMiscRegNoEffect(MISCREG_TPC) !=
+                            shared_data->tpc[i-1])
+                        diffTpc = true;
+                    if (thread->readMiscRegNoEffect(MISCREG_TNPC) !=
+                            shared_data->tnpc[i-1])
+                        diffTnpc = true;
+                    if (thread->readMiscRegNoEffect(MISCREG_TSTATE) !=
+                            shared_data->tstate[i-1])
+                        diffTstate = true;
+                    if (thread->readMiscRegNoEffect(MISCREG_TT) !=
+                            shared_data->tt[i-1])
+                        diffTt = true;
+                    if (thread->readMiscRegNoEffect(MISCREG_HTSTATE) !=
+                            shared_data->htstate[i-1])
+                        diffHtstate = true;
+                }
+                thread->setMiscRegNoEffect(MISCREG_TL, oldTl);
+
+                if(shared_data->tba != thread->readMiscRegNoEffect(MISCREG_TBA))
+                    diffTba = true;
+                //When the hpstate register is read by an instruction,
+                //legion has bit 11 set. When it's in storage, it doesn't.
+                //Since we don't directly support seperate interpretations
+                //of the registers like that, the bit is always set to 1 and
+                //we just don't compare it. It's not supposed to matter
+                //anyway.
+                if((shared_data->hpstate | (1 << 11)) !=
+                        thread->readMiscRegNoEffect(MISCREG_HPSTATE))
+                    diffHpstate = true;
+                if(shared_data->htba !=
+                        thread->readMiscRegNoEffect(MISCREG_HTBA))
+                    diffHtba = true;
+                if(shared_data->pstate !=
+                        thread->readMiscRegNoEffect(MISCREG_PSTATE))
+                    diffPstate = true;
+                //if(shared_data->y !=
+                //        thread->readMiscRegNoEffect(MISCREG_Y))
+                if(shared_data->y !=
+                        thread->readIntReg(NumIntArchRegs + 1))
+                    diffY = true;
+                if(shared_data->fsr !=
+                        thread->readMiscRegNoEffect(MISCREG_FSR)) {
+                    diffFsr = true;
+                    if (mbits(shared_data->fsr, 63,10) ==
+                            mbits(thread->readMiscRegNoEffect(MISCREG_FSR),
+                                63,10)) {
+                        thread->setMiscRegNoEffect(MISCREG_FSR,
+                                shared_data->fsr);
+                        diffFsr = false;
+                    }
+                }
+                //if(shared_data->ccr !=
+                //        thread->readMiscRegNoEffect(MISCREG_CCR))
+                if(shared_data->ccr !=
+                        thread->readIntReg(NumIntArchRegs + 2))
+                    diffCcr = true;
+                if(shared_data->gl !=
+                        thread->readMiscRegNoEffect(MISCREG_GL))
+                    diffGl = true;
+                if(shared_data->asi !=
+                        thread->readMiscRegNoEffect(MISCREG_ASI))
+                    diffAsi = true;
+                if(shared_data->pil !=
+                        thread->readMiscRegNoEffect(MISCREG_PIL))
+                    diffPil = true;
+                if(shared_data->cwp !=
+                        thread->readMiscRegNoEffect(MISCREG_CWP))
+                    diffCwp = true;
+                //if(shared_data->cansave !=
+                //        thread->readMiscRegNoEffect(MISCREG_CANSAVE))
+                if(shared_data->cansave !=
+                        thread->readIntReg(NumIntArchRegs + 3))
+                    diffCansave = true;
+                //if(shared_data->canrestore !=
+                //        thread->readMiscRegNoEffect(MISCREG_CANRESTORE))
+                if(shared_data->canrestore !=
+                        thread->readIntReg(NumIntArchRegs + 4))
+                    diffCanrestore = true;
+                //if(shared_data->otherwin !=
+                //        thread->readMiscRegNoEffect(MISCREG_OTHERWIN))
+                if(shared_data->otherwin !=
+                        thread->readIntReg(NumIntArchRegs + 6))
+                    diffOtherwin = true;
+                //if(shared_data->cleanwin !=
+                //        thread->readMiscRegNoEffect(MISCREG_CLEANWIN))
+                if(shared_data->cleanwin !=
+                        thread->readIntReg(NumIntArchRegs + 5))
+                    diffCleanwin = true;
+
+                for (int i = 0; i < 64; i++) {
+                    if (shared_data->itb[i] !=
+                            thread->getITBPtr()->TteRead(i))
+                        diffTlb = true;
+                    if (shared_data->dtb[i] !=
+                            thread->getDTBPtr()->TteRead(i))
+                        diffTlb = true;
+                }
+
+                if (diffPC || diffCC || diffInst ||
+                    diffIntRegs || diffFpRegs ||
+                    diffTpc || diffTnpc || diffTstate || diffTt ||
+                    diffHpstate || diffHtstate || diffHtba ||
+                    diffPstate || diffY || diffCcr || diffTl || diffFsr ||
+                    diffGl || diffAsi || diffPil || diffCwp ||
+                    diffCansave || diffCanrestore ||
+                    diffOtherwin || diffCleanwin || diffTlb) {
+
+                    outs << "Differences found between M5 and Legion:";
+                    if (diffPC)
+                        outs << " [PC]";
+                    if (diffCC)
+                        outs << " [CC]";
+                    if (diffInst)
+                        outs << " [Instruction]";
+                    if (diffIntRegs)
+                        outs << " [IntRegs]";
+                    if (diffFpRegs)
+                        outs << " [FpRegs]";
+                    if (diffTpc)
+                        outs << " [Tpc]";
+                    if (diffTnpc)
+                        outs << " [Tnpc]";
+                    if (diffTstate)
+                        outs << " [Tstate]";
+                    if (diffTt)
+                        outs << " [Tt]";
+                    if (diffHpstate)
+                        outs << " [Hpstate]";
+                    if (diffHtstate)
+                        outs << " [Htstate]";
+                    if (diffHtba)
+                        outs << " [Htba]";
+                    if (diffPstate)
+                        outs << " [Pstate]";
+                    if (diffY)
+                        outs << " [Y]";
+                    if (diffFsr)
+                        outs << " [FSR]";
+                    if (diffCcr)
+                        outs << " [Ccr]";
+                    if (diffTl)
+                        outs << " [Tl]";
+                    if (diffGl)
+                        outs << " [Gl]";
+                    if (diffAsi)
+                        outs << " [Asi]";
+                    if (diffPil)
+                        outs << " [Pil]";
+                    if (diffCwp)
+                        outs << " [Cwp]";
+                    if (diffCansave)
+                        outs << " [Cansave]";
+                    if (diffCanrestore)
+                        outs << " [Canrestore]";
+                    if (diffOtherwin)
+                        outs << " [Otherwin]";
+                    if (diffCleanwin)
+                        outs << " [Cleanwin]";
+                    if (diffTlb)
+                        outs << " [Tlb]";
+                    outs << endl << endl;
+
+                    outs << right << setfill(' ') << setw(15)
+                         << "M5 PC: " << "0x"<< setw(16) << setfill('0')
+                         << hex << m5Pc << endl;
+                    outs << setfill(' ') << setw(15)
+                         << "Legion PC: " << "0x"
+                         << setw(16) << setfill('0') << hex
+                         << lgnPc << endl << endl;
+
+                    outs << right << setfill(' ') << setw(15)
+                         << "M5 CC: " << "0x"
+                         << setw(16) << setfill('0') << hex
+                         << thread->getCpuPtr()->instCount() << endl;
+                    outs << setfill(' ') << setw(15)
+                         << "Legion CC: " << "0x"
+                         << setw(16) << setfill('0') << hex
+                         << shared_data->cycle_count << endl << endl;
+
+                    outs << setfill(' ') << setw(15)
+                         << "M5 Inst: " << "0x"
+                         << setw(8) << setfill('0') << hex
+                         << staticInst->machInst
+                         << staticInst->disassemble(m5Pc, debugSymbolTable)
+                         << endl;
+
+                    predecoder.setTC(thread);
+                    predecoder.moreBytes(m5Pc, m5Pc,
+                            shared_data->instruction);
+
+                    assert(predecoder.extMachInstReady());
+
+                    StaticInstPtr legionInst =
+                        StaticInst::decode(predecoder.getExtMachInst(), lgnPc);
+                    outs << setfill(' ') << setw(15)
+                         << " Legion Inst: "
+                         << "0x" << setw(8) << setfill('0') << hex
+                         << shared_data->instruction
+                         << legionInst->disassemble(lgnPc, debugSymbolTable)
+                         << endl << endl;
+
+                    printSectionHeader(outs, "General State");
+                    printColumnLabels(outs);
+                    printRegPair(outs, "HPstate",
+                            thread->readMiscRegNoEffect(MISCREG_HPSTATE),
+                            shared_data->hpstate | (1 << 11));
+                    printRegPair(outs, "Htba",
+                            thread->readMiscRegNoEffect(MISCREG_HTBA),
+                            shared_data->htba);
+                    printRegPair(outs, "Pstate",
+                            thread->readMiscRegNoEffect(MISCREG_PSTATE),
+                            shared_data->pstate);
+                    printRegPair(outs, "Y",
+                            //thread->readMiscRegNoEffect(MISCREG_Y),
+                            thread->readIntReg(NumIntArchRegs + 1),
+                            shared_data->y);
+                    printRegPair(outs, "FSR",
+                            thread->readMiscRegNoEffect(MISCREG_FSR),
+                            shared_data->fsr);
+                    printRegPair(outs, "Ccr",
+                            //thread->readMiscRegNoEffect(MISCREG_CCR),
+                            thread->readIntReg(NumIntArchRegs + 2),
+                            shared_data->ccr);
+                    printRegPair(outs, "Tl",
+                            thread->readMiscRegNoEffect(MISCREG_TL),
+                            shared_data->tl);
+                    printRegPair(outs, "Gl",
+                            thread->readMiscRegNoEffect(MISCREG_GL),
+                            shared_data->gl);
+                    printRegPair(outs, "Asi",
+                            thread->readMiscRegNoEffect(MISCREG_ASI),
+                            shared_data->asi);
+                    printRegPair(outs, "Pil",
+                            thread->readMiscRegNoEffect(MISCREG_PIL),
+                            shared_data->pil);
+                    printRegPair(outs, "Cwp",
+                            thread->readMiscRegNoEffect(MISCREG_CWP),
+                            shared_data->cwp);
+                    printRegPair(outs, "Cansave",
+                            //thread->readMiscRegNoEffect(MISCREG_CANSAVE),
+                            thread->readIntReg(NumIntArchRegs + 3),
+                            shared_data->cansave);
+                    printRegPair(outs, "Canrestore",
+                            //thread->readMiscRegNoEffect(MISCREG_CANRESTORE),
+                            thread->readIntReg(NumIntArchRegs + 4),
+                            shared_data->canrestore);
+                    printRegPair(outs, "Otherwin",
+                            //thread->readMiscRegNoEffect(MISCREG_OTHERWIN),
+                            thread->readIntReg(NumIntArchRegs + 6),
+                            shared_data->otherwin);
+                    printRegPair(outs, "Cleanwin",
+                            //thread->readMiscRegNoEffect(MISCREG_CLEANWIN),
+                            thread->readIntReg(NumIntArchRegs + 5),
+                            shared_data->cleanwin);
+                    outs << endl;
+                    for (int i = 1; i <= MaxTL; i++) {
+                        printLevelHeader(outs, i);
+                        printColumnLabels(outs);
+                        thread->setMiscRegNoEffect(MISCREG_TL, i);
+                        printRegPair(outs, "Tpc",
+                                thread->readMiscRegNoEffect(MISCREG_TPC),
+                                shared_data->tpc[i-1]);
+                        printRegPair(outs, "Tnpc",
+                                thread->readMiscRegNoEffect(MISCREG_TNPC),
+                                shared_data->tnpc[i-1]);
+                        printRegPair(outs, "Tstate",
+                                thread->readMiscRegNoEffect(MISCREG_TSTATE),
+                                shared_data->tstate[i-1]);
+                        printRegPair(outs, "Tt",
+                                thread->readMiscRegNoEffect(MISCREG_TT),
+                                shared_data->tt[i-1]);
+                        printRegPair(outs, "Htstate",
+                                thread->readMiscRegNoEffect(MISCREG_HTSTATE),
+                                shared_data->htstate[i-1]);
+                    }
+                    thread->setMiscRegNoEffect(MISCREG_TL, oldTl);
+                    outs << endl;
+
+                    printSectionHeader(outs, "General Purpose Registers");
+                    static const char * regtypes[4] =
+                        {"%g", "%o", "%l", "%i"};
+                    for(int y = 0; y < 4; y++) {
+                        for(int x = 0; x < 8; x++) {
+                            char label[8];
+                            sprintf(label, "%s%d", regtypes[y], x);
+                            printRegPair(outs, label,
+                                    thread->readIntReg(y*8+x),
+                                    shared_data->intregs[y*8+x]);
+                        }
+                    }
+                    if (diffFpRegs) {
+                        for (int x = 0; x < 32; x++) {
+                            char label[8];
+                            sprintf(label, "%%f%d", x);
+                            printRegPair(outs, label,
+                                thread->readFloatRegBits(x*2,
+                                    FloatRegFile::DoubleWidth),
+                                shared_data->fpregs[x]);
+                        }
+                    }
+                    if (diffTlb) {
+                        printColumnLabels(outs);
+                        char label[8];
+                        for (int x = 0; x < 64; x++) {
+                            if (shared_data->itb[x] !=
+                                    ULL(0xFFFFFFFFFFFFFFFF) ||
+                                thread->getITBPtr()->TteRead(x) !=
+                                ULL(0xFFFFFFFFFFFFFFFF)) {
+                                    sprintf(label, "I-TLB:%02d", x);
+                                    printRegPair(outs, label,
+                                            thread->getITBPtr()->TteRead(x),
+                                            shared_data->itb[x]);
+                            }
+                        }
+                        for (int x = 0; x < 64; x++) {
+                            if (shared_data->dtb[x] !=
+                                    ULL(0xFFFFFFFFFFFFFFFF) ||
+                                thread->getDTBPtr()->TteRead(x) !=
+                                ULL(0xFFFFFFFFFFFFFFFF))  {
+                                    sprintf(label, "D-TLB:%02d", x);
+                                    printRegPair(outs, label,
+                                            thread->getDTBPtr()->TteRead(x),
+                                            shared_data->dtb[x]);
+                            }
+                        }
+                        thread->getITBPtr()->dumpAll();
+                        thread->getDTBPtr()->dumpAll();
+                    }
+
+                    diffcount++;
+                    if (diffcount > 3)
+                        fatal("Differences found between Legion and M5\n");
+                } else
+                    diffcount = 0;
+
+                compared = true;
+                shared_data->flags = OWN_LEGION;
+            }
+        } // while
+    } // if not microop
+}
+
+/* namespace Trace */ }
+
+////////////////////////////////////////////////////////////////////////
+//
+//  ExeTracer Simulation Object
+//
+Trace::LegionTrace *
+LegionTraceParams::create()
+{
+    return new Trace::LegionTrace(name);
+};
diff --git a/src/cpu/legiontrace.hh b/src/cpu/legiontrace.hh
new file mode 100644 (file)
index 0000000..55c05e7
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2001-2005 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.
+ *
+ * Authors: Steve Reinhardt
+ *          Nathan Binkert
+ */
+
+#ifndef __LEGIONTRACE_HH__
+#define __LEGIONTRACE_HH__
+
+#include "base/trace.hh"
+#include "cpu/static_inst.hh"
+#include "sim/host.hh"
+#include "sim/insttracer.hh"
+
+class ThreadContext;
+
+namespace Trace {
+
+class LegionTraceRecord : public InstRecord
+{
+  public:
+    LegionTraceRecord(Tick _when, ThreadContext *_thread,
+               const StaticInstPtr &_staticInst, Addr _pc, bool spec)
+        : InstRecord(_when, _thread, _staticInst, _pc, spec)
+    {
+    }
+
+    void dump();
+};
+
+class LegionTrace : public InstTracer
+{
+  public:
+
+    LegionTrace(const std::string & name) : InstTracer(name)
+    {}
+
+    LegionTraceRecord *
+    getInstRecord(Tick when, ThreadContext *tc,
+            const StaticInstPtr staticInst, Addr pc)
+    {
+        if (tc->misspeculating())
+            return NULL;
+
+        return new LegionTraceRecord(when, tc,
+                staticInst, pc, tc->misspeculating());
+    }
+};
+
+/* namespace Trace */ }
+
+#endif // __LEGIONTRACE_HH__
diff --git a/src/cpu/nativetrace.cc b/src/cpu/nativetrace.cc
new file mode 100644 (file)
index 0000000..57304c7
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2001-2005 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.
+ *
+ * Authors: Steve Reinhardt
+ *          Lisa Hsu
+ *          Nathan Binkert
+ *          Steve Raasch
+ */
+
+#include <errno.h>
+
+#include "arch/regfile.hh"
+#include "arch/utility.hh"
+#include "base/loader/symtab.hh"
+#include "base/socket.hh"
+#include "cpu/nativetrace.hh"
+#include "cpu/static_inst.hh"
+#include "cpu/thread_context.hh"
+#include "params/NativeTrace.hh"
+
+//XXX This is temporary
+#include "arch/isa_specific.hh"
+
+using namespace std;
+using namespace TheISA;
+
+namespace Trace {
+
+NativeTrace::NativeTrace(const std::string & _name) : InstTracer(_name)
+{
+    int port = 8000;
+    while(!native_listener.listen(port, true))
+    {
+        DPRINTF(GDBMisc, "Can't bind port %d\n", port);
+        port++;
+    }
+    ccprintf(cerr, "Listening for native process on port %d\n", port);
+    fd = native_listener.accept();
+}
+
+bool
+NativeTraceRecord::checkIntReg(const char * regName, int index, int size)
+{
+    uint64_t regVal;
+    int res = read(parent->fd, &regVal, size);
+    if(res < 0)
+        panic("Read call failed! %s\n", strerror(errno));
+    regVal = TheISA::gtoh(regVal);
+    uint64_t realRegVal = thread->readIntReg(index);
+    if(regVal != realRegVal)
+    {
+        DPRINTFN("Register %s should be %#x but is %#x.\n",
+                regName, regVal, realRegVal);
+        return false;
+    }
+    return true;
+}
+
+bool NativeTraceRecord::checkPC(const char * regName, int size)
+{
+    uint64_t regVal;
+    int res = read(parent->fd, &regVal, size);
+    if(res < 0)
+        panic("Read call failed! %s\n", strerror(errno));
+    regVal = TheISA::gtoh(regVal);
+    uint64_t realRegVal = thread->readNextPC();
+    if(regVal != realRegVal)
+    {
+        DPRINTFN("%s should be %#x but is %#x.\n",
+                regName, regVal, realRegVal);
+        return false;
+    }
+    return true;
+}
+
+void
+Trace::NativeTraceRecord::dump()
+{
+//    ostream &outs = Trace::output();
+
+    //Don't print what happens for each micro-op, just print out
+    //once at the last op, and for regular instructions.
+    if(!staticInst->isMicroop() || staticInst->isLastMicroop())
+    {
+        checkIntReg("rax", INTREG_RAX, sizeof(uint64_t));
+        checkIntReg("rbx", INTREG_RBX, sizeof(uint64_t));
+        checkIntReg("rcx", INTREG_RCX, sizeof(uint64_t));
+        checkIntReg("rdx", INTREG_RDX, sizeof(uint64_t));
+        checkIntReg("rsp", INTREG_RSP, sizeof(uint64_t));
+        checkIntReg("rbp", INTREG_RBP, sizeof(uint64_t));
+        checkIntReg("rsi", INTREG_RSI, sizeof(uint64_t));
+        checkIntReg("rdi", INTREG_RDI, sizeof(uint64_t));
+        checkIntReg("r8", INTREG_R8, sizeof(uint64_t));
+        checkIntReg("r9", INTREG_R9, sizeof(uint64_t));
+        checkIntReg("r10", INTREG_R10, sizeof(uint64_t));
+        checkIntReg("r11", INTREG_R11, sizeof(uint64_t));
+        checkIntReg("r12", INTREG_R12, sizeof(uint64_t));
+        checkIntReg("r13", INTREG_R13, sizeof(uint64_t));
+        checkIntReg("r14", INTREG_R14, sizeof(uint64_t));
+        checkIntReg("r15", INTREG_R15, sizeof(uint64_t));
+        checkPC("rip", sizeof(uint64_t));
+#if THE_ISA == SPARC_ISA
+        /*for(int f = 0; f <= 62; f+=2)
+        {
+            uint64_t regVal;
+            int res = read(fd, &regVal, sizeof(regVal));
+            if(res < 0)
+                panic("First read call failed! %s\n", strerror(errno));
+            regVal = TheISA::gtoh(regVal);
+            uint64_t realRegVal = thread->readFloatRegBits(f, 64);
+            if(regVal != realRegVal)
+            {
+                DPRINTF(ExecRegDelta, "Register f%d should be %#x but is %#x.\n", f, regVal, realRegVal);
+            }
+        }*/
+        uint64_t regVal;
+        int res = read(fd, &regVal, sizeof(regVal));
+        if(res < 0)
+            panic("First read call failed! %s\n", strerror(errno));
+        regVal = TheISA::gtoh(regVal);
+        uint64_t realRegVal = thread->readNextPC();
+        if(regVal != realRegVal)
+        {
+            DPRINTF(ExecRegDelta,
+                    "Register pc should be %#x but is %#x.\n",
+                    regVal, realRegVal);
+        }
+        res = read(fd, &regVal, sizeof(regVal));
+        if(res < 0)
+            panic("First read call failed! %s\n", strerror(errno));
+        regVal = TheISA::gtoh(regVal);
+        realRegVal = thread->readNextNPC();
+        if(regVal != realRegVal)
+        {
+            DPRINTF(ExecRegDelta,
+                    "Register npc should be %#x but is %#x.\n",
+                    regVal, realRegVal);
+        }
+        res = read(fd, &regVal, sizeof(regVal));
+        if(res < 0)
+            panic("First read call failed! %s\n", strerror(errno));
+        regVal = TheISA::gtoh(regVal);
+        realRegVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2);
+        if((regVal & 0xF) != (realRegVal & 0xF))
+        {
+            DPRINTF(ExecRegDelta,
+                    "Register ccr should be %#x but is %#x.\n",
+                    regVal, realRegVal);
+        }
+#endif
+    }
+}
+
+/* namespace Trace */ }
+
+////////////////////////////////////////////////////////////////////////
+//
+//  ExeTracer Simulation Object
+//
+Trace::NativeTrace *
+NativeTraceParams::create()
+{
+    return new Trace::NativeTrace(name);
+};
diff --git a/src/cpu/nativetrace.hh b/src/cpu/nativetrace.hh
new file mode 100644 (file)
index 0000000..4839579
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2001-2005 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.
+ *
+ * Authors: Steve Reinhardt
+ *          Nathan Binkert
+ */
+
+#ifndef __NATIVETRACE_HH__
+#define __NATIVETRACE_HH__
+
+#include "base/trace.hh"
+#include "cpu/static_inst.hh"
+#include "sim/host.hh"
+#include "sim/insttracer.hh"
+
+class ThreadContext;
+
+
+namespace Trace {
+
+class NativeTrace;
+
+class NativeTraceRecord : public InstRecord
+{
+  protected:
+    NativeTrace * parent;
+
+    bool
+    checkIntReg(const char * regName, int index, int size);
+
+    bool
+    checkPC(const char * regName, int size);
+
+  public:
+    NativeTraceRecord(NativeTrace * _parent,
+               Tick _when, ThreadContext *_thread,
+               const StaticInstPtr &_staticInst, Addr _pc, bool spec)
+        : InstRecord(_when, _thread, _staticInst, _pc, spec), parent(_parent)
+    {
+    }
+
+    void dump();
+};
+
+class NativeTrace : public InstTracer
+{
+  protected:
+    int fd;
+
+    ListenSocket native_listener;
+
+  public:
+
+    NativeTrace(const std::string & name);
+
+    NativeTraceRecord *
+    getInstRecord(Tick when, ThreadContext *tc,
+            const StaticInstPtr staticInst, Addr pc)
+    {
+        if (tc->misspeculating())
+            return NULL;
+
+        return new NativeTraceRecord(this, when, tc,
+                staticInst, pc, tc->misspeculating());
+    }
+
+    friend class NativeTraceRecord;
+};
+
+/* namespace Trace */ }
+
+#endif // __EXETRACE_HH__
index 01e9b5b31bbdd69a9e51c00c8aa1563ea905f2d1..d1c66025850c84dc5257622d7258d848bd8f5b5b 100644 (file)
@@ -1156,9 +1156,8 @@ DefaultFetch<Impl>::fetch(bool &status_change)
 
 #if TRACING_ON
                 instruction->traceData =
-                    Trace::getInstRecord(curTick, cpu->tcBase(tid),
-                                         instruction->staticInst,
-                                         instruction->readPC());
+                    cpu->getTracer()->getInstRecord(curTick, cpu->tcBase(tid),
+                            instruction->staticInst, instruction->readPC());
 #else
                 instruction->traceData = NULL;
 #endif
index b2c24daadfa97f835011b6e6518543ed7529f30d..888ef49602bb81ad04dc74f62318b9bd9b84b33d 100644 (file)
@@ -590,6 +590,7 @@ AtomicSimpleCPUParams::create()
     params->simulate_stalls = simulate_stalls;
     params->system = system;
     params->cpu_id = cpu_id;
+    params->tracer = tracer;
 
 #if FULL_SYSTEM
     params->itb = itb;
index 4359ebebf5500b562f8db6ed7dd5231da386cf41..d2dd52b640f6e45f696a53c57029a6cc0943ba1f 100644 (file)
@@ -417,7 +417,7 @@ BaseSimpleCPU::preExecute()
     if(curStaticInst)
     {
 #if TRACING_ON
-        traceData = Trace::getInstRecord(curTick, tc, curStaticInst,
+        traceData = tracer->getInstRecord(curTick, tc, curStaticInst,
                                          thread->readPC());
 
         DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n",
index 754bd8c5f7d3a423259ac58b2f9c9f8038663fd7..855aaab593595c9bb4159359ec39f1fa86ab52eb 100644 (file)
@@ -719,6 +719,7 @@ TimingSimpleCPUParams::create()
     params->functionTraceStart = function_trace_start;
     params->system = system;
     params->cpu_id = cpu_id;
+    params->tracer = tracer;
 
 #if FULL_SYSTEM
     params->itb = itb;
diff --git a/src/sim/InstTracer.py b/src/sim/InstTracer.py
new file mode 100644 (file)
index 0000000..f7500f1
--- /dev/null
@@ -0,0 +1,35 @@
+# Copyright (c) 2007 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.
+#
+# Authors: Gabe Black
+
+from m5.SimObject import SimObject
+from m5.params import *
+
+class InstTracer(SimObject):
+    type = 'InstTracer'
+    cxx_namespace = 'Trace'
+    abstract = True
index 455e5678a36b841533afefd93de03e53768d588f..6bd53e205ef0f8704b37db1becc190c5e634c32c 100644 (file)
@@ -32,6 +32,7 @@ Import('*')
 
 SimObject('Root.py')
 SimObject('System.py')
+SimObject('InstTracer.py')
 
 Source('async.cc')
 Source('core.cc')
diff --git a/src/sim/insttracer.hh b/src/sim/insttracer.hh
new file mode 100644 (file)
index 0000000..ebeae1f
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2001-2005 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.
+ *
+ * Authors: Steve Reinhardt
+ *          Nathan Binkert
+ */
+
+#ifndef __INSTRECORD_HH__
+#define __INSTRECORD_HH__
+
+#include "base/trace.hh"
+#include "cpu/inst_seq.hh"     // for InstSeqNum
+#include "cpu/static_inst.hh"
+#include "sim/host.hh"
+#include "sim/sim_object.hh"
+
+class ThreadContext;
+
+namespace Trace {
+
+class InstRecord
+{
+  protected:
+    Tick when;
+
+    // The following fields are initialized by the constructor and
+    // thus guaranteed to be valid.
+    ThreadContext *thread;
+    // need to make this ref-counted so it doesn't go away before we
+    // dump the record
+    StaticInstPtr staticInst;
+    Addr PC;
+    bool misspeculating;
+
+    // The remaining fields are only valid for particular instruction
+    // types (e.g, addresses for memory ops) or when particular
+    // options are enabled (e.g., tracing full register contents).
+    // Each data field has an associated valid flag to indicate
+    // whether the data field is valid.
+    Addr addr;
+    bool addr_valid;
+
+    union {
+        uint64_t as_int;
+        double as_double;
+    } data;
+    enum {
+        DataInvalid = 0,
+        DataInt8 = 1,  // set to equal number of bytes
+        DataInt16 = 2,
+        DataInt32 = 4,
+        DataInt64 = 8,
+        DataDouble = 3
+    } data_status;
+
+    InstSeqNum fetch_seq;
+    bool fetch_seq_valid;
+
+    InstSeqNum cp_seq;
+    bool cp_seq_valid;
+
+  public:
+    InstRecord(Tick _when, ThreadContext *_thread,
+               const StaticInstPtr &_staticInst,
+               Addr _pc, bool spec)
+        : when(_when), thread(_thread),
+          staticInst(_staticInst), PC(_pc),
+          misspeculating(spec)
+    {
+        data_status = DataInvalid;
+        addr_valid = false;
+
+        fetch_seq_valid = false;
+        cp_seq_valid = false;
+    }
+
+    virtual ~InstRecord() { }
+
+    void setAddr(Addr a) { addr = a; addr_valid = true; }
+
+    void setData(Twin64_t d) { data.as_int = d.a; data_status = DataInt64; }
+    void setData(Twin32_t d) { data.as_int = d.a; data_status = DataInt32; }
+    void setData(uint64_t d) { data.as_int = d; data_status = DataInt64; }
+    void setData(uint32_t d) { data.as_int = d; data_status = DataInt32; }
+    void setData(uint16_t d) { data.as_int = d; data_status = DataInt16; }
+    void setData(uint8_t d) { data.as_int = d; data_status = DataInt8; }
+
+    void setData(int64_t d) { setData((uint64_t)d); }
+    void setData(int32_t d) { setData((uint32_t)d); }
+    void setData(int16_t d) { setData((uint16_t)d); }
+    void setData(int8_t d)  { setData((uint8_t)d); }
+
+    void setData(double d) { data.as_double = d; data_status = DataDouble; }
+
+    void setFetchSeq(InstSeqNum seq)
+    { fetch_seq = seq; fetch_seq_valid = true; }
+
+    void setCPSeq(InstSeqNum seq)
+    { cp_seq = seq; cp_seq_valid = true; }
+
+    virtual void dump() = 0;
+};
+
+class InstTracer : public SimObject
+{
+  public:
+    InstTracer(const std::string & name) : SimObject(name)
+    {}
+
+    virtual ~InstTracer()
+    {};
+
+    virtual InstRecord *
+        getInstRecord(Tick when, ThreadContext *tc,
+                const StaticInstPtr staticInst, Addr pc) = 0;
+};
+
+
+
+}; // namespace Trace
+
+#endif // __INSTRECORD_HH__