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