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