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