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