exetrace.cc revision 3972:2c65c89843c5
1/*
2 * Copyright (c) 2001-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Steve Reinhardt
29 *          Lisa Hsu
30 *          Nathan Binkert
31 *          Steve Raasch
32 */
33
34#include <fstream>
35#include <iomanip>
36#include <sys/ipc.h>
37#include <sys/shm.h>
38
39#include "arch/regfile.hh"
40#include "arch/utility.hh"
41#include "base/loader/symtab.hh"
42#include "config/full_system.hh"
43#include "cpu/base.hh"
44#include "cpu/exetrace.hh"
45#include "cpu/static_inst.hh"
46#include "sim/param.hh"
47#include "sim/system.hh"
48
49#if FULL_SYSTEM
50#include "arch/tlb.hh"
51#endif
52
53//XXX This is temporary
54#include "arch/isa_specific.hh"
55#include "cpu/m5legion_interface.h"
56
57using namespace std;
58using namespace TheISA;
59
60#if THE_ISA == SPARC_ISA && FULL_SYSTEM
61static int diffcount = 0;
62static bool wasMicro = false;
63#endif
64
65namespace Trace {
66SharedData *shared_data = NULL;
67}
68
69////////////////////////////////////////////////////////////////////////
70//
71//  Methods for the InstRecord object
72//
73
74#if THE_ISA == SPARC_ISA
75
76inline char * genCenteredLabel(int length, char * buffer, char * label)
77{
78    int labelLength = strlen(label);
79    assert(labelLength <= length);
80    int leftPad = (length - labelLength) / 2;
81    int rightPad = length - leftPad - labelLength;
82    char format[64];
83    sprintf(format, "%%%ds%%s%%%ds", leftPad, rightPad);
84    sprintf(buffer, format, "", label, "");
85    return buffer;
86}
87
88inline void printRegPair(ostream & os, char const * title, uint64_t a, uint64_t b)
89{
90    ccprintf(os, "  %16s  |  %#018x   %s   %#-018x  \n",
91            title, a, (a == b) ? "|" : "X", b);
92}
93
94inline void printColumnLabels(ostream & os)
95{
96    static char * regLabel = genCenteredLabel(16, new char[17], "Register");
97    static char * m5Label = genCenteredLabel(18, new char[18], "M5");
98    static char * legionLabel = genCenteredLabel(18, new char[18], "Legion");
99    ccprintf(os, "  %s  |  %s   |   %s  \n", regLabel, m5Label, legionLabel);
100    ccprintf(os, "--------------------+-----------------------+-----------------------\n");
101}
102
103inline void printSectionHeader(ostream & os, char * name)
104{
105    char sectionString[70];
106    genCenteredLabel(69, sectionString, name);
107    ccprintf(os, "====================================================================\n");
108    ccprintf(os, "%69s\n", sectionString);
109    ccprintf(os, "====================================================================\n");
110}
111
112inline void printLevelHeader(ostream & os, int level)
113{
114    char sectionString[70];
115    char levelName[70];
116    sprintf(levelName, "Trap stack level %d", level);
117    genCenteredLabel(69, sectionString, levelName);
118    ccprintf(os, "====================================================================\n");
119    ccprintf(os, "%69s\n", sectionString);
120    ccprintf(os, "====================================================================\n");
121}
122
123#endif
124
125void
126Trace::InstRecord::dump(ostream &outs)
127{
128    DPRINTF(Sparc, "Instruction: %#X\n", staticInst->machInst);
129    if (flags[PRINT_REG_DELTA])
130    {
131#if THE_ISA == SPARC_ISA
132        //Don't print what happens for each micro-op, just print out
133        //once at the last op, and for regular instructions.
134        if(!staticInst->isMicroOp() || staticInst->isLastMicroOp())
135        {
136            static uint64_t regs[32] = {
137                0, 0, 0, 0, 0, 0, 0, 0,
138                0, 0, 0, 0, 0, 0, 0, 0,
139                0, 0, 0, 0, 0, 0, 0, 0,
140                0, 0, 0, 0, 0, 0, 0, 0};
141            static uint64_t ccr = 0;
142            static uint64_t y = 0;
143            static uint64_t floats[32];
144            uint64_t newVal;
145            static const char * prefixes[4] = {"G", "O", "L", "I"};
146
147            outs << hex;
148            outs << "PC = " << thread->readNextPC();
149            outs << " NPC = " << thread->readNextNPC();
150            newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2);
151            //newVal = thread->readMiscReg(SparcISA::MISCREG_CCR);
152            if(newVal != ccr)
153            {
154                outs << " CCR = " << newVal;
155                ccr = newVal;
156            }
157            newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 1);
158            //newVal = thread->readMiscReg(SparcISA::MISCREG_Y);
159            if(newVal != y)
160            {
161                outs << " Y = " << newVal;
162                y = newVal;
163            }
164            for(int y = 0; y < 4; y++)
165            {
166                for(int x = 0; x < 8; x++)
167                {
168                    int index = x + 8 * y;
169                    newVal = thread->readIntReg(index);
170                    if(regs[index] != newVal)
171                    {
172                        outs << " " << prefixes[y] << dec << x << " = " << hex << newVal;
173                        regs[index] = newVal;
174                    }
175                }
176            }
177            for(int y = 0; y < 32; y++)
178            {
179                newVal = thread->readFloatRegBits(2 * y, 64);
180                if(floats[y] != newVal)
181                {
182                    outs << " F" << dec << (2 * y) << " = " << hex << newVal;
183                    floats[y] = newVal;
184                }
185            }
186            outs << dec << endl;
187        }
188#endif
189    }
190    else if (flags[INTEL_FORMAT]) {
191#if FULL_SYSTEM
192        bool is_trace_system = (thread->getCpuPtr()->system->name() == trace_system);
193#else
194        bool is_trace_system = true;
195#endif
196        if (is_trace_system) {
197            ccprintf(outs, "%7d ) ", cycle);
198            outs << "0x" << hex << PC << ":\t";
199            if (staticInst->isLoad()) {
200                outs << "<RD 0x" << hex << addr;
201                outs << ">";
202            } else if (staticInst->isStore()) {
203                outs << "<WR 0x" << hex << addr;
204                outs << ">";
205            }
206            outs << endl;
207        }
208    } else {
209        if (flags[PRINT_CYCLE])
210            ccprintf(outs, "%7d: ", cycle);
211
212        outs << thread->getCpuPtr()->name() << " ";
213
214        if (flags[TRACE_MISSPEC])
215            outs << (misspeculating ? "-" : "+") << " ";
216
217        if (flags[PRINT_THREAD_NUM])
218            outs << "T" << thread->getThreadNum() << " : ";
219
220
221        std::string sym_str;
222        Addr sym_addr;
223        if (debugSymbolTable
224            && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr)
225            && flags[PC_SYMBOL]) {
226            if (PC != sym_addr)
227                sym_str += csprintf("+%d", PC - sym_addr);
228            outs << "@" << sym_str << " : ";
229        }
230        else {
231            outs << "0x" << hex << PC << " : ";
232        }
233
234        //
235        //  Print decoded instruction
236        //
237
238#if defined(__GNUC__) && (__GNUC__ < 3)
239        // There's a bug in gcc 2.x library that prevents setw()
240        // from working properly on strings
241        string mc(staticInst->disassemble(PC, debugSymbolTable));
242        while (mc.length() < 26)
243            mc += " ";
244        outs << mc;
245#else
246        outs << setw(26) << left << staticInst->disassemble(PC, debugSymbolTable);
247#endif
248
249        outs << " : ";
250
251        if (flags[PRINT_OP_CLASS]) {
252            outs << opClassStrings[staticInst->opClass()] << " : ";
253        }
254
255        if (flags[PRINT_RESULT_DATA] && data_status != DataInvalid) {
256            outs << " D=";
257#if 0
258            if (data_status == DataDouble)
259                ccprintf(outs, "%f", data.as_double);
260            else
261                ccprintf(outs, "%#018x", data.as_int);
262#else
263            ccprintf(outs, "%#018x", data.as_int);
264#endif
265        }
266
267        if (flags[PRINT_EFF_ADDR] && addr_valid)
268            outs << " A=0x" << hex << addr;
269
270        if (flags[PRINT_INT_REGS] && regs_valid) {
271            for (int i = 0; i < TheISA::NumIntRegs;)
272                for (int j = i + 1; i <= j; i++)
273                    ccprintf(outs, "r%02d = %#018x%s", i,
274                            iregs->regs.readReg(i),
275                            ((i == j) ? "\n" : "    "));
276            outs << "\n";
277        }
278
279        if (flags[PRINT_FETCH_SEQ] && fetch_seq_valid)
280            outs << "  FetchSeq=" << dec << fetch_seq;
281
282        if (flags[PRINT_CP_SEQ] && cp_seq_valid)
283            outs << "  CPSeq=" << dec << cp_seq;
284
285        //
286        //  End of line...
287        //
288        outs << endl;
289    }
290#if THE_ISA == SPARC_ISA && FULL_SYSTEM
291    // Compare
292    if (flags[LEGION_LOCKSTEP])
293    {
294        bool compared = false;
295        bool diffPC   = false;
296        bool diffCC   = false;
297        bool diffInst = false;
298        bool diffRegs = false;
299        bool diffTpc = false;
300        bool diffTnpc = false;
301        bool diffTstate = false;
302        bool diffTt = false;
303        bool diffTba = false;
304        bool diffHpstate = false;
305        bool diffHtstate = false;
306        bool diffHtba = false;
307        bool diffPstate = false;
308        bool diffY = false;
309        bool diffCcr = false;
310        bool diffTl = false;
311        bool diffGl = false;
312        bool diffAsi = false;
313        bool diffPil = false;
314        bool diffCwp = false;
315        bool diffCansave = false;
316        bool diffCanrestore = false;
317        bool diffOtherwin = false;
318        bool diffCleanwin = false;
319        bool diffTlb = false;
320        Addr m5Pc, lgnPc;
321
322        // We took a trap on a micro-op...
323        if (wasMicro && !staticInst->isMicroOp())
324        {
325            // let's skip comparing this cycle
326            while (!compared)
327                if (shared_data->flags == OWN_M5) {
328                    shared_data->flags = OWN_LEGION;
329                    compared = true;
330                }
331            compared = false;
332            wasMicro = false;
333        }
334
335        if (staticInst->isLastMicroOp())
336            wasMicro = false;
337        else if (staticInst->isMicroOp())
338            wasMicro = true;
339
340
341        if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) {
342            while (!compared) {
343                if (shared_data->flags == OWN_M5) {
344                    m5Pc = PC & TheISA::PAddrImplMask;
345                    lgnPc = shared_data->pc & TheISA::PAddrImplMask;
346                    if (lgnPc != m5Pc)
347                       diffPC = true;
348
349                    if (shared_data->cycle_count !=
350                            thread->getCpuPtr()->instCount())
351                        diffCC = true;
352
353                    if (shared_data->instruction !=
354                            (SparcISA::MachInst)staticInst->machInst) {
355                        diffInst = true;
356                    }
357                    for (int i = 0; i < TheISA::NumIntArchRegs; i++) {
358                        if (thread->readIntReg(i) != shared_data->intregs[i]) {
359                            diffRegs = true;
360                        }
361                    }
362                    uint64_t oldTl = thread->readMiscReg(MISCREG_TL);
363                    if (oldTl != shared_data->tl)
364                        diffTl = true;
365                    for (int i = 1; i <= MaxTL; i++) {
366                        thread->setMiscReg(MISCREG_TL, i);
367                        if (thread->readMiscReg(MISCREG_TPC) !=
368                                shared_data->tpc[i-1])
369                            diffTpc = true;
370                        if (thread->readMiscReg(MISCREG_TNPC) !=
371                                shared_data->tnpc[i-1])
372                            diffTnpc = true;
373                        if (thread->readMiscReg(MISCREG_TSTATE) !=
374                                shared_data->tstate[i-1])
375                            diffTstate = true;
376                        if (thread->readMiscReg(MISCREG_TT) !=
377                                shared_data->tt[i-1])
378                            diffTt = true;
379                        if (thread->readMiscReg(MISCREG_HTSTATE) !=
380                                shared_data->htstate[i-1])
381                            diffHtstate = true;
382                    }
383                    thread->setMiscReg(MISCREG_TL, oldTl);
384
385                    if(shared_data->tba != thread->readMiscReg(MISCREG_TBA))
386                        diffTba = true;
387                    //When the hpstate register is read by an instruction,
388                    //legion has bit 11 set. When it's in storage, it doesn't.
389                    //Since we don't directly support seperate interpretations
390                    //of the registers like that, the bit is always set to 1 and
391                    //we just don't compare it. It's not supposed to matter
392                    //anyway.
393                    if((shared_data->hpstate | (1 << 11)) != thread->readMiscReg(MISCREG_HPSTATE))
394                        diffHpstate = true;
395                    if(shared_data->htba != thread->readMiscReg(MISCREG_HTBA))
396                        diffHtba = true;
397                    if(shared_data->pstate != thread->readMiscReg(MISCREG_PSTATE))
398                        diffPstate = true;
399                    //if(shared_data->y != thread->readMiscReg(MISCREG_Y))
400                    if(shared_data->y !=
401                            thread->readIntReg(NumIntArchRegs + 1))
402                        diffY = true;
403                    //if(shared_data->ccr != thread->readMiscReg(MISCREG_CCR))
404                    if(shared_data->ccr !=
405                            thread->readIntReg(NumIntArchRegs + 2))
406                        diffCcr = true;
407                    if(shared_data->gl != thread->readMiscReg(MISCREG_GL))
408                        diffGl = true;
409                    if(shared_data->asi != thread->readMiscReg(MISCREG_ASI))
410                        diffAsi = true;
411                    if(shared_data->pil != thread->readMiscReg(MISCREG_PIL))
412                        diffPil = true;
413                    if(shared_data->cwp != thread->readMiscReg(MISCREG_CWP))
414                        diffCwp = true;
415                    //if(shared_data->cansave != thread->readMiscReg(MISCREG_CANSAVE))
416                    if(shared_data->cansave !=
417                            thread->readIntReg(NumIntArchRegs + 3))
418                        diffCansave = true;
419                    //if(shared_data->canrestore !=
420                    //	    thread->readMiscReg(MISCREG_CANRESTORE))
421                    if(shared_data->canrestore !=
422                            thread->readMiscReg(NumIntArchRegs + 4))
423                        diffCanrestore = true;
424                    //if(shared_data->otherwin != thread->readMiscReg(MISCREG_OTHERWIN))
425                    if(shared_data->otherwin !=
426                            thread->readIntReg(NumIntArchRegs + 5))
427                        diffOtherwin = true;
428                    //if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN))
429                    if(shared_data->cleanwin !=
430                            thread->readMiscReg(NumIntArchRegs + 6))
431                        diffCleanwin = true;
432
433                    for (int i = 0; i < 64; i++) {
434                        if (shared_data->itb[i] !=  thread->getITBPtr()->TteRead(i))
435                                diffTlb = true;
436                        if (shared_data->dtb[i] !=  thread->getDTBPtr()->TteRead(i))
437                                diffTlb = true;
438                    }
439
440                    if ((diffPC || diffCC || diffInst || diffRegs || diffTpc ||
441                            diffTnpc || diffTstate || diffTt || diffHpstate ||
442                            diffHtstate || diffHtba || diffPstate || diffY ||
443                            diffCcr || diffTl || diffGl || diffAsi || diffPil ||
444                            diffCwp || diffCansave || diffCanrestore ||
445                            diffOtherwin || diffCleanwin || diffTlb)
446                        && !((staticInst->machInst & 0xC1F80000) == 0x81D00000)
447                        && !(((staticInst->machInst & 0xC0000000) == 0xC0000000)
448                            && shared_data->tl == thread->readMiscReg(MISCREG_TL) + 1)
449                       ) {
450
451                        outs << "Differences found between M5 and Legion:";
452                        if (diffPC)
453                            outs << " [PC]";
454                        if (diffCC)
455                            outs << " [CC]";
456                        if (diffInst)
457                            outs << " [Instruction]";
458                        if (diffRegs)
459                            outs << " [IntRegs]";
460                        if (diffTpc)
461                            outs << " [Tpc]";
462                        if (diffTnpc)
463                            outs << " [Tnpc]";
464                        if (diffTstate)
465                            outs << " [Tstate]";
466                        if (diffTt)
467                            outs << " [Tt]";
468                        if (diffHpstate)
469                            outs << " [Hpstate]";
470                        if (diffHtstate)
471                            outs << " [Htstate]";
472                        if (diffHtba)
473                            outs << " [Htba]";
474                        if (diffPstate)
475                            outs << " [Pstate]";
476                        if (diffY)
477                            outs << " [Y]";
478                        if (diffCcr)
479                            outs << " [Ccr]";
480                        if (diffTl)
481                            outs << " [Tl]";
482                        if (diffGl)
483                            outs << " [Gl]";
484                        if (diffAsi)
485                            outs << " [Asi]";
486                        if (diffPil)
487                            outs << " [Pil]";
488                        if (diffCwp)
489                            outs << " [Cwp]";
490                        if (diffCansave)
491                            outs << " [Cansave]";
492                        if (diffCanrestore)
493                            outs << " [Canrestore]";
494                        if (diffOtherwin)
495                            outs << " [Otherwin]";
496                        if (diffCleanwin)
497                            outs << " [Cleanwin]";
498                        if (diffTlb)
499                            outs << " [Tlb]";
500                        outs << endl << endl;
501
502                        outs << right << setfill(' ') << setw(15)
503                             << "M5 PC: " << "0x"<< setw(16) << setfill('0')
504                             << hex << m5Pc << endl;
505                        outs << setfill(' ') << setw(15)
506                             << "Legion PC: " << "0x"<< setw(16) << setfill('0') << hex
507                             << lgnPc << endl << endl;
508
509                        outs << right << setfill(' ') << setw(15)
510                             << "M5 CC: " << "0x"<< setw(16) << setfill('0')
511                             << hex << thread->getCpuPtr()->instCount() << endl;
512                        outs << setfill(' ') << setw(15)
513                             << "Legion CC: " << "0x"<< setw(16) << setfill('0') << hex
514                             << shared_data->cycle_count << endl << endl;
515
516                        outs << setfill(' ') << setw(15)
517                             << "M5 Inst: "  << "0x"<< setw(8)
518                             << setfill('0') << hex << staticInst->machInst
519                             << staticInst->disassemble(m5Pc, debugSymbolTable)
520                             << endl;
521
522                        StaticInstPtr legionInst =
523                            StaticInst::decode(makeExtMI(shared_data->instruction,
524                                        thread));
525                        outs << setfill(' ') << setw(15)
526                             << " Legion Inst: "
527                             << "0x" << setw(8) << setfill('0') << hex
528                             << shared_data->instruction
529                             << legionInst->disassemble(lgnPc, debugSymbolTable)
530                             << endl << endl;
531
532                        printSectionHeader(outs, "General State");
533                        printColumnLabels(outs);
534                        printRegPair(outs, "HPstate",
535                                thread->readMiscReg(MISCREG_HPSTATE),
536                                shared_data->hpstate | (1 << 11));
537                        printRegPair(outs, "Htba",
538                                thread->readMiscReg(MISCREG_HTBA),
539                                shared_data->htba);
540                        printRegPair(outs, "Pstate",
541                                thread->readMiscReg(MISCREG_PSTATE),
542                                shared_data->pstate);
543                        printRegPair(outs, "Y",
544                                //thread->readMiscReg(MISCREG_Y),
545                                thread->readMiscReg(NumIntArchRegs + 1),
546                                shared_data->y);
547                        printRegPair(outs, "Ccr",
548                                //thread->readMiscReg(MISCREG_CCR),
549                                thread->readMiscReg(NumIntArchRegs + 2),
550                                shared_data->ccr);
551                        printRegPair(outs, "Tl",
552                                thread->readMiscReg(MISCREG_TL),
553                                shared_data->tl);
554                        printRegPair(outs, "Gl",
555                                thread->readMiscReg(MISCREG_GL),
556                                shared_data->gl);
557                        printRegPair(outs, "Asi",
558                                thread->readMiscReg(MISCREG_ASI),
559                                shared_data->asi);
560                        printRegPair(outs, "Pil",
561                                thread->readMiscReg(MISCREG_PIL),
562                                shared_data->pil);
563                        printRegPair(outs, "Cwp",
564                                thread->readMiscReg(MISCREG_CWP),
565                                shared_data->cwp);
566                        printRegPair(outs, "Cansave",
567                                //thread->readMiscReg(MISCREG_CANSAVE),
568                                thread->readIntReg(NumIntArchRegs + 3),
569                                shared_data->cansave);
570                        printRegPair(outs, "Canrestore",
571                                //thread->readMiscReg(MISCREG_CANRESTORE),
572                                thread->readIntReg(NumIntArchRegs + 4),
573                                shared_data->canrestore);
574                        printRegPair(outs, "Otherwin",
575                                //thread->readMiscReg(MISCREG_OTHERWIN),
576                                thread->readIntReg(NumIntArchRegs + 5),
577                                shared_data->otherwin);
578                        printRegPair(outs, "Cleanwin",
579                                //thread->readMiscReg(MISCREG_CLEANWIN),
580                                thread->readIntReg(NumIntArchRegs + 6),
581                                shared_data->cleanwin);
582                        outs << endl;
583                        for (int i = 1; i <= MaxTL; i++) {
584                            printLevelHeader(outs, i);
585                            printColumnLabels(outs);
586                            thread->setMiscReg(MISCREG_TL, i);
587                            printRegPair(outs, "Tpc",
588                                    thread->readMiscReg(MISCREG_TPC),
589                                    shared_data->tpc[i-1]);
590                            printRegPair(outs, "Tnpc",
591                                    thread->readMiscReg(MISCREG_TNPC),
592                                    shared_data->tnpc[i-1]);
593                            printRegPair(outs, "Tstate",
594                                    thread->readMiscReg(MISCREG_TSTATE),
595                                    shared_data->tstate[i-1]);
596                            printRegPair(outs, "Tt",
597                                    thread->readMiscReg(MISCREG_TT),
598                                    shared_data->tt[i-1]);
599                            printRegPair(outs, "Htstate",
600                                    thread->readMiscReg(MISCREG_HTSTATE),
601                                    shared_data->htstate[i-1]);
602                        }
603                        thread->setMiscReg(MISCREG_TL, oldTl);
604                        outs << endl;
605
606                        printSectionHeader(outs, "General Purpose Registers");
607                        static const char * regtypes[4] = {"%g", "%o", "%l", "%i"};
608                        for(int y = 0; y < 4; y++)
609                        {
610                            for(int x = 0; x < 8; x++)
611                            {
612                                char label[8];
613                                sprintf(label, "%s%d", regtypes[y], x);
614                                printRegPair(outs, label,
615                                        thread->readIntReg(y*8+x),
616                                        shared_data->intregs[y*8+x]);
617                                /*outs << regtypes[y] << x << "         " ;
618                                outs <<  "0x" << hex << setw(16)
619                                    << thread->readIntReg(y*8+x);
620                                if (thread->readIntReg(y*8 + x)
621                                        != shared_data->intregs[y*8+x])
622                                    outs << "     X     ";
623                                else
624                                    outs << "     |     ";
625                                outs << "0x" << setw(16) << hex
626                                    << shared_data->intregs[y*8+x]
627                                    << endl;*/
628                            }
629                        }
630                        if (diffTlb) {
631                            printColumnLabels(outs);
632                            char label[8];
633                            for (int x = 0; x < 64; x++) {
634                                if (shared_data->itb[x] !=  ULL(0xFFFFFFFFFFFFFFFF) ||
635                                    thread->getITBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF))  {
636                                        sprintf(label, "I-TLB:%02d", x);
637                                        printRegPair(outs, label, thread->getITBPtr()->TteRead(x),
638                                                shared_data->itb[x]);
639                                }
640                            }
641                            for (int x = 0; x < 64; x++) {
642                                if (shared_data->dtb[x] !=  ULL(0xFFFFFFFFFFFFFFFF) ||
643                                    thread->getDTBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF))  {
644                                        sprintf(label, "D-TLB:%02d", x);
645                                        printRegPair(outs, label, thread->getDTBPtr()->TteRead(x),
646                                                shared_data->dtb[x]);
647                                }
648                            }
649                            thread->getITBPtr()->dumpAll();
650                            thread->getDTBPtr()->dumpAll();
651                        }
652
653                        diffcount++;
654                        if (diffcount > 2)
655                            fatal("Differences found between Legion and M5\n");
656                    } else
657                        diffcount = 0;
658
659                    compared = true;
660                    shared_data->flags = OWN_LEGION;
661                }
662            } // while
663        } // if not microop
664    }
665#endif
666}
667
668
669vector<bool> Trace::InstRecord::flags(NUM_BITS);
670string Trace::InstRecord::trace_system;
671
672////////////////////////////////////////////////////////////////////////
673//
674// Parameter space for per-cycle execution address tracing options.
675// Derive from ParamContext so we can override checkParams() function.
676//
677class ExecutionTraceParamContext : public ParamContext
678{
679  public:
680    ExecutionTraceParamContext(const string &_iniSection)
681        : ParamContext(_iniSection)
682        {
683        }
684
685    void checkParams();	// defined at bottom of file
686};
687
688ExecutionTraceParamContext exeTraceParams("exetrace");
689
690Param<bool> exe_trace_spec(&exeTraceParams, "speculative",
691                           "capture speculative instructions", true);
692
693Param<bool> exe_trace_print_cycle(&exeTraceParams, "print_cycle",
694                                  "print cycle number", true);
695Param<bool> exe_trace_print_opclass(&exeTraceParams, "print_opclass",
696                                  "print op class", true);
697Param<bool> exe_trace_print_thread(&exeTraceParams, "print_thread",
698                                  "print thread number", true);
699Param<bool> exe_trace_print_effaddr(&exeTraceParams, "print_effaddr",
700                                  "print effective address", true);
701Param<bool> exe_trace_print_data(&exeTraceParams, "print_data",
702                                  "print result data", true);
703Param<bool> exe_trace_print_iregs(&exeTraceParams, "print_iregs",
704                                  "print all integer regs", false);
705Param<bool> exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq",
706                                  "print fetch sequence number", false);
707Param<bool> exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq",
708                                  "print correct-path sequence number", false);
709Param<bool> exe_trace_print_reg_delta(&exeTraceParams, "print_reg_delta",
710                                  "print which registers changed to what", false);
711Param<bool> exe_trace_pc_symbol(&exeTraceParams, "pc_symbol",
712                                  "Use symbols for the PC if available", true);
713Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format",
714                                   "print trace in intel compatible format", false);
715Param<bool> exe_trace_legion_lockstep(&exeTraceParams, "legion_lockstep",
716                                   "Compare sim state to legion state every cycle",
717                                   false);
718Param<string> exe_trace_system(&exeTraceParams, "trace_system",
719                                   "print trace of which system (client or server)",
720                                   "client");
721
722
723//
724// Helper function for ExecutionTraceParamContext::checkParams() just
725// to get us into the InstRecord namespace
726//
727void
728Trace::InstRecord::setParams()
729{
730    flags[TRACE_MISSPEC]     = exe_trace_spec;
731
732    flags[PRINT_CYCLE]       = exe_trace_print_cycle;
733    flags[PRINT_OP_CLASS]    = exe_trace_print_opclass;
734    flags[PRINT_THREAD_NUM]  = exe_trace_print_thread;
735    flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr;
736    flags[PRINT_EFF_ADDR]    = exe_trace_print_data;
737    flags[PRINT_INT_REGS]    = exe_trace_print_iregs;
738    flags[PRINT_FETCH_SEQ]   = exe_trace_print_fetchseq;
739    flags[PRINT_CP_SEQ]      = exe_trace_print_cp_seq;
740    flags[PRINT_REG_DELTA]   = exe_trace_print_reg_delta;
741    flags[PC_SYMBOL]         = exe_trace_pc_symbol;
742    flags[INTEL_FORMAT]      = exe_trace_intel_format;
743    flags[LEGION_LOCKSTEP]   = exe_trace_legion_lockstep;
744    trace_system	     = exe_trace_system;
745
746    // If were going to be in lockstep with Legion
747    // Setup shared memory, and get otherwise ready
748    if (flags[LEGION_LOCKSTEP]) {
749        int shmfd = shmget('M' << 24 | getuid(), sizeof(SharedData), 0777);
750        if (shmfd < 0)
751            fatal("Couldn't get shared memory fd. Is Legion running?");
752
753        shared_data = (SharedData*)shmat(shmfd, NULL, SHM_RND);
754        if (shared_data == (SharedData*)-1)
755            fatal("Couldn't allocate shared memory");
756
757        if (shared_data->flags != OWN_M5)
758            fatal("Shared memory has invalid owner");
759
760        if (shared_data->version != VERSION)
761            fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION,
762                    shared_data->version);
763
764        // step legion forward one cycle so we can get register values
765        shared_data->flags = OWN_LEGION;
766    }
767}
768
769void
770ExecutionTraceParamContext::checkParams()
771{
772    Trace::InstRecord::setParams();
773}
774
775