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