exetrace.cc revision 3949:b6664282d899
114205Sandreas.sandberg@arm.com/* 214205Sandreas.sandberg@arm.com * Copyright (c) 2001-2005 The Regents of The University of Michigan 314205Sandreas.sandberg@arm.com * All rights reserved. 414205Sandreas.sandberg@arm.com * 514205Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without 614205Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are 714205Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright 814205Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer; 914205Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright 1014205Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the 1114205Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution; 1214205Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its 1314205Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from 1414205Sandreas.sandberg@arm.com * this software without specific prior written permission. 1514205Sandreas.sandberg@arm.com * 1614205Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1714205Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1814205Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1914205Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2014205Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2114205Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2214205Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2314205Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2414205Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2514205Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2614205Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2714205Sandreas.sandberg@arm.com * 2814205Sandreas.sandberg@arm.com * Authors: Steve Reinhardt 2914205Sandreas.sandberg@arm.com * Lisa Hsu 3014205Sandreas.sandberg@arm.com * Nathan Binkert 3114205Sandreas.sandberg@arm.com * Steve Raasch 3214205Sandreas.sandberg@arm.com */ 3314205Sandreas.sandberg@arm.com 3414205Sandreas.sandberg@arm.com#include <fstream> 3514205Sandreas.sandberg@arm.com#include <iomanip> 3614205Sandreas.sandberg@arm.com#include <sys/ipc.h> 3714205Sandreas.sandberg@arm.com#include <sys/shm.h> 3814205Sandreas.sandberg@arm.com 3914205Sandreas.sandberg@arm.com#include "arch/regfile.hh" 4014205Sandreas.sandberg@arm.com#include "arch/utility.hh" 4114205Sandreas.sandberg@arm.com#include "base/loader/symtab.hh" 4214205Sandreas.sandberg@arm.com#include "config/full_system.hh" 4314205Sandreas.sandberg@arm.com#include "cpu/base.hh" 4414205Sandreas.sandberg@arm.com#include "cpu/exetrace.hh" 4514205Sandreas.sandberg@arm.com#include "cpu/static_inst.hh" 4614205Sandreas.sandberg@arm.com#include "sim/param.hh" 4714205Sandreas.sandberg@arm.com#include "sim/system.hh" 4814205Sandreas.sandberg@arm.com 4914205Sandreas.sandberg@arm.com#if FULL_SYSTEM 5014205Sandreas.sandberg@arm.com#include "arch/tlb.hh" 5114205Sandreas.sandberg@arm.com#endif 5214205Sandreas.sandberg@arm.com 5314205Sandreas.sandberg@arm.com//XXX This is temporary 5414205Sandreas.sandberg@arm.com#include "arch/isa_specific.hh" 5514205Sandreas.sandberg@arm.com#include "cpu/m5legion_interface.h" 5614205Sandreas.sandberg@arm.com 5714205Sandreas.sandberg@arm.comusing namespace std; 5814205Sandreas.sandberg@arm.comusing namespace TheISA; 5914205Sandreas.sandberg@arm.com 6014205Sandreas.sandberg@arm.com#if THE_ISA == SPARC_ISA && FULL_SYSTEM 6114205Sandreas.sandberg@arm.comstatic int diffcount = 0; 6214205Sandreas.sandberg@arm.com#endif 6314205Sandreas.sandberg@arm.com 6414205Sandreas.sandberg@arm.comnamespace Trace { 6514205Sandreas.sandberg@arm.comSharedData *shared_data = NULL; 6614205Sandreas.sandberg@arm.com} 6714205Sandreas.sandberg@arm.com 6814205Sandreas.sandberg@arm.com//////////////////////////////////////////////////////////////////////// 6914205Sandreas.sandberg@arm.com// 7014205Sandreas.sandberg@arm.com// Methods for the InstRecord object 7114205Sandreas.sandberg@arm.com// 7214205Sandreas.sandberg@arm.com 7314205Sandreas.sandberg@arm.com#if THE_ISA == SPARC_ISA 7414205Sandreas.sandberg@arm.com 7514205Sandreas.sandberg@arm.cominline char * genCenteredLabel(int length, char * buffer, char * label) 7614205Sandreas.sandberg@arm.com{ 7714205Sandreas.sandberg@arm.com int labelLength = strlen(label); 7814205Sandreas.sandberg@arm.com assert(labelLength <= length); 7914205Sandreas.sandberg@arm.com int leftPad = (length - labelLength) / 2; 8014205Sandreas.sandberg@arm.com int rightPad = length - leftPad - labelLength; 8114205Sandreas.sandberg@arm.com char format[64]; 8214205Sandreas.sandberg@arm.com sprintf(format, "%%%ds%%s%%%ds", leftPad, rightPad); 8314205Sandreas.sandberg@arm.com sprintf(buffer, format, "", label, ""); 8414205Sandreas.sandberg@arm.com return buffer; 8514205Sandreas.sandberg@arm.com} 8614205Sandreas.sandberg@arm.com 8714205Sandreas.sandberg@arm.cominline void printRegPair(ostream & os, char const * title, uint64_t a, uint64_t b) 8814205Sandreas.sandberg@arm.com{ 8914205Sandreas.sandberg@arm.com ccprintf(os, " %16s | %#018x %s %#-018x \n", 9014205Sandreas.sandberg@arm.com title, a, (a == b) ? "|" : "X", b); 9114205Sandreas.sandberg@arm.com} 9214205Sandreas.sandberg@arm.com 9314205Sandreas.sandberg@arm.cominline void printColumnLabels(ostream & os) 9414205Sandreas.sandberg@arm.com{ 9514205Sandreas.sandberg@arm.com static char * regLabel = genCenteredLabel(16, new char[17], "Register"); 9614205Sandreas.sandberg@arm.com static char * m5Label = genCenteredLabel(18, new char[18], "M5"); 9714205Sandreas.sandberg@arm.com static char * legionLabel = genCenteredLabel(18, new char[18], "Legion"); 9814205Sandreas.sandberg@arm.com ccprintf(os, " %s | %s | %s \n", regLabel, m5Label, legionLabel); 9914205Sandreas.sandberg@arm.com ccprintf(os, "--------------------+-----------------------+-----------------------\n"); 10014205Sandreas.sandberg@arm.com} 10114205Sandreas.sandberg@arm.com 10214205Sandreas.sandberg@arm.cominline void printSectionHeader(ostream & os, char * name) 10314205Sandreas.sandberg@arm.com{ 10414205Sandreas.sandberg@arm.com char sectionString[70]; 10514205Sandreas.sandberg@arm.com genCenteredLabel(69, sectionString, name); 10614205Sandreas.sandberg@arm.com ccprintf(os, "====================================================================\n"); 10714205Sandreas.sandberg@arm.com ccprintf(os, "%69s\n", sectionString); 10814205Sandreas.sandberg@arm.com ccprintf(os, "====================================================================\n"); 10914205Sandreas.sandberg@arm.com} 11014205Sandreas.sandberg@arm.com 11114205Sandreas.sandberg@arm.cominline void printLevelHeader(ostream & os, int level) 11214205Sandreas.sandberg@arm.com{ 11314205Sandreas.sandberg@arm.com char sectionString[70]; 11414205Sandreas.sandberg@arm.com char levelName[70]; 11514205Sandreas.sandberg@arm.com sprintf(levelName, "Trap stack level %d", level); 11614205Sandreas.sandberg@arm.com genCenteredLabel(69, sectionString, levelName); 11714205Sandreas.sandberg@arm.com ccprintf(os, "====================================================================\n"); 11814205Sandreas.sandberg@arm.com ccprintf(os, "%69s\n", sectionString); 11914205Sandreas.sandberg@arm.com ccprintf(os, "====================================================================\n"); 12014205Sandreas.sandberg@arm.com} 12114205Sandreas.sandberg@arm.com 12214205Sandreas.sandberg@arm.com#endif 12314205Sandreas.sandberg@arm.com 12414205Sandreas.sandberg@arm.comvoid 12514205Sandreas.sandberg@arm.comTrace::InstRecord::dump(ostream &outs) 12614205Sandreas.sandberg@arm.com{ 12714205Sandreas.sandberg@arm.com if (flags[PRINT_REG_DELTA]) 12814205Sandreas.sandberg@arm.com { 12914205Sandreas.sandberg@arm.com#if THE_ISA == SPARC_ISA 13014205Sandreas.sandberg@arm.com //Don't print what happens for each micro-op, just print out 13114205Sandreas.sandberg@arm.com //once at the last op, and for regular instructions. 13214205Sandreas.sandberg@arm.com if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) 13314205Sandreas.sandberg@arm.com { 13414205Sandreas.sandberg@arm.com static uint64_t regs[32] = { 13514205Sandreas.sandberg@arm.com 0, 0, 0, 0, 0, 0, 0, 0, 13614205Sandreas.sandberg@arm.com 0, 0, 0, 0, 0, 0, 0, 0, 13714205Sandreas.sandberg@arm.com 0, 0, 0, 0, 0, 0, 0, 0, 13814205Sandreas.sandberg@arm.com 0, 0, 0, 0, 0, 0, 0, 0}; 13914205Sandreas.sandberg@arm.com static uint64_t ccr = 0; 14014205Sandreas.sandberg@arm.com static uint64_t y = 0; 14114205Sandreas.sandberg@arm.com static uint64_t floats[32]; 14214205Sandreas.sandberg@arm.com uint64_t newVal; 14314205Sandreas.sandberg@arm.com static const char * prefixes[4] = {"G", "O", "L", "I"}; 14414205Sandreas.sandberg@arm.com 14514205Sandreas.sandberg@arm.com outs << hex; 14614205Sandreas.sandberg@arm.com outs << "PC = " << thread->readNextPC(); 14714205Sandreas.sandberg@arm.com outs << " NPC = " << thread->readNextNPC(); 14814205Sandreas.sandberg@arm.com newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2); 14914205Sandreas.sandberg@arm.com //newVal = thread->readMiscReg(SparcISA::MISCREG_CCR); 15014205Sandreas.sandberg@arm.com if(newVal != ccr) 15114205Sandreas.sandberg@arm.com { 15214205Sandreas.sandberg@arm.com outs << " CCR = " << newVal; 15314205Sandreas.sandberg@arm.com ccr = newVal; 15414205Sandreas.sandberg@arm.com } 15514205Sandreas.sandberg@arm.com newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 1); 15614205Sandreas.sandberg@arm.com //newVal = thread->readMiscReg(SparcISA::MISCREG_Y); 15714205Sandreas.sandberg@arm.com if(newVal != y) 15814205Sandreas.sandberg@arm.com { 15914205Sandreas.sandberg@arm.com outs << " Y = " << newVal; 16014205Sandreas.sandberg@arm.com y = newVal; 16114205Sandreas.sandberg@arm.com } 16214205Sandreas.sandberg@arm.com for(int y = 0; y < 4; y++) 16314205Sandreas.sandberg@arm.com { 16414205Sandreas.sandberg@arm.com for(int x = 0; x < 8; x++) 16514205Sandreas.sandberg@arm.com { 16614205Sandreas.sandberg@arm.com int index = x + 8 * y; 16714205Sandreas.sandberg@arm.com newVal = thread->readIntReg(index); 16814205Sandreas.sandberg@arm.com if(regs[index] != newVal) 16914205Sandreas.sandberg@arm.com { 17014205Sandreas.sandberg@arm.com outs << " " << prefixes[y] << dec << x << " = " << hex << newVal; 17114205Sandreas.sandberg@arm.com regs[index] = newVal; 17214205Sandreas.sandberg@arm.com } 17314205Sandreas.sandberg@arm.com } 17414205Sandreas.sandberg@arm.com } 17514205Sandreas.sandberg@arm.com for(int y = 0; y < 32; y++) 176 { 177 newVal = thread->readFloatRegBits(2 * y, 64); 178 if(floats[y] != newVal) 179 { 180 outs << " F" << dec << (2 * y) << " = " << hex << newVal; 181 floats[y] = newVal; 182 } 183 } 184 outs << dec << endl; 185 } 186#endif 187 } 188 else if (flags[INTEL_FORMAT]) { 189#if FULL_SYSTEM 190 bool is_trace_system = (thread->getCpuPtr()->system->name() == trace_system); 191#else 192 bool is_trace_system = true; 193#endif 194 if (is_trace_system) { 195 ccprintf(outs, "%7d ) ", cycle); 196 outs << "0x" << hex << PC << ":\t"; 197 if (staticInst->isLoad()) { 198 outs << "<RD 0x" << hex << addr; 199 outs << ">"; 200 } else if (staticInst->isStore()) { 201 outs << "<WR 0x" << hex << addr; 202 outs << ">"; 203 } 204 outs << endl; 205 } 206 } else { 207 if (flags[PRINT_CYCLE]) 208 ccprintf(outs, "%7d: ", cycle); 209 210 outs << thread->getCpuPtr()->name() << " "; 211 212 if (flags[TRACE_MISSPEC]) 213 outs << (misspeculating ? "-" : "+") << " "; 214 215 if (flags[PRINT_THREAD_NUM]) 216 outs << "T" << thread->getThreadNum() << " : "; 217 218 219 std::string sym_str; 220 Addr sym_addr; 221 if (debugSymbolTable 222 && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr) 223 && flags[PC_SYMBOL]) { 224 if (PC != sym_addr) 225 sym_str += csprintf("+%d", PC - sym_addr); 226 outs << "@" << sym_str << " : "; 227 } 228 else { 229 outs << "0x" << hex << PC << " : "; 230 } 231 232 // 233 // Print decoded instruction 234 // 235 236#if defined(__GNUC__) && (__GNUC__ < 3) 237 // There's a bug in gcc 2.x library that prevents setw() 238 // from working properly on strings 239 string mc(staticInst->disassemble(PC, debugSymbolTable)); 240 while (mc.length() < 26) 241 mc += " "; 242 outs << mc; 243#else 244 outs << setw(26) << left << staticInst->disassemble(PC, debugSymbolTable); 245#endif 246 247 outs << " : "; 248 249 if (flags[PRINT_OP_CLASS]) { 250 outs << opClassStrings[staticInst->opClass()] << " : "; 251 } 252 253 if (flags[PRINT_RESULT_DATA] && data_status != DataInvalid) { 254 outs << " D="; 255#if 0 256 if (data_status == DataDouble) 257 ccprintf(outs, "%f", data.as_double); 258 else 259 ccprintf(outs, "%#018x", data.as_int); 260#else 261 ccprintf(outs, "%#018x", data.as_int); 262#endif 263 } 264 265 if (flags[PRINT_EFF_ADDR] && addr_valid) 266 outs << " A=0x" << hex << addr; 267 268 if (flags[PRINT_INT_REGS] && regs_valid) { 269 for (int i = 0; i < TheISA::NumIntRegs;) 270 for (int j = i + 1; i <= j; i++) 271 ccprintf(outs, "r%02d = %#018x%s", i, 272 iregs->regs.readReg(i), 273 ((i == j) ? "\n" : " ")); 274 outs << "\n"; 275 } 276 277 if (flags[PRINT_FETCH_SEQ] && fetch_seq_valid) 278 outs << " FetchSeq=" << dec << fetch_seq; 279 280 if (flags[PRINT_CP_SEQ] && cp_seq_valid) 281 outs << " CPSeq=" << dec << cp_seq; 282 283 // 284 // End of line... 285 // 286 outs << endl; 287 } 288#if THE_ISA == SPARC_ISA && FULL_SYSTEM 289 // Compare 290 if (flags[LEGION_LOCKSTEP]) 291 { 292 bool compared = false; 293 bool diffPC = false; 294 bool diffCC = false; 295 bool diffInst = false; 296 bool diffRegs = false; 297 bool diffTpc = false; 298 bool diffTnpc = false; 299 bool diffTstate = false; 300 bool diffTt = false; 301 bool diffTba = false; 302 bool diffHpstate = false; 303 bool diffHtstate = false; 304 bool diffHtba = false; 305 bool diffPstate = false; 306 bool diffY = false; 307 bool diffCcr = false; 308 bool diffTl = false; 309 bool diffGl = false; 310 bool diffAsi = false; 311 bool diffPil = false; 312 bool diffCwp = false; 313 bool diffCansave = false; 314 bool diffCanrestore = false; 315 bool diffOtherwin = false; 316 bool diffCleanwin = false; 317 Addr m5Pc, lgnPc; 318 319 320 if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) { 321 while (!compared) { 322 if (shared_data->flags == OWN_M5) { 323 m5Pc = PC & TheISA::PAddrImplMask; 324 lgnPc = shared_data->pc & TheISA::PAddrImplMask; 325 if (lgnPc != m5Pc) 326 diffPC = true; 327 328 if (shared_data->cycle_count != 329 thread->getCpuPtr()->instCount()) 330 diffCC = true; 331 332 if (shared_data->instruction != 333 (SparcISA::MachInst)staticInst->machInst) { 334 diffInst = true; 335 } 336 for (int i = 0; i < TheISA::NumIntArchRegs; i++) { 337 if (thread->readIntReg(i) != shared_data->intregs[i]) { 338 diffRegs = true; 339 } 340 } 341 uint64_t oldTl = thread->readMiscReg(MISCREG_TL); 342 if (oldTl != shared_data->tl) 343 diffTl = true; 344 for (int i = 1; i <= MaxTL; i++) { 345 thread->setMiscReg(MISCREG_TL, i); 346 if (thread->readMiscReg(MISCREG_TPC) != 347 shared_data->tpc[i-1]) 348 diffTpc = true; 349 if (thread->readMiscReg(MISCREG_TNPC) != 350 shared_data->tnpc[i-1]) 351 diffTnpc = true; 352 if (thread->readMiscReg(MISCREG_TSTATE) != 353 shared_data->tstate[i-1]) 354 diffTstate = true; 355 if (thread->readMiscReg(MISCREG_TT) != 356 shared_data->tt[i-1]) 357 diffTt = true; 358 if (thread->readMiscReg(MISCREG_HTSTATE) != 359 shared_data->htstate[i-1]) 360 diffHtstate = true; 361 } 362 thread->setMiscReg(MISCREG_TL, oldTl); 363 364 if(shared_data->tba != thread->readMiscReg(MISCREG_TBA)) 365 diffTba = true; 366 //When the hpstate register is read by an instruction, 367 //legion has bit 11 set. When it's in storage, it doesn't. 368 //Since we don't directly support seperate interpretations 369 //of the registers like that, the bit is always set to 1 and 370 //we just don't compare it. It's not supposed to matter 371 //anyway. 372 if((shared_data->hpstate | (1 << 11)) != thread->readMiscReg(MISCREG_HPSTATE)) 373 diffHpstate = true; 374 if(shared_data->htba != thread->readMiscReg(MISCREG_HTBA)) 375 diffHtba = true; 376 if(shared_data->pstate != thread->readMiscReg(MISCREG_PSTATE)) 377 diffPstate = true; 378 //if(shared_data->y != thread->readMiscReg(MISCREG_Y)) 379 if(shared_data->y != 380 thread->readIntReg(NumIntArchRegs + 1)) 381 diffY = true; 382 //if(shared_data->ccr != thread->readMiscReg(MISCREG_CCR)) 383 if(shared_data->ccr != 384 thread->readIntReg(NumIntArchRegs + 2)) 385 diffCcr = true; 386 if(shared_data->gl != thread->readMiscReg(MISCREG_GL)) 387 diffGl = true; 388 if(shared_data->asi != thread->readMiscReg(MISCREG_ASI)) 389 diffAsi = true; 390 if(shared_data->pil != thread->readMiscReg(MISCREG_PIL)) 391 diffPil = true; 392 if(shared_data->cwp != thread->readMiscReg(MISCREG_CWP)) 393 diffCwp = true; 394 //if(shared_data->cansave != thread->readMiscReg(MISCREG_CANSAVE)) 395 if(shared_data->cansave != 396 thread->readIntReg(NumIntArchRegs + 3)) 397 diffCansave = true; 398 //if(shared_data->canrestore != 399 // thread->readMiscReg(MISCREG_CANRESTORE)) 400 if(shared_data->canrestore != 401 thread->readMiscReg(NumIntArchRegs + 4)) 402 diffCanrestore = true; 403 //if(shared_data->otherwin != thread->readMiscReg(MISCREG_OTHERWIN)) 404 if(shared_data->otherwin != 405 thread->readIntReg(NumIntArchRegs + 5)) 406 diffOtherwin = true; 407 //if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN)) 408 if(shared_data->cleanwin != 409 thread->readMiscReg(NumIntArchRegs + 6)) 410 diffCleanwin = true; 411 412 if ((diffPC || diffCC || diffInst || diffRegs || diffTpc || 413 diffTnpc || diffTstate || diffTt || diffHpstate || 414 diffHtstate || diffHtba || diffPstate || diffY || 415 diffCcr || diffTl || diffGl || diffAsi || diffPil || 416 diffCwp || diffCansave || diffCanrestore || 417 diffOtherwin || diffCleanwin) 418 && !((staticInst->machInst & 0xC1F80000) == 0x81D00000)) { 419 outs << "Differences found between M5 and Legion:"; 420 if (diffPC) 421 outs << " [PC]"; 422 if (diffCC) 423 outs << " [CC]"; 424 if (diffInst) 425 outs << " [Instruction]"; 426 if (diffRegs) 427 outs << " [IntRegs]"; 428 if (diffTpc) 429 outs << " [Tpc]"; 430 if (diffTnpc) 431 outs << " [Tnpc]"; 432 if (diffTstate) 433 outs << " [Tstate]"; 434 if (diffTt) 435 outs << " [Tt]"; 436 if (diffHpstate) 437 outs << " [Hpstate]"; 438 if (diffHtstate) 439 outs << " [Htstate]"; 440 if (diffHtba) 441 outs << " [Htba]"; 442 if (diffPstate) 443 outs << " [Pstate]"; 444 if (diffY) 445 outs << " [Y]"; 446 if (diffCcr) 447 outs << " [Ccr]"; 448 if (diffTl) 449 outs << " [Tl]"; 450 if (diffGl) 451 outs << " [Gl]"; 452 if (diffAsi) 453 outs << " [Asi]"; 454 if (diffPil) 455 outs << " [Pil]"; 456 if (diffCwp) 457 outs << " [Cwp]"; 458 if (diffCansave) 459 outs << " [Cansave]"; 460 if (diffCanrestore) 461 outs << " [Canrestore]"; 462 if (diffOtherwin) 463 outs << " [Otherwin]"; 464 if (diffCleanwin) 465 outs << " [Cleanwin]"; 466 outs << endl << endl; 467 468 outs << right << setfill(' ') << setw(15) 469 << "M5 PC: " << "0x"<< setw(16) << setfill('0') 470 << hex << m5Pc << endl; 471 outs << setfill(' ') << setw(15) 472 << "Legion PC: " << "0x"<< setw(16) << setfill('0') << hex 473 << lgnPc << endl << endl; 474 475 outs << right << setfill(' ') << setw(15) 476 << "M5 CC: " << "0x"<< setw(16) << setfill('0') 477 << hex << thread->getCpuPtr()->instCount() << endl; 478 outs << setfill(' ') << setw(15) 479 << "Legion CC: " << "0x"<< setw(16) << setfill('0') << hex 480 << shared_data->cycle_count << endl << endl; 481 482 outs << setfill(' ') << setw(15) 483 << "M5 Inst: " << "0x"<< setw(8) 484 << setfill('0') << hex << staticInst->machInst 485 << staticInst->disassemble(m5Pc, debugSymbolTable) 486 << endl; 487 488 StaticInstPtr legionInst = 489 StaticInst::decode(makeExtMI(shared_data->instruction, 490 thread)); 491 outs << setfill(' ') << setw(15) 492 << " Legion Inst: " 493 << "0x" << setw(8) << setfill('0') << hex 494 << shared_data->instruction 495 << legionInst->disassemble(lgnPc, debugSymbolTable) 496 << endl << endl; 497 498 printSectionHeader(outs, "General State"); 499 printColumnLabels(outs); 500 printRegPair(outs, "HPstate", 501 thread->readMiscReg(MISCREG_HPSTATE), 502 shared_data->hpstate | (1 << 11)); 503 printRegPair(outs, "Htba", 504 thread->readMiscReg(MISCREG_HTBA), 505 shared_data->htba); 506 printRegPair(outs, "Pstate", 507 thread->readMiscReg(MISCREG_PSTATE), 508 shared_data->pstate); 509 printRegPair(outs, "Y", 510 //thread->readMiscReg(MISCREG_Y), 511 thread->readMiscReg(NumIntArchRegs + 1), 512 shared_data->y); 513 printRegPair(outs, "Ccr", 514 //thread->readMiscReg(MISCREG_CCR), 515 thread->readMiscReg(NumIntArchRegs + 2), 516 shared_data->ccr); 517 printRegPair(outs, "Tl", 518 thread->readMiscReg(MISCREG_TL), 519 shared_data->tl); 520 printRegPair(outs, "Gl", 521 thread->readMiscReg(MISCREG_GL), 522 shared_data->gl); 523 printRegPair(outs, "Asi", 524 thread->readMiscReg(MISCREG_ASI), 525 shared_data->asi); 526 printRegPair(outs, "Pil", 527 thread->readMiscReg(MISCREG_PIL), 528 shared_data->pil); 529 printRegPair(outs, "Cwp", 530 thread->readMiscReg(MISCREG_CWP), 531 shared_data->cwp); 532 printRegPair(outs, "Cansave", 533 //thread->readMiscReg(MISCREG_CANSAVE), 534 thread->readIntReg(NumIntArchRegs + 3), 535 shared_data->cansave); 536 printRegPair(outs, "Canrestore", 537 //thread->readMiscReg(MISCREG_CANRESTORE), 538 thread->readIntReg(NumIntArchRegs + 4), 539 shared_data->canrestore); 540 printRegPair(outs, "Otherwin", 541 //thread->readMiscReg(MISCREG_OTHERWIN), 542 thread->readIntReg(NumIntArchRegs + 5), 543 shared_data->otherwin); 544 printRegPair(outs, "Cleanwin", 545 //thread->readMiscReg(MISCREG_CLEANWIN), 546 thread->readIntReg(NumIntArchRegs + 6), 547 shared_data->cleanwin); 548 outs << endl; 549 for (int i = 1; i <= MaxTL; i++) { 550 printLevelHeader(outs, i); 551 printColumnLabels(outs); 552 thread->setMiscReg(MISCREG_TL, i); 553 printRegPair(outs, "Tpc", 554 thread->readMiscReg(MISCREG_TPC), 555 shared_data->tpc[i-1]); 556 printRegPair(outs, "Tnpc", 557 thread->readMiscReg(MISCREG_TNPC), 558 shared_data->tnpc[i-1]); 559 printRegPair(outs, "Tstate", 560 thread->readMiscReg(MISCREG_TSTATE), 561 shared_data->tstate[i-1]); 562 printRegPair(outs, "Tt", 563 thread->readMiscReg(MISCREG_TT), 564 shared_data->tt[i-1]); 565 printRegPair(outs, "Htstate", 566 thread->readMiscReg(MISCREG_HTSTATE), 567 shared_data->htstate[i-1]); 568 } 569 thread->setMiscReg(MISCREG_TL, oldTl); 570 outs << endl; 571 572 printSectionHeader(outs, "General Purpose Registers"); 573 static const char * regtypes[4] = {"%g", "%o", "%l", "%i"}; 574 for(int y = 0; y < 4; y++) 575 { 576 for(int x = 0; x < 8; x++) 577 { 578 char label[8]; 579 sprintf(label, "%s%d", regtypes[y], x); 580 printRegPair(outs, label, 581 thread->readIntReg(y*8+x), 582 shared_data->intregs[y*8+x]); 583 /*outs << regtypes[y] << x << " " ; 584 outs << "0x" << hex << setw(16) 585 << thread->readIntReg(y*8+x); 586 if (thread->readIntReg(y*8 + x) 587 != shared_data->intregs[y*8+x]) 588 outs << " X "; 589 else 590 outs << " | "; 591 outs << "0x" << setw(16) << hex 592 << shared_data->intregs[y*8+x] 593 << endl;*/ 594 } 595 } 596 thread->getITBPtr()->dumpAll(); 597 thread->getDTBPtr()->dumpAll(); 598 599 diffcount++; 600 if (diffcount > 2) 601 fatal("Differences found between Legion and M5\n"); 602 } 603 604 compared = true; 605 shared_data->flags = OWN_LEGION; 606 } 607 } // while 608 } // if not microop 609 } 610#endif 611} 612 613 614vector<bool> Trace::InstRecord::flags(NUM_BITS); 615string Trace::InstRecord::trace_system; 616 617//////////////////////////////////////////////////////////////////////// 618// 619// Parameter space for per-cycle execution address tracing options. 620// Derive from ParamContext so we can override checkParams() function. 621// 622class ExecutionTraceParamContext : public ParamContext 623{ 624 public: 625 ExecutionTraceParamContext(const string &_iniSection) 626 : ParamContext(_iniSection) 627 { 628 } 629 630 void checkParams(); // defined at bottom of file 631}; 632 633ExecutionTraceParamContext exeTraceParams("exetrace"); 634 635Param<bool> exe_trace_spec(&exeTraceParams, "speculative", 636 "capture speculative instructions", true); 637 638Param<bool> exe_trace_print_cycle(&exeTraceParams, "print_cycle", 639 "print cycle number", true); 640Param<bool> exe_trace_print_opclass(&exeTraceParams, "print_opclass", 641 "print op class", true); 642Param<bool> exe_trace_print_thread(&exeTraceParams, "print_thread", 643 "print thread number", true); 644Param<bool> exe_trace_print_effaddr(&exeTraceParams, "print_effaddr", 645 "print effective address", true); 646Param<bool> exe_trace_print_data(&exeTraceParams, "print_data", 647 "print result data", true); 648Param<bool> exe_trace_print_iregs(&exeTraceParams, "print_iregs", 649 "print all integer regs", false); 650Param<bool> exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq", 651 "print fetch sequence number", false); 652Param<bool> exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq", 653 "print correct-path sequence number", false); 654Param<bool> exe_trace_print_reg_delta(&exeTraceParams, "print_reg_delta", 655 "print which registers changed to what", false); 656Param<bool> exe_trace_pc_symbol(&exeTraceParams, "pc_symbol", 657 "Use symbols for the PC if available", true); 658Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format", 659 "print trace in intel compatible format", false); 660Param<bool> exe_trace_legion_lockstep(&exeTraceParams, "legion_lockstep", 661 "Compare sim state to legion state every cycle", 662 false); 663Param<string> exe_trace_system(&exeTraceParams, "trace_system", 664 "print trace of which system (client or server)", 665 "client"); 666 667 668// 669// Helper function for ExecutionTraceParamContext::checkParams() just 670// to get us into the InstRecord namespace 671// 672void 673Trace::InstRecord::setParams() 674{ 675 flags[TRACE_MISSPEC] = exe_trace_spec; 676 677 flags[PRINT_CYCLE] = exe_trace_print_cycle; 678 flags[PRINT_OP_CLASS] = exe_trace_print_opclass; 679 flags[PRINT_THREAD_NUM] = exe_trace_print_thread; 680 flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr; 681 flags[PRINT_EFF_ADDR] = exe_trace_print_data; 682 flags[PRINT_INT_REGS] = exe_trace_print_iregs; 683 flags[PRINT_FETCH_SEQ] = exe_trace_print_fetchseq; 684 flags[PRINT_CP_SEQ] = exe_trace_print_cp_seq; 685 flags[PRINT_REG_DELTA] = exe_trace_print_reg_delta; 686 flags[PC_SYMBOL] = exe_trace_pc_symbol; 687 flags[INTEL_FORMAT] = exe_trace_intel_format; 688 flags[LEGION_LOCKSTEP] = exe_trace_legion_lockstep; 689 trace_system = exe_trace_system; 690 691 // If were going to be in lockstep with Legion 692 // Setup shared memory, and get otherwise ready 693 if (flags[LEGION_LOCKSTEP]) { 694 int shmfd = shmget('M' << 24 | getuid(), sizeof(SharedData), 0777); 695 if (shmfd < 0) 696 fatal("Couldn't get shared memory fd. Is Legion running?"); 697 698 shared_data = (SharedData*)shmat(shmfd, NULL, SHM_RND); 699 if (shared_data == (SharedData*)-1) 700 fatal("Couldn't allocate shared memory"); 701 702 if (shared_data->flags != OWN_M5) 703 fatal("Shared memory has invalid owner"); 704 705 if (shared_data->version != VERSION) 706 fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION, 707 shared_data->version); 708 709 // step legion forward one cycle so we can get register values 710 shared_data->flags = OWN_LEGION; 711 } 712} 713 714void 715ExecutionTraceParamContext::checkParams() 716{ 717 Trace::InstRecord::setParams(); 718} 719 720