exetrace.cc revision 3949:b6664282d899
114205Sandreas.sandberg@arm.com/*
214205Sandreas.sandberg@arm.com * Copyright (c) 2001-2005 The Regents of The University of Michigan
314205Sandreas.sandberg@arm.com * All rights reserved.
414205Sandreas.sandberg@arm.com *
514205Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without
614205Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are
714205Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright
814205Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer;
914205Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright
1014205Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the
1114205Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution;
1214205Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its
1314205Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from
1414205Sandreas.sandberg@arm.com * this software without specific prior written permission.
1514205Sandreas.sandberg@arm.com *
1614205Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1714205Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1814205Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1914205Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2014205Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2114205Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2214205Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2314205Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2414205Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2514205Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2614205Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2714205Sandreas.sandberg@arm.com *
2814205Sandreas.sandberg@arm.com * Authors: Steve Reinhardt
2914205Sandreas.sandberg@arm.com *          Lisa Hsu
3014205Sandreas.sandberg@arm.com *          Nathan Binkert
3114205Sandreas.sandberg@arm.com *          Steve Raasch
3214205Sandreas.sandberg@arm.com */
3314205Sandreas.sandberg@arm.com
3414205Sandreas.sandberg@arm.com#include <fstream>
3514205Sandreas.sandberg@arm.com#include <iomanip>
3614205Sandreas.sandberg@arm.com#include <sys/ipc.h>
3714205Sandreas.sandberg@arm.com#include <sys/shm.h>
3814205Sandreas.sandberg@arm.com
3914205Sandreas.sandberg@arm.com#include "arch/regfile.hh"
4014205Sandreas.sandberg@arm.com#include "arch/utility.hh"
4114205Sandreas.sandberg@arm.com#include "base/loader/symtab.hh"
4214205Sandreas.sandberg@arm.com#include "config/full_system.hh"
4314205Sandreas.sandberg@arm.com#include "cpu/base.hh"
4414205Sandreas.sandberg@arm.com#include "cpu/exetrace.hh"
4514205Sandreas.sandberg@arm.com#include "cpu/static_inst.hh"
4614205Sandreas.sandberg@arm.com#include "sim/param.hh"
4714205Sandreas.sandberg@arm.com#include "sim/system.hh"
4814205Sandreas.sandberg@arm.com
4914205Sandreas.sandberg@arm.com#if FULL_SYSTEM
5014205Sandreas.sandberg@arm.com#include "arch/tlb.hh"
5114205Sandreas.sandberg@arm.com#endif
5214205Sandreas.sandberg@arm.com
5314205Sandreas.sandberg@arm.com//XXX This is temporary
5414205Sandreas.sandberg@arm.com#include "arch/isa_specific.hh"
5514205Sandreas.sandberg@arm.com#include "cpu/m5legion_interface.h"
5614205Sandreas.sandberg@arm.com
5714205Sandreas.sandberg@arm.comusing namespace std;
5814205Sandreas.sandberg@arm.comusing namespace TheISA;
5914205Sandreas.sandberg@arm.com
6014205Sandreas.sandberg@arm.com#if THE_ISA == SPARC_ISA && FULL_SYSTEM
6114205Sandreas.sandberg@arm.comstatic int diffcount = 0;
6214205Sandreas.sandberg@arm.com#endif
6314205Sandreas.sandberg@arm.com
6414205Sandreas.sandberg@arm.comnamespace Trace {
6514205Sandreas.sandberg@arm.comSharedData *shared_data = NULL;
6614205Sandreas.sandberg@arm.com}
6714205Sandreas.sandberg@arm.com
6814205Sandreas.sandberg@arm.com////////////////////////////////////////////////////////////////////////
6914205Sandreas.sandberg@arm.com//
7014205Sandreas.sandberg@arm.com//  Methods for the InstRecord object
7114205Sandreas.sandberg@arm.com//
7214205Sandreas.sandberg@arm.com
7314205Sandreas.sandberg@arm.com#if THE_ISA == SPARC_ISA
7414205Sandreas.sandberg@arm.com
7514205Sandreas.sandberg@arm.cominline char * genCenteredLabel(int length, char * buffer, char * label)
7614205Sandreas.sandberg@arm.com{
7714205Sandreas.sandberg@arm.com    int labelLength = strlen(label);
7814205Sandreas.sandberg@arm.com    assert(labelLength <= length);
7914205Sandreas.sandberg@arm.com    int leftPad = (length - labelLength) / 2;
8014205Sandreas.sandberg@arm.com    int rightPad = length - leftPad - labelLength;
8114205Sandreas.sandberg@arm.com    char format[64];
8214205Sandreas.sandberg@arm.com    sprintf(format, "%%%ds%%s%%%ds", leftPad, rightPad);
8314205Sandreas.sandberg@arm.com    sprintf(buffer, format, "", label, "");
8414205Sandreas.sandberg@arm.com    return buffer;
8514205Sandreas.sandberg@arm.com}
8614205Sandreas.sandberg@arm.com
8714205Sandreas.sandberg@arm.cominline void printRegPair(ostream & os, char const * title, uint64_t a, uint64_t b)
8814205Sandreas.sandberg@arm.com{
8914205Sandreas.sandberg@arm.com    ccprintf(os, "  %16s  |  %#018x   %s   %#-018x  \n",
9014205Sandreas.sandberg@arm.com            title, a, (a == b) ? "|" : "X", b);
9114205Sandreas.sandberg@arm.com}
9214205Sandreas.sandberg@arm.com
9314205Sandreas.sandberg@arm.cominline void printColumnLabels(ostream & os)
9414205Sandreas.sandberg@arm.com{
9514205Sandreas.sandberg@arm.com    static char * regLabel = genCenteredLabel(16, new char[17], "Register");
9614205Sandreas.sandberg@arm.com    static char * m5Label = genCenteredLabel(18, new char[18], "M5");
9714205Sandreas.sandberg@arm.com    static char * legionLabel = genCenteredLabel(18, new char[18], "Legion");
9814205Sandreas.sandberg@arm.com    ccprintf(os, "  %s  |  %s   |   %s  \n", regLabel, m5Label, legionLabel);
9914205Sandreas.sandberg@arm.com    ccprintf(os, "--------------------+-----------------------+-----------------------\n");
10014205Sandreas.sandberg@arm.com}
10114205Sandreas.sandberg@arm.com
10214205Sandreas.sandberg@arm.cominline void printSectionHeader(ostream & os, char * name)
10314205Sandreas.sandberg@arm.com{
10414205Sandreas.sandberg@arm.com    char sectionString[70];
10514205Sandreas.sandberg@arm.com    genCenteredLabel(69, sectionString, name);
10614205Sandreas.sandberg@arm.com    ccprintf(os, "====================================================================\n");
10714205Sandreas.sandberg@arm.com    ccprintf(os, "%69s\n", sectionString);
10814205Sandreas.sandberg@arm.com    ccprintf(os, "====================================================================\n");
10914205Sandreas.sandberg@arm.com}
11014205Sandreas.sandberg@arm.com
11114205Sandreas.sandberg@arm.cominline void printLevelHeader(ostream & os, int level)
11214205Sandreas.sandberg@arm.com{
11314205Sandreas.sandberg@arm.com    char sectionString[70];
11414205Sandreas.sandberg@arm.com    char levelName[70];
11514205Sandreas.sandberg@arm.com    sprintf(levelName, "Trap stack level %d", level);
11614205Sandreas.sandberg@arm.com    genCenteredLabel(69, sectionString, levelName);
11714205Sandreas.sandberg@arm.com    ccprintf(os, "====================================================================\n");
11814205Sandreas.sandberg@arm.com    ccprintf(os, "%69s\n", sectionString);
11914205Sandreas.sandberg@arm.com    ccprintf(os, "====================================================================\n");
12014205Sandreas.sandberg@arm.com}
12114205Sandreas.sandberg@arm.com
12214205Sandreas.sandberg@arm.com#endif
12314205Sandreas.sandberg@arm.com
12414205Sandreas.sandberg@arm.comvoid
12514205Sandreas.sandberg@arm.comTrace::InstRecord::dump(ostream &outs)
12614205Sandreas.sandberg@arm.com{
12714205Sandreas.sandberg@arm.com    if (flags[PRINT_REG_DELTA])
12814205Sandreas.sandberg@arm.com    {
12914205Sandreas.sandberg@arm.com#if THE_ISA == SPARC_ISA
13014205Sandreas.sandberg@arm.com        //Don't print what happens for each micro-op, just print out
13114205Sandreas.sandberg@arm.com        //once at the last op, and for regular instructions.
13214205Sandreas.sandberg@arm.com        if(!staticInst->isMicroOp() || staticInst->isLastMicroOp())
13314205Sandreas.sandberg@arm.com        {
13414205Sandreas.sandberg@arm.com            static uint64_t regs[32] = {
13514205Sandreas.sandberg@arm.com                0, 0, 0, 0, 0, 0, 0, 0,
13614205Sandreas.sandberg@arm.com                0, 0, 0, 0, 0, 0, 0, 0,
13714205Sandreas.sandberg@arm.com                0, 0, 0, 0, 0, 0, 0, 0,
13814205Sandreas.sandberg@arm.com                0, 0, 0, 0, 0, 0, 0, 0};
13914205Sandreas.sandberg@arm.com            static uint64_t ccr = 0;
14014205Sandreas.sandberg@arm.com            static uint64_t y = 0;
14114205Sandreas.sandberg@arm.com            static uint64_t floats[32];
14214205Sandreas.sandberg@arm.com            uint64_t newVal;
14314205Sandreas.sandberg@arm.com            static const char * prefixes[4] = {"G", "O", "L", "I"};
14414205Sandreas.sandberg@arm.com
14514205Sandreas.sandberg@arm.com            outs << hex;
14614205Sandreas.sandberg@arm.com            outs << "PC = " << thread->readNextPC();
14714205Sandreas.sandberg@arm.com            outs << " NPC = " << thread->readNextNPC();
14814205Sandreas.sandberg@arm.com            newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2);
14914205Sandreas.sandberg@arm.com            //newVal = thread->readMiscReg(SparcISA::MISCREG_CCR);
15014205Sandreas.sandberg@arm.com            if(newVal != ccr)
15114205Sandreas.sandberg@arm.com            {
15214205Sandreas.sandberg@arm.com                outs << " CCR = " << newVal;
15314205Sandreas.sandberg@arm.com                ccr = newVal;
15414205Sandreas.sandberg@arm.com            }
15514205Sandreas.sandberg@arm.com            newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 1);
15614205Sandreas.sandberg@arm.com            //newVal = thread->readMiscReg(SparcISA::MISCREG_Y);
15714205Sandreas.sandberg@arm.com            if(newVal != y)
15814205Sandreas.sandberg@arm.com            {
15914205Sandreas.sandberg@arm.com                outs << " Y = " << newVal;
16014205Sandreas.sandberg@arm.com                y = newVal;
16114205Sandreas.sandberg@arm.com            }
16214205Sandreas.sandberg@arm.com            for(int y = 0; y < 4; y++)
16314205Sandreas.sandberg@arm.com            {
16414205Sandreas.sandberg@arm.com                for(int x = 0; x < 8; x++)
16514205Sandreas.sandberg@arm.com                {
16614205Sandreas.sandberg@arm.com                    int index = x + 8 * y;
16714205Sandreas.sandberg@arm.com                    newVal = thread->readIntReg(index);
16814205Sandreas.sandberg@arm.com                    if(regs[index] != newVal)
16914205Sandreas.sandberg@arm.com                    {
17014205Sandreas.sandberg@arm.com                        outs << " " << prefixes[y] << dec << x << " = " << hex << newVal;
17114205Sandreas.sandberg@arm.com                        regs[index] = newVal;
17214205Sandreas.sandberg@arm.com                    }
17314205Sandreas.sandberg@arm.com                }
17414205Sandreas.sandberg@arm.com            }
17514205Sandreas.sandberg@arm.com            for(int y = 0; y < 32; y++)
176            {
177                newVal = thread->readFloatRegBits(2 * y, 64);
178                if(floats[y] != newVal)
179                {
180                    outs << " F" << dec << (2 * y) << " = " << hex << newVal;
181                    floats[y] = newVal;
182                }
183            }
184            outs << dec << endl;
185        }
186#endif
187    }
188    else if (flags[INTEL_FORMAT]) {
189#if FULL_SYSTEM
190        bool is_trace_system = (thread->getCpuPtr()->system->name() == trace_system);
191#else
192        bool is_trace_system = true;
193#endif
194        if (is_trace_system) {
195            ccprintf(outs, "%7d ) ", cycle);
196            outs << "0x" << hex << PC << ":\t";
197            if (staticInst->isLoad()) {
198                outs << "<RD 0x" << hex << addr;
199                outs << ">";
200            } else if (staticInst->isStore()) {
201                outs << "<WR 0x" << hex << addr;
202                outs << ">";
203            }
204            outs << endl;
205        }
206    } else {
207        if (flags[PRINT_CYCLE])
208            ccprintf(outs, "%7d: ", cycle);
209
210        outs << thread->getCpuPtr()->name() << " ";
211
212        if (flags[TRACE_MISSPEC])
213            outs << (misspeculating ? "-" : "+") << " ";
214
215        if (flags[PRINT_THREAD_NUM])
216            outs << "T" << thread->getThreadNum() << " : ";
217
218
219        std::string sym_str;
220        Addr sym_addr;
221        if (debugSymbolTable
222            && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr)
223            && flags[PC_SYMBOL]) {
224            if (PC != sym_addr)
225                sym_str += csprintf("+%d", PC - sym_addr);
226            outs << "@" << sym_str << " : ";
227        }
228        else {
229            outs << "0x" << hex << PC << " : ";
230        }
231
232        //
233        //  Print decoded instruction
234        //
235
236#if defined(__GNUC__) && (__GNUC__ < 3)
237        // There's a bug in gcc 2.x library that prevents setw()
238        // from working properly on strings
239        string mc(staticInst->disassemble(PC, debugSymbolTable));
240        while (mc.length() < 26)
241            mc += " ";
242        outs << mc;
243#else
244        outs << setw(26) << left << staticInst->disassemble(PC, debugSymbolTable);
245#endif
246
247        outs << " : ";
248
249        if (flags[PRINT_OP_CLASS]) {
250            outs << opClassStrings[staticInst->opClass()] << " : ";
251        }
252
253        if (flags[PRINT_RESULT_DATA] && data_status != DataInvalid) {
254            outs << " D=";
255#if 0
256            if (data_status == DataDouble)
257                ccprintf(outs, "%f", data.as_double);
258            else
259                ccprintf(outs, "%#018x", data.as_int);
260#else
261            ccprintf(outs, "%#018x", data.as_int);
262#endif
263        }
264
265        if (flags[PRINT_EFF_ADDR] && addr_valid)
266            outs << " A=0x" << hex << addr;
267
268        if (flags[PRINT_INT_REGS] && regs_valid) {
269            for (int i = 0; i < TheISA::NumIntRegs;)
270                for (int j = i + 1; i <= j; i++)
271                    ccprintf(outs, "r%02d = %#018x%s", i,
272                            iregs->regs.readReg(i),
273                            ((i == j) ? "\n" : "    "));
274            outs << "\n";
275        }
276
277        if (flags[PRINT_FETCH_SEQ] && fetch_seq_valid)
278            outs << "  FetchSeq=" << dec << fetch_seq;
279
280        if (flags[PRINT_CP_SEQ] && cp_seq_valid)
281            outs << "  CPSeq=" << dec << cp_seq;
282
283        //
284        //  End of line...
285        //
286        outs << endl;
287    }
288#if THE_ISA == SPARC_ISA && FULL_SYSTEM
289    // Compare
290    if (flags[LEGION_LOCKSTEP])
291    {
292        bool compared = false;
293        bool diffPC   = false;
294        bool diffCC   = false;
295        bool diffInst = false;
296        bool diffRegs = false;
297        bool diffTpc = false;
298        bool diffTnpc = false;
299        bool diffTstate = false;
300        bool diffTt = false;
301        bool diffTba = false;
302        bool diffHpstate = false;
303        bool diffHtstate = false;
304        bool diffHtba = false;
305        bool diffPstate = false;
306        bool diffY = false;
307        bool diffCcr = false;
308        bool diffTl = false;
309        bool diffGl = false;
310        bool diffAsi = false;
311        bool diffPil = false;
312        bool diffCwp = false;
313        bool diffCansave = false;
314        bool diffCanrestore = false;
315        bool diffOtherwin = false;
316        bool diffCleanwin = false;
317        Addr m5Pc, lgnPc;
318
319
320        if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) {
321            while (!compared) {
322                if (shared_data->flags == OWN_M5) {
323                    m5Pc = PC & TheISA::PAddrImplMask;
324                    lgnPc = shared_data->pc & TheISA::PAddrImplMask;
325                    if (lgnPc != m5Pc)
326                       diffPC = true;
327
328                    if (shared_data->cycle_count !=
329                            thread->getCpuPtr()->instCount())
330                        diffCC = true;
331
332                    if (shared_data->instruction !=
333                            (SparcISA::MachInst)staticInst->machInst) {
334                        diffInst = true;
335                    }
336                    for (int i = 0; i < TheISA::NumIntArchRegs; i++) {
337                        if (thread->readIntReg(i) != shared_data->intregs[i]) {
338                            diffRegs = true;
339                        }
340                    }
341                    uint64_t oldTl = thread->readMiscReg(MISCREG_TL);
342                    if (oldTl != shared_data->tl)
343                        diffTl = true;
344                    for (int i = 1; i <= MaxTL; i++) {
345                        thread->setMiscReg(MISCREG_TL, i);
346                        if (thread->readMiscReg(MISCREG_TPC) !=
347                                shared_data->tpc[i-1])
348                            diffTpc = true;
349                        if (thread->readMiscReg(MISCREG_TNPC) !=
350                                shared_data->tnpc[i-1])
351                            diffTnpc = true;
352                        if (thread->readMiscReg(MISCREG_TSTATE) !=
353                                shared_data->tstate[i-1])
354                            diffTstate = true;
355                        if (thread->readMiscReg(MISCREG_TT) !=
356                                shared_data->tt[i-1])
357                            diffTt = true;
358                        if (thread->readMiscReg(MISCREG_HTSTATE) !=
359                                shared_data->htstate[i-1])
360                            diffHtstate = true;
361                    }
362                    thread->setMiscReg(MISCREG_TL, oldTl);
363
364                    if(shared_data->tba != thread->readMiscReg(MISCREG_TBA))
365                        diffTba = true;
366                    //When the hpstate register is read by an instruction,
367                    //legion has bit 11 set. When it's in storage, it doesn't.
368                    //Since we don't directly support seperate interpretations
369                    //of the registers like that, the bit is always set to 1 and
370                    //we just don't compare it. It's not supposed to matter
371                    //anyway.
372                    if((shared_data->hpstate | (1 << 11)) != thread->readMiscReg(MISCREG_HPSTATE))
373                        diffHpstate = true;
374                    if(shared_data->htba != thread->readMiscReg(MISCREG_HTBA))
375                        diffHtba = true;
376                    if(shared_data->pstate != thread->readMiscReg(MISCREG_PSTATE))
377                        diffPstate = true;
378                    //if(shared_data->y != thread->readMiscReg(MISCREG_Y))
379                    if(shared_data->y !=
380                            thread->readIntReg(NumIntArchRegs + 1))
381                        diffY = true;
382                    //if(shared_data->ccr != thread->readMiscReg(MISCREG_CCR))
383                    if(shared_data->ccr !=
384                            thread->readIntReg(NumIntArchRegs + 2))
385                        diffCcr = true;
386                    if(shared_data->gl != thread->readMiscReg(MISCREG_GL))
387                        diffGl = true;
388                    if(shared_data->asi != thread->readMiscReg(MISCREG_ASI))
389                        diffAsi = true;
390                    if(shared_data->pil != thread->readMiscReg(MISCREG_PIL))
391                        diffPil = true;
392                    if(shared_data->cwp != thread->readMiscReg(MISCREG_CWP))
393                        diffCwp = true;
394                    //if(shared_data->cansave != thread->readMiscReg(MISCREG_CANSAVE))
395                    if(shared_data->cansave !=
396                            thread->readIntReg(NumIntArchRegs + 3))
397                        diffCansave = true;
398                    //if(shared_data->canrestore !=
399                    //	    thread->readMiscReg(MISCREG_CANRESTORE))
400                    if(shared_data->canrestore !=
401                            thread->readMiscReg(NumIntArchRegs + 4))
402                        diffCanrestore = true;
403                    //if(shared_data->otherwin != thread->readMiscReg(MISCREG_OTHERWIN))
404                    if(shared_data->otherwin !=
405                            thread->readIntReg(NumIntArchRegs + 5))
406                        diffOtherwin = true;
407                    //if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN))
408                    if(shared_data->cleanwin !=
409                            thread->readMiscReg(NumIntArchRegs + 6))
410                        diffCleanwin = true;
411
412                    if ((diffPC || diffCC || diffInst || diffRegs || diffTpc ||
413                            diffTnpc || diffTstate || diffTt || diffHpstate ||
414                            diffHtstate || diffHtba || diffPstate || diffY ||
415                            diffCcr || diffTl || diffGl || diffAsi || diffPil ||
416                            diffCwp || diffCansave || diffCanrestore ||
417                            diffOtherwin || diffCleanwin)
418                        && !((staticInst->machInst & 0xC1F80000) == 0x81D00000)) {
419                        outs << "Differences found between M5 and Legion:";
420                        if (diffPC)
421                            outs << " [PC]";
422                        if (diffCC)
423                            outs << " [CC]";
424                        if (diffInst)
425                            outs << " [Instruction]";
426                        if (diffRegs)
427                            outs << " [IntRegs]";
428                        if (diffTpc)
429                            outs << " [Tpc]";
430                        if (diffTnpc)
431                            outs << " [Tnpc]";
432                        if (diffTstate)
433                            outs << " [Tstate]";
434                        if (diffTt)
435                            outs << " [Tt]";
436                        if (diffHpstate)
437                            outs << " [Hpstate]";
438                        if (diffHtstate)
439                            outs << " [Htstate]";
440                        if (diffHtba)
441                            outs << " [Htba]";
442                        if (diffPstate)
443                            outs << " [Pstate]";
444                        if (diffY)
445                            outs << " [Y]";
446                        if (diffCcr)
447                            outs << " [Ccr]";
448                        if (diffTl)
449                            outs << " [Tl]";
450                        if (diffGl)
451                            outs << " [Gl]";
452                        if (diffAsi)
453                            outs << " [Asi]";
454                        if (diffPil)
455                            outs << " [Pil]";
456                        if (diffCwp)
457                            outs << " [Cwp]";
458                        if (diffCansave)
459                            outs << " [Cansave]";
460                        if (diffCanrestore)
461                            outs << " [Canrestore]";
462                        if (diffOtherwin)
463                            outs << " [Otherwin]";
464                        if (diffCleanwin)
465                            outs << " [Cleanwin]";
466                        outs << endl << endl;
467
468                        outs << right << setfill(' ') << setw(15)
469                             << "M5 PC: " << "0x"<< setw(16) << setfill('0')
470                             << hex << m5Pc << endl;
471                        outs << setfill(' ') << setw(15)
472                             << "Legion PC: " << "0x"<< setw(16) << setfill('0') << hex
473                             << lgnPc << endl << endl;
474
475                        outs << right << setfill(' ') << setw(15)
476                             << "M5 CC: " << "0x"<< setw(16) << setfill('0')
477                             << hex << thread->getCpuPtr()->instCount() << endl;
478                        outs << setfill(' ') << setw(15)
479                             << "Legion CC: " << "0x"<< setw(16) << setfill('0') << hex
480                             << shared_data->cycle_count << endl << endl;
481
482                        outs << setfill(' ') << setw(15)
483                             << "M5 Inst: "  << "0x"<< setw(8)
484                             << setfill('0') << hex << staticInst->machInst
485                             << staticInst->disassemble(m5Pc, debugSymbolTable)
486                             << endl;
487
488                        StaticInstPtr legionInst =
489                            StaticInst::decode(makeExtMI(shared_data->instruction,
490                                        thread));
491                        outs << setfill(' ') << setw(15)
492                             << " Legion Inst: "
493                             << "0x" << setw(8) << setfill('0') << hex
494                             << shared_data->instruction
495                             << legionInst->disassemble(lgnPc, debugSymbolTable)
496                             << endl << endl;
497
498                        printSectionHeader(outs, "General State");
499                        printColumnLabels(outs);
500                        printRegPair(outs, "HPstate",
501                                thread->readMiscReg(MISCREG_HPSTATE),
502                                shared_data->hpstate | (1 << 11));
503                        printRegPair(outs, "Htba",
504                                thread->readMiscReg(MISCREG_HTBA),
505                                shared_data->htba);
506                        printRegPair(outs, "Pstate",
507                                thread->readMiscReg(MISCREG_PSTATE),
508                                shared_data->pstate);
509                        printRegPair(outs, "Y",
510                                //thread->readMiscReg(MISCREG_Y),
511                                thread->readMiscReg(NumIntArchRegs + 1),
512                                shared_data->y);
513                        printRegPair(outs, "Ccr",
514                                //thread->readMiscReg(MISCREG_CCR),
515                                thread->readMiscReg(NumIntArchRegs + 2),
516                                shared_data->ccr);
517                        printRegPair(outs, "Tl",
518                                thread->readMiscReg(MISCREG_TL),
519                                shared_data->tl);
520                        printRegPair(outs, "Gl",
521                                thread->readMiscReg(MISCREG_GL),
522                                shared_data->gl);
523                        printRegPair(outs, "Asi",
524                                thread->readMiscReg(MISCREG_ASI),
525                                shared_data->asi);
526                        printRegPair(outs, "Pil",
527                                thread->readMiscReg(MISCREG_PIL),
528                                shared_data->pil);
529                        printRegPair(outs, "Cwp",
530                                thread->readMiscReg(MISCREG_CWP),
531                                shared_data->cwp);
532                        printRegPair(outs, "Cansave",
533                                //thread->readMiscReg(MISCREG_CANSAVE),
534                                thread->readIntReg(NumIntArchRegs + 3),
535                                shared_data->cansave);
536                        printRegPair(outs, "Canrestore",
537                                //thread->readMiscReg(MISCREG_CANRESTORE),
538                                thread->readIntReg(NumIntArchRegs + 4),
539                                shared_data->canrestore);
540                        printRegPair(outs, "Otherwin",
541                                //thread->readMiscReg(MISCREG_OTHERWIN),
542                                thread->readIntReg(NumIntArchRegs + 5),
543                                shared_data->otherwin);
544                        printRegPair(outs, "Cleanwin",
545                                //thread->readMiscReg(MISCREG_CLEANWIN),
546                                thread->readIntReg(NumIntArchRegs + 6),
547                                shared_data->cleanwin);
548                        outs << endl;
549                        for (int i = 1; i <= MaxTL; i++) {
550                            printLevelHeader(outs, i);
551                            printColumnLabels(outs);
552                            thread->setMiscReg(MISCREG_TL, i);
553                            printRegPair(outs, "Tpc",
554                                    thread->readMiscReg(MISCREG_TPC),
555                                    shared_data->tpc[i-1]);
556                            printRegPair(outs, "Tnpc",
557                                    thread->readMiscReg(MISCREG_TNPC),
558                                    shared_data->tnpc[i-1]);
559                            printRegPair(outs, "Tstate",
560                                    thread->readMiscReg(MISCREG_TSTATE),
561                                    shared_data->tstate[i-1]);
562                            printRegPair(outs, "Tt",
563                                    thread->readMiscReg(MISCREG_TT),
564                                    shared_data->tt[i-1]);
565                            printRegPair(outs, "Htstate",
566                                    thread->readMiscReg(MISCREG_HTSTATE),
567                                    shared_data->htstate[i-1]);
568                        }
569                        thread->setMiscReg(MISCREG_TL, oldTl);
570                        outs << endl;
571
572                        printSectionHeader(outs, "General Purpose Registers");
573                        static const char * regtypes[4] = {"%g", "%o", "%l", "%i"};
574                        for(int y = 0; y < 4; y++)
575                        {
576                            for(int x = 0; x < 8; x++)
577                            {
578                                char label[8];
579                                sprintf(label, "%s%d", regtypes[y], x);
580                                printRegPair(outs, label,
581                                        thread->readIntReg(y*8+x),
582                                        shared_data->intregs[y*8+x]);
583                                /*outs << regtypes[y] << x << "         " ;
584                                outs <<  "0x" << hex << setw(16)
585                                    << thread->readIntReg(y*8+x);
586                                if (thread->readIntReg(y*8 + x)
587                                        != shared_data->intregs[y*8+x])
588                                    outs << "     X     ";
589                                else
590                                    outs << "     |     ";
591                                outs << "0x" << setw(16) << hex
592                                    << shared_data->intregs[y*8+x]
593                                    << endl;*/
594                            }
595                        }
596                        thread->getITBPtr()->dumpAll();
597                        thread->getDTBPtr()->dumpAll();
598
599                        diffcount++;
600                        if (diffcount > 2)
601                            fatal("Differences found between Legion and M5\n");
602                    }
603
604                    compared = true;
605                    shared_data->flags = OWN_LEGION;
606                }
607            } // while
608        } // if not microop
609    }
610#endif
611}
612
613
614vector<bool> Trace::InstRecord::flags(NUM_BITS);
615string Trace::InstRecord::trace_system;
616
617////////////////////////////////////////////////////////////////////////
618//
619// Parameter space for per-cycle execution address tracing options.
620// Derive from ParamContext so we can override checkParams() function.
621//
622class ExecutionTraceParamContext : public ParamContext
623{
624  public:
625    ExecutionTraceParamContext(const string &_iniSection)
626        : ParamContext(_iniSection)
627        {
628        }
629
630    void checkParams();	// defined at bottom of file
631};
632
633ExecutionTraceParamContext exeTraceParams("exetrace");
634
635Param<bool> exe_trace_spec(&exeTraceParams, "speculative",
636                           "capture speculative instructions", true);
637
638Param<bool> exe_trace_print_cycle(&exeTraceParams, "print_cycle",
639                                  "print cycle number", true);
640Param<bool> exe_trace_print_opclass(&exeTraceParams, "print_opclass",
641                                  "print op class", true);
642Param<bool> exe_trace_print_thread(&exeTraceParams, "print_thread",
643                                  "print thread number", true);
644Param<bool> exe_trace_print_effaddr(&exeTraceParams, "print_effaddr",
645                                  "print effective address", true);
646Param<bool> exe_trace_print_data(&exeTraceParams, "print_data",
647                                  "print result data", true);
648Param<bool> exe_trace_print_iregs(&exeTraceParams, "print_iregs",
649                                  "print all integer regs", false);
650Param<bool> exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq",
651                                  "print fetch sequence number", false);
652Param<bool> exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq",
653                                  "print correct-path sequence number", false);
654Param<bool> exe_trace_print_reg_delta(&exeTraceParams, "print_reg_delta",
655                                  "print which registers changed to what", false);
656Param<bool> exe_trace_pc_symbol(&exeTraceParams, "pc_symbol",
657                                  "Use symbols for the PC if available", true);
658Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format",
659                                   "print trace in intel compatible format", false);
660Param<bool> exe_trace_legion_lockstep(&exeTraceParams, "legion_lockstep",
661                                   "Compare sim state to legion state every cycle",
662                                   false);
663Param<string> exe_trace_system(&exeTraceParams, "trace_system",
664                                   "print trace of which system (client or server)",
665                                   "client");
666
667
668//
669// Helper function for ExecutionTraceParamContext::checkParams() just
670// to get us into the InstRecord namespace
671//
672void
673Trace::InstRecord::setParams()
674{
675    flags[TRACE_MISSPEC]     = exe_trace_spec;
676
677    flags[PRINT_CYCLE]       = exe_trace_print_cycle;
678    flags[PRINT_OP_CLASS]    = exe_trace_print_opclass;
679    flags[PRINT_THREAD_NUM]  = exe_trace_print_thread;
680    flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr;
681    flags[PRINT_EFF_ADDR]    = exe_trace_print_data;
682    flags[PRINT_INT_REGS]    = exe_trace_print_iregs;
683    flags[PRINT_FETCH_SEQ]   = exe_trace_print_fetchseq;
684    flags[PRINT_CP_SEQ]      = exe_trace_print_cp_seq;
685    flags[PRINT_REG_DELTA]   = exe_trace_print_reg_delta;
686    flags[PC_SYMBOL]         = exe_trace_pc_symbol;
687    flags[INTEL_FORMAT]      = exe_trace_intel_format;
688    flags[LEGION_LOCKSTEP]   = exe_trace_legion_lockstep;
689    trace_system	     = exe_trace_system;
690
691    // If were going to be in lockstep with Legion
692    // Setup shared memory, and get otherwise ready
693    if (flags[LEGION_LOCKSTEP]) {
694        int shmfd = shmget('M' << 24 | getuid(), sizeof(SharedData), 0777);
695        if (shmfd < 0)
696            fatal("Couldn't get shared memory fd. Is Legion running?");
697
698        shared_data = (SharedData*)shmat(shmfd, NULL, SHM_RND);
699        if (shared_data == (SharedData*)-1)
700            fatal("Couldn't allocate shared memory");
701
702        if (shared_data->flags != OWN_M5)
703            fatal("Shared memory has invalid owner");
704
705        if (shared_data->version != VERSION)
706            fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION,
707                    shared_data->version);
708
709        // step legion forward one cycle so we can get register values
710        shared_data->flags = OWN_LEGION;
711    }
712}
713
714void
715ExecutionTraceParamContext::checkParams()
716{
717    Trace::InstRecord::setParams();
718}
719
720