summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/sparc/process.cc47
-rw-r--r--src/arch/x86/insts/static_inst.hh3
-rw-r--r--src/arch/x86/isa/insts/data_transfer/stack_operations.py19
-rw-r--r--src/arch/x86/isa/microops/limmop.isa6
-rw-r--r--src/arch/x86/process.cc175
-rw-r--r--src/arch/x86/syscallreturn.hh6
-rw-r--r--src/cpu/BaseCPU.py6
-rw-r--r--src/cpu/ExeTracer.py36
-rw-r--r--src/cpu/IntelTrace.py36
-rw-r--r--src/cpu/LegionTrace.py36
-rw-r--r--src/cpu/NativeTrace.py36
-rw-r--r--src/cpu/SConscript11
-rw-r--r--src/cpu/base.cc6
-rw-r--r--src/cpu/base.hh8
-rw-r--r--src/cpu/exetrace.cc788
-rw-r--r--src/cpu/exetrace.hh135
-rw-r--r--src/cpu/inteltrace.cc70
-rw-r--r--src/cpu/inteltrace.hh84
-rw-r--r--src/cpu/legiontrace.cc600
-rw-r--r--src/cpu/legiontrace.hh77
-rw-r--r--src/cpu/nativetrace.cc188
-rw-r--r--src/cpu/nativetrace.hh96
-rw-r--r--src/cpu/o3/fetch_impl.hh5
-rw-r--r--src/cpu/simple/atomic.cc1
-rw-r--r--src/cpu/simple/base.cc2
-rw-r--r--src/cpu/simple/timing.cc1
-rw-r--r--src/sim/InstTracer.py35
-rw-r--r--src/sim/SConscript1
-rw-r--r--src/sim/insttracer.hh146
-rw-r--r--src/sim/process.hh26
-rw-r--r--util/statetrace/arch/tracechild_amd64.cc322
-rw-r--r--util/statetrace/arch/tracechild_amd64.hh110
-rw-r--r--util/statetrace/printer.cc10
-rw-r--r--util/statetrace/statetrace.cc184
-rw-r--r--util/statetrace/tracechild_arch.cc5
-rw-r--r--util/style.py2
36 files changed, 2268 insertions, 1051 deletions
diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc
index bc950301a..41a1c2136 100644
--- a/src/arch/sparc/process.cc
+++ b/src/arch/sparc/process.cc
@@ -194,25 +194,6 @@ Sparc64LiveProcess::argsInit(int intSize, int pageSize)
// load object file into target memory
objFile->loadSections(initVirtMem);
- //These are the auxilliary vector types
- enum auxTypes
- {
- SPARC_AT_HWCAP = 16,
- SPARC_AT_PAGESZ = 6,
- SPARC_AT_CLKTCK = 17,
- SPARC_AT_PHDR = 3,
- SPARC_AT_PHENT = 4,
- SPARC_AT_PHNUM = 5,
- SPARC_AT_BASE = 7,
- SPARC_AT_FLAGS = 8,
- SPARC_AT_ENTRY = 9,
- SPARC_AT_UID = 11,
- SPARC_AT_EUID = 12,
- SPARC_AT_GID = 13,
- SPARC_AT_EGID = 14,
- SPARC_AT_SECURE = 23
- };
-
enum hardwareCaps
{
M5_HWCAP_SPARC_FLUSH = 1,
@@ -241,34 +222,34 @@ Sparc64LiveProcess::argsInit(int intSize, int pageSize)
if(elfObject)
{
//Bits which describe the system hardware capabilities
- auxv.push_back(auxv_t(SPARC_AT_HWCAP, hwcap));
+ auxv.push_back(auxv_t(M5_AT_HWCAP, hwcap));
//The system page size
- auxv.push_back(auxv_t(SPARC_AT_PAGESZ, SparcISA::VMPageSize));
+ auxv.push_back(auxv_t(M5_AT_PAGESZ, SparcISA::VMPageSize));
//Defined to be 100 in the kernel source.
//Frequency at which times() increments
- auxv.push_back(auxv_t(SPARC_AT_CLKTCK, 100));
+ auxv.push_back(auxv_t(M5_AT_CLKTCK, 100));
// For statically linked executables, this is the virtual address of the
// program header tables if they appear in the executable image
- auxv.push_back(auxv_t(SPARC_AT_PHDR, elfObject->programHeaderTable()));
+ auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable()));
// This is the size of a program header entry from the elf file.
- auxv.push_back(auxv_t(SPARC_AT_PHENT, elfObject->programHeaderSize()));
+ auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize()));
// This is the number of program headers from the original elf file.
- auxv.push_back(auxv_t(SPARC_AT_PHNUM, elfObject->programHeaderCount()));
+ auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount()));
//This is the address of the elf "interpreter", It should be set
//to 0 for regular executables. It should be something else
//(not sure what) for dynamic libraries.
- auxv.push_back(auxv_t(SPARC_AT_BASE, 0));
+ auxv.push_back(auxv_t(M5_AT_BASE, 0));
//This is hardwired to 0 in the elf loading code in the kernel
- auxv.push_back(auxv_t(SPARC_AT_FLAGS, 0));
+ auxv.push_back(auxv_t(M5_AT_FLAGS, 0));
//The entry point to the program
- auxv.push_back(auxv_t(SPARC_AT_ENTRY, objFile->entryPoint()));
+ auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint()));
//Different user and group IDs
- auxv.push_back(auxv_t(SPARC_AT_UID, uid()));
- auxv.push_back(auxv_t(SPARC_AT_EUID, euid()));
- auxv.push_back(auxv_t(SPARC_AT_GID, gid()));
- auxv.push_back(auxv_t(SPARC_AT_EGID, egid()));
+ auxv.push_back(auxv_t(M5_AT_UID, uid()));
+ auxv.push_back(auxv_t(M5_AT_EUID, euid()));
+ auxv.push_back(auxv_t(M5_AT_GID, gid()));
+ auxv.push_back(auxv_t(M5_AT_EGID, egid()));
//Whether to enable "secure mode" in the executable
- auxv.push_back(auxv_t(SPARC_AT_SECURE, 0));
+ auxv.push_back(auxv_t(M5_AT_SECURE, 0));
}
//Figure out how big the initial stack needs to be
diff --git a/src/arch/x86/insts/static_inst.hh b/src/arch/x86/insts/static_inst.hh
index c39c2956e..f42e6693d 100644
--- a/src/arch/x86/insts/static_inst.hh
+++ b/src/arch/x86/insts/static_inst.hh
@@ -58,6 +58,7 @@
#ifndef __ARCH_X86_INSTS_STATICINST_HH__
#define __ARCH_X86_INSTS_STATICINST_HH__
+#include "base/trace.hh"
#include "cpu/static_inst.hh"
namespace X86ISA
@@ -113,7 +114,7 @@ namespace X86ISA
default:
panic("Tried to merge with unrecognized size %d.\n", size);
}
- return val;
+ return reg;
}
inline uint64_t pick(uint64_t from, int size)
diff --git a/src/arch/x86/isa/insts/data_transfer/stack_operations.py b/src/arch/x86/isa/insts/data_transfer/stack_operations.py
index 889e7b88b..1c13b44b4 100644
--- a/src/arch/x86/isa/insts/data_transfer/stack_operations.py
+++ b/src/arch/x86/isa/insts/data_transfer/stack_operations.py
@@ -85,8 +85,10 @@ def macroop PUSH_R {
# Make the default data size of pops 64 bits in 64 bit mode
.adjust_env oszIn64Override
+ # This needs to work slightly differently from the other versions of push
+ # because the -original- version of the stack pointer is what gets pushed
+ st reg, ss, [0, t0, rsp], "-env.dataSize"
subi rsp, rsp, dsz
- st reg, ss, [0, t0, rsp]
};
def macroop PUSH_I {
@@ -130,14 +132,13 @@ def macroop PUSHA {
};
def macroop POPA {
- st rdi, ss, [0, t0, rsp], "0 * env.dataSize"
- st rsi, ss, [0, t0, rsp], "1 * env.dataSize"
- st rbp, ss, [0, t0, rsp], "2 * env.dataSize"
- st rsp, ss, [0, t0, rsp], "3 * env.dataSize"
- st rbx, ss, [0, t0, rsp], "4 * env.dataSize"
- st rdx, ss, [0, t0, rsp], "5 * env.dataSize"
- st rcx, ss, [0, t0, rsp], "6 * env.dataSize"
- st rax, ss, [0, t0, rsp], "7 * env.dataSize"
+ ld rdi, ss, [0, t0, rsp], "0 * env.dataSize"
+ ld rsi, ss, [0, t0, rsp], "1 * env.dataSize"
+ ld rbp, ss, [0, t0, rsp], "2 * env.dataSize"
+ ld rbx, ss, [0, t0, rsp], "4 * env.dataSize"
+ ld rdx, ss, [0, t0, rsp], "5 * env.dataSize"
+ ld rcx, ss, [0, t0, rsp], "6 * env.dataSize"
+ ld rax, ss, [0, t0, rsp], "7 * env.dataSize"
addi rsp, rsp, "8 * env.dataSize"
};
'''
diff --git a/src/arch/x86/isa/microops/limmop.isa b/src/arch/x86/isa/microops/limmop.isa
index 37180d7fa..ec68c36dc 100644
--- a/src/arch/x86/isa/microops/limmop.isa
+++ b/src/arch/x86/isa/microops/limmop.isa
@@ -142,12 +142,12 @@ def template MicroLimmOpConstructor {{
let {{
class LimmOp(X86Microop):
- def __init__(self, dest, imm):
+ def __init__(self, dest, imm, dataSize="env.dataSize"):
self.className = "Limm"
self.mnemonic = "limm"
self.dest = dest
self.imm = imm
- self.dataSize = "env.dataSize"
+ self.dataSize = dataSize
def getAllocator(self, *microFlags):
allocator = '''new %(class_name)s(machInst, mnemonic
@@ -165,7 +165,7 @@ let {{
let {{
# Build up the all register version of this micro op
iop = InstObjParams("limm", "Limm", 'X86MicroopBase',
- {"code" : "DestReg = imm;"})
+ {"code" : "DestReg = merge(DestReg, imm, dataSize);"})
header_output += MicroLimmOpDeclare.subst(iop)
decoder_output += MicroLimmOpConstructor.subst(iop)
decoder_output += MicroLimmOpDisassembly.subst(iop)
diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc
index 09962fdb6..6d30e53e3 100644
--- a/src/arch/x86/process.cc
+++ b/src/arch/x86/process.cc
@@ -122,9 +122,10 @@ X86LiveProcess::X86LiveProcess(const std::string &nm, ObjectFile *objFile,
// Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
- // Set up stack. On SPARC Linux, stack goes from the top of memory
- // downward, less the hole for the kernel address space.
- stack_base = (Addr)0x80000000000ULL;
+ // Set up stack. On X86_64 Linux, stack goes from the top of memory
+ // downward, less the hole for the kernel address space plus one page
+ // for undertermined purposes.
+ stack_base = (Addr)0x7FFFFFFFF000ULL;
// Set up region for mmaps. Tru64 seems to start just above 0 and
// grow up from there.
@@ -165,29 +166,49 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
else
filename = argv[0];
- Addr alignmentMask = ~(intSize - 1);
+ //We want 16 byte alignment
+ Addr alignmentMask = ~mask(4);
// load object file into target memory
objFile->loadSections(initVirtMem);
- //These are the auxilliary vector types
- enum auxTypes
- {
- X86_AT_NULL = 0,
- X86_AT_IGNORE = 1,
- X86_AT_EXECFD = 2,
- X86_AT_PHDR = 3,
- X86_AT_PHENT = 4,
- X86_AT_PHNUM = 5,
- X86_AT_PAGESZ = 6,
- X86_AT_BASE = 7,
- X86_AT_FLAGS = 8,
- X86_AT_ENTRY = 9,
- X86_AT_NOTELF = 10,
- X86_AT_UID = 11,
- X86_AT_EUID = 12,
- X86_AT_GID = 13,
- X86_AT_EGID = 14
+ enum X86CpuFeature {
+ X86_OnboardFPU = 1 << 0,
+ X86_VirtualModeExtensions = 1 << 1,
+ X86_DebuggingExtensions = 1 << 2,
+ X86_PageSizeExtensions = 1 << 3,
+
+ X86_TimeStampCounter = 1 << 4,
+ X86_ModelSpecificRegisters = 1 << 5,
+ X86_PhysicalAddressExtensions = 1 << 6,
+ X86_MachineCheckExtensions = 1 << 7,
+
+ X86_CMPXCHG8Instruction = 1 << 8,
+ X86_OnboardAPIC = 1 << 9,
+ X86_SYSENTER_SYSEXIT = 1 << 11,
+
+ X86_MemoryTypeRangeRegisters = 1 << 12,
+ X86_PageGlobalEnable = 1 << 13,
+ X86_MachineCheckArchitecture = 1 << 14,
+ X86_CMOVInstruction = 1 << 15,
+
+ X86_PageAttributeTable = 1 << 16,
+ X86_36BitPSEs = 1 << 17,
+ X86_ProcessorSerialNumber = 1 << 18,
+ X86_CLFLUSHInstruction = 1 << 19,
+
+ X86_DebugTraceStore = 1 << 21,
+ X86_ACPIViaMSR = 1 << 22,
+ X86_MultimediaExtensions = 1 << 23,
+
+ X86_FXSAVE_FXRSTOR = 1 << 24,
+ X86_StreamingSIMDExtensions = 1 << 25,
+ X86_StreamingSIMDExtensions2 = 1 << 26,
+ X86_CPUSelfSnoop = 1 << 27,
+
+ X86_HyperThreading = 1 << 28,
+ X86_AutomaticClockControl = 1 << 29,
+ X86_IA64Processor = 1 << 30
};
//Setup the auxilliary vectors. These will already have endian conversion.
@@ -195,36 +216,71 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
if(elfObject)
{
- /*
+ uint64_t features =
+ X86_OnboardFPU |
+ X86_VirtualModeExtensions |
+ X86_DebuggingExtensions |
+ X86_PageSizeExtensions |
+ X86_TimeStampCounter |
+ X86_ModelSpecificRegisters |
+ X86_PhysicalAddressExtensions |
+ X86_MachineCheckExtensions |
+ X86_CMPXCHG8Instruction |
+ X86_OnboardAPIC |
+ X86_SYSENTER_SYSEXIT |
+ X86_MemoryTypeRangeRegisters |
+ X86_PageGlobalEnable |
+ X86_MachineCheckArchitecture |
+ X86_CMOVInstruction |
+ X86_PageAttributeTable |
+ X86_36BitPSEs |
+// X86_ProcessorSerialNumber |
+ X86_CLFLUSHInstruction |
+// X86_DebugTraceStore |
+// X86_ACPIViaMSR |
+ X86_MultimediaExtensions |
+ X86_FXSAVE_FXRSTOR |
+ X86_StreamingSIMDExtensions |
+ X86_StreamingSIMDExtensions2 |
+// X86_CPUSelfSnoop |
+// X86_HyperThreading |
+// X86_AutomaticClockControl |
+// X86_IA64Processor |
+ 0;
+
//Bits which describe the system hardware capabilities
- auxv.push_back(auxv_t(SPARC_AT_HWCAP, hwcap));
+ //XXX Figure out what these should be
+ auxv.push_back(auxv_t(M5_AT_HWCAP, features));
//The system page size
- auxv.push_back(auxv_t(SPARC_AT_PAGESZ, SparcISA::VMPageSize));
- //Defined to be 100 in the kernel source.
+ auxv.push_back(auxv_t(M5_AT_PAGESZ, X86ISA::VMPageSize));
//Frequency at which times() increments
- auxv.push_back(auxv_t(SPARC_AT_CLKTCK, 100));
+ auxv.push_back(auxv_t(M5_AT_CLKTCK, 100));
// For statically linked executables, this is the virtual address of the
// program header tables if they appear in the executable image
- auxv.push_back(auxv_t(SPARC_AT_PHDR, elfObject->programHeaderTable()));
+ auxv.push_back(auxv_t(M5_AT_PHDR, elfObject->programHeaderTable()));
// This is the size of a program header entry from the elf file.
- auxv.push_back(auxv_t(SPARC_AT_PHENT, elfObject->programHeaderSize()));
+ auxv.push_back(auxv_t(M5_AT_PHENT, elfObject->programHeaderSize()));
// This is the number of program headers from the original elf file.
- auxv.push_back(auxv_t(SPARC_AT_PHNUM, elfObject->programHeaderCount()));
+ auxv.push_back(auxv_t(M5_AT_PHNUM, elfObject->programHeaderCount()));
+ //Defined to be 100 in the kernel source.
//This is the address of the elf "interpreter", It should be set
//to 0 for regular executables. It should be something else
//(not sure what) for dynamic libraries.
- auxv.push_back(auxv_t(SPARC_AT_BASE, 0));
- //This is hardwired to 0 in the elf loading code in the kernel
- auxv.push_back(auxv_t(SPARC_AT_FLAGS, 0));
+ auxv.push_back(auxv_t(M5_AT_BASE, 0));
+
+ //XXX Figure out what this should be.
+ auxv.push_back(auxv_t(M5_AT_FLAGS, 0));
//The entry point to the program
- auxv.push_back(auxv_t(SPARC_AT_ENTRY, objFile->entryPoint()));
+ auxv.push_back(auxv_t(M5_AT_ENTRY, objFile->entryPoint()));
//Different user and group IDs
- auxv.push_back(auxv_t(SPARC_AT_UID, uid()));
- auxv.push_back(auxv_t(SPARC_AT_EUID, euid()));
- auxv.push_back(auxv_t(SPARC_AT_GID, gid()));
- auxv.push_back(auxv_t(SPARC_AT_EGID, egid()));
+ auxv.push_back(auxv_t(M5_AT_UID, uid()));
+ auxv.push_back(auxv_t(M5_AT_EUID, euid()));
+ auxv.push_back(auxv_t(M5_AT_GID, gid()));
+ auxv.push_back(auxv_t(M5_AT_EGID, egid()));
//Whether to enable "secure mode" in the executable
- auxv.push_back(auxv_t(SPARC_AT_SECURE, 0));*/
+ auxv.push_back(auxv_t(M5_AT_SECURE, 0));
+ //The string "x86_64" with unknown meaning
+ auxv.push_back(auxv_t(M5_AT_PLATFORM, 0));
}
//Figure out how big the initial stack needs to be
@@ -234,29 +290,39 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
//This is the name of the file which is present on the initial stack
//It's purpose is to let the user space linker examine the original file.
- int file_name_size = filename.size() + 1;
+ int file_name_size = filename.size();
+
+ string platform = "x86_64";
+ int aux_data_size = platform.size() + 1;
int env_data_size = 0;
for (int i = 0; i < envp.size(); ++i) {
- env_data_size += envp[i].size() + 1;
+ env_data_size += envp[i].size();
}
int arg_data_size = 0;
for (int i = 0; i < argv.size(); ++i) {
- arg_data_size += argv[i].size() + 1;
+ arg_data_size += argv[i].size();
}
+ //The auxiliary vector data needs to be padded so it's size is a multiple
+ //of the alignment mask.
+ int aux_padding =
+ ((aux_data_size + ~alignmentMask) & alignmentMask) - aux_data_size;
+
//The info_block needs to be padded so it's size is a multiple of the
//alignment mask. Also, it appears that there needs to be at least some
//padding, so if the size is already a multiple, we need to increase it
//anyway.
int info_block_size =
- (file_name_size +
+ (mysterious_size +
+ file_name_size +
env_data_size +
arg_data_size +
- intSize) & alignmentMask;
+ ~alignmentMask) & alignmentMask;
int info_block_padding =
info_block_size -
+ mysterious_size -
file_name_size -
env_data_size -
arg_data_size;
@@ -270,8 +336,9 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
int argc_size = intSize;
int space_needed =
- mysterious_size +
info_block_size +
+ aux_data_size +
+ aux_padding +
aux_array_size +
envp_array_size +
argv_array_size +
@@ -290,7 +357,8 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
Addr file_name_base = mysterious_base - file_name_size;
Addr env_data_base = file_name_base - env_data_size;
Addr arg_data_base = env_data_base - arg_data_size;
- Addr auxv_array_base = arg_data_base - aux_array_size - info_block_padding;
+ Addr aux_data_base = arg_data_base - aux_data_size - info_block_padding;
+ Addr auxv_array_base = aux_data_base - aux_array_size - aux_padding;
Addr envp_array_base = auxv_array_base - envp_array_size;
Addr argv_array_base = envp_array_base - argv_array_size;
Addr argc_base = argv_array_base - argc_size;
@@ -299,6 +367,7 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
DPRINTF(X86, "0x%x - file name\n", file_name_base);
DPRINTF(X86, "0x%x - env data\n", env_data_base);
DPRINTF(X86, "0x%x - arg data\n", arg_data_base);
+ DPRINTF(X86, "0x%x - aux data\n", aux_data_base);
DPRINTF(X86, "0x%x - auxv array\n", auxv_array_base);
DPRINTF(X86, "0x%x - envp array\n", envp_array_base);
DPRINTF(X86, "0x%x - argv array\n", argv_array_base);
@@ -319,6 +388,10 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
//Write the file name
initVirtMem->writeString(file_name_base, filename.c_str());
+ //Fix up the aux vector which points to the "platform" string
+ assert(auxv[auxv.size() - 1].a_type = M5_AT_PLATFORM);
+ auxv[auxv.size() - 1].a_val = aux_data_base;
+
//Copy the aux stuff
for(int x = 0; x < auxv.size(); x++)
{
@@ -332,15 +405,19 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(),
(uint8_t*)&zero, 2 * intSize);
+ initVirtMem->writeString(aux_data_base, platform.c_str());
+
copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
//Set up the thread context to start running the process
- assert(NumArgumentRegs >= 2);
- threadContexts[0]->setIntReg(ArgumentReg[0], argc);
- threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base);
+ //Because of the peculiarities of how syscall works, I believe
+ //a process starts with r11 containing the value of eflags or maybe r11
+ //from before the call to execve. Empirically this value is 0x200.
+ threadContexts[0]->setIntReg(INTREG_R11, 0x200);
+ //Set the stack pointer register
threadContexts[0]->setIntReg(StackPointerReg, stack_min);
Addr prog_entry = objFile->entryPoint();
diff --git a/src/arch/x86/syscallreturn.hh b/src/arch/x86/syscallreturn.hh
index 6a7fdba58..be9715d21 100644
--- a/src/arch/x86/syscallreturn.hh
+++ b/src/arch/x86/syscallreturn.hh
@@ -67,7 +67,11 @@ namespace X86ISA
static inline void setSyscallReturn(SyscallReturn return_value,
ThreadContext * tc)
{
- tc->setIntReg(INTREG_RAX, return_value.value());
+ if (return_value.successful()) {
+ tc->setIntReg(INTREG_RAX, return_value.value());
+ } else {
+ tc->setIntReg(INTREG_RAX, -return_value.value());
+ }
}
};
diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py
index 6c2aace51..8be84392d 100644
--- a/src/cpu/BaseCPU.py
+++ b/src/cpu/BaseCPU.py
@@ -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
index 000000000..e904f9e7d
--- /dev/null
+++ b/src/cpu/ExeTracer.py
@@ -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
index 000000000..6e8f567b3
--- /dev/null
+++ b/src/cpu/IntelTrace.py
@@ -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
index 000000000..f9b6470a6
--- /dev/null
+++ b/src/cpu/LegionTrace.py
@@ -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
index 000000000..96b4e991b
--- /dev/null
+++ b/src/cpu/NativeTrace.py
@@ -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'
diff --git a/src/cpu/SConscript b/src/cpu/SConscript
index adf47fa4d..b686c0d95 100644
--- a/src/cpu/SConscript
+++ b/src/cpu/SConscript
@@ -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
diff --git a/src/cpu/base.cc b/src/cpu/base.cc
index 3b8d85c9c..ee409048b 100644
--- a/src/cpu/base.cc
+++ b/src/cpu/base.cc
@@ -106,14 +106,10 @@ BaseCPU::BaseCPU(Params *p)
#endif
{
// currentTick = curTick;
- DPRINTF(FullCPU, "BaseCPU: Creating object, mem address %#x.\n", this);
// add self to global list of CPUs
cpuList.push_back(this);
- DPRINTF(FullCPU, "BaseCPU: CPU added to cpuList, mem address %#x.\n",
- this);
-
if (number_of_threads > maxThreadsPerCPU)
maxThreadsPerCPU = number_of_threads;
@@ -188,6 +184,7 @@ BaseCPU::BaseCPU(Params *p)
if (params->profile)
profileEvent = new ProfileEvent(this, params->profile);
#endif
+ tracer = params->tracer;
}
BaseCPU::Params::Params()
@@ -196,6 +193,7 @@ BaseCPU::Params::Params()
profile = false;
#endif
checker = NULL;
+ tracer = NULL;
}
void
diff --git a/src/cpu/base.hh b/src/cpu/base.hh
index 4d8300186..76f6e4684 100644
--- a/src/cpu/base.hh
+++ b/src/cpu/base.hh
@@ -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;
diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc
index 25d41811e..38c22da94 100644
--- a/src/cpu/exetrace.cc
+++ b/src/cpu/exetrace.cc
@@ -31,772 +31,90 @@
* 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);
+};
diff --git a/src/cpu/exetrace.hh b/src/cpu/exetrace.hh
index 8c0fa22cb..76907d955 100644
--- a/src/cpu/exetrace.hh
+++ b/src/cpu/exetrace.hh
@@ -32,141 +32,52 @@
#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
index 000000000..afa51b517
--- /dev/null
+++ b/src/cpu/inteltrace.cc
@@ -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
index 000000000..21afe0fc0
--- /dev/null
+++ b/src/cpu/inteltrace.hh
@@ -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
index 000000000..58181cb88
--- /dev/null
+++ b/src/cpu/legiontrace.cc
@@ -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
index 000000000..55c05e7ae
--- /dev/null
+++ b/src/cpu/legiontrace.hh
@@ -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
index 000000000..90a0e1a62
--- /dev/null
+++ b/src/cpu/nativetrace.cc
@@ -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("rcx", INTREG_RCX, sizeof(uint64_t));
+ checkIntReg("rdx", INTREG_RDX, sizeof(uint64_t));
+ checkIntReg("rbx", INTREG_RBX, 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
index 000000000..48395792d
--- /dev/null
+++ b/src/cpu/nativetrace.hh
@@ -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__
diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh
index aa0c69ac4..ab411c7fe 100644
--- a/src/cpu/o3/fetch_impl.hh
+++ b/src/cpu/o3/fetch_impl.hh
@@ -1150,9 +1150,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
diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc
index b830cbf3a..604c48086 100644
--- a/src/cpu/simple/atomic.cc
+++ b/src/cpu/simple/atomic.cc
@@ -570,6 +570,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;
diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc
index 4359ebebf..d2dd52b64 100644
--- a/src/cpu/simple/base.cc
+++ b/src/cpu/simple/base.cc
@@ -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",
diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc
index b1cb80949..a70ca7c75 100644
--- a/src/cpu/simple/timing.cc
+++ b/src/cpu/simple/timing.cc
@@ -725,6 +725,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
index 000000000..f7500f1e8
--- /dev/null
+++ b/src/sim/InstTracer.py
@@ -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
diff --git a/src/sim/SConscript b/src/sim/SConscript
index 455e5678a..6bd53e205 100644
--- a/src/sim/SConscript
+++ b/src/sim/SConscript
@@ -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
index 000000000..ebeae1fe9
--- /dev/null
+++ b/src/sim/insttracer.hh
@@ -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__
diff --git a/src/sim/process.hh b/src/sim/process.hh
index fa46b9c95..8c702da60 100644
--- a/src/sim/process.hh
+++ b/src/sim/process.hh
@@ -214,6 +214,32 @@ class LiveProcess : public Process
public:
+ enum AuxiliaryVectorType {
+ M5_AT_NULL = 0,
+ M5_AT_IGNORE = 1,
+ M5_AT_EXECFD = 2,
+ M5_AT_PHDR = 3,
+ M5_AT_PHENT = 4,
+ M5_AT_PHNUM = 5,
+ M5_AT_PAGESZ = 6,
+ M5_AT_BASE = 7,
+ M5_AT_FLAGS = 8,
+ M5_AT_ENTRY = 9,
+ M5_AT_NOTELF = 10,
+ M5_AT_UID = 11,
+ M5_AT_EUID = 12,
+ M5_AT_GID = 13,
+ M5_AT_EGID = 14,
+ // The following may be specific to Linux
+ M5_AT_PLATFORM = 15,
+ M5_AT_HWCAP = 16,
+ M5_AT_CLKTCK = 17,
+
+ M5_AT_SECURE = 23,
+
+ M5_AT_VECTOR_SIZE = 44
+ };
+
inline uint64_t uid() {return __uid;}
inline uint64_t euid() {return __euid;}
inline uint64_t gid() {return __gid;}
diff --git a/util/statetrace/arch/tracechild_amd64.cc b/util/statetrace/arch/tracechild_amd64.cc
new file mode 100644
index 000000000..088e547e4
--- /dev/null
+++ b/util/statetrace/arch/tracechild_amd64.cc
@@ -0,0 +1,322 @@
+/*
+ * 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
+ */
+
+#include <iostream>
+#include <iomanip>
+#include <errno.h>
+#include <sys/ptrace.h>
+#include <stdint.h>
+
+#include "tracechild_amd64.hh"
+
+using namespace std;
+
+char * AMD64TraceChild::regNames[numregs] = {
+ //GPRs
+ "rax", "rbx", "rcx", "rdx",
+ //Index registers
+ "rsi", "rdi",
+ //Base pointer and stack pointer
+ "rbp", "rsp",
+ //New 64 bit mode registers
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ //Segmentation registers
+ "cs", "ds", "es", "fs", "gs", "ss", "fs_base", "gs_base",
+ //PC
+ "rip",
+ //Flags
+ "eflags"};
+
+bool AMD64TraceChild::sendState(int socket)
+{
+ uint64_t regVal = 0;
+ for(int x = 0; x <= R15; x++)
+ {
+ regVal = getRegVal(x);
+ if(write(socket, &regVal, sizeof(regVal)) == -1)
+ {
+ cerr << "Write failed! " << strerror(errno) << endl;
+ tracing = false;
+ return false;
+ }
+ }
+ regVal = getRegVal(RIP);
+ if(write(socket, &regVal, sizeof(regVal)) == -1)
+ {
+ cerr << "Write failed! " << strerror(errno) << endl;
+ tracing = false;
+ return false;
+ }
+ return true;
+}
+
+int64_t AMD64TraceChild::getRegs(user_regs_struct & myregs, int num)
+{
+ assert(num < numregs && num >= 0);
+ switch(num)
+ {
+ //GPRs
+ case RAX: return myregs.rax;
+ case RBX: return myregs.rbx;
+ case RCX: return myregs.rcx;
+ case RDX: return myregs.rdx;
+ //Index registers
+ case RSI: return myregs.rsi;
+ case RDI: return myregs.rdi;
+ //Base pointer and stack pointer
+ case RBP: return myregs.rbp;
+ case RSP: return myregs.rsp;
+ //New 64 bit mode registers
+ case R8: return myregs.r8;
+ case R9: return myregs.r9;
+ case R10: return myregs.r10;
+ case R11: return myregs.r11;
+ case R12: return myregs.r12;
+ case R13: return myregs.r13;
+ case R14: return myregs.r14;
+ case R15: return myregs.r15;
+ //Segmentation registers
+ case CS: return myregs.cs;
+ case DS: return myregs.ds;
+ case ES: return myregs.es;
+ case FS: return myregs.fs;
+ case GS: return myregs.gs;
+ case SS: return myregs.ss;
+ case FS_BASE: return myregs.fs_base;
+ case GS_BASE: return myregs.gs_base;
+ //PC
+ case RIP: return myregs.rip;
+ //Flags
+ case EFLAGS: return myregs.eflags;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+bool AMD64TraceChild::update(int pid)
+{
+ oldregs = regs;
+ if(ptrace(PTRACE_GETREGS, pid, 0, &regs) != 0)
+ {
+ cerr << "update: " << strerror(errno) << endl;
+ return false;
+ }
+ for(unsigned int x = 0; x < numregs; x++)
+ regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
+ return true;
+}
+
+AMD64TraceChild::AMD64TraceChild()
+{
+ for(unsigned int x = 0; x < numregs; x++)
+ regDiffSinceUpdate[x] = false;
+}
+
+int64_t AMD64TraceChild::getRegVal(int num)
+{
+ return getRegs(regs, num);
+}
+
+int64_t AMD64TraceChild::getOldRegVal(int num)
+{
+ return getRegs(oldregs, num);
+}
+
+char * AMD64TraceChild::printReg(int num)
+{
+ sprintf(printBuffer, "0x%08X", getRegVal(num));
+ return printBuffer;
+}
+
+ostream & AMD64TraceChild::outputStartState(ostream & os)
+{
+ uint64_t sp = getSP();
+ uint64_t pc = getPC();
+ char obuf[1024];
+ sprintf(obuf, "Initial stack pointer = 0x%016llx\n", sp);
+ os << obuf;
+ sprintf(obuf, "Initial program counter = 0x%016llx\n", pc);
+ os << obuf;
+
+ //Output the argument count
+ uint64_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ sprintf(obuf, "0x%016llx: Argc = 0x%016llx\n", sp, cargc);
+ os << obuf;
+ sp += 8;
+
+ //Output argv pointers
+ int argCount = 0;
+ uint64_t cargv;
+ do
+ {
+ cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ sprintf(obuf, "0x%016llx: argv[%d] = 0x%016llx\n",
+ sp, argCount++, cargv);
+ os << obuf;
+ sp += 8;
+ } while(cargv);
+
+ //Output the envp pointers
+ int envCount = 0;
+ uint64_t cenvp;
+ do
+ {
+ cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ sprintf(obuf, "0x%016llx: envp[%d] = 0x%016llx\n",
+ sp, envCount++, cenvp);
+ os << obuf;
+ sp += 8;
+ } while(cenvp);
+ uint64_t auxType, auxVal;
+ do
+ {
+ auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ sp += 8;
+ auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ sp += 8;
+ sprintf(obuf, "0x%016llx: Auxiliary vector = {0x%016llx, 0x%016llx}\n",
+ sp - 16, auxType, auxVal);
+ os << obuf;
+ } while(auxType != 0 || auxVal != 0);
+ //Print out the argument strings, environment strings, and file name.
+ string current;
+ uint64_t buf;
+ uint64_t currentStart = sp;
+ bool clearedInitialPadding = false;
+ do
+ {
+ buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
+ char * cbuf = (char *)&buf;
+ for(int x = 0; x < sizeof(uint64_t); x++)
+ {
+ if(cbuf[x])
+ current += cbuf[x];
+ else
+ {
+ sprintf(obuf, "0x%016llx: \"%s\"\n",
+ currentStart, current.c_str());
+ os << obuf;
+ current = "";
+ currentStart = sp + x + 1;
+ }
+ }
+ sp += 8;
+ clearedInitialPadding = clearedInitialPadding || buf != 0;
+ } while(!clearedInitialPadding || buf != 0);
+ return os;
+}
+
+uint64_t AMD64TraceChild::findSyscall()
+{
+ uint64_t rip = getPC();
+ bool foundOpcode = false;
+ bool twoByteOpcode = false;
+ for(;;)
+ {
+ uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, rip, 0);
+ for(int i = 0; i < sizeof(uint64_t); i++)
+ {
+ unsigned char byte = buf & 0xFF;
+ if(!foundOpcode)
+ {
+ if(!(byte == 0x66 || //operand override
+ byte == 0x67 || //address override
+ byte == 0x2E || //cs
+ byte == 0x3E || //ds
+ byte == 0x26 || //es
+ byte == 0x64 || //fs
+ byte == 0x65 || //gs
+ byte == 0x36 || //ss
+ byte == 0xF0 || //lock
+ byte == 0xF2 || //repe
+ byte == 0xF3 || //repne
+ (byte >= 0x40 && byte <= 0x4F) // REX
+ ))
+ {
+ foundOpcode = true;
+ }
+ }
+ if(foundOpcode)
+ {
+ if(twoByteOpcode)
+ {
+ //SYSCALL or SYSENTER
+ if(byte == 0x05 || byte == 0x34)
+ return rip + 1;
+ else
+ return 0;
+ }
+ if(!twoByteOpcode)
+ {
+ if(byte == 0xCC) // INT3
+ return rip + 1;
+ else if(byte == 0xCD) // INT with byte immediate
+ return rip + 2;
+ else if(byte == 0x0F) // two byte opcode prefix
+ twoByteOpcode = true;
+ else
+ return 0;
+ }
+ }
+ buf >>= 8;
+ rip++;
+ }
+ }
+}
+
+bool AMD64TraceChild::step()
+{
+ uint64_t ripAfterSyscall = findSyscall();
+ if(ripAfterSyscall)
+ {
+ //Get the original contents of memory
+ uint64_t buf = ptrace(PTRACE_PEEKDATA, pid, ripAfterSyscall, 0);
+ //Patch the first two bytes of the memory immediately after this with
+ //jmp -2. Either single stepping will take over before this
+ //instruction, leaving the rip where it should be, or it will take
+ //over after this instruction, -still- leaving the rip where it should
+ //be.
+ uint64_t newBuf = (buf & ~0xFFFF) | 0xFEEB;
+ //Write the patched memory to the processes address space
+ ptrace(PTRACE_POKEDATA, pid, ripAfterSyscall, newBuf);
+ //Step and hit it
+ ptraceSingleStep();
+ //Put things back to the way they started
+ ptrace(PTRACE_POKEDATA, pid, ripAfterSyscall, buf);
+ }
+ else
+ ptraceSingleStep();
+}
+
+TraceChild * genTraceChild()
+{
+ return new AMD64TraceChild;
+}
diff --git a/util/statetrace/arch/tracechild_amd64.hh b/util/statetrace/arch/tracechild_amd64.hh
new file mode 100644
index 000000000..e7457f677
--- /dev/null
+++ b/util/statetrace/arch/tracechild_amd64.hh
@@ -0,0 +1,110 @@
+/*
+ * 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
+ */
+
+#ifndef REGSTATE_AMD64_HH
+#define REGSTATE_AMD64_HH
+
+#include <sys/user.h>
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <assert.h>
+#include <string>
+
+#include "tracechild.hh"
+
+class AMD64TraceChild : public TraceChild
+{
+ public:
+ enum RegNum
+ {
+ //GPRs
+ RAX, RCX, RDX, RBX,
+ //Base pointer and stack pointer
+ RSP, RBP,
+ //Index registers
+ RSI, RDI,
+ //New 64 bit mode registers
+ R8, R9, R10, R11, R12, R13, R14, R15,
+ //Segmentation registers
+ CS, DS, ES, FS, GS, SS, FS_BASE, GS_BASE,
+ //PC
+ RIP,
+ //Flags
+ EFLAGS,
+ numregs
+ };
+ private:
+ char printBuffer [256];
+ static char * regNames[numregs];
+ int64_t getRegs(user_regs_struct & myregs, int num);
+ user_regs_struct regs;
+ user_regs_struct oldregs;
+ bool regDiffSinceUpdate[numregs];
+
+ uint64_t findSyscall();
+
+ protected:
+ bool update(int pid);
+
+ public:
+
+ AMD64TraceChild();
+
+ bool sendState(int socket);
+
+ int getNumRegs()
+ {
+ return numregs;
+ }
+
+ bool diffSinceUpdate(int num)
+ {
+ assert(num < numregs && num >= 0);
+ return regDiffSinceUpdate[num];
+ }
+
+ std::string getRegName(int num)
+ {
+ assert(num < numregs && num >= 0);
+ return regNames[num];
+ }
+
+ int64_t getRegVal(int num);
+ int64_t getOldRegVal(int num);
+ uint64_t getPC() {return getRegVal(RIP);}
+ uint64_t getSP() {return getRegVal(RSP);}
+ std::ostream & outputStartState(std::ostream & output);
+
+ char * printReg(int num);
+
+ bool step();
+};
+
+#endif
diff --git a/util/statetrace/printer.cc b/util/statetrace/printer.cc
index b14671f2c..178972ea8 100644
--- a/util/statetrace/printer.cc
+++ b/util/statetrace/printer.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 The Regents of The University of Michigan
+ * Copyright (c) 2006-2007 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -181,7 +181,10 @@ bool NestingPrinter::configure(string config)
lastEndPos = endPos;
constStrings.push_back(prefix);
string subConfig, subString;
- int commaPos, lastCommaPos, childSwitchVar;
+ long int commaPos, lastCommaPos, childSwitchVar;
+ //Set up the register printer
+ RegPrinter * regPrinter = new RegPrinter(child);
+ NestingPrinter * nestingPrinter = new NestingPrinter(child);
switch(type)
{
//If we found a plain register printer
@@ -189,8 +192,6 @@ bool NestingPrinter::configure(string config)
numPrinters++;
//Get the register name
subConfig = config.substr(startPos + 2, endPos - startPos - 2);
- //Set up the register printer
- RegPrinter * regPrinter = new RegPrinter(child);
if(!regPrinter->configure(subConfig))
{
delete regPrinter;
@@ -203,7 +204,6 @@ bool NestingPrinter::configure(string config)
case PRINTER_NESTING:
numPrinters++;
//Punt on reading in all the parameters of the nesting printer
- NestingPrinter * nestingPrinter = new NestingPrinter(child);
subConfig = config.substr(startPos + 2, endPos - startPos - 2);
lastCommaPos = string::npos;
commaPos = subConfig.find(",");
diff --git a/util/statetrace/statetrace.cc b/util/statetrace/statetrace.cc
index 4fe47dc02..5f7224b25 100644
--- a/util/statetrace/statetrace.cc
+++ b/util/statetrace/statetrace.cc
@@ -49,115 +49,115 @@ using namespace std;
void printUsage(const char * execName)
{
- cout << execName << " -h | -r -- <command> <arguments>" << endl;
+ cout << execName << " -h | -r -- <command> <arguments>" << endl;
}
int main(int argc, char * argv[], char * envp[])
{
- TraceChild * child = genTraceChild();
- string args;
- int startProgramArgs;
+ TraceChild * child = genTraceChild();
+ string args;
+ int startProgramArgs;
- //Parse the command line arguments
- bool printInitial = false;
- bool printTrace = true;
- for(int x = 1; x < argc; x++)
+ //Parse the command line arguments
+ bool printInitial = false;
+ bool printTrace = true;
+ for(int x = 1; x < argc; x++)
+ {
+ if(!strcmp(argv[x], "-h"))
{
- if(!strcmp(argv[x], "-h"))
- {
- printUsage(argv[0]);
- return 0;
- }
- else if(!strcmp(argv[x], "-r"))
- {
- cout << "Legal register names:" << endl;
- int numRegs = child->getNumRegs();
- for(unsigned int x = 0; x < numRegs; x++)
- {
- cout << "\t" << child->getRegName(x) << endl;
- }
- return 0;
- }
- else if(!strcmp(argv[x], "-i"))
- {
- printInitial = true;
- }
- else if(!strcmp(argv[x], "-nt"))
- {
- printTrace = false;
- }
- else if(!strcmp(argv[x], "--"))
- {
- x++;
- if(x >= argc)
- {
- cerr << "Incorrect usage.\n" << endl;
- printUsage(argv[0]);
- return 1;
- }
- startProgramArgs = x;
- break;
- }
- else
- {
- cerr << "Incorrect usage.\n" << endl;
- printUsage(argv[0]);
- return 1;
- }
+ printUsage(argv[0]);
+ return 0;
}
- if(!child->startTracing(argv[startProgramArgs],
- argv + startProgramArgs))
+ else if(!strcmp(argv[x], "-r"))
{
- cerr << "Couldn't start target program" << endl;
- return 1;
+ cout << "Legal register names:" << endl;
+ int numRegs = child->getNumRegs();
+ for(unsigned int x = 0; x < numRegs; x++)
+ {
+ cout << "\t" << child->getRegName(x) << endl;
+ }
+ return 0;
}
- if(printInitial)
+ else if(!strcmp(argv[x], "-i"))
{
- child->outputStartState(cout);
+ printInitial = true;
}
- if(printTrace)
+ else if(!strcmp(argv[x], "-nt"))
{
- // Connect to m5
- bool portSet = false;
- int port;
- int sock = socket(AF_INET, SOCK_STREAM, 0);
- if(sock < 0)
- {
- cerr << "Error opening socket! " << strerror(errno) << endl;
- return 1;
- }
- struct hostent *server;
- server = gethostbyname("zower.eecs.umich.edu");
- if(!server)
- {
- cerr << "Couldn't get host ip! " << strerror(errno) << endl;
- return 1;
- }
- struct sockaddr_in serv_addr;
- bzero((char *)&serv_addr, sizeof(serv_addr));
- serv_addr.sin_family = AF_INET;
- bcopy((char *)server->h_addr,
- (char *)&serv_addr.sin_addr.s_addr,
- server->h_length);
- serv_addr.sin_port = htons(8000);
- if(connect(sock, (sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
+ printTrace = false;
+ }
+ else if(!strcmp(argv[x], "--"))
+ {
+ x++;
+ if(x >= argc)
{
- cerr << "Couldn't connect to server! " << strerror(errno) << endl;
+ cerr << "Incorrect usage.\n" << endl;
+ printUsage(argv[0]);
return 1;
}
- child->step();
- while(child->isTracing())
- {
- if(!child->sendState(sock))
- break;
- child->step();
- }
+ startProgramArgs = x;
+ break;
}
- if(!child->stopTracing())
+ else
{
- cerr << "Couldn't stop child" << endl;
- return 1;
+ cerr << "Incorrect usage.\n" << endl;
+ printUsage(argv[0]);
+ return 1;
+ }
+ }
+ if(!child->startTracing(argv[startProgramArgs],
+ argv + startProgramArgs))
+ {
+ cerr << "Couldn't start target program" << endl;
+ return 1;
+ }
+ if(printInitial)
+ {
+ child->outputStartState(cout);
+ }
+ if(printTrace)
+ {
+ // Connect to m5
+ bool portSet = false;
+ int port;
+ int sock = socket(AF_INET, SOCK_STREAM, 0);
+ if(sock < 0)
+ {
+ cerr << "Error opening socket! " << strerror(errno) << endl;
+ return 1;
+ }
+ struct hostent *server;
+ server = gethostbyname("localhost");
+ if(!server)
+ {
+ cerr << "Couldn't get host ip! " << strerror(errno) << endl;
+ return 1;
+ }
+ struct sockaddr_in serv_addr;
+ bzero((char *)&serv_addr, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ bcopy((char *)server->h_addr,
+ (char *)&serv_addr.sin_addr.s_addr,
+ server->h_length);
+ serv_addr.sin_port = htons(8000);
+ if(connect(sock, (sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
+ {
+ cerr << "Couldn't connect to server! " << strerror(errno) << endl;
+ return 1;
+ }
+ child->step();
+ while(child->isTracing())
+ {
+ if(!child->sendState(sock))
+ break;
+ child->step();
}
- return 0;
+ }
+ if(!child->stopTracing())
+ {
+ cerr << "Couldn't stop child" << endl;
+ return 1;
+ }
+ return 0;
}
diff --git a/util/statetrace/tracechild_arch.cc b/util/statetrace/tracechild_arch.cc
index 603ccb12c..570a12b54 100644
--- a/util/statetrace/tracechild_arch.cc
+++ b/util/statetrace/tracechild_arch.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 The Regents of The University of Michigan
+ * Copyright (c) 2006-2007 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,8 @@
#if defined __alpha__
#error "Alpha architecture not implemented"
#elif defined __amd64__
- #error "AMD64 architecture not implemented"
+// #error "AMD64 architecture not implemented"
+ #include "arch/tracechild_amd64.cc"
#elif defined __hppa__
#error "Hppa architecture not implemented"
#elif defined __i386__ || defined __i486__ || \
diff --git a/util/style.py b/util/style.py
index 7238b9801..3d7336388 100644
--- a/util/style.py
+++ b/util/style.py
@@ -306,7 +306,7 @@ def check_whitespace(ui, repo, hooktype, node, parent1, parent2):
lines = mdiff.splitnewlines(file_data)
mod_lines = modified_lines(pctx[0].data(), file_data, len(lines))
if len(pctx) == 2:
- m2 = modified_lines(pctx[1].data(), file_data)
+ m2 = modified_lines(pctx[1].data(), file_data, len(lines))
mod_lines = mod_lines & m2 # only the lines that are new in both
fixonly = set()