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