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