| /* |
| * 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 <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 "sim/param.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" |
| |
| 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() |
| { |
| 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, ®Val, 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, ®Val, 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, ®Val, 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, ®Val, 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, ®Val, 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(ExecOpClass)) { |
| outs << opClassStrings[staticInst->opClass()] << " : "; |
| } |
| |
| 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(ExecEffAddr) && addr_valid) |
| outs << " A=0x" << hex << addr; |
| |
| 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; |
| } |
| #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; |
| |
| predecoder.setTC(thread); |
| predecoder.moreBytes(m5Pc, 0, shared_data->instruction); |
| |
| assert(predecoder.extMachInstReady()); |
| |
| StaticInstPtr legionInst = |
| StaticInst::decode(predecoder.getExtMachInst()); |
| 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 |
| } |
| #endif |
| } |
| |
| /* namespace Trace */ } |