exetrace.cc revision 3989:6ce62f2fdeb4
1/*
2 * Copyright (c) 2001-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Steve Reinhardt
29 *          Lisa Hsu
30 *          Nathan Binkert
31 *          Steve Raasch
32 */
33
34#include <fstream>
35#include <iomanip>
36#include <sys/ipc.h>
37#include <sys/shm.h>
38
39#include "arch/regfile.hh"
40#include "arch/utility.hh"
41#include "base/loader/symtab.hh"
42#include "config/full_system.hh"
43#include "cpu/base.hh"
44#include "cpu/exetrace.hh"
45#include "cpu/static_inst.hh"
46#include "sim/param.hh"
47#include "sim/system.hh"
48
49#if FULL_SYSTEM
50#include "arch/tlb.hh"
51#endif
52
53//XXX This is temporary
54#include "arch/isa_specific.hh"
55#include "cpu/m5legion_interface.h"
56
57using namespace std;
58using namespace TheISA;
59
60#if THE_ISA == SPARC_ISA && FULL_SYSTEM
61static int diffcount = 0;
62static bool wasMicro = false;
63#endif
64
65namespace Trace {
66SharedData *shared_data = NULL;
67}
68
69////////////////////////////////////////////////////////////////////////
70//
71//  Methods for the InstRecord object
72//
73
74#if THE_ISA == SPARC_ISA
75
76inline char * genCenteredLabel(int length, char * buffer, char * label)
77{
78    int labelLength = strlen(label);
79    assert(labelLength <= length);
80    int leftPad = (length - labelLength) / 2;
81    int rightPad = length - leftPad - labelLength;
82    char format[64];
83    sprintf(format, "%%%ds%%s%%%ds", leftPad, rightPad);
84    sprintf(buffer, format, "", label, "");
85    return buffer;
86}
87
88inline void printRegPair(ostream & os, char const * title, uint64_t a, uint64_t b)
89{
90    ccprintf(os, "  %16s  |  %#018x   %s   %#-018x  \n",
91            title, a, (a == b) ? "|" : "X", b);
92}
93
94inline void printColumnLabels(ostream & os)
95{
96    static char * regLabel = genCenteredLabel(16, new char[17], "Register");
97    static char * m5Label = genCenteredLabel(18, new char[18], "M5");
98    static char * legionLabel = genCenteredLabel(18, new char[18], "Legion");
99    ccprintf(os, "  %s  |  %s   |   %s  \n", regLabel, m5Label, legionLabel);
100    ccprintf(os, "--------------------+-----------------------+-----------------------\n");
101}
102
103inline void printSectionHeader(ostream & os, char * name)
104{
105    char sectionString[70];
106    genCenteredLabel(69, sectionString, name);
107    ccprintf(os, "====================================================================\n");
108    ccprintf(os, "%69s\n", sectionString);
109    ccprintf(os, "====================================================================\n");
110}
111
112inline void printLevelHeader(ostream & os, int level)
113{
114    char sectionString[70];
115    char levelName[70];
116    sprintf(levelName, "Trap stack level %d", level);
117    genCenteredLabel(69, sectionString, levelName);
118    ccprintf(os, "====================================================================\n");
119    ccprintf(os, "%69s\n", sectionString);
120    ccprintf(os, "====================================================================\n");
121}
122
123#endif
124
125void
126Trace::InstRecord::dump(ostream &outs)
127{
128    DPRINTF(Sparc, "Instruction: %#X\n", staticInst->machInst);
129    if (flags[PRINT_REG_DELTA])
130    {
131#if THE_ISA == SPARC_ISA
132        //Don't print what happens for each micro-op, just print out
133        //once at the last op, and for regular instructions.
134        if(!staticInst->isMicroOp() || staticInst->isLastMicroOp())
135        {
136            static uint64_t regs[32] = {
137                0, 0, 0, 0, 0, 0, 0, 0,
138                0, 0, 0, 0, 0, 0, 0, 0,
139                0, 0, 0, 0, 0, 0, 0, 0,
140                0, 0, 0, 0, 0, 0, 0, 0};
141            static uint64_t ccr = 0;
142            static uint64_t y = 0;
143            static uint64_t floats[32];
144            uint64_t newVal;
145            static const char * prefixes[4] = {"G", "O", "L", "I"};
146
147            outs << hex;
148            outs << "PC = " << thread->readNextPC();
149            outs << " NPC = " << thread->readNextNPC();
150            newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2);
151            //newVal = thread->readMiscReg(SparcISA::MISCREG_CCR);
152            if(newVal != ccr)
153            {
154                outs << " CCR = " << newVal;
155                ccr = newVal;
156            }
157            newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 1);
158            //newVal = thread->readMiscReg(SparcISA::MISCREG_Y);
159            if(newVal != y)
160            {
161                outs << " Y = " << newVal;
162                y = newVal;
163            }
164            for(int y = 0; y < 4; y++)
165            {
166                for(int x = 0; x < 8; x++)
167                {
168                    int index = x + 8 * y;
169                    newVal = thread->readIntReg(index);
170                    if(regs[index] != newVal)
171                    {
172                        outs << " " << prefixes[y] << dec << x << " = " << hex << newVal;
173                        regs[index] = newVal;
174                    }
175                }
176            }
177            for(int y = 0; y < 32; y++)
178            {
179                newVal = thread->readFloatRegBits(2 * y, 64);
180                if(floats[y] != newVal)
181                {
182                    outs << " F" << dec << (2 * y) << " = " << hex << newVal;
183                    floats[y] = newVal;
184                }
185            }
186            outs << dec << endl;
187        }
188#endif
189    }
190    else if (flags[INTEL_FORMAT]) {
191#if FULL_SYSTEM
192        bool is_trace_system = (thread->getCpuPtr()->system->name() == trace_system);
193#else
194        bool is_trace_system = true;
195#endif
196        if (is_trace_system) {
197            ccprintf(outs, "%7d ) ", cycle);
198            outs << "0x" << hex << PC << ":\t";
199            if (staticInst->isLoad()) {
200                outs << "<RD 0x" << hex << addr;
201                outs << ">";
202            } else if (staticInst->isStore()) {
203                outs << "<WR 0x" << hex << addr;
204                outs << ">";
205            }
206            outs << endl;
207        }
208    } else {
209        if (flags[PRINT_CYCLE])
210            ccprintf(outs, "%7d: ", cycle);
211
212        outs << thread->getCpuPtr()->name() << " ";
213
214        if (flags[TRACE_MISSPEC])
215            outs << (misspeculating ? "-" : "+") << " ";
216
217        if (flags[PRINT_THREAD_NUM])
218            outs << "T" << thread->getThreadNum() << " : ";
219
220
221        std::string sym_str;
222        Addr sym_addr;
223        if (debugSymbolTable
224            && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr)
225            && flags[PC_SYMBOL]) {
226            if (PC != sym_addr)
227                sym_str += csprintf("+%d", PC - sym_addr);
228            outs << "@" << sym_str << " : ";
229        }
230        else {
231            outs << "0x" << hex << PC << " : ";
232        }
233
234        //
235        //  Print decoded instruction
236        //
237
238#if defined(__GNUC__) && (__GNUC__ < 3)
239        // There's a bug in gcc 2.x library that prevents setw()
240        // from working properly on strings
241        string mc(staticInst->disassemble(PC, debugSymbolTable));
242        while (mc.length() < 26)
243            mc += " ";
244        outs << mc;
245#else
246        outs << setw(26) << left << staticInst->disassemble(PC, debugSymbolTable);
247#endif
248
249        outs << " : ";
250
251        if (flags[PRINT_OP_CLASS]) {
252            outs << opClassStrings[staticInst->opClass()] << " : ";
253        }
254
255        if (flags[PRINT_RESULT_DATA] && data_status != DataInvalid) {
256            outs << " D=";
257#if 0
258            if (data_status == DataDouble)
259                ccprintf(outs, "%f", data.as_double);
260            else
261                ccprintf(outs, "%#018x", data.as_int);
262#else
263            ccprintf(outs, "%#018x", data.as_int);
264#endif
265        }
266
267        if (flags[PRINT_EFF_ADDR] && addr_valid)
268            outs << " A=0x" << hex << addr;
269
270        if (flags[PRINT_INT_REGS] && regs_valid) {
271            for (int i = 0; i < TheISA::NumIntRegs;)
272                for (int j = i + 1; i <= j; i++)
273                    ccprintf(outs, "r%02d = %#018x%s", i,
274                            iregs->regs.readReg(i),
275                            ((i == j) ? "\n" : "    "));
276            outs << "\n";
277        }
278
279        if (flags[PRINT_FETCH_SEQ] && fetch_seq_valid)
280            outs << "  FetchSeq=" << dec << fetch_seq;
281
282        if (flags[PRINT_CP_SEQ] && cp_seq_valid)
283            outs << "  CPSeq=" << dec << cp_seq;
284
285        //
286        //  End of line...
287        //
288        outs << endl;
289    }
290#if THE_ISA == SPARC_ISA && FULL_SYSTEM
291    // Compare
292    if (flags[LEGION_LOCKSTEP])
293    {
294        bool compared = false;
295        bool diffPC   = false;
296        bool diffCC   = false;
297        bool diffInst = false;
298        bool diffIntRegs = false;
299        bool diffFpRegs = false;
300        bool diffTpc = false;
301        bool diffTnpc = false;
302        bool diffTstate = false;
303        bool diffTt = false;
304        bool diffTba = false;
305        bool diffHpstate = false;
306        bool diffHtstate = false;
307        bool diffHtba = false;
308        bool diffPstate = false;
309        bool diffY = false;
310        bool diffCcr = false;
311        bool diffTl = false;
312        bool diffGl = false;
313        bool diffAsi = false;
314        bool diffPil = false;
315        bool diffCwp = false;
316        bool diffCansave = false;
317        bool diffCanrestore = false;
318        bool diffOtherwin = false;
319        bool diffCleanwin = false;
320        bool diffTlb = false;
321        Addr m5Pc, lgnPc;
322
323        // We took a trap on a micro-op...
324        if (wasMicro && !staticInst->isMicroOp())
325        {
326            // let's skip comparing this cycle
327            while (!compared)
328                if (shared_data->flags == OWN_M5) {
329                    shared_data->flags = OWN_LEGION;
330                    compared = true;
331                }
332            compared = false;
333            wasMicro = false;
334        }
335
336        if (staticInst->isLastMicroOp())
337            wasMicro = false;
338        else if (staticInst->isMicroOp())
339            wasMicro = true;
340
341
342        if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) {
343            while (!compared) {
344                if (shared_data->flags == OWN_M5) {
345                    m5Pc = PC & TheISA::PAddrImplMask;
346                    if (bits(shared_data->pstate,3,3)) {
347                        m5Pc &= mask(32);
348                    }
349                    lgnPc = shared_data->pc & TheISA::PAddrImplMask;
350                    if (lgnPc != m5Pc)
351                       diffPC = true;
352
353                    if (shared_data->cycle_count !=
354                            thread->getCpuPtr()->instCount())
355                        diffCC = true;
356
357                    if (shared_data->instruction !=
358                            (SparcISA::MachInst)staticInst->machInst) {
359                        diffInst = true;
360                    }
361                    // assume we have %g0 working correctly
362                    for (int i = 1; i < TheISA::NumIntArchRegs; i++) {
363                        if (thread->readIntReg(i) != shared_data->intregs[i]) {
364                            diffIntRegs = true;
365                        }
366                    }
367                    for (int i = 0; i < TheISA::NumFloatRegs/2; i++) {
368                        if (thread->readFloatRegBits(i*2,FloatRegFile::DoubleWidth) != shared_data->fpregs[i]) {
369                            diffFpRegs = true;
370                        }
371                    }
372                            uint64_t oldTl = thread->readMiscReg(MISCREG_TL);
373                    if (oldTl != shared_data->tl)
374                        diffTl = true;
375                    for (int i = 1; i <= MaxTL; i++) {
376                        thread->setMiscReg(MISCREG_TL, i);
377                        if (thread->readMiscReg(MISCREG_TPC) !=
378                                shared_data->tpc[i-1])
379                            diffTpc = true;
380                        if (thread->readMiscReg(MISCREG_TNPC) !=
381                                shared_data->tnpc[i-1])
382                            diffTnpc = true;
383                        if (thread->readMiscReg(MISCREG_TSTATE) !=
384                                shared_data->tstate[i-1])
385                            diffTstate = true;
386                        if (thread->readMiscReg(MISCREG_TT) !=
387                                shared_data->tt[i-1])
388                            diffTt = true;
389                        if (thread->readMiscReg(MISCREG_HTSTATE) !=
390                                shared_data->htstate[i-1])
391                            diffHtstate = true;
392                    }
393                    thread->setMiscReg(MISCREG_TL, oldTl);
394
395                    if(shared_data->tba != thread->readMiscReg(MISCREG_TBA))
396                        diffTba = true;
397                    //When the hpstate register is read by an instruction,
398                    //legion has bit 11 set. When it's in storage, it doesn't.
399                    //Since we don't directly support seperate interpretations
400                    //of the registers like that, the bit is always set to 1 and
401                    //we just don't compare it. It's not supposed to matter
402                    //anyway.
403                    if((shared_data->hpstate | (1 << 11)) != thread->readMiscReg(MISCREG_HPSTATE))
404                        diffHpstate = true;
405                    if(shared_data->htba != thread->readMiscReg(MISCREG_HTBA))
406                        diffHtba = true;
407                    if(shared_data->pstate != thread->readMiscReg(MISCREG_PSTATE))
408                        diffPstate = true;
409                    //if(shared_data->y != thread->readMiscReg(MISCREG_Y))
410                    if(shared_data->y !=
411                            thread->readIntReg(NumIntArchRegs + 1))
412                        diffY = true;
413                    //if(shared_data->ccr != thread->readMiscReg(MISCREG_CCR))
414                    if(shared_data->ccr !=
415                            thread->readIntReg(NumIntArchRegs + 2))
416                        diffCcr = true;
417                    if(shared_data->gl != thread->readMiscReg(MISCREG_GL))
418                        diffGl = true;
419                    if(shared_data->asi != thread->readMiscReg(MISCREG_ASI))
420                        diffAsi = true;
421                    if(shared_data->pil != thread->readMiscReg(MISCREG_PIL))
422                        diffPil = true;
423                    if(shared_data->cwp != thread->readMiscReg(MISCREG_CWP))
424                        diffCwp = true;
425                    //if(shared_data->cansave != thread->readMiscReg(MISCREG_CANSAVE))
426                    if(shared_data->cansave !=
427                            thread->readIntReg(NumIntArchRegs + 3))
428                        diffCansave = true;
429                    //if(shared_data->canrestore !=
430                    //	    thread->readMiscReg(MISCREG_CANRESTORE))
431                    if(shared_data->canrestore !=
432                            thread->readIntReg(NumIntArchRegs + 4))
433                        diffCanrestore = true;
434                    //if(shared_data->otherwin != thread->readMiscReg(MISCREG_OTHERWIN))
435                    if(shared_data->otherwin !=
436                            thread->readIntReg(NumIntArchRegs + 6))
437                        diffOtherwin = true;
438                    //if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN))
439                    if(shared_data->cleanwin !=
440                            thread->readIntReg(NumIntArchRegs + 5))
441                        diffCleanwin = true;
442
443                    for (int i = 0; i < 64; i++) {
444                        if (shared_data->itb[i] !=  thread->getITBPtr()->TteRead(i))
445                                diffTlb = true;
446                        if (shared_data->dtb[i] !=  thread->getDTBPtr()->TteRead(i))
447                                diffTlb = true;
448                    }
449
450                    if ((diffPC || diffCC || diffInst || diffIntRegs ||
451                         diffFpRegs || diffTpc || diffTnpc || diffTstate ||
452                         diffTt || diffHpstate || diffHtstate || diffHtba ||
453                         diffPstate || diffY || diffCcr || diffTl || diffGl ||
454                         diffAsi || diffPil || diffCwp || diffCansave ||
455                         diffCanrestore || diffOtherwin || diffCleanwin || diffTlb)
456                        && !((staticInst->machInst & 0xC1F80000) == 0x81D00000)
457                        && !(((staticInst->machInst & 0xC0000000) == 0xC0000000)
458                            && shared_data->tl == thread->readMiscReg(MISCREG_TL) + 1)
459                       ) {
460
461                        outs << "Differences found between M5 and Legion:";
462                        if (diffPC)
463                            outs << " [PC]";
464                        if (diffCC)
465                            outs << " [CC]";
466                        if (diffInst)
467                            outs << " [Instruction]";
468                        if (diffIntRegs)
469                            outs << " [IntRegs]";
470                        if (diffFpRegs)
471                            outs << " [FpRegs]";
472                        if (diffTpc)
473                            outs << " [Tpc]";
474                        if (diffTnpc)
475                            outs << " [Tnpc]";
476                        if (diffTstate)
477                            outs << " [Tstate]";
478                        if (diffTt)
479                            outs << " [Tt]";
480                        if (diffHpstate)
481                            outs << " [Hpstate]";
482                        if (diffHtstate)
483                            outs << " [Htstate]";
484                        if (diffHtba)
485                            outs << " [Htba]";
486                        if (diffPstate)
487                            outs << " [Pstate]";
488                        if (diffY)
489                            outs << " [Y]";
490                        if (diffCcr)
491                            outs << " [Ccr]";
492                        if (diffTl)
493                            outs << " [Tl]";
494                        if (diffGl)
495                            outs << " [Gl]";
496                        if (diffAsi)
497                            outs << " [Asi]";
498                        if (diffPil)
499                            outs << " [Pil]";
500                        if (diffCwp)
501                            outs << " [Cwp]";
502                        if (diffCansave)
503                            outs << " [Cansave]";
504                        if (diffCanrestore)
505                            outs << " [Canrestore]";
506                        if (diffOtherwin)
507                            outs << " [Otherwin]";
508                        if (diffCleanwin)
509                            outs << " [Cleanwin]";
510                        if (diffTlb)
511                            outs << " [Tlb]";
512                        outs << endl << endl;
513
514                        outs << right << setfill(' ') << setw(15)
515                             << "M5 PC: " << "0x"<< setw(16) << setfill('0')
516                             << hex << m5Pc << endl;
517                        outs << setfill(' ') << setw(15)
518                             << "Legion PC: " << "0x"<< setw(16) << setfill('0') << hex
519                             << lgnPc << endl << endl;
520
521                        outs << right << setfill(' ') << setw(15)
522                             << "M5 CC: " << "0x"<< setw(16) << setfill('0')
523                             << hex << thread->getCpuPtr()->instCount() << endl;
524                        outs << setfill(' ') << setw(15)
525                             << "Legion CC: " << "0x"<< setw(16) << setfill('0') << hex
526                             << shared_data->cycle_count << endl << endl;
527
528                        outs << setfill(' ') << setw(15)
529                             << "M5 Inst: "  << "0x"<< setw(8)
530                             << setfill('0') << hex << staticInst->machInst
531                             << staticInst->disassemble(m5Pc, debugSymbolTable)
532                             << endl;
533
534                        StaticInstPtr legionInst =
535                            StaticInst::decode(makeExtMI(shared_data->instruction,
536                                        thread));
537                        outs << setfill(' ') << setw(15)
538                             << " Legion Inst: "
539                             << "0x" << setw(8) << setfill('0') << hex
540                             << shared_data->instruction
541                             << legionInst->disassemble(lgnPc, debugSymbolTable)
542                             << endl << endl;
543
544                        printSectionHeader(outs, "General State");
545                        printColumnLabels(outs);
546                        printRegPair(outs, "HPstate",
547                                thread->readMiscReg(MISCREG_HPSTATE),
548                                shared_data->hpstate | (1 << 11));
549                        printRegPair(outs, "Htba",
550                                thread->readMiscReg(MISCREG_HTBA),
551                                shared_data->htba);
552                        printRegPair(outs, "Pstate",
553                                thread->readMiscReg(MISCREG_PSTATE),
554                                shared_data->pstate);
555                        printRegPair(outs, "Y",
556                                //thread->readMiscReg(MISCREG_Y),
557                                thread->readIntReg(NumIntArchRegs + 1),
558                                shared_data->y);
559                        printRegPair(outs, "Ccr",
560                                //thread->readMiscReg(MISCREG_CCR),
561                                thread->readIntReg(NumIntArchRegs + 2),
562                                shared_data->ccr);
563                        printRegPair(outs, "Tl",
564                                thread->readMiscReg(MISCREG_TL),
565                                shared_data->tl);
566                        printRegPair(outs, "Gl",
567                                thread->readMiscReg(MISCREG_GL),
568                                shared_data->gl);
569                        printRegPair(outs, "Asi",
570                                thread->readMiscReg(MISCREG_ASI),
571                                shared_data->asi);
572                        printRegPair(outs, "Pil",
573                                thread->readMiscReg(MISCREG_PIL),
574                                shared_data->pil);
575                        printRegPair(outs, "Cwp",
576                                thread->readMiscReg(MISCREG_CWP),
577                                shared_data->cwp);
578                        printRegPair(outs, "Cansave",
579                                //thread->readMiscReg(MISCREG_CANSAVE),
580                                thread->readIntReg(NumIntArchRegs + 3),
581                                shared_data->cansave);
582                        printRegPair(outs, "Canrestore",
583                                //thread->readMiscReg(MISCREG_CANRESTORE),
584                                thread->readIntReg(NumIntArchRegs + 4),
585                                shared_data->canrestore);
586                        printRegPair(outs, "Otherwin",
587                                //thread->readMiscReg(MISCREG_OTHERWIN),
588                                thread->readIntReg(NumIntArchRegs + 6),
589                                shared_data->otherwin);
590                        printRegPair(outs, "Cleanwin",
591                                //thread->readMiscReg(MISCREG_CLEANWIN),
592                                thread->readIntReg(NumIntArchRegs + 5),
593                                shared_data->cleanwin);
594                        outs << endl;
595                        for (int i = 1; i <= MaxTL; i++) {
596                            printLevelHeader(outs, i);
597                            printColumnLabels(outs);
598                            thread->setMiscReg(MISCREG_TL, i);
599                            printRegPair(outs, "Tpc",
600                                    thread->readMiscReg(MISCREG_TPC),
601                                    shared_data->tpc[i-1]);
602                            printRegPair(outs, "Tnpc",
603                                    thread->readMiscReg(MISCREG_TNPC),
604                                    shared_data->tnpc[i-1]);
605                            printRegPair(outs, "Tstate",
606                                    thread->readMiscReg(MISCREG_TSTATE),
607                                    shared_data->tstate[i-1]);
608                            printRegPair(outs, "Tt",
609                                    thread->readMiscReg(MISCREG_TT),
610                                    shared_data->tt[i-1]);
611                            printRegPair(outs, "Htstate",
612                                    thread->readMiscReg(MISCREG_HTSTATE),
613                                    shared_data->htstate[i-1]);
614                        }
615                        thread->setMiscReg(MISCREG_TL, oldTl);
616                        outs << endl;
617
618                        printSectionHeader(outs, "General Purpose Registers");
619                        static const char * regtypes[4] = {"%g", "%o", "%l", "%i"};
620                        for(int y = 0; y < 4; y++) {
621                            for(int x = 0; x < 8; x++) {
622                                char label[8];
623                                sprintf(label, "%s%d", regtypes[y], x);
624                                printRegPair(outs, label,
625                                        thread->readIntReg(y*8+x),
626                                        shared_data->intregs[y*8+x]);
627                            }
628                        }
629                        if (diffFpRegs) {
630                            for (int x = 0; x < 32; x++) {
631                                char label[8];
632                                sprintf(label, "%%f%d", x);
633                                printRegPair(outs, label,
634                                 thread->readFloatRegBits(x,FloatRegFile::DoubleWidth),
635                                 shared_data->fpregs[x]);
636                            }
637                        }
638                        if (diffTlb) {
639                            printColumnLabels(outs);
640                            char label[8];
641                            for (int x = 0; x < 64; x++) {
642                                if (shared_data->itb[x] !=  ULL(0xFFFFFFFFFFFFFFFF) ||
643                                    thread->getITBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF))  {
644                                        sprintf(label, "I-TLB:%02d", x);
645                                        printRegPair(outs, label, thread->getITBPtr()->TteRead(x),
646                                                shared_data->itb[x]);
647                                }
648                            }
649                            for (int x = 0; x < 64; x++) {
650                                if (shared_data->dtb[x] !=  ULL(0xFFFFFFFFFFFFFFFF) ||
651                                    thread->getDTBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF))  {
652                                        sprintf(label, "D-TLB:%02d", x);
653                                        printRegPair(outs, label, thread->getDTBPtr()->TteRead(x),
654                                                shared_data->dtb[x]);
655                                }
656                            }
657                            thread->getITBPtr()->dumpAll();
658                            thread->getDTBPtr()->dumpAll();
659                        }
660
661                        diffcount++;
662                        if (diffcount > 2)
663                            fatal("Differences found between Legion and M5\n");
664                    } else
665                        diffcount = 0;
666
667                    compared = true;
668                    shared_data->flags = OWN_LEGION;
669                }
670            } // while
671        } // if not microop
672    }
673#endif
674}
675
676
677vector<bool> Trace::InstRecord::flags(NUM_BITS);
678string Trace::InstRecord::trace_system;
679
680////////////////////////////////////////////////////////////////////////
681//
682// Parameter space for per-cycle execution address tracing options.
683// Derive from ParamContext so we can override checkParams() function.
684//
685class ExecutionTraceParamContext : public ParamContext
686{
687  public:
688    ExecutionTraceParamContext(const string &_iniSection)
689        : ParamContext(_iniSection)
690        {
691        }
692
693    void checkParams();	// defined at bottom of file
694};
695
696ExecutionTraceParamContext exeTraceParams("exetrace");
697
698Param<bool> exe_trace_spec(&exeTraceParams, "speculative",
699                           "capture speculative instructions", true);
700
701Param<bool> exe_trace_print_cycle(&exeTraceParams, "print_cycle",
702                                  "print cycle number", true);
703Param<bool> exe_trace_print_opclass(&exeTraceParams, "print_opclass",
704                                  "print op class", true);
705Param<bool> exe_trace_print_thread(&exeTraceParams, "print_thread",
706                                  "print thread number", true);
707Param<bool> exe_trace_print_effaddr(&exeTraceParams, "print_effaddr",
708                                  "print effective address", true);
709Param<bool> exe_trace_print_data(&exeTraceParams, "print_data",
710                                  "print result data", true);
711Param<bool> exe_trace_print_iregs(&exeTraceParams, "print_iregs",
712                                  "print all integer regs", false);
713Param<bool> exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq",
714                                  "print fetch sequence number", false);
715Param<bool> exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq",
716                                  "print correct-path sequence number", false);
717Param<bool> exe_trace_print_reg_delta(&exeTraceParams, "print_reg_delta",
718                                  "print which registers changed to what", false);
719Param<bool> exe_trace_pc_symbol(&exeTraceParams, "pc_symbol",
720                                  "Use symbols for the PC if available", true);
721Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format",
722                                   "print trace in intel compatible format", false);
723Param<bool> exe_trace_legion_lockstep(&exeTraceParams, "legion_lockstep",
724                                   "Compare sim state to legion state every cycle",
725                                   false);
726Param<string> exe_trace_system(&exeTraceParams, "trace_system",
727                                   "print trace of which system (client or server)",
728                                   "client");
729
730
731//
732// Helper function for ExecutionTraceParamContext::checkParams() just
733// to get us into the InstRecord namespace
734//
735void
736Trace::InstRecord::setParams()
737{
738    flags[TRACE_MISSPEC]     = exe_trace_spec;
739
740    flags[PRINT_CYCLE]       = exe_trace_print_cycle;
741    flags[PRINT_OP_CLASS]    = exe_trace_print_opclass;
742    flags[PRINT_THREAD_NUM]  = exe_trace_print_thread;
743    flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr;
744    flags[PRINT_EFF_ADDR]    = exe_trace_print_data;
745    flags[PRINT_INT_REGS]    = exe_trace_print_iregs;
746    flags[PRINT_FETCH_SEQ]   = exe_trace_print_fetchseq;
747    flags[PRINT_CP_SEQ]      = exe_trace_print_cp_seq;
748    flags[PRINT_REG_DELTA]   = exe_trace_print_reg_delta;
749    flags[PC_SYMBOL]         = exe_trace_pc_symbol;
750    flags[INTEL_FORMAT]      = exe_trace_intel_format;
751    flags[LEGION_LOCKSTEP]   = exe_trace_legion_lockstep;
752    trace_system	     = exe_trace_system;
753
754    // If were going to be in lockstep with Legion
755    // Setup shared memory, and get otherwise ready
756    if (flags[LEGION_LOCKSTEP]) {
757        int shmfd = shmget('M' << 24 | getuid(), sizeof(SharedData), 0777);
758        if (shmfd < 0)
759            fatal("Couldn't get shared memory fd. Is Legion running?");
760
761        shared_data = (SharedData*)shmat(shmfd, NULL, SHM_RND);
762        if (shared_data == (SharedData*)-1)
763            fatal("Couldn't allocate shared memory");
764
765        if (shared_data->flags != OWN_M5)
766            fatal("Shared memory has invalid owner");
767
768        if (shared_data->version != VERSION)
769            fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION,
770                    shared_data->version);
771
772        // step legion forward one cycle so we can get register values
773        shared_data->flags = OWN_LEGION;
774    }
775}
776
777void
778ExecutionTraceParamContext::checkParams()
779{
780    Trace::InstRecord::setParams();
781}
782
783