exetrace.cc revision 4008:ccad3906006a
1/* 2 * Copyright (c) 2001-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Steve Reinhardt 29 * Lisa Hsu 30 * Nathan Binkert 31 * Steve Raasch 32 */ 33 34#include <fstream> 35#include <iomanip> 36#include <sys/ipc.h> 37#include <sys/shm.h> 38 39#include "arch/regfile.hh" 40#include "arch/utility.hh" 41#include "base/loader/symtab.hh" 42#include "config/full_system.hh" 43#include "cpu/base.hh" 44#include "cpu/exetrace.hh" 45#include "cpu/static_inst.hh" 46#include "sim/param.hh" 47#include "sim/system.hh" 48 49#if FULL_SYSTEM 50#include "arch/tlb.hh" 51#endif 52 53//XXX This is temporary 54#include "arch/isa_specific.hh" 55#include "cpu/m5legion_interface.h" 56 57using namespace std; 58using namespace TheISA; 59 60#if THE_ISA == SPARC_ISA && FULL_SYSTEM 61static int diffcount = 0; 62static bool wasMicro = false; 63#endif 64 65namespace Trace { 66SharedData *shared_data = NULL; 67} 68 69//////////////////////////////////////////////////////////////////////// 70// 71// Methods for the InstRecord object 72// 73 74#if THE_ISA == SPARC_ISA 75 76inline 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 88inline 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 94inline 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 103inline 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 112inline 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 125void 126Trace::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 { 460 461 outs << "Differences found between M5 and Legion:"; 462 if (diffPC) 463 outs << " [PC]"; 464 if (diffCC) 465 outs << " [CC]"; 466 if (diffInst) 467 outs << " [Instruction]"; 468 if (diffIntRegs) 469 outs << " [IntRegs]"; 470 if (diffFpRegs) 471 outs << " [FpRegs]"; 472 if (diffTpc) 473 outs << " [Tpc]"; 474 if (diffTnpc) 475 outs << " [Tnpc]"; 476 if (diffTstate) 477 outs << " [Tstate]"; 478 if (diffTt) 479 outs << " [Tt]"; 480 if (diffHpstate) 481 outs << " [Hpstate]"; 482 if (diffHtstate) 483 outs << " [Htstate]"; 484 if (diffHtba) 485 outs << " [Htba]"; 486 if (diffPstate) 487 outs << " [Pstate]"; 488 if (diffY) 489 outs << " [Y]"; 490 if (diffFsr) 491 outs << " [FSR]"; 492 if (diffCcr) 493 outs << " [Ccr]"; 494 if (diffTl) 495 outs << " [Tl]"; 496 if (diffGl) 497 outs << " [Gl]"; 498 if (diffAsi) 499 outs << " [Asi]"; 500 if (diffPil) 501 outs << " [Pil]"; 502 if (diffCwp) 503 outs << " [Cwp]"; 504 if (diffCansave) 505 outs << " [Cansave]"; 506 if (diffCanrestore) 507 outs << " [Canrestore]"; 508 if (diffOtherwin) 509 outs << " [Otherwin]"; 510 if (diffCleanwin) 511 outs << " [Cleanwin]"; 512 if (diffTlb) 513 outs << " [Tlb]"; 514 outs << endl << endl; 515 516 outs << right << setfill(' ') << setw(15) 517 << "M5 PC: " << "0x"<< setw(16) << setfill('0') 518 << hex << m5Pc << endl; 519 outs << setfill(' ') << setw(15) 520 << "Legion PC: " << "0x"<< setw(16) << setfill('0') << hex 521 << lgnPc << endl << endl; 522 523 outs << right << setfill(' ') << setw(15) 524 << "M5 CC: " << "0x"<< setw(16) << setfill('0') 525 << hex << thread->getCpuPtr()->instCount() << endl; 526 outs << setfill(' ') << setw(15) 527 << "Legion CC: " << "0x"<< setw(16) << setfill('0') << hex 528 << shared_data->cycle_count << endl << endl; 529 530 outs << setfill(' ') << setw(15) 531 << "M5 Inst: " << "0x"<< setw(8) 532 << setfill('0') << hex << staticInst->machInst 533 << staticInst->disassemble(m5Pc, debugSymbolTable) 534 << endl; 535 536 StaticInstPtr legionInst = 537 StaticInst::decode(makeExtMI(shared_data->instruction, 538 thread)); 539 outs << setfill(' ') << setw(15) 540 << " Legion Inst: " 541 << "0x" << setw(8) << setfill('0') << hex 542 << shared_data->instruction 543 << legionInst->disassemble(lgnPc, debugSymbolTable) 544 << endl << endl; 545 546 printSectionHeader(outs, "General State"); 547 printColumnLabels(outs); 548 printRegPair(outs, "HPstate", 549 thread->readMiscReg(MISCREG_HPSTATE), 550 shared_data->hpstate | (1 << 11)); 551 printRegPair(outs, "Htba", 552 thread->readMiscReg(MISCREG_HTBA), 553 shared_data->htba); 554 printRegPair(outs, "Pstate", 555 thread->readMiscReg(MISCREG_PSTATE), 556 shared_data->pstate); 557 printRegPair(outs, "Y", 558 //thread->readMiscReg(MISCREG_Y), 559 thread->readIntReg(NumIntArchRegs + 1), 560 shared_data->y); 561 printRegPair(outs, "FSR", 562 thread->readMiscReg(MISCREG_FSR), 563 shared_data->fsr); 564 printRegPair(outs, "Ccr", 565 //thread->readMiscReg(MISCREG_CCR), 566 thread->readIntReg(NumIntArchRegs + 2), 567 shared_data->ccr); 568 printRegPair(outs, "Tl", 569 thread->readMiscReg(MISCREG_TL), 570 shared_data->tl); 571 printRegPair(outs, "Gl", 572 thread->readMiscReg(MISCREG_GL), 573 shared_data->gl); 574 printRegPair(outs, "Asi", 575 thread->readMiscReg(MISCREG_ASI), 576 shared_data->asi); 577 printRegPair(outs, "Pil", 578 thread->readMiscReg(MISCREG_PIL), 579 shared_data->pil); 580 printRegPair(outs, "Cwp", 581 thread->readMiscReg(MISCREG_CWP), 582 shared_data->cwp); 583 printRegPair(outs, "Cansave", 584 //thread->readMiscReg(MISCREG_CANSAVE), 585 thread->readIntReg(NumIntArchRegs + 3), 586 shared_data->cansave); 587 printRegPair(outs, "Canrestore", 588 //thread->readMiscReg(MISCREG_CANRESTORE), 589 thread->readIntReg(NumIntArchRegs + 4), 590 shared_data->canrestore); 591 printRegPair(outs, "Otherwin", 592 //thread->readMiscReg(MISCREG_OTHERWIN), 593 thread->readIntReg(NumIntArchRegs + 6), 594 shared_data->otherwin); 595 printRegPair(outs, "Cleanwin", 596 //thread->readMiscReg(MISCREG_CLEANWIN), 597 thread->readIntReg(NumIntArchRegs + 5), 598 shared_data->cleanwin); 599 outs << endl; 600 for (int i = 1; i <= MaxTL; i++) { 601 printLevelHeader(outs, i); 602 printColumnLabels(outs); 603 thread->setMiscReg(MISCREG_TL, i); 604 printRegPair(outs, "Tpc", 605 thread->readMiscReg(MISCREG_TPC), 606 shared_data->tpc[i-1]); 607 printRegPair(outs, "Tnpc", 608 thread->readMiscReg(MISCREG_TNPC), 609 shared_data->tnpc[i-1]); 610 printRegPair(outs, "Tstate", 611 thread->readMiscReg(MISCREG_TSTATE), 612 shared_data->tstate[i-1]); 613 printRegPair(outs, "Tt", 614 thread->readMiscReg(MISCREG_TT), 615 shared_data->tt[i-1]); 616 printRegPair(outs, "Htstate", 617 thread->readMiscReg(MISCREG_HTSTATE), 618 shared_data->htstate[i-1]); 619 } 620 thread->setMiscReg(MISCREG_TL, oldTl); 621 outs << endl; 622 623 printSectionHeader(outs, "General Purpose Registers"); 624 static const char * regtypes[4] = {"%g", "%o", "%l", "%i"}; 625 for(int y = 0; y < 4; y++) { 626 for(int x = 0; x < 8; x++) { 627 char label[8]; 628 sprintf(label, "%s%d", regtypes[y], x); 629 printRegPair(outs, label, 630 thread->readIntReg(y*8+x), 631 shared_data->intregs[y*8+x]); 632 } 633 } 634 if (diffFpRegs) { 635 for (int x = 0; x < 32; x++) { 636 char label[8]; 637 sprintf(label, "%%f%d", x); 638 printRegPair(outs, label, 639 thread->readFloatRegBits(x*2,FloatRegFile::DoubleWidth), 640 shared_data->fpregs[x]); 641 } 642 } 643 if (diffTlb) { 644 printColumnLabels(outs); 645 char label[8]; 646 for (int x = 0; x < 64; x++) { 647 if (shared_data->itb[x] != ULL(0xFFFFFFFFFFFFFFFF) || 648 thread->getITBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF)) { 649 sprintf(label, "I-TLB:%02d", x); 650 printRegPair(outs, label, thread->getITBPtr()->TteRead(x), 651 shared_data->itb[x]); 652 } 653 } 654 for (int x = 0; x < 64; x++) { 655 if (shared_data->dtb[x] != ULL(0xFFFFFFFFFFFFFFFF) || 656 thread->getDTBPtr()->TteRead(x) != ULL(0xFFFFFFFFFFFFFFFF)) { 657 sprintf(label, "D-TLB:%02d", x); 658 printRegPair(outs, label, thread->getDTBPtr()->TteRead(x), 659 shared_data->dtb[x]); 660 } 661 } 662 thread->getITBPtr()->dumpAll(); 663 thread->getDTBPtr()->dumpAll(); 664 } 665 666 diffcount++; 667 if (diffcount > 2) 668 fatal("Differences found between Legion and M5\n"); 669 } else 670 diffcount = 0; 671 672 compared = true; 673 shared_data->flags = OWN_LEGION; 674 } 675 } // while 676 } // if not microop 677 } 678#endif 679} 680 681 682vector<bool> Trace::InstRecord::flags(NUM_BITS); 683string Trace::InstRecord::trace_system; 684 685//////////////////////////////////////////////////////////////////////// 686// 687// Parameter space for per-cycle execution address tracing options. 688// Derive from ParamContext so we can override checkParams() function. 689// 690class ExecutionTraceParamContext : public ParamContext 691{ 692 public: 693 ExecutionTraceParamContext(const string &_iniSection) 694 : ParamContext(_iniSection) 695 { 696 } 697 698 void checkParams(); // defined at bottom of file 699}; 700 701ExecutionTraceParamContext exeTraceParams("exetrace"); 702 703Param<bool> exe_trace_spec(&exeTraceParams, "speculative", 704 "capture speculative instructions", true); 705 706Param<bool> exe_trace_print_cycle(&exeTraceParams, "print_cycle", 707 "print cycle number", true); 708Param<bool> exe_trace_print_opclass(&exeTraceParams, "print_opclass", 709 "print op class", true); 710Param<bool> exe_trace_print_thread(&exeTraceParams, "print_thread", 711 "print thread number", true); 712Param<bool> exe_trace_print_effaddr(&exeTraceParams, "print_effaddr", 713 "print effective address", true); 714Param<bool> exe_trace_print_data(&exeTraceParams, "print_data", 715 "print result data", true); 716Param<bool> exe_trace_print_iregs(&exeTraceParams, "print_iregs", 717 "print all integer regs", false); 718Param<bool> exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq", 719 "print fetch sequence number", false); 720Param<bool> exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq", 721 "print correct-path sequence number", false); 722Param<bool> exe_trace_print_reg_delta(&exeTraceParams, "print_reg_delta", 723 "print which registers changed to what", false); 724Param<bool> exe_trace_pc_symbol(&exeTraceParams, "pc_symbol", 725 "Use symbols for the PC if available", true); 726Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format", 727 "print trace in intel compatible format", false); 728Param<bool> exe_trace_legion_lockstep(&exeTraceParams, "legion_lockstep", 729 "Compare sim state to legion state every cycle", 730 false); 731Param<string> exe_trace_system(&exeTraceParams, "trace_system", 732 "print trace of which system (client or server)", 733 "client"); 734 735 736// 737// Helper function for ExecutionTraceParamContext::checkParams() just 738// to get us into the InstRecord namespace 739// 740void 741Trace::InstRecord::setParams() 742{ 743 flags[TRACE_MISSPEC] = exe_trace_spec; 744 745 flags[PRINT_CYCLE] = exe_trace_print_cycle; 746 flags[PRINT_OP_CLASS] = exe_trace_print_opclass; 747 flags[PRINT_THREAD_NUM] = exe_trace_print_thread; 748 flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr; 749 flags[PRINT_EFF_ADDR] = exe_trace_print_data; 750 flags[PRINT_INT_REGS] = exe_trace_print_iregs; 751 flags[PRINT_FETCH_SEQ] = exe_trace_print_fetchseq; 752 flags[PRINT_CP_SEQ] = exe_trace_print_cp_seq; 753 flags[PRINT_REG_DELTA] = exe_trace_print_reg_delta; 754 flags[PC_SYMBOL] = exe_trace_pc_symbol; 755 flags[INTEL_FORMAT] = exe_trace_intel_format; 756 flags[LEGION_LOCKSTEP] = exe_trace_legion_lockstep; 757 trace_system = exe_trace_system; 758 759 // If were going to be in lockstep with Legion 760 // Setup shared memory, and get otherwise ready 761 if (flags[LEGION_LOCKSTEP]) { 762 int shmfd = shmget('M' << 24 | getuid(), sizeof(SharedData), 0777); 763 if (shmfd < 0) 764 fatal("Couldn't get shared memory fd. Is Legion running?"); 765 766 shared_data = (SharedData*)shmat(shmfd, NULL, SHM_RND); 767 if (shared_data == (SharedData*)-1) 768 fatal("Couldn't allocate shared memory"); 769 770 if (shared_data->flags != OWN_M5) 771 fatal("Shared memory has invalid owner"); 772 773 if (shared_data->version != VERSION) 774 fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION, 775 shared_data->version); 776 777 // step legion forward one cycle so we can get register values 778 shared_data->flags = OWN_LEGION; 779 } 780} 781 782void 783ExecutionTraceParamContext::checkParams() 784{ 785 Trace::InstRecord::setParams(); 786} 787 788