exetrace.cc revision 3949:b6664282d899
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        Addr m5Pc, lgnPc;
318
319
320        if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) {
321            while (!compared) {
322                if (shared_data->flags == OWN_M5) {
323                    m5Pc = PC & TheISA::PAddrImplMask;
324                    lgnPc = shared_data->pc & TheISA::PAddrImplMask;
325                    if (lgnPc != m5Pc)
326                       diffPC = true;
327
328                    if (shared_data->cycle_count !=
329                            thread->getCpuPtr()->instCount())
330                        diffCC = true;
331
332                    if (shared_data->instruction !=
333                            (SparcISA::MachInst)staticInst->machInst) {
334                        diffInst = true;
335                    }
336                    for (int i = 0; i < TheISA::NumIntArchRegs; i++) {
337                        if (thread->readIntReg(i) != shared_data->intregs[i]) {
338                            diffRegs = true;
339                        }
340                    }
341                    uint64_t oldTl = thread->readMiscReg(MISCREG_TL);
342                    if (oldTl != shared_data->tl)
343                        diffTl = true;
344                    for (int i = 1; i <= MaxTL; i++) {
345                        thread->setMiscReg(MISCREG_TL, i);
346                        if (thread->readMiscReg(MISCREG_TPC) !=
347                                shared_data->tpc[i-1])
348                            diffTpc = true;
349                        if (thread->readMiscReg(MISCREG_TNPC) !=
350                                shared_data->tnpc[i-1])
351                            diffTnpc = true;
352                        if (thread->readMiscReg(MISCREG_TSTATE) !=
353                                shared_data->tstate[i-1])
354                            diffTstate = true;
355                        if (thread->readMiscReg(MISCREG_TT) !=
356                                shared_data->tt[i-1])
357                            diffTt = true;
358                        if (thread->readMiscReg(MISCREG_HTSTATE) !=
359                                shared_data->htstate[i-1])
360                            diffHtstate = true;
361                    }
362                    thread->setMiscReg(MISCREG_TL, oldTl);
363
364                    if(shared_data->tba != thread->readMiscReg(MISCREG_TBA))
365                        diffTba = true;
366                    //When the hpstate register is read by an instruction,
367                    //legion has bit 11 set. When it's in storage, it doesn't.
368                    //Since we don't directly support seperate interpretations
369                    //of the registers like that, the bit is always set to 1 and
370                    //we just don't compare it. It's not supposed to matter
371                    //anyway.
372                    if((shared_data->hpstate | (1 << 11)) != thread->readMiscReg(MISCREG_HPSTATE))
373                        diffHpstate = true;
374                    if(shared_data->htba != thread->readMiscReg(MISCREG_HTBA))
375                        diffHtba = true;
376                    if(shared_data->pstate != thread->readMiscReg(MISCREG_PSTATE))
377                        diffPstate = true;
378                    //if(shared_data->y != thread->readMiscReg(MISCREG_Y))
379                    if(shared_data->y !=
380                            thread->readIntReg(NumIntArchRegs + 1))
381                        diffY = true;
382                    //if(shared_data->ccr != thread->readMiscReg(MISCREG_CCR))
383                    if(shared_data->ccr !=
384                            thread->readIntReg(NumIntArchRegs + 2))
385                        diffCcr = true;
386                    if(shared_data->gl != thread->readMiscReg(MISCREG_GL))
387                        diffGl = true;
388                    if(shared_data->asi != thread->readMiscReg(MISCREG_ASI))
389                        diffAsi = true;
390                    if(shared_data->pil != thread->readMiscReg(MISCREG_PIL))
391                        diffPil = true;
392                    if(shared_data->cwp != thread->readMiscReg(MISCREG_CWP))
393                        diffCwp = true;
394                    //if(shared_data->cansave != thread->readMiscReg(MISCREG_CANSAVE))
395                    if(shared_data->cansave !=
396                            thread->readIntReg(NumIntArchRegs + 3))
397                        diffCansave = true;
398                    //if(shared_data->canrestore !=
399                    //	    thread->readMiscReg(MISCREG_CANRESTORE))
400                    if(shared_data->canrestore !=
401                            thread->readMiscReg(NumIntArchRegs + 4))
402                        diffCanrestore = true;
403                    //if(shared_data->otherwin != thread->readMiscReg(MISCREG_OTHERWIN))
404                    if(shared_data->otherwin !=
405                            thread->readIntReg(NumIntArchRegs + 5))
406                        diffOtherwin = true;
407                    //if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN))
408                    if(shared_data->cleanwin !=
409                            thread->readMiscReg(NumIntArchRegs + 6))
410                        diffCleanwin = true;
411
412                    if ((diffPC || diffCC || diffInst || diffRegs || diffTpc ||
413                            diffTnpc || diffTstate || diffTt || diffHpstate ||
414                            diffHtstate || diffHtba || diffPstate || diffY ||
415                            diffCcr || diffTl || diffGl || diffAsi || diffPil ||
416                            diffCwp || diffCansave || diffCanrestore ||
417                            diffOtherwin || diffCleanwin)
418                        && !((staticInst->machInst & 0xC1F80000) == 0x81D00000)) {
419                        outs << "Differences found between M5 and Legion:";
420                        if (diffPC)
421                            outs << " [PC]";
422                        if (diffCC)
423                            outs << " [CC]";
424                        if (diffInst)
425                            outs << " [Instruction]";
426                        if (diffRegs)
427                            outs << " [IntRegs]";
428                        if (diffTpc)
429                            outs << " [Tpc]";
430                        if (diffTnpc)
431                            outs << " [Tnpc]";
432                        if (diffTstate)
433                            outs << " [Tstate]";
434                        if (diffTt)
435                            outs << " [Tt]";
436                        if (diffHpstate)
437                            outs << " [Hpstate]";
438                        if (diffHtstate)
439                            outs << " [Htstate]";
440                        if (diffHtba)
441                            outs << " [Htba]";
442                        if (diffPstate)
443                            outs << " [Pstate]";
444                        if (diffY)
445                            outs << " [Y]";
446                        if (diffCcr)
447                            outs << " [Ccr]";
448                        if (diffTl)
449                            outs << " [Tl]";
450                        if (diffGl)
451                            outs << " [Gl]";
452                        if (diffAsi)
453                            outs << " [Asi]";
454                        if (diffPil)
455                            outs << " [Pil]";
456                        if (diffCwp)
457                            outs << " [Cwp]";
458                        if (diffCansave)
459                            outs << " [Cansave]";
460                        if (diffCanrestore)
461                            outs << " [Canrestore]";
462                        if (diffOtherwin)
463                            outs << " [Otherwin]";
464                        if (diffCleanwin)
465                            outs << " [Cleanwin]";
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                                thread->readMiscReg(NumIntArchRegs + 1),
512                                shared_data->y);
513                        printRegPair(outs, "Ccr",
514                                //thread->readMiscReg(MISCREG_CCR),
515                                thread->readMiscReg(NumIntArchRegs + 2),
516                                shared_data->ccr);
517                        printRegPair(outs, "Tl",
518                                thread->readMiscReg(MISCREG_TL),
519                                shared_data->tl);
520                        printRegPair(outs, "Gl",
521                                thread->readMiscReg(MISCREG_GL),
522                                shared_data->gl);
523                        printRegPair(outs, "Asi",
524                                thread->readMiscReg(MISCREG_ASI),
525                                shared_data->asi);
526                        printRegPair(outs, "Pil",
527                                thread->readMiscReg(MISCREG_PIL),
528                                shared_data->pil);
529                        printRegPair(outs, "Cwp",
530                                thread->readMiscReg(MISCREG_CWP),
531                                shared_data->cwp);
532                        printRegPair(outs, "Cansave",
533                                //thread->readMiscReg(MISCREG_CANSAVE),
534                                thread->readIntReg(NumIntArchRegs + 3),
535                                shared_data->cansave);
536                        printRegPair(outs, "Canrestore",
537                                //thread->readMiscReg(MISCREG_CANRESTORE),
538                                thread->readIntReg(NumIntArchRegs + 4),
539                                shared_data->canrestore);
540                        printRegPair(outs, "Otherwin",
541                                //thread->readMiscReg(MISCREG_OTHERWIN),
542                                thread->readIntReg(NumIntArchRegs + 5),
543                                shared_data->otherwin);
544                        printRegPair(outs, "Cleanwin",
545                                //thread->readMiscReg(MISCREG_CLEANWIN),
546                                thread->readIntReg(NumIntArchRegs + 6),
547                                shared_data->cleanwin);
548                        outs << endl;
549                        for (int i = 1; i <= MaxTL; i++) {
550                            printLevelHeader(outs, i);
551                            printColumnLabels(outs);
552                            thread->setMiscReg(MISCREG_TL, i);
553                            printRegPair(outs, "Tpc",
554                                    thread->readMiscReg(MISCREG_TPC),
555                                    shared_data->tpc[i-1]);
556                            printRegPair(outs, "Tnpc",
557                                    thread->readMiscReg(MISCREG_TNPC),
558                                    shared_data->tnpc[i-1]);
559                            printRegPair(outs, "Tstate",
560                                    thread->readMiscReg(MISCREG_TSTATE),
561                                    shared_data->tstate[i-1]);
562                            printRegPair(outs, "Tt",
563                                    thread->readMiscReg(MISCREG_TT),
564                                    shared_data->tt[i-1]);
565                            printRegPair(outs, "Htstate",
566                                    thread->readMiscReg(MISCREG_HTSTATE),
567                                    shared_data->htstate[i-1]);
568                        }
569                        thread->setMiscReg(MISCREG_TL, oldTl);
570                        outs << endl;
571
572                        printSectionHeader(outs, "General Purpose Registers");
573                        static const char * regtypes[4] = {"%g", "%o", "%l", "%i"};
574                        for(int y = 0; y < 4; y++)
575                        {
576                            for(int x = 0; x < 8; x++)
577                            {
578                                char label[8];
579                                sprintf(label, "%s%d", regtypes[y], x);
580                                printRegPair(outs, label,
581                                        thread->readIntReg(y*8+x),
582                                        shared_data->intregs[y*8+x]);
583                                /*outs << regtypes[y] << x << "         " ;
584                                outs <<  "0x" << hex << setw(16)
585                                    << thread->readIntReg(y*8+x);
586                                if (thread->readIntReg(y*8 + x)
587                                        != shared_data->intregs[y*8+x])
588                                    outs << "     X     ";
589                                else
590                                    outs << "     |     ";
591                                outs << "0x" << setw(16) << hex
592                                    << shared_data->intregs[y*8+x]
593                                    << endl;*/
594                            }
595                        }
596                        thread->getITBPtr()->dumpAll();
597                        thread->getDTBPtr()->dumpAll();
598
599                        diffcount++;
600                        if (diffcount > 2)
601                            fatal("Differences found between Legion and M5\n");
602                    }
603
604                    compared = true;
605                    shared_data->flags = OWN_LEGION;
606                }
607            } // while
608        } // if not microop
609    }
610#endif
611}
612
613
614vector<bool> Trace::InstRecord::flags(NUM_BITS);
615string Trace::InstRecord::trace_system;
616
617////////////////////////////////////////////////////////////////////////
618//
619// Parameter space for per-cycle execution address tracing options.
620// Derive from ParamContext so we can override checkParams() function.
621//
622class ExecutionTraceParamContext : public ParamContext
623{
624  public:
625    ExecutionTraceParamContext(const string &_iniSection)
626        : ParamContext(_iniSection)
627        {
628        }
629
630    void checkParams();	// defined at bottom of file
631};
632
633ExecutionTraceParamContext exeTraceParams("exetrace");
634
635Param<bool> exe_trace_spec(&exeTraceParams, "speculative",
636                           "capture speculative instructions", true);
637
638Param<bool> exe_trace_print_cycle(&exeTraceParams, "print_cycle",
639                                  "print cycle number", true);
640Param<bool> exe_trace_print_opclass(&exeTraceParams, "print_opclass",
641                                  "print op class", true);
642Param<bool> exe_trace_print_thread(&exeTraceParams, "print_thread",
643                                  "print thread number", true);
644Param<bool> exe_trace_print_effaddr(&exeTraceParams, "print_effaddr",
645                                  "print effective address", true);
646Param<bool> exe_trace_print_data(&exeTraceParams, "print_data",
647                                  "print result data", true);
648Param<bool> exe_trace_print_iregs(&exeTraceParams, "print_iregs",
649                                  "print all integer regs", false);
650Param<bool> exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq",
651                                  "print fetch sequence number", false);
652Param<bool> exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq",
653                                  "print correct-path sequence number", false);
654Param<bool> exe_trace_print_reg_delta(&exeTraceParams, "print_reg_delta",
655                                  "print which registers changed to what", false);
656Param<bool> exe_trace_pc_symbol(&exeTraceParams, "pc_symbol",
657                                  "Use symbols for the PC if available", true);
658Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format",
659                                   "print trace in intel compatible format", false);
660Param<bool> exe_trace_legion_lockstep(&exeTraceParams, "legion_lockstep",
661                                   "Compare sim state to legion state every cycle",
662                                   false);
663Param<string> exe_trace_system(&exeTraceParams, "trace_system",
664                                   "print trace of which system (client or server)",
665                                   "client");
666
667
668//
669// Helper function for ExecutionTraceParamContext::checkParams() just
670// to get us into the InstRecord namespace
671//
672void
673Trace::InstRecord::setParams()
674{
675    flags[TRACE_MISSPEC]     = exe_trace_spec;
676
677    flags[PRINT_CYCLE]       = exe_trace_print_cycle;
678    flags[PRINT_OP_CLASS]    = exe_trace_print_opclass;
679    flags[PRINT_THREAD_NUM]  = exe_trace_print_thread;
680    flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr;
681    flags[PRINT_EFF_ADDR]    = exe_trace_print_data;
682    flags[PRINT_INT_REGS]    = exe_trace_print_iregs;
683    flags[PRINT_FETCH_SEQ]   = exe_trace_print_fetchseq;
684    flags[PRINT_CP_SEQ]      = exe_trace_print_cp_seq;
685    flags[PRINT_REG_DELTA]   = exe_trace_print_reg_delta;
686    flags[PC_SYMBOL]         = exe_trace_pc_symbol;
687    flags[INTEL_FORMAT]      = exe_trace_intel_format;
688    flags[LEGION_LOCKSTEP]   = exe_trace_legion_lockstep;
689    trace_system	     = exe_trace_system;
690
691    // If were going to be in lockstep with Legion
692    // Setup shared memory, and get otherwise ready
693    if (flags[LEGION_LOCKSTEP]) {
694        int shmfd = shmget('M' << 24 | getuid(), sizeof(SharedData), 0777);
695        if (shmfd < 0)
696            fatal("Couldn't get shared memory fd. Is Legion running?");
697
698        shared_data = (SharedData*)shmat(shmfd, NULL, SHM_RND);
699        if (shared_data == (SharedData*)-1)
700            fatal("Couldn't allocate shared memory");
701
702        if (shared_data->flags != OWN_M5)
703            fatal("Shared memory has invalid owner");
704
705        if (shared_data->version != VERSION)
706            fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION,
707                    shared_data->version);
708
709        // step legion forward one cycle so we can get register values
710        shared_data->flags = OWN_LEGION;
711    }
712}
713
714void
715ExecutionTraceParamContext::checkParams()
716{
717    Trace::InstRecord::setParams();
718}
719
720