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