exetrace.cc revision 4046:ef34b290091e
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()
127{
128    ostream &outs = Trace::output();
129
130    DPRINTF(Sparc, "Instruction: %#X\n", staticInst->machInst);
131    if (flags[PRINT_REG_DELTA])
132    {
133#if THE_ISA == SPARC_ISA
134        //Don't print what happens for each micro-op, just print out
135        //once at the last op, and for regular instructions.
136        if(!staticInst->isMicroOp() || staticInst->isLastMicroOp())
137        {
138            static uint64_t regs[32] = {
139                0, 0, 0, 0, 0, 0, 0, 0,
140                0, 0, 0, 0, 0, 0, 0, 0,
141                0, 0, 0, 0, 0, 0, 0, 0,
142                0, 0, 0, 0, 0, 0, 0, 0};
143            static uint64_t ccr = 0;
144            static uint64_t y = 0;
145            static uint64_t floats[32];
146            uint64_t newVal;
147            static const char * prefixes[4] = {"G", "O", "L", "I"};
148
149            outs << hex;
150            outs << "PC = " << thread->readNextPC();
151            outs << " NPC = " << thread->readNextNPC();
152            newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2);
153            //newVal = thread->readMiscReg(SparcISA::MISCREG_CCR);
154            if(newVal != ccr)
155            {
156                outs << " CCR = " << newVal;
157                ccr = newVal;
158            }
159            newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 1);
160            //newVal = thread->readMiscReg(SparcISA::MISCREG_Y);
161            if(newVal != y)
162            {
163                outs << " Y = " << newVal;
164                y = newVal;
165            }
166            for(int y = 0; y < 4; y++)
167            {
168                for(int x = 0; x < 8; x++)
169                {
170                    int index = x + 8 * y;
171                    newVal = thread->readIntReg(index);
172                    if(regs[index] != newVal)
173                    {
174                        outs << " " << prefixes[y] << dec << x << " = " << hex << newVal;
175                        regs[index] = newVal;
176                    }
177                }
178            }
179            for(int y = 0; y < 32; y++)
180            {
181                newVal = thread->readFloatRegBits(2 * y, 64);
182                if(floats[y] != newVal)
183                {
184                    outs << " F" << dec << (2 * y) << " = " << hex << newVal;
185                    floats[y] = newVal;
186                }
187            }
188            outs << dec << endl;
189        }
190#endif
191    }
192    else if (flags[INTEL_FORMAT]) {
193#if FULL_SYSTEM
194        bool is_trace_system = (thread->getCpuPtr()->system->name() == trace_system);
195#else
196        bool is_trace_system = true;
197#endif
198        if (is_trace_system) {
199            ccprintf(outs, "%7d ) ", when);
200            outs << "0x" << hex << PC << ":\t";
201            if (staticInst->isLoad()) {
202                outs << "<RD 0x" << hex << addr;
203                outs << ">";
204            } else if (staticInst->isStore()) {
205                outs << "<WR 0x" << hex << addr;
206                outs << ">";
207            }
208            outs << endl;
209        }
210    } else {
211        if (flags[PRINT_TICKS])
212            ccprintf(outs, "%7d: ", when);
213
214        outs << thread->getCpuPtr()->name() << " ";
215
216        if (flags[TRACE_MISSPEC])
217            outs << (misspeculating ? "-" : "+") << " ";
218
219        if (flags[PRINT_THREAD_NUM])
220            outs << "T" << thread->getThreadNum() << " : ";
221
222
223        std::string sym_str;
224        Addr sym_addr;
225        if (debugSymbolTable
226            && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr)
227            && flags[PC_SYMBOL]) {
228            if (PC != sym_addr)
229                sym_str += csprintf("+%d", PC - sym_addr);
230            outs << "@" << sym_str << " : ";
231        }
232        else {
233            outs << "0x" << hex << PC << " : ";
234        }
235
236        //
237        //  Print decoded instruction
238        //
239
240#if defined(__GNUC__) && (__GNUC__ < 3)
241        // There's a bug in gcc 2.x library that prevents setw()
242        // from working properly on strings
243        string mc(staticInst->disassemble(PC, debugSymbolTable));
244        while (mc.length() < 26)
245            mc += " ";
246        outs << mc;
247#else
248        outs << setw(26) << left << staticInst->disassemble(PC, debugSymbolTable);
249#endif
250
251        outs << " : ";
252
253        if (flags[PRINT_OP_CLASS]) {
254            outs << opClassStrings[staticInst->opClass()] << " : ";
255        }
256
257        if (flags[PRINT_RESULT_DATA] && data_status != DataInvalid) {
258            outs << " D=";
259#if 0
260            if (data_status == DataDouble)
261                ccprintf(outs, "%f", data.as_double);
262            else
263                ccprintf(outs, "%#018x", data.as_int);
264#else
265            ccprintf(outs, "%#018x", data.as_int);
266#endif
267        }
268
269        if (flags[PRINT_EFF_ADDR] && addr_valid)
270            outs << " A=0x" << hex << addr;
271
272        if (flags[PRINT_INT_REGS] && regs_valid) {
273            for (int i = 0; i < TheISA::NumIntRegs;)
274                for (int j = i + 1; i <= j; i++)
275                    ccprintf(outs, "r%02d = %#018x%s", i,
276                            iregs->regs.readReg(i),
277                            ((i == j) ? "\n" : "    "));
278            outs << "\n";
279        }
280
281        if (flags[PRINT_FETCH_SEQ] && fetch_seq_valid)
282            outs << "  FetchSeq=" << dec << fetch_seq;
283
284        if (flags[PRINT_CP_SEQ] && cp_seq_valid)
285            outs << "  CPSeq=" << dec << cp_seq;
286
287        //
288        //  End of line...
289        //
290        outs << endl;
291    }
292#if THE_ISA == SPARC_ISA && FULL_SYSTEM
293    // Compare
294    if (flags[LEGION_LOCKSTEP])
295    {
296        bool compared = false;
297        bool diffPC   = false;
298        bool diffCC   = false;
299        bool diffInst = false;
300        bool diffIntRegs = false;
301        bool diffFpRegs = false;
302        bool diffTpc = false;
303        bool diffTnpc = false;
304        bool diffTstate = false;
305        bool diffTt = false;
306        bool diffTba = false;
307        bool diffHpstate = false;
308        bool diffHtstate = false;
309        bool diffHtba = false;
310        bool diffPstate = false;
311        bool diffY = false;
312        bool diffFsr = false;
313        bool diffCcr = false;
314        bool diffTl = false;
315        bool diffGl = false;
316        bool diffAsi = false;
317        bool diffPil = false;
318        bool diffCwp = false;
319        bool diffCansave = false;
320        bool diffCanrestore = false;
321        bool diffOtherwin = false;
322        bool diffCleanwin = false;
323        bool diffTlb = false;
324        Addr m5Pc, lgnPc;
325
326        // We took a trap on a micro-op...
327        if (wasMicro && !staticInst->isMicroOp())
328        {
329            // let's skip comparing this tick
330            while (!compared)
331                if (shared_data->flags == OWN_M5) {
332                    shared_data->flags = OWN_LEGION;
333                    compared = true;
334                }
335            compared = false;
336            wasMicro = false;
337        }
338
339        if (staticInst->isLastMicroOp())
340            wasMicro = false;
341        else if (staticInst->isMicroOp())
342            wasMicro = true;
343
344
345        if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) {
346            while (!compared) {
347                if (shared_data->flags == OWN_M5) {
348                    m5Pc = PC & TheISA::PAddrImplMask;
349                    if (bits(shared_data->pstate,3,3)) {
350                        m5Pc &= mask(32);
351                    }
352                    lgnPc = shared_data->pc & TheISA::PAddrImplMask;
353                    if (lgnPc != m5Pc)
354                       diffPC = true;
355
356                    if (shared_data->cycle_count !=
357                            thread->getCpuPtr()->instCount())
358                        diffCC = true;
359
360                    if (shared_data->instruction !=
361                            (SparcISA::MachInst)staticInst->machInst) {
362                        diffInst = true;
363                    }
364                    // assume we have %g0 working correctly
365                    for (int i = 1; i < TheISA::NumIntArchRegs; i++) {
366                        if (thread->readIntReg(i) != shared_data->intregs[i]) {
367                            diffIntRegs = true;
368                        }
369                    }
370                    for (int i = 0; i < TheISA::NumFloatRegs/2; i++) {
371                        if (thread->readFloatRegBits(i*2,FloatRegFile::DoubleWidth) != shared_data->fpregs[i]) {
372                            diffFpRegs = true;
373                        }
374                    }
375                            uint64_t oldTl = thread->readMiscReg(MISCREG_TL);
376                    if (oldTl != shared_data->tl)
377                        diffTl = true;
378                    for (int i = 1; i <= MaxTL; i++) {
379                        thread->setMiscReg(MISCREG_TL, i);
380                        if (thread->readMiscReg(MISCREG_TPC) !=
381                                shared_data->tpc[i-1])
382                            diffTpc = true;
383                        if (thread->readMiscReg(MISCREG_TNPC) !=
384                                shared_data->tnpc[i-1])
385                            diffTnpc = true;
386                        if (thread->readMiscReg(MISCREG_TSTATE) !=
387                                shared_data->tstate[i-1])
388                            diffTstate = true;
389                        if (thread->readMiscReg(MISCREG_TT) !=
390                                shared_data->tt[i-1])
391                            diffTt = true;
392                        if (thread->readMiscReg(MISCREG_HTSTATE) !=
393                                shared_data->htstate[i-1])
394                            diffHtstate = true;
395                    }
396                    thread->setMiscReg(MISCREG_TL, oldTl);
397
398                    if(shared_data->tba != thread->readMiscReg(MISCREG_TBA))
399                        diffTba = true;
400                    //When the hpstate register is read by an instruction,
401                    //legion has bit 11 set. When it's in storage, it doesn't.
402                    //Since we don't directly support seperate interpretations
403                    //of the registers like that, the bit is always set to 1 and
404                    //we just don't compare it. It's not supposed to matter
405                    //anyway.
406                    if((shared_data->hpstate | (1 << 11)) != thread->readMiscReg(MISCREG_HPSTATE))
407                        diffHpstate = true;
408                    if(shared_data->htba != thread->readMiscReg(MISCREG_HTBA))
409                        diffHtba = true;
410                    if(shared_data->pstate != thread->readMiscReg(MISCREG_PSTATE))
411                        diffPstate = true;
412                    //if(shared_data->y != thread->readMiscReg(MISCREG_Y))
413                    if(shared_data->y !=
414                            thread->readIntReg(NumIntArchRegs + 1))
415                        diffY = true;
416                    if(shared_data->fsr != thread->readMiscReg(MISCREG_FSR)) {
417                        diffFsr = true;
418                        if (mbits(shared_data->fsr, 63,10) ==
419                                mbits(thread->readMiscReg(MISCREG_FSR), 63,10)) {
420                            thread->setMiscReg(MISCREG_FSR, shared_data->fsr);
421                            diffFsr = false;
422                        }
423                    }
424                    //if(shared_data->ccr != thread->readMiscReg(MISCREG_CCR))
425                    if(shared_data->ccr !=
426                            thread->readIntReg(NumIntArchRegs + 2))
427                        diffCcr = true;
428                    if(shared_data->gl != thread->readMiscReg(MISCREG_GL))
429                        diffGl = true;
430                    if(shared_data->asi != thread->readMiscReg(MISCREG_ASI))
431                        diffAsi = true;
432                    if(shared_data->pil != thread->readMiscReg(MISCREG_PIL))
433                        diffPil = true;
434                    if(shared_data->cwp != thread->readMiscReg(MISCREG_CWP))
435                        diffCwp = true;
436                    //if(shared_data->cansave != thread->readMiscReg(MISCREG_CANSAVE))
437                    if(shared_data->cansave !=
438                            thread->readIntReg(NumIntArchRegs + 3))
439                        diffCansave = true;
440                    //if(shared_data->canrestore !=
441                    //	    thread->readMiscReg(MISCREG_CANRESTORE))
442                    if(shared_data->canrestore !=
443                            thread->readIntReg(NumIntArchRegs + 4))
444                        diffCanrestore = true;
445                    //if(shared_data->otherwin != thread->readMiscReg(MISCREG_OTHERWIN))
446                    if(shared_data->otherwin !=
447                            thread->readIntReg(NumIntArchRegs + 6))
448                        diffOtherwin = true;
449                    //if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN))
450                    if(shared_data->cleanwin !=
451                            thread->readIntReg(NumIntArchRegs + 5))
452                        diffCleanwin = true;
453
454                    for (int i = 0; i < 64; i++) {
455                        if (shared_data->itb[i] !=  thread->getITBPtr()->TteRead(i))
456                                diffTlb = true;
457                        if (shared_data->dtb[i] !=  thread->getDTBPtr()->TteRead(i))
458                                diffTlb = true;
459                    }
460
461                    if (diffPC || diffCC || diffInst || diffIntRegs ||
462                         diffFpRegs || diffTpc || diffTnpc || diffTstate ||
463                         diffTt || diffHpstate || diffHtstate || diffHtba ||
464                         diffPstate || diffY || diffCcr || diffTl || diffFsr ||
465                         diffGl || diffAsi || diffPil || diffCwp || diffCansave ||
466                         diffCanrestore || diffOtherwin || diffCleanwin || diffTlb)
467                       {
468
469                        outs << "Differences found between M5 and Legion:";
470                        if (diffPC)
471                            outs << " [PC]";
472                        if (diffCC)
473                            outs << " [CC]";
474                        if (diffInst)
475                            outs << " [Instruction]";
476                        if (diffIntRegs)
477                            outs << " [IntRegs]";
478                        if (diffFpRegs)
479                            outs << " [FpRegs]";
480                        if (diffTpc)
481                            outs << " [Tpc]";
482                        if (diffTnpc)
483                            outs << " [Tnpc]";
484                        if (diffTstate)
485                            outs << " [Tstate]";
486                        if (diffTt)
487                            outs << " [Tt]";
488                        if (diffHpstate)
489                            outs << " [Hpstate]";
490                        if (diffHtstate)
491                            outs << " [Htstate]";
492                        if (diffHtba)
493                            outs << " [Htba]";
494                        if (diffPstate)
495                            outs << " [Pstate]";
496                        if (diffY)
497                            outs << " [Y]";
498                        if (diffFsr)
499                            outs << " [FSR]";
500                        if (diffCcr)
501                            outs << " [Ccr]";
502                        if (diffTl)
503                            outs << " [Tl]";
504                        if (diffGl)
505                            outs << " [Gl]";
506                        if (diffAsi)
507                            outs << " [Asi]";
508                        if (diffPil)
509                            outs << " [Pil]";
510                        if (diffCwp)
511                            outs << " [Cwp]";
512                        if (diffCansave)
513                            outs << " [Cansave]";
514                        if (diffCanrestore)
515                            outs << " [Canrestore]";
516                        if (diffOtherwin)
517                            outs << " [Otherwin]";
518                        if (diffCleanwin)
519                            outs << " [Cleanwin]";
520                        if (diffTlb)
521                            outs << " [Tlb]";
522                        outs << endl << endl;
523
524                        outs << right << setfill(' ') << setw(15)
525                             << "M5 PC: " << "0x"<< setw(16) << setfill('0')
526                             << hex << m5Pc << endl;
527                        outs << setfill(' ') << setw(15)
528                             << "Legion PC: " << "0x"<< setw(16) << setfill('0') << hex
529                             << lgnPc << endl << endl;
530
531                        outs << right << setfill(' ') << setw(15)
532                             << "M5 CC: " << "0x"<< setw(16) << setfill('0')
533                             << hex << thread->getCpuPtr()->instCount() << endl;
534                        outs << setfill(' ') << setw(15)
535                             << "Legion CC: " << "0x"<< setw(16) << setfill('0') << hex
536                             << shared_data->cycle_count << endl << endl;
537
538                        outs << setfill(' ') << setw(15)
539                             << "M5 Inst: "  << "0x"<< setw(8)
540                             << setfill('0') << hex << staticInst->machInst
541                             << staticInst->disassemble(m5Pc, debugSymbolTable)
542                             << endl;
543
544                        StaticInstPtr legionInst =
545                            StaticInst::decode(makeExtMI(shared_data->instruction,
546                                        thread));
547                        outs << setfill(' ') << setw(15)
548                             << " Legion Inst: "
549                             << "0x" << setw(8) << setfill('0') << hex
550                             << shared_data->instruction
551                             << legionInst->disassemble(lgnPc, debugSymbolTable)
552                             << endl << endl;
553
554                        printSectionHeader(outs, "General State");
555                        printColumnLabels(outs);
556                        printRegPair(outs, "HPstate",
557                                thread->readMiscReg(MISCREG_HPSTATE),
558                                shared_data->hpstate | (1 << 11));
559                        printRegPair(outs, "Htba",
560                                thread->readMiscReg(MISCREG_HTBA),
561                                shared_data->htba);
562                        printRegPair(outs, "Pstate",
563                                thread->readMiscReg(MISCREG_PSTATE),
564                                shared_data->pstate);
565                        printRegPair(outs, "Y",
566                                //thread->readMiscReg(MISCREG_Y),
567                                thread->readIntReg(NumIntArchRegs + 1),
568                                shared_data->y);
569                        printRegPair(outs, "FSR",
570                                thread->readMiscReg(MISCREG_FSR),
571                                shared_data->fsr);
572                        printRegPair(outs, "Ccr",
573                                //thread->readMiscReg(MISCREG_CCR),
574                                thread->readIntReg(NumIntArchRegs + 2),
575                                shared_data->ccr);
576                        printRegPair(outs, "Tl",
577                                thread->readMiscReg(MISCREG_TL),
578                                shared_data->tl);
579                        printRegPair(outs, "Gl",
580                                thread->readMiscReg(MISCREG_GL),
581                                shared_data->gl);
582                        printRegPair(outs, "Asi",
583                                thread->readMiscReg(MISCREG_ASI),
584                                shared_data->asi);
585                        printRegPair(outs, "Pil",
586                                thread->readMiscReg(MISCREG_PIL),
587                                shared_data->pil);
588                        printRegPair(outs, "Cwp",
589                                thread->readMiscReg(MISCREG_CWP),
590                                shared_data->cwp);
591                        printRegPair(outs, "Cansave",
592                                //thread->readMiscReg(MISCREG_CANSAVE),
593                                thread->readIntReg(NumIntArchRegs + 3),
594                                shared_data->cansave);
595                        printRegPair(outs, "Canrestore",
596                                //thread->readMiscReg(MISCREG_CANRESTORE),
597                                thread->readIntReg(NumIntArchRegs + 4),
598                                shared_data->canrestore);
599                        printRegPair(outs, "Otherwin",
600                                //thread->readMiscReg(MISCREG_OTHERWIN),
601                                thread->readIntReg(NumIntArchRegs + 6),
602                                shared_data->otherwin);
603                        printRegPair(outs, "Cleanwin",
604                                //thread->readMiscReg(MISCREG_CLEANWIN),
605                                thread->readIntReg(NumIntArchRegs + 5),
606                                shared_data->cleanwin);
607                        outs << endl;
608                        for (int i = 1; i <= MaxTL; i++) {
609                            printLevelHeader(outs, i);
610                            printColumnLabels(outs);
611                            thread->setMiscReg(MISCREG_TL, i);
612                            printRegPair(outs, "Tpc",
613                                    thread->readMiscReg(MISCREG_TPC),
614                                    shared_data->tpc[i-1]);
615                            printRegPair(outs, "Tnpc",
616                                    thread->readMiscReg(MISCREG_TNPC),
617                                    shared_data->tnpc[i-1]);
618                            printRegPair(outs, "Tstate",
619                                    thread->readMiscReg(MISCREG_TSTATE),
620                                    shared_data->tstate[i-1]);
621                            printRegPair(outs, "Tt",
622                                    thread->readMiscReg(MISCREG_TT),
623                                    shared_data->tt[i-1]);
624                            printRegPair(outs, "Htstate",
625                                    thread->readMiscReg(MISCREG_HTSTATE),
626                                    shared_data->htstate[i-1]);
627                        }
628                        thread->setMiscReg(MISCREG_TL, oldTl);
629                        outs << endl;
630
631                        printSectionHeader(outs, "General Purpose Registers");
632                        static const char * regtypes[4] = {"%g", "%o", "%l", "%i"};
633                        for(int y = 0; y < 4; y++) {
634                            for(int x = 0; x < 8; x++) {
635                                char label[8];
636                                sprintf(label, "%s%d", regtypes[y], x);
637                                printRegPair(outs, label,
638                                        thread->readIntReg(y*8+x),
639                                        shared_data->intregs[y*8+x]);
640                            }
641                        }
642                        if (diffFpRegs) {
643                            for (int x = 0; x < 32; x++) {
644                                char label[8];
645                                sprintf(label, "%%f%d", x);
646                                printRegPair(outs, label,
647                                 thread->readFloatRegBits(x*2,FloatRegFile::DoubleWidth),
648                                 shared_data->fpregs[x]);
649                            }
650                        }
651                        if (diffTlb) {
652                            printColumnLabels(outs);
653                            char label[8];
654                            for (int x = 0; x < 64; x++) {
655                                if (shared_data->itb[x] !=  ULL(0xFFFFFFFFFFFFFFFF) ||
656                                    thread->getITBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF))  {
657                                        sprintf(label, "I-TLB:%02d", x);
658                                        printRegPair(outs, label, thread->getITBPtr()->TteRead(x),
659                                                shared_data->itb[x]);
660                                }
661                            }
662                            for (int x = 0; x < 64; x++) {
663                                if (shared_data->dtb[x] !=  ULL(0xFFFFFFFFFFFFFFFF) ||
664                                    thread->getDTBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF))  {
665                                        sprintf(label, "D-TLB:%02d", x);
666                                        printRegPair(outs, label, thread->getDTBPtr()->TteRead(x),
667                                                shared_data->dtb[x]);
668                                }
669                            }
670                            thread->getITBPtr()->dumpAll();
671                            thread->getDTBPtr()->dumpAll();
672                        }
673
674                        diffcount++;
675                        if (diffcount > 3)
676                            fatal("Differences found between Legion and M5\n");
677                    } else
678                        diffcount = 0;
679
680                    compared = true;
681                    shared_data->flags = OWN_LEGION;
682                }
683            } // while
684        } // if not microop
685    }
686#endif
687}
688
689
690vector<bool> Trace::InstRecord::flags(NUM_BITS);
691string Trace::InstRecord::trace_system;
692
693////////////////////////////////////////////////////////////////////////
694//
695// Parameter space for per-cycle execution address tracing options.
696// Derive from ParamContext so we can override checkParams() function.
697//
698class ExecutionTraceParamContext : public ParamContext
699{
700  public:
701    ExecutionTraceParamContext(const string &_iniSection)
702        : ParamContext(_iniSection)
703        {
704        }
705
706    void checkParams();	// defined at bottom of file
707};
708
709ExecutionTraceParamContext exeTraceParams("exetrace");
710
711Param<bool> exe_trace_spec(&exeTraceParams, "speculative",
712                           "capture speculative instructions", true);
713
714Param<bool> exe_trace_print_cycle(&exeTraceParams, "print_cycle",
715                                  "print cycle number", true);
716Param<bool> exe_trace_print_opclass(&exeTraceParams, "print_opclass",
717                                  "print op class", true);
718Param<bool> exe_trace_print_thread(&exeTraceParams, "print_thread",
719                                  "print thread number", true);
720Param<bool> exe_trace_print_effaddr(&exeTraceParams, "print_effaddr",
721                                  "print effective address", true);
722Param<bool> exe_trace_print_data(&exeTraceParams, "print_data",
723                                  "print result data", true);
724Param<bool> exe_trace_print_iregs(&exeTraceParams, "print_iregs",
725                                  "print all integer regs", false);
726Param<bool> exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq",
727                                  "print fetch sequence number", false);
728Param<bool> exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq",
729                                  "print correct-path sequence number", false);
730Param<bool> exe_trace_print_reg_delta(&exeTraceParams, "print_reg_delta",
731                                  "print which registers changed to what", false);
732Param<bool> exe_trace_pc_symbol(&exeTraceParams, "pc_symbol",
733                                  "Use symbols for the PC if available", true);
734Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format",
735                                   "print trace in intel compatible format", false);
736Param<bool> exe_trace_legion_lockstep(&exeTraceParams, "legion_lockstep",
737                                   "Compare sim state to legion state every cycle",
738                                   false);
739Param<string> exe_trace_system(&exeTraceParams, "trace_system",
740                                   "print trace of which system (client or server)",
741                                   "client");
742
743
744//
745// Helper function for ExecutionTraceParamContext::checkParams() just
746// to get us into the InstRecord namespace
747//
748void
749Trace::InstRecord::setParams()
750{
751    flags[TRACE_MISSPEC]     = exe_trace_spec;
752
753    flags[PRINT_TICKS]       = exe_trace_print_cycle;
754    flags[PRINT_OP_CLASS]    = exe_trace_print_opclass;
755    flags[PRINT_THREAD_NUM]  = exe_trace_print_thread;
756    flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr;
757    flags[PRINT_EFF_ADDR]    = exe_trace_print_data;
758    flags[PRINT_INT_REGS]    = exe_trace_print_iregs;
759    flags[PRINT_FETCH_SEQ]   = exe_trace_print_fetchseq;
760    flags[PRINT_CP_SEQ]      = exe_trace_print_cp_seq;
761    flags[PRINT_REG_DELTA]   = exe_trace_print_reg_delta;
762    flags[PC_SYMBOL]         = exe_trace_pc_symbol;
763    flags[INTEL_FORMAT]      = exe_trace_intel_format;
764    flags[LEGION_LOCKSTEP]   = exe_trace_legion_lockstep;
765    trace_system	     = exe_trace_system;
766
767    // If were going to be in lockstep with Legion
768    // Setup shared memory, and get otherwise ready
769    if (flags[LEGION_LOCKSTEP]) {
770        int shmfd = shmget('M' << 24 | getuid(), sizeof(SharedData), 0777);
771        if (shmfd < 0)
772            fatal("Couldn't get shared memory fd. Is Legion running?");
773
774        shared_data = (SharedData*)shmat(shmfd, NULL, SHM_RND);
775        if (shared_data == (SharedData*)-1)
776            fatal("Couldn't allocate shared memory");
777
778        if (shared_data->flags != OWN_M5)
779            fatal("Shared memory has invalid owner");
780
781        if (shared_data->version != VERSION)
782            fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION,
783                    shared_data->version);
784
785        // step legion forward one cycle so we can get register values
786        shared_data->flags = OWN_LEGION;
787    }
788}
789
790void
791ExecutionTraceParamContext::checkParams()
792{
793    Trace::InstRecord::setParams();
794}
795
796