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