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