cpu_impl.hh revision 3349
12SN/A/* 21458SN/A * Copyright (c) 2006 The Regents of The University of Michigan 32SN/A * All rights reserved. 42SN/A * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Kevin Lim 292665Ssaidi@eecs.umich.edu */ 302SN/A 312SN/A#include <list> 321147SN/A#include <string> 331147SN/A 342SN/A#include "base/refcnt.hh" 352037SN/A#include "cpu/base_dyn_inst.hh" 362037SN/A#include "cpu/checker/cpu.hh" 372428SN/A#include "cpu/simple_thread.hh" 381858SN/A#include "cpu/thread_context.hh" 3956SN/A#include "cpu/static_inst.hh" 402SN/A#include "sim/sim_object.hh" 412107SN/A#include "sim/stats.hh" 422SN/A 432972Sgblack@eecs.umich.edu#if FULL_SYSTEM 442972Sgblack@eecs.umich.edu#include "arch/vtophys.hh" 452972Sgblack@eecs.umich.edu#endif // FULL_SYSTEM 462238SN/A 472972Sgblack@eecs.umich.eduusing namespace std; 482972Sgblack@eecs.umich.edu//The CheckerCPU does alpha only 492972Sgblack@eecs.umich.eduusing namespace AlphaISA; 502972Sgblack@eecs.umich.edu 512972Sgblack@eecs.umich.edutemplate <class DynInstPtr> 522972Sgblack@eecs.umich.eduvoid 532972Sgblack@eecs.umich.eduChecker<DynInstPtr>::verify(DynInstPtr &completed_inst) 542972Sgblack@eecs.umich.edu{ 552972Sgblack@eecs.umich.edu DynInstPtr inst; 562972Sgblack@eecs.umich.edu 572972Sgblack@eecs.umich.edu // Either check this instruction, or add it to a list of 582972Sgblack@eecs.umich.edu // instructions waiting to be checked. Instructions must be 592238SN/A // checked in program order, so if a store has committed yet not 602972Sgblack@eecs.umich.edu // completed, there may be some instructions that are waiting 612238SN/A // behind it that have completed and must be checked. 623093Sksewell@umich.edu if (!instList.empty()) { 633093Sksewell@umich.edu if (youngestSN < completed_inst->seqNum) { 643093Sksewell@umich.edu DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n", 652972Sgblack@eecs.umich.edu completed_inst->seqNum, completed_inst->readPC()); 662972Sgblack@eecs.umich.edu instList.push_back(completed_inst); 672972Sgblack@eecs.umich.edu youngestSN = completed_inst->seqNum; 682972Sgblack@eecs.umich.edu } 692972Sgblack@eecs.umich.edu 702972Sgblack@eecs.umich.edu if (!instList.front()->isCompleted()) { 712972Sgblack@eecs.umich.edu return; 722972Sgblack@eecs.umich.edu } else { 732972Sgblack@eecs.umich.edu inst = instList.front(); 742972Sgblack@eecs.umich.edu instList.pop_front(); 752972Sgblack@eecs.umich.edu } 762972Sgblack@eecs.umich.edu } else { 772972Sgblack@eecs.umich.edu if (!completed_inst->isCompleted()) { 782972Sgblack@eecs.umich.edu if (youngestSN < completed_inst->seqNum) { 792972Sgblack@eecs.umich.edu DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n", 802972Sgblack@eecs.umich.edu completed_inst->seqNum, completed_inst->readPC()); 812972Sgblack@eecs.umich.edu instList.push_back(completed_inst); 822972Sgblack@eecs.umich.edu youngestSN = completed_inst->seqNum; 832972Sgblack@eecs.umich.edu } 842972Sgblack@eecs.umich.edu return; 852972Sgblack@eecs.umich.edu } else { 862972Sgblack@eecs.umich.edu if (youngestSN < completed_inst->seqNum) { 872972Sgblack@eecs.umich.edu inst = completed_inst; 882972Sgblack@eecs.umich.edu youngestSN = completed_inst->seqNum; 892972Sgblack@eecs.umich.edu } else { 902972Sgblack@eecs.umich.edu return; 912972Sgblack@eecs.umich.edu } 922972Sgblack@eecs.umich.edu } 932972Sgblack@eecs.umich.edu } 942972Sgblack@eecs.umich.edu 952972Sgblack@eecs.umich.edu unverifiedInst = inst; 962972Sgblack@eecs.umich.edu 972972Sgblack@eecs.umich.edu // Try to check all instructions that are completed, ending if we 982972Sgblack@eecs.umich.edu // run out of instructions to check or if an instruction is not 992972Sgblack@eecs.umich.edu // yet completed. 1002972Sgblack@eecs.umich.edu while (1) { 1012972Sgblack@eecs.umich.edu DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n", 1022972Sgblack@eecs.umich.edu inst->seqNum, inst->readPC()); 1032972Sgblack@eecs.umich.edu unverifiedResult.integer = inst->readIntResult(); 1042972Sgblack@eecs.umich.edu unverifiedReq = inst->req; 1052972Sgblack@eecs.umich.edu unverifiedMemData = inst->memData; 1062972Sgblack@eecs.umich.edu numCycles++; 1072972Sgblack@eecs.umich.edu 1082972Sgblack@eecs.umich.edu Fault fault = NoFault; 1092972Sgblack@eecs.umich.edu 1102972Sgblack@eecs.umich.edu // maintain $r0 semantics 1112972Sgblack@eecs.umich.edu thread->setIntReg(ZeroReg, 0); 1122972Sgblack@eecs.umich.edu#ifdef TARGET_ALPHA 1132972Sgblack@eecs.umich.edu thread->setFloatRegDouble(ZeroReg, 0.0); 1142972Sgblack@eecs.umich.edu#endif // TARGET_ALPHA 1152972Sgblack@eecs.umich.edu 1162972Sgblack@eecs.umich.edu // Check if any recent PC changes match up with anything we 1172972Sgblack@eecs.umich.edu // expect to happen. This is mostly to check if traps or 1182972Sgblack@eecs.umich.edu // PC-based events have occurred in both the checker and CPU. 1192972Sgblack@eecs.umich.edu if (changedPC) { 1202972Sgblack@eecs.umich.edu DPRINTF(Checker, "Changed PC recently to %#x\n", 1212972Sgblack@eecs.umich.edu thread->readPC()); 1222972Sgblack@eecs.umich.edu if (willChangePC) { 1232972Sgblack@eecs.umich.edu if (newPC == thread->readPC()) { 1242972Sgblack@eecs.umich.edu DPRINTF(Checker, "Changed PC matches expected PC\n"); 1252972Sgblack@eecs.umich.edu } else { 1262972Sgblack@eecs.umich.edu warn("%lli: Changed PC does not match expected PC, " 1272972Sgblack@eecs.umich.edu "changed: %#x, expected: %#x", 1282972Sgblack@eecs.umich.edu curTick, thread->readPC(), newPC); 1292972Sgblack@eecs.umich.edu CheckerCPU::handleError(); 1302972Sgblack@eecs.umich.edu } 1312238SN/A willChangePC = false; 1322238SN/A } 1332238SN/A changedPC = false; 1342512SN/A } 1352972Sgblack@eecs.umich.edu if (changedNextPC) { 1362972Sgblack@eecs.umich.edu DPRINTF(Checker, "Changed NextPC recently to %#x\n", 1372972Sgblack@eecs.umich.edu thread->readNextPC()); 1382972Sgblack@eecs.umich.edu changedNextPC = false; 1392972Sgblack@eecs.umich.edu } 1402972Sgblack@eecs.umich.edu 1412972Sgblack@eecs.umich.edu // Try to fetch the instruction 1422972Sgblack@eecs.umich.edu 1432972Sgblack@eecs.umich.edu#if FULL_SYSTEM 1442972Sgblack@eecs.umich.edu#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0 1452972Sgblack@eecs.umich.edu#else 1462972Sgblack@eecs.umich.edu#define IFETCH_FLAGS(pc) 0 1472972Sgblack@eecs.umich.edu#endif 1482972Sgblack@eecs.umich.edu 1492972Sgblack@eecs.umich.edu uint64_t fetch_PC = thread->readPC() & ~3; 1502972Sgblack@eecs.umich.edu 1512972Sgblack@eecs.umich.edu // set up memory request for instruction fetch 1522972Sgblack@eecs.umich.edu memReq = new Request(inst->threadNumber, fetch_PC, 1532972Sgblack@eecs.umich.edu sizeof(uint32_t), 1542972Sgblack@eecs.umich.edu IFETCH_FLAGS(thread->readPC()), 1552972Sgblack@eecs.umich.edu fetch_PC, thread->readCpuId(), inst->threadNumber); 1562972Sgblack@eecs.umich.edu 1572972Sgblack@eecs.umich.edu bool succeeded = translateInstReq(memReq); 1582972Sgblack@eecs.umich.edu 1592972Sgblack@eecs.umich.edu if (!succeeded) { 1602972Sgblack@eecs.umich.edu if (inst->getFault() == NoFault) { 1612972Sgblack@eecs.umich.edu // In this case the instruction was not a dummy 1622972Sgblack@eecs.umich.edu // instruction carrying an ITB fault. In the single 1632972Sgblack@eecs.umich.edu // threaded case the ITB should still be able to 1642972Sgblack@eecs.umich.edu // translate this instruction; in the SMT case it's 1652972Sgblack@eecs.umich.edu // possible that its ITB entry was kicked out. 1662972Sgblack@eecs.umich.edu warn("%lli: Instruction PC %#x was not found in the ITB!", 1672972Sgblack@eecs.umich.edu curTick, thread->readPC()); 1682972Sgblack@eecs.umich.edu handleError(inst); 1692972Sgblack@eecs.umich.edu 1702972Sgblack@eecs.umich.edu // go to the next instruction 1712972Sgblack@eecs.umich.edu thread->setPC(thread->readNextPC()); 1722972Sgblack@eecs.umich.edu thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); 1732972Sgblack@eecs.umich.edu 1742972Sgblack@eecs.umich.edu break; 1752972Sgblack@eecs.umich.edu } else { 1762972Sgblack@eecs.umich.edu // The instruction is carrying an ITB fault. Handle 1772972Sgblack@eecs.umich.edu // the fault and see if our results match the CPU on 1782972Sgblack@eecs.umich.edu // the next tick(). 1792972Sgblack@eecs.umich.edu fault = inst->getFault(); 1802972Sgblack@eecs.umich.edu } 1812972Sgblack@eecs.umich.edu } 1822972Sgblack@eecs.umich.edu 1832972Sgblack@eecs.umich.edu if (fault == NoFault) { 1842972Sgblack@eecs.umich.edu PacketPtr pkt = new Packet(memReq, Packet::ReadReq, 1852972Sgblack@eecs.umich.edu Packet::Broadcast); 1862972Sgblack@eecs.umich.edu 1872972Sgblack@eecs.umich.edu pkt->dataStatic(&machInst); 1882972Sgblack@eecs.umich.edu 1892972Sgblack@eecs.umich.edu icachePort->sendFunctional(pkt); 1902972Sgblack@eecs.umich.edu 1912972Sgblack@eecs.umich.edu delete pkt; 1922972Sgblack@eecs.umich.edu 1932972Sgblack@eecs.umich.edu // keep an instruction count 1942972Sgblack@eecs.umich.edu numInst++; 1952972Sgblack@eecs.umich.edu 1962972Sgblack@eecs.umich.edu // decode the instruction 1972972Sgblack@eecs.umich.edu machInst = gtoh(machInst); 1982972Sgblack@eecs.umich.edu // Checks that the instruction matches what we expected it to be. 1992972Sgblack@eecs.umich.edu // Checks both the machine instruction and the PC. 2002972Sgblack@eecs.umich.edu validateInst(inst); 2012972Sgblack@eecs.umich.edu 2022972Sgblack@eecs.umich.edu curStaticInst = StaticInst::decode(makeExtMI(machInst, 2032972Sgblack@eecs.umich.edu thread->readPC())); 2042972Sgblack@eecs.umich.edu 2052972Sgblack@eecs.umich.edu#if FULL_SYSTEM 2062972Sgblack@eecs.umich.edu thread->setInst(machInst); 2072972Sgblack@eecs.umich.edu#endif // FULL_SYSTEM 2082972Sgblack@eecs.umich.edu 2092972Sgblack@eecs.umich.edu fault = inst->getFault(); 2102972Sgblack@eecs.umich.edu } 2112972Sgblack@eecs.umich.edu 2122972Sgblack@eecs.umich.edu // Discard fetch's memReq. 2132972Sgblack@eecs.umich.edu delete memReq; 2142972Sgblack@eecs.umich.edu memReq = NULL; 2152972Sgblack@eecs.umich.edu 2162972Sgblack@eecs.umich.edu // Either the instruction was a fault and we should process the fault, 2172972Sgblack@eecs.umich.edu // or we should just go ahead execute the instruction. This assumes 2182972Sgblack@eecs.umich.edu // that the instruction is properly marked as a fault. 2192972Sgblack@eecs.umich.edu if (fault == NoFault) { 2202972Sgblack@eecs.umich.edu 2212972Sgblack@eecs.umich.edu thread->funcExeInst++; 2222972Sgblack@eecs.umich.edu 2232972Sgblack@eecs.umich.edu if (!inst->isUnverifiable()) 2242972Sgblack@eecs.umich.edu fault = curStaticInst->execute(this, NULL); 2252972Sgblack@eecs.umich.edu 2262512SN/A // Checks to make sure instrution results are correct. 2272512SN/A validateExecution(inst); 2282972Sgblack@eecs.umich.edu 2292512SN/A if (curStaticInst->isLoad()) { 2302972Sgblack@eecs.umich.edu ++numLoad; 2312972Sgblack@eecs.umich.edu } 2322972Sgblack@eecs.umich.edu } 2332972Sgblack@eecs.umich.edu 2342972Sgblack@eecs.umich.edu if (fault != NoFault) { 2352SN/A#if FULL_SYSTEM 2362972Sgblack@eecs.umich.edu fault->invoke(tc); 2372972Sgblack@eecs.umich.edu willChangePC = true; 2382972Sgblack@eecs.umich.edu newPC = thread->readPC(); 2392449SN/A DPRINTF(Checker, "Fault, PC is now %#x\n", newPC); 2402972Sgblack@eecs.umich.edu#endif 2412972Sgblack@eecs.umich.edu } else { 2422227SN/A#if THE_ISA != MIPS_ISA 2432972Sgblack@eecs.umich.edu // go to the next instruction 2442SN/A thread->setPC(thread->readNextPC()); 2452972Sgblack@eecs.umich.edu thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); 2462972Sgblack@eecs.umich.edu#else 2472972Sgblack@eecs.umich.edu // go to the next instruction 2482972Sgblack@eecs.umich.edu thread->setPC(thread->readNextPC()); 2492972Sgblack@eecs.umich.edu thread->setNextPC(thread->readNextNPC()); 2502972Sgblack@eecs.umich.edu thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); 2512972Sgblack@eecs.umich.edu#endif 2522972Sgblack@eecs.umich.edu 2532972Sgblack@eecs.umich.edu } 2542972Sgblack@eecs.umich.edu 2552972Sgblack@eecs.umich.edu#if FULL_SYSTEM 2562972Sgblack@eecs.umich.edu // @todo: Determine if these should happen only if the 2572972Sgblack@eecs.umich.edu // instruction hasn't faulted. In the SimpleCPU case this may 2582972Sgblack@eecs.umich.edu // not be true, but in the O3 or Ozone case this may be true. 2592972Sgblack@eecs.umich.edu Addr oldpc; 2602972Sgblack@eecs.umich.edu int count = 0; 2612972Sgblack@eecs.umich.edu do { 2622972Sgblack@eecs.umich.edu oldpc = thread->readPC(); 2632972Sgblack@eecs.umich.edu system->pcEventQueue.service(tc); 2642972Sgblack@eecs.umich.edu count++; 2652972Sgblack@eecs.umich.edu } while (oldpc != thread->readPC()); 2662972Sgblack@eecs.umich.edu if (count > 1) { 2672972Sgblack@eecs.umich.edu willChangePC = true; 2682972Sgblack@eecs.umich.edu newPC = thread->readPC(); 2692972Sgblack@eecs.umich.edu DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC); 2702972Sgblack@eecs.umich.edu } 2712972Sgblack@eecs.umich.edu#endif 2722972Sgblack@eecs.umich.edu 2732972Sgblack@eecs.umich.edu // @todo: Optionally can check all registers. (Or just those 2742972Sgblack@eecs.umich.edu // that have been modified). 2752972Sgblack@eecs.umich.edu validateState(); 2762972Sgblack@eecs.umich.edu 2772972Sgblack@eecs.umich.edu if (memReq) { 2782972Sgblack@eecs.umich.edu delete memReq; 2792972Sgblack@eecs.umich.edu memReq = NULL; 2802972Sgblack@eecs.umich.edu } 2812972Sgblack@eecs.umich.edu 2822972Sgblack@eecs.umich.edu // Continue verifying instructions if there's another completed 2832972Sgblack@eecs.umich.edu // instruction waiting to be verified. 2842972Sgblack@eecs.umich.edu if (instList.empty()) { 2852264SN/A break; 2862107SN/A } else if (instList.front()->isCompleted()) { 2871147SN/A inst = instList.front(); 288 instList.pop_front(); 289 } else { 290 break; 291 } 292 } 293 unverifiedInst = NULL; 294} 295 296template <class DynInstPtr> 297void 298Checker<DynInstPtr>::switchOut() 299{ 300 instList.clear(); 301} 302 303template <class DynInstPtr> 304void 305Checker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU) 306{ 307} 308 309template <class DynInstPtr> 310void 311Checker<DynInstPtr>::validateInst(DynInstPtr &inst) 312{ 313 if (inst->readPC() != thread->readPC()) { 314 warn("%lli: PCs do not match! Inst: %#x, checker: %#x", 315 curTick, inst->readPC(), thread->readPC()); 316 if (changedPC) { 317 warn("%lli: Changed PCs recently, may not be an error", 318 curTick); 319 } else { 320 handleError(inst); 321 } 322 } 323 324 MachInst mi = static_cast<MachInst>(inst->staticInst->machInst); 325 326 if (mi != machInst) { 327 warn("%lli: Binary instructions do not match! Inst: %#x, " 328 "checker: %#x", 329 curTick, mi, machInst); 330 handleError(inst); 331 } 332} 333 334template <class DynInstPtr> 335void 336Checker<DynInstPtr>::validateExecution(DynInstPtr &inst) 337{ 338 bool result_mismatch = false; 339 if (inst->numDestRegs()) { 340 // @todo: Support more destination registers. 341 if (inst->isUnverifiable()) { 342 // Unverifiable instructions assume they were executed 343 // properly by the CPU. Grab the result from the 344 // instruction and write it to the register. 345 copyResult(inst); 346 } else if (result.integer != inst->readIntResult()) { 347 result_mismatch = true; 348 } 349 } 350 351 if (result_mismatch) { 352 warn("%lli: Instruction results do not match! (Values may not " 353 "actually be integers) Inst: %#x, checker: %#x", 354 curTick, inst->readIntResult(), result.integer); 355 356 // It's useful to verify load values from memory, but in MP 357 // systems the value obtained at execute may be different than 358 // the value obtained at completion. Similarly DMA can 359 // present the same problem on even UP systems. Thus there is 360 // the option to only warn on loads having a result error. 361 if (inst->isLoad() && warnOnlyOnLoadError) { 362 copyResult(inst); 363 } else { 364 handleError(inst); 365 } 366 } 367 368 if (inst->readNextPC() != thread->readNextPC()) { 369 warn("%lli: Instruction next PCs do not match! Inst: %#x, " 370 "checker: %#x", 371 curTick, inst->readNextPC(), thread->readNextPC()); 372 handleError(inst); 373 } 374 375 // Checking side effect registers can be difficult if they are not 376 // checked simultaneously with the execution of the instruction. 377 // This is because other valid instructions may have modified 378 // these registers in the meantime, and their values are not 379 // stored within the DynInst. 380 while (!miscRegIdxs.empty()) { 381 int misc_reg_idx = miscRegIdxs.front(); 382 miscRegIdxs.pop(); 383 384 if (inst->tcBase()->readMiscReg(misc_reg_idx) != 385 thread->readMiscReg(misc_reg_idx)) { 386 warn("%lli: Misc reg idx %i (side effect) does not match! " 387 "Inst: %#x, checker: %#x", 388 curTick, misc_reg_idx, 389 inst->tcBase()->readMiscReg(misc_reg_idx), 390 thread->readMiscReg(misc_reg_idx)); 391 handleError(inst); 392 } 393 } 394} 395 396template <class DynInstPtr> 397void 398Checker<DynInstPtr>::validateState() 399{ 400 if (updateThisCycle) { 401 warn("%lli: Instruction PC %#x results didn't match up, copying all " 402 "registers from main CPU", curTick, unverifiedInst->readPC()); 403 // Heavy-weight copying of all registers 404 thread->copyArchRegs(unverifiedInst->tcBase()); 405 // Also advance the PC. Hopefully no PC-based events happened. 406#if THE_ISA != MIPS_ISA 407 // go to the next instruction 408 thread->setPC(thread->readNextPC()); 409 thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); 410#else 411 // go to the next instruction 412 thread->setPC(thread->readNextPC()); 413 thread->setNextPC(thread->readNextNPC()); 414 thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); 415#endif 416 updateThisCycle = false; 417 } 418} 419 420template <class DynInstPtr> 421void 422Checker<DynInstPtr>::copyResult(DynInstPtr &inst) 423{ 424 RegIndex idx = inst->destRegIdx(0); 425 if (idx < TheISA::FP_Base_DepTag) { 426 thread->setIntReg(idx, inst->readIntResult()); 427 } else if (idx < TheISA::Fpcr_DepTag) { 428 thread->setFloatRegBits(idx, inst->readIntResult()); 429 } else { 430 thread->setMiscReg(idx, inst->readIntResult()); 431 } 432} 433 434template <class DynInstPtr> 435void 436Checker<DynInstPtr>::dumpAndExit(DynInstPtr &inst) 437{ 438 cprintf("Error detected, instruction information:\n"); 439 cprintf("PC:%#x, nextPC:%#x\n[sn:%lli]\n[tid:%i]\n" 440 "Completed:%i\n", 441 inst->readPC(), 442 inst->readNextPC(), 443 inst->seqNum, 444 inst->threadNumber, 445 inst->isCompleted()); 446 inst->dump(); 447 CheckerCPU::dumpAndExit(); 448} 449 450template <class DynInstPtr> 451void 452Checker<DynInstPtr>::dumpInsts() 453{ 454 int num = 0; 455 456 InstListIt inst_list_it = --(instList.end()); 457 458 cprintf("Inst list size: %i\n", instList.size()); 459 460 while (inst_list_it != instList.end()) 461 { 462 cprintf("Instruction:%i\n", 463 num); 464 465 cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" 466 "Completed:%i\n", 467 (*inst_list_it)->readPC(), 468 (*inst_list_it)->seqNum, 469 (*inst_list_it)->threadNumber, 470 (*inst_list_it)->isCompleted()); 471 472 cprintf("\n"); 473 474 inst_list_it--; 475 ++num; 476 } 477 478} 479