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