exetrace.cc revision 3980:9bcb2a2e9bb8
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                    for (int i = 0; i < TheISA::NumIntArchRegs; i++) {
362                        if (thread->readIntReg(i) != shared_data->intregs[i]) {
363                            diffIntRegs = true;
364                        }
365                    }
366                    for (int i = 0; i < TheISA::NumFloatRegs/2; i++) {
367                        if (thread->readFloatRegBits(i,FloatRegFile::DoubleWidth) != shared_data->fpregs[i]) {
368                            diffFpRegs = true;
369                        }
370                    }
371                            uint64_t oldTl = thread->readMiscReg(MISCREG_TL);
372                    if (oldTl != shared_data->tl)
373                        diffTl = true;
374                    for (int i = 1; i <= MaxTL; i++) {
375                        thread->setMiscReg(MISCREG_TL, i);
376                        if (thread->readMiscReg(MISCREG_TPC) !=
377                                shared_data->tpc[i-1])
378                            diffTpc = true;
379                        if (thread->readMiscReg(MISCREG_TNPC) !=
380                                shared_data->tnpc[i-1])
381                            diffTnpc = true;
382                        if (thread->readMiscReg(MISCREG_TSTATE) !=
383                                shared_data->tstate[i-1])
384                            diffTstate = true;
385                        if (thread->readMiscReg(MISCREG_TT) !=
386                                shared_data->tt[i-1])
387                            diffTt = true;
388                        if (thread->readMiscReg(MISCREG_HTSTATE) !=
389                                shared_data->htstate[i-1])
390                            diffHtstate = true;
391                    }
392                    thread->setMiscReg(MISCREG_TL, oldTl);
393
394                    if(shared_data->tba != thread->readMiscReg(MISCREG_TBA))
395                        diffTba = true;
396                    //When the hpstate register is read by an instruction,
397                    //legion has bit 11 set. When it's in storage, it doesn't.
398                    //Since we don't directly support seperate interpretations
399                    //of the registers like that, the bit is always set to 1 and
400                    //we just don't compare it. It's not supposed to matter
401                    //anyway.
402                    if((shared_data->hpstate | (1 << 11)) != thread->readMiscReg(MISCREG_HPSTATE))
403                        diffHpstate = true;
404                    if(shared_data->htba != thread->readMiscReg(MISCREG_HTBA))
405                        diffHtba = true;
406                    if(shared_data->pstate != thread->readMiscReg(MISCREG_PSTATE))
407                        diffPstate = true;
408                    //if(shared_data->y != thread->readMiscReg(MISCREG_Y))
409                    if(shared_data->y !=
410                            thread->readIntReg(NumIntArchRegs + 1))
411                        diffY = true;
412                    //if(shared_data->ccr != thread->readMiscReg(MISCREG_CCR))
413                    if(shared_data->ccr !=
414                            thread->readIntReg(NumIntArchRegs + 2))
415                        diffCcr = true;
416                    if(shared_data->gl != thread->readMiscReg(MISCREG_GL))
417                        diffGl = true;
418                    if(shared_data->asi != thread->readMiscReg(MISCREG_ASI))
419                        diffAsi = true;
420                    if(shared_data->pil != thread->readMiscReg(MISCREG_PIL))
421                        diffPil = true;
422                    if(shared_data->cwp != thread->readMiscReg(MISCREG_CWP))
423                        diffCwp = true;
424                    //if(shared_data->cansave != thread->readMiscReg(MISCREG_CANSAVE))
425                    if(shared_data->cansave !=
426                            thread->readIntReg(NumIntArchRegs + 3))
427                        diffCansave = true;
428                    //if(shared_data->canrestore !=
429                    //	    thread->readMiscReg(MISCREG_CANRESTORE))
430                    if(shared_data->canrestore !=
431                            thread->readMiscReg(NumIntArchRegs + 4))
432                        diffCanrestore = true;
433                    //if(shared_data->otherwin != thread->readMiscReg(MISCREG_OTHERWIN))
434                    if(shared_data->otherwin !=
435                            thread->readIntReg(NumIntArchRegs + 5))
436                        diffOtherwin = true;
437                    //if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN))
438                    if(shared_data->cleanwin !=
439                            thread->readMiscReg(NumIntArchRegs + 6))
440                        diffCleanwin = true;
441
442                    for (int i = 0; i < 64; i++) {
443                        if (shared_data->itb[i] !=  thread->getITBPtr()->TteRead(i))
444                                diffTlb = true;
445                        if (shared_data->dtb[i] !=  thread->getDTBPtr()->TteRead(i))
446                                diffTlb = true;
447                    }
448
449                    if ((diffPC || diffCC || diffInst || diffIntRegs ||
450                         diffFpRegs || diffTpc || diffTnpc || diffTstate ||
451                         diffTt || diffHpstate || diffHtstate || diffHtba ||
452                         diffPstate || diffY || diffCcr || diffTl || diffGl ||
453                         diffAsi || diffPil || diffCwp || diffCansave ||
454                         diffCanrestore || diffOtherwin || diffCleanwin || diffTlb)
455                        && !((staticInst->machInst & 0xC1F80000) == 0x81D00000)
456                        && !(((staticInst->machInst & 0xC0000000) == 0xC0000000)
457                            && shared_data->tl == thread->readMiscReg(MISCREG_TL) + 1)
458                       ) {
459
460                        outs << "Differences found between M5 and Legion:";
461                        if (diffPC)
462                            outs << " [PC]";
463                        if (diffCC)
464                            outs << " [CC]";
465                        if (diffInst)
466                            outs << " [Instruction]";
467                        if (diffIntRegs)
468                            outs << " [IntRegs]";
469                        if (diffFpRegs)
470                            outs << " [FpRegs]";
471                        if (diffTpc)
472                            outs << " [Tpc]";
473                        if (diffTnpc)
474                            outs << " [Tnpc]";
475                        if (diffTstate)
476                            outs << " [Tstate]";
477                        if (diffTt)
478                            outs << " [Tt]";
479                        if (diffHpstate)
480                            outs << " [Hpstate]";
481                        if (diffHtstate)
482                            outs << " [Htstate]";
483                        if (diffHtba)
484                            outs << " [Htba]";
485                        if (diffPstate)
486                            outs << " [Pstate]";
487                        if (diffY)
488                            outs << " [Y]";
489                        if (diffCcr)
490                            outs << " [Ccr]";
491                        if (diffTl)
492                            outs << " [Tl]";
493                        if (diffGl)
494                            outs << " [Gl]";
495                        if (diffAsi)
496                            outs << " [Asi]";
497                        if (diffPil)
498                            outs << " [Pil]";
499                        if (diffCwp)
500                            outs << " [Cwp]";
501                        if (diffCansave)
502                            outs << " [Cansave]";
503                        if (diffCanrestore)
504                            outs << " [Canrestore]";
505                        if (diffOtherwin)
506                            outs << " [Otherwin]";
507                        if (diffCleanwin)
508                            outs << " [Cleanwin]";
509                        if (diffTlb)
510                            outs << " [Tlb]";
511                        outs << endl << endl;
512
513                        outs << right << setfill(' ') << setw(15)
514                             << "M5 PC: " << "0x"<< setw(16) << setfill('0')
515                             << hex << m5Pc << endl;
516                        outs << setfill(' ') << setw(15)
517                             << "Legion PC: " << "0x"<< setw(16) << setfill('0') << hex
518                             << lgnPc << endl << endl;
519
520                        outs << right << setfill(' ') << setw(15)
521                             << "M5 CC: " << "0x"<< setw(16) << setfill('0')
522                             << hex << thread->getCpuPtr()->instCount() << endl;
523                        outs << setfill(' ') << setw(15)
524                             << "Legion CC: " << "0x"<< setw(16) << setfill('0') << hex
525                             << shared_data->cycle_count << endl << endl;
526
527                        outs << setfill(' ') << setw(15)
528                             << "M5 Inst: "  << "0x"<< setw(8)
529                             << setfill('0') << hex << staticInst->machInst
530                             << staticInst->disassemble(m5Pc, debugSymbolTable)
531                             << endl;
532
533                        StaticInstPtr legionInst =
534                            StaticInst::decode(makeExtMI(shared_data->instruction,
535                                        thread));
536                        outs << setfill(' ') << setw(15)
537                             << " Legion Inst: "
538                             << "0x" << setw(8) << setfill('0') << hex
539                             << shared_data->instruction
540                             << legionInst->disassemble(lgnPc, debugSymbolTable)
541                             << endl << endl;
542
543                        printSectionHeader(outs, "General State");
544                        printColumnLabels(outs);
545                        printRegPair(outs, "HPstate",
546                                thread->readMiscReg(MISCREG_HPSTATE),
547                                shared_data->hpstate | (1 << 11));
548                        printRegPair(outs, "Htba",
549                                thread->readMiscReg(MISCREG_HTBA),
550                                shared_data->htba);
551                        printRegPair(outs, "Pstate",
552                                thread->readMiscReg(MISCREG_PSTATE),
553                                shared_data->pstate);
554                        printRegPair(outs, "Y",
555                                //thread->readMiscReg(MISCREG_Y),
556                                thread->readMiscReg(NumIntArchRegs + 1),
557                                shared_data->y);
558                        printRegPair(outs, "Ccr",
559                                //thread->readMiscReg(MISCREG_CCR),
560                                thread->readMiscReg(NumIntArchRegs + 2),
561                                shared_data->ccr);
562                        printRegPair(outs, "Tl",
563                                thread->readMiscReg(MISCREG_TL),
564                                shared_data->tl);
565                        printRegPair(outs, "Gl",
566                                thread->readMiscReg(MISCREG_GL),
567                                shared_data->gl);
568                        printRegPair(outs, "Asi",
569                                thread->readMiscReg(MISCREG_ASI),
570                                shared_data->asi);
571                        printRegPair(outs, "Pil",
572                                thread->readMiscReg(MISCREG_PIL),
573                                shared_data->pil);
574                        printRegPair(outs, "Cwp",
575                                thread->readMiscReg(MISCREG_CWP),
576                                shared_data->cwp);
577                        printRegPair(outs, "Cansave",
578                                //thread->readMiscReg(MISCREG_CANSAVE),
579                                thread->readIntReg(NumIntArchRegs + 3),
580                                shared_data->cansave);
581                        printRegPair(outs, "Canrestore",
582                                //thread->readMiscReg(MISCREG_CANRESTORE),
583                                thread->readIntReg(NumIntArchRegs + 4),
584                                shared_data->canrestore);
585                        printRegPair(outs, "Otherwin",
586                                //thread->readMiscReg(MISCREG_OTHERWIN),
587                                thread->readIntReg(NumIntArchRegs + 5),
588                                shared_data->otherwin);
589                        printRegPair(outs, "Cleanwin",
590                                //thread->readMiscReg(MISCREG_CLEANWIN),
591                                thread->readIntReg(NumIntArchRegs + 6),
592                                shared_data->cleanwin);
593                        outs << endl;
594                        for (int i = 1; i <= MaxTL; i++) {
595                            printLevelHeader(outs, i);
596                            printColumnLabels(outs);
597                            thread->setMiscReg(MISCREG_TL, i);
598                            printRegPair(outs, "Tpc",
599                                    thread->readMiscReg(MISCREG_TPC),
600                                    shared_data->tpc[i-1]);
601                            printRegPair(outs, "Tnpc",
602                                    thread->readMiscReg(MISCREG_TNPC),
603                                    shared_data->tnpc[i-1]);
604                            printRegPair(outs, "Tstate",
605                                    thread->readMiscReg(MISCREG_TSTATE),
606                                    shared_data->tstate[i-1]);
607                            printRegPair(outs, "Tt",
608                                    thread->readMiscReg(MISCREG_TT),
609                                    shared_data->tt[i-1]);
610                            printRegPair(outs, "Htstate",
611                                    thread->readMiscReg(MISCREG_HTSTATE),
612                                    shared_data->htstate[i-1]);
613                        }
614                        thread->setMiscReg(MISCREG_TL, oldTl);
615                        outs << endl;
616
617                        printSectionHeader(outs, "General Purpose Registers");
618                        static const char * regtypes[4] = {"%g", "%o", "%l", "%i"};
619                        for(int y = 0; y < 4; y++) {
620                            for(int x = 0; x < 8; x++) {
621                                char label[8];
622                                sprintf(label, "%s%d", regtypes[y], x);
623                                printRegPair(outs, label,
624                                        thread->readIntReg(y*8+x),
625                                        shared_data->intregs[y*8+x]);
626                            }
627                        }
628                        if (diffFpRegs) {
629                            for (int x = 0; x < 32; x++) {
630                                char label[8];
631                                sprintf(label, "%%f%d", x);
632                                printRegPair(outs, label,
633                                 thread->readFloatRegBits(x,FloatRegFile::DoubleWidth),
634                                 shared_data->fpregs[x]);
635                            }
636                        }
637                        if (diffTlb) {
638                            printColumnLabels(outs);
639                            char label[8];
640                            for (int x = 0; x < 64; x++) {
641                                if (shared_data->itb[x] !=  ULL(0xFFFFFFFFFFFFFFFF) ||
642                                    thread->getITBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF))  {
643                                        sprintf(label, "I-TLB:%02d", x);
644                                        printRegPair(outs, label, thread->getITBPtr()->TteRead(x),
645                                                shared_data->itb[x]);
646                                }
647                            }
648                            for (int x = 0; x < 64; x++) {
649                                if (shared_data->dtb[x] !=  ULL(0xFFFFFFFFFFFFFFFF) ||
650                                    thread->getDTBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF))  {
651                                        sprintf(label, "D-TLB:%02d", x);
652                                        printRegPair(outs, label, thread->getDTBPtr()->TteRead(x),
653                                                shared_data->dtb[x]);
654                                }
655                            }
656                            thread->getITBPtr()->dumpAll();
657                            thread->getDTBPtr()->dumpAll();
658                        }
659
660                        diffcount++;
661                        if (diffcount > 2)
662                            fatal("Differences found between Legion and M5\n");
663                    } else
664                        diffcount = 0;
665
666                    compared = true;
667                    shared_data->flags = OWN_LEGION;
668                }
669            } // while
670        } // if not microop
671    }
672#endif
673}
674
675
676vector<bool> Trace::InstRecord::flags(NUM_BITS);
677string Trace::InstRecord::trace_system;
678
679////////////////////////////////////////////////////////////////////////
680//
681// Parameter space for per-cycle execution address tracing options.
682// Derive from ParamContext so we can override checkParams() function.
683//
684class ExecutionTraceParamContext : public ParamContext
685{
686  public:
687    ExecutionTraceParamContext(const string &_iniSection)
688        : ParamContext(_iniSection)
689        {
690        }
691
692    void checkParams();	// defined at bottom of file
693};
694
695ExecutionTraceParamContext exeTraceParams("exetrace");
696
697Param<bool> exe_trace_spec(&exeTraceParams, "speculative",
698                           "capture speculative instructions", true);
699
700Param<bool> exe_trace_print_cycle(&exeTraceParams, "print_cycle",
701                                  "print cycle number", true);
702Param<bool> exe_trace_print_opclass(&exeTraceParams, "print_opclass",
703                                  "print op class", true);
704Param<bool> exe_trace_print_thread(&exeTraceParams, "print_thread",
705                                  "print thread number", true);
706Param<bool> exe_trace_print_effaddr(&exeTraceParams, "print_effaddr",
707                                  "print effective address", true);
708Param<bool> exe_trace_print_data(&exeTraceParams, "print_data",
709                                  "print result data", true);
710Param<bool> exe_trace_print_iregs(&exeTraceParams, "print_iregs",
711                                  "print all integer regs", false);
712Param<bool> exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq",
713                                  "print fetch sequence number", false);
714Param<bool> exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq",
715                                  "print correct-path sequence number", false);
716Param<bool> exe_trace_print_reg_delta(&exeTraceParams, "print_reg_delta",
717                                  "print which registers changed to what", false);
718Param<bool> exe_trace_pc_symbol(&exeTraceParams, "pc_symbol",
719                                  "Use symbols for the PC if available", true);
720Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format",
721                                   "print trace in intel compatible format", false);
722Param<bool> exe_trace_legion_lockstep(&exeTraceParams, "legion_lockstep",
723                                   "Compare sim state to legion state every cycle",
724                                   false);
725Param<string> exe_trace_system(&exeTraceParams, "trace_system",
726                                   "print trace of which system (client or server)",
727                                   "client");
728
729
730//
731// Helper function for ExecutionTraceParamContext::checkParams() just
732// to get us into the InstRecord namespace
733//
734void
735Trace::InstRecord::setParams()
736{
737    flags[TRACE_MISSPEC]     = exe_trace_spec;
738
739    flags[PRINT_CYCLE]       = exe_trace_print_cycle;
740    flags[PRINT_OP_CLASS]    = exe_trace_print_opclass;
741    flags[PRINT_THREAD_NUM]  = exe_trace_print_thread;
742    flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr;
743    flags[PRINT_EFF_ADDR]    = exe_trace_print_data;
744    flags[PRINT_INT_REGS]    = exe_trace_print_iregs;
745    flags[PRINT_FETCH_SEQ]   = exe_trace_print_fetchseq;
746    flags[PRINT_CP_SEQ]      = exe_trace_print_cp_seq;
747    flags[PRINT_REG_DELTA]   = exe_trace_print_reg_delta;
748    flags[PC_SYMBOL]         = exe_trace_pc_symbol;
749    flags[INTEL_FORMAT]      = exe_trace_intel_format;
750    flags[LEGION_LOCKSTEP]   = exe_trace_legion_lockstep;
751    trace_system	     = exe_trace_system;
752
753    // If were going to be in lockstep with Legion
754    // Setup shared memory, and get otherwise ready
755    if (flags[LEGION_LOCKSTEP]) {
756        int shmfd = shmget('M' << 24 | getuid(), sizeof(SharedData), 0777);
757        if (shmfd < 0)
758            fatal("Couldn't get shared memory fd. Is Legion running?");
759
760        shared_data = (SharedData*)shmat(shmfd, NULL, SHM_RND);
761        if (shared_data == (SharedData*)-1)
762            fatal("Couldn't allocate shared memory");
763
764        if (shared_data->flags != OWN_M5)
765            fatal("Shared memory has invalid owner");
766
767        if (shared_data->version != VERSION)
768            fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION,
769                    shared_data->version);
770
771        // step legion forward one cycle so we can get register values
772        shared_data->flags = OWN_LEGION;
773    }
774}
775
776void
777ExecutionTraceParamContext::checkParams()
778{
779    Trace::InstRecord::setParams();
780}
781
782