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