cpu_impl.hh revision 2765:2962455d1c0a
1/* 2 * Copyright (c) 2006 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: Kevin Lim 29 */ 30 31#include <list> 32#include <string> 33 34#include "base/refcnt.hh" 35#include "cpu/base.hh" 36#include "cpu/base_dyn_inst.hh" 37#include "cpu/checker/cpu.hh" 38#include "cpu/simple_thread.hh" 39#include "cpu/thread_context.hh" 40#include "cpu/static_inst.hh" 41#include "mem/packet_impl.hh" 42#include "sim/byteswap.hh" 43#include "sim/sim_object.hh" 44#include "sim/stats.hh" 45 46#if FULL_SYSTEM 47#include "sim/system.hh" 48#include "arch/vtophys.hh" 49#include "kern/kernel_stats.hh" 50#endif // FULL_SYSTEM 51 52using namespace std; 53//The CheckerCPU does alpha only 54using namespace AlphaISA; 55 56void 57CheckerCPU::init() 58{ 59} 60 61CheckerCPU::CheckerCPU(Params *p) 62 : BaseCPU(p), thread(NULL), tc(NULL) 63{ 64 memReq = NULL; 65 66 numInst = 0; 67 startNumInst = 0; 68 numLoad = 0; 69 startNumLoad = 0; 70 youngestSN = 0; 71 72 changedPC = willChangePC = changedNextPC = false; 73 74 exitOnError = p->exitOnError; 75 warnOnlyOnLoadError = p->warnOnlyOnLoadError; 76#if FULL_SYSTEM 77 itb = p->itb; 78 dtb = p->dtb; 79 systemPtr = NULL; 80#else 81 process = p->process; 82#endif 83 84 result.integer = 0; 85} 86 87CheckerCPU::~CheckerCPU() 88{ 89} 90 91void 92CheckerCPU::setMemory(MemObject *mem) 93{ 94#if !FULL_SYSTEM 95 memPtr = mem; 96 thread = new SimpleThread(this, /* thread_num */ 0, process, 97 /* asid */ 0, mem); 98 99 thread->setStatus(ThreadContext::Suspended); 100 tc = thread->getTC(); 101 threadContexts.push_back(tc); 102#endif 103} 104 105void 106CheckerCPU::setSystem(System *system) 107{ 108#if FULL_SYSTEM 109 systemPtr = system; 110 111 thread = new SimpleThread(this, 0, systemPtr, itb, dtb, false); 112 113 thread->setStatus(ThreadContext::Suspended); 114 tc = thread->getTC(); 115 threadContexts.push_back(tc); 116 delete thread->kernelStats; 117 thread->kernelStats = NULL; 118#endif 119} 120 121void 122CheckerCPU::setIcachePort(Port *icache_port) 123{ 124 icachePort = icache_port; 125} 126 127void 128CheckerCPU::setDcachePort(Port *dcache_port) 129{ 130 dcachePort = dcache_port; 131} 132 133void 134CheckerCPU::serialize(ostream &os) 135{ 136/* 137 BaseCPU::serialize(os); 138 SERIALIZE_SCALAR(inst); 139 nameOut(os, csprintf("%s.xc", name())); 140 thread->serialize(os); 141 cacheCompletionEvent.serialize(os); 142*/ 143} 144 145void 146CheckerCPU::unserialize(Checkpoint *cp, const string §ion) 147{ 148/* 149 BaseCPU::unserialize(cp, section); 150 UNSERIALIZE_SCALAR(inst); 151 thread->unserialize(cp, csprintf("%s.xc", section)); 152*/ 153} 154 155Fault 156CheckerCPU::copySrcTranslate(Addr src) 157{ 158 panic("Unimplemented!"); 159} 160 161Fault 162CheckerCPU::copy(Addr dest) 163{ 164 panic("Unimplemented!"); 165} 166 167template <class T> 168Fault 169CheckerCPU::read(Addr addr, T &data, unsigned flags) 170{ 171 // need to fill in CPU & thread IDs here 172 memReq = new Request(); 173 174 memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 175 176 // translate to physical address 177 translateDataReadReq(memReq); 178 179 Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); 180 181 pkt->dataStatic(&data); 182 183 if (!(memReq->getFlags() & UNCACHEABLE)) { 184 // Access memory to see if we have the same data 185 dcachePort->sendFunctional(pkt); 186 } else { 187 // Assume the data is correct if it's an uncached access 188 memcpy(&data, &unverifiedResult.integer, sizeof(T)); 189 } 190 191 delete pkt; 192 193 return NoFault; 194} 195 196#ifndef DOXYGEN_SHOULD_SKIP_THIS 197 198template 199Fault 200CheckerCPU::read(Addr addr, uint64_t &data, unsigned flags); 201 202template 203Fault 204CheckerCPU::read(Addr addr, uint32_t &data, unsigned flags); 205 206template 207Fault 208CheckerCPU::read(Addr addr, uint16_t &data, unsigned flags); 209 210template 211Fault 212CheckerCPU::read(Addr addr, uint8_t &data, unsigned flags); 213 214#endif //DOXYGEN_SHOULD_SKIP_THIS 215 216template<> 217Fault 218CheckerCPU::read(Addr addr, double &data, unsigned flags) 219{ 220 return read(addr, *(uint64_t*)&data, flags); 221} 222 223template<> 224Fault 225CheckerCPU::read(Addr addr, float &data, unsigned flags) 226{ 227 return read(addr, *(uint32_t*)&data, flags); 228} 229 230template<> 231Fault 232CheckerCPU::read(Addr addr, int32_t &data, unsigned flags) 233{ 234 return read(addr, (uint32_t&)data, flags); 235} 236 237template <class T> 238Fault 239CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 240{ 241 // need to fill in CPU & thread IDs here 242 memReq = new Request(); 243 244 memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 245 246 // translate to physical address 247 thread->translateDataWriteReq(memReq); 248 249 // Can compare the write data and result only if it's cacheable, 250 // not a store conditional, or is a store conditional that 251 // succeeded. 252 // @todo: Verify that actual memory matches up with these values. 253 // Right now it only verifies that the instruction data is the 254 // same as what was in the request that got sent to memory; there 255 // is no verification that it is the same as what is in memory. 256 // This is because the LSQ would have to be snooped in the CPU to 257 // verify this data. 258 if (unverifiedReq && 259 !(unverifiedReq->getFlags() & UNCACHEABLE) && 260 (!(unverifiedReq->getFlags() & LOCKED) || 261 ((unverifiedReq->getFlags() & LOCKED) && 262 unverifiedReq->getScResult() == 1))) { 263 T inst_data; 264/* 265 // This code would work if the LSQ allowed for snooping. 266 Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); 267 pkt.dataStatic(&inst_data); 268 269 dcachePort->sendFunctional(pkt); 270 271 delete pkt; 272*/ 273 memcpy(&inst_data, unverifiedMemData, sizeof(T)); 274 275 if (data != inst_data) { 276 warn("%lli: Store value does not match value in memory! " 277 "Instruction: %#x, memory: %#x", 278 curTick, inst_data, data); 279 handleError(); 280 } 281 } 282 283 // Assume the result was the same as the one passed in. This checker 284 // doesn't check if the SC should succeed or fail, it just checks the 285 // value. 286 if (res && unverifiedReq->scResultValid()) 287 *res = unverifiedReq->getScResult(); 288 289 return NoFault; 290} 291 292 293#ifndef DOXYGEN_SHOULD_SKIP_THIS 294template 295Fault 296CheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res); 297 298template 299Fault 300CheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res); 301 302template 303Fault 304CheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res); 305 306template 307Fault 308CheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res); 309 310#endif //DOXYGEN_SHOULD_SKIP_THIS 311 312template<> 313Fault 314CheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res) 315{ 316 return write(*(uint64_t*)&data, addr, flags, res); 317} 318 319template<> 320Fault 321CheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res) 322{ 323 return write(*(uint32_t*)&data, addr, flags, res); 324} 325 326template<> 327Fault 328CheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) 329{ 330 return write((uint32_t)data, addr, flags, res); 331} 332 333 334#if FULL_SYSTEM 335Addr 336CheckerCPU::dbg_vtophys(Addr addr) 337{ 338 return vtophys(tc, addr); 339} 340#endif // FULL_SYSTEM 341 342bool 343CheckerCPU::translateInstReq(Request *req) 344{ 345#if FULL_SYSTEM 346 return (thread->translateInstReq(req) == NoFault); 347#else 348 thread->translateInstReq(req); 349 return true; 350#endif 351} 352 353void 354CheckerCPU::translateDataReadReq(Request *req) 355{ 356 thread->translateDataReadReq(req); 357 358 if (req->getVaddr() != unverifiedReq->getVaddr()) { 359 warn("%lli: Request virtual addresses do not match! Inst: %#x, " 360 "checker: %#x", 361 curTick, unverifiedReq->getVaddr(), req->getVaddr()); 362 handleError(); 363 } 364 req->setPaddr(unverifiedReq->getPaddr()); 365 366 if (checkFlags(req)) { 367 warn("%lli: Request flags do not match! Inst: %#x, checker: %#x", 368 curTick, unverifiedReq->getFlags(), req->getFlags()); 369 handleError(); 370 } 371} 372 373void 374CheckerCPU::translateDataWriteReq(Request *req) 375{ 376 thread->translateDataWriteReq(req); 377 378 if (req->getVaddr() != unverifiedReq->getVaddr()) { 379 warn("%lli: Request virtual addresses do not match! Inst: %#x, " 380 "checker: %#x", 381 curTick, unverifiedReq->getVaddr(), req->getVaddr()); 382 handleError(); 383 } 384 req->setPaddr(unverifiedReq->getPaddr()); 385 386 if (checkFlags(req)) { 387 warn("%lli: Request flags do not match! Inst: %#x, checker: %#x", 388 curTick, unverifiedReq->getFlags(), req->getFlags()); 389 handleError(); 390 } 391} 392 393bool 394CheckerCPU::checkFlags(Request *req) 395{ 396 // Remove any dynamic flags that don't have to do with the request itself. 397 unsigned flags = unverifiedReq->getFlags(); 398 unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | NO_FAULT; 399 flags = flags & (mask); 400 if (flags == req->getFlags()) { 401 return false; 402 } else { 403 return true; 404 } 405} 406 407void 408CheckerCPU::dumpAndExit() 409{ 410 warn("%lli: Checker PC:%#x, next PC:%#x", 411 curTick, thread->readPC(), thread->readNextPC()); 412 panic("Checker found an error!"); 413} 414 415template <class DynInstPtr> 416void 417Checker<DynInstPtr>::verify(DynInstPtr &completed_inst) 418{ 419 DynInstPtr inst; 420 421 // Either check this instruction, or add it to a list of 422 // instructions waiting to be checked. Instructions must be 423 // checked in program order, so if a store has committed yet not 424 // completed, there may be some instructions that are waiting 425 // behind it that have completed and must be checked. 426 if (!instList.empty()) { 427 if (youngestSN < completed_inst->seqNum) { 428 DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n", 429 completed_inst->seqNum, completed_inst->readPC()); 430 instList.push_back(completed_inst); 431 youngestSN = completed_inst->seqNum; 432 } 433 434 if (!instList.front()->isCompleted()) { 435 return; 436 } else { 437 inst = instList.front(); 438 instList.pop_front(); 439 } 440 } else { 441 if (!completed_inst->isCompleted()) { 442 if (youngestSN < completed_inst->seqNum) { 443 DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n", 444 completed_inst->seqNum, completed_inst->readPC()); 445 instList.push_back(completed_inst); 446 youngestSN = completed_inst->seqNum; 447 } 448 return; 449 } else { 450 if (youngestSN < completed_inst->seqNum) { 451 inst = completed_inst; 452 youngestSN = completed_inst->seqNum; 453 } else { 454 return; 455 } 456 } 457 } 458 459 // Try to check all instructions that are completed, ending if we 460 // run out of instructions to check or if an instruction is not 461 // yet completed. 462 while (1) { 463 DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n", 464 inst->seqNum, inst->readPC()); 465 unverifiedResult.integer = inst->readIntResult(); 466 unverifiedReq = inst->req; 467 unverifiedMemData = inst->memData; 468 numCycles++; 469 470 Fault fault = NoFault; 471 472 // maintain $r0 semantics 473 thread->setIntReg(ZeroReg, 0); 474#ifdef TARGET_ALPHA 475 thread->setFloatRegDouble(ZeroReg, 0.0); 476#endif // TARGET_ALPHA 477 478 // Check if any recent PC changes match up with anything we 479 // expect to happen. This is mostly to check if traps or 480 // PC-based events have occurred in both the checker and CPU. 481 if (changedPC) { 482 DPRINTF(Checker, "Changed PC recently to %#x\n", 483 thread->readPC()); 484 if (willChangePC) { 485 if (newPC == thread->readPC()) { 486 DPRINTF(Checker, "Changed PC matches expected PC\n"); 487 } else { 488 warn("%lli: Changed PC does not match expected PC, " 489 "changed: %#x, expected: %#x", 490 curTick, thread->readPC(), newPC); 491 CheckerCPU::handleError(); 492 } 493 willChangePC = false; 494 } 495 changedPC = false; 496 } 497 if (changedNextPC) { 498 DPRINTF(Checker, "Changed NextPC recently to %#x\n", 499 thread->readNextPC()); 500 changedNextPC = false; 501 } 502 503 // Try to fetch the instruction 504 505#if FULL_SYSTEM 506#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0 507#else 508#define IFETCH_FLAGS(pc) 0 509#endif 510 511 uint64_t fetch_PC = thread->readPC() & ~3; 512 513 // set up memory request for instruction fetch 514 memReq = new Request(inst->threadNumber, fetch_PC, 515 sizeof(uint32_t), 516 IFETCH_FLAGS(thread->readPC()), 517 fetch_PC, thread->readCpuId(), inst->threadNumber); 518 519 bool succeeded = translateInstReq(memReq); 520 521 if (!succeeded) { 522 if (inst->getFault() == NoFault) { 523 // In this case the instruction was not a dummy 524 // instruction carrying an ITB fault. In the single 525 // threaded case the ITB should still be able to 526 // translate this instruction; in the SMT case it's 527 // possible that its ITB entry was kicked out. 528 warn("%lli: Instruction PC %#x was not found in the ITB!", 529 curTick, thread->readPC()); 530 handleError(inst); 531 532 // go to the next instruction 533 thread->setPC(thread->readNextPC()); 534 thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); 535 536 return; 537 } else { 538 // The instruction is carrying an ITB fault. Handle 539 // the fault and see if our results match the CPU on 540 // the next tick(). 541 fault = inst->getFault(); 542 } 543 } 544 545 if (fault == NoFault) { 546 Packet *pkt = new Packet(memReq, Packet::ReadReq, 547 Packet::Broadcast); 548 549 pkt->dataStatic(&machInst); 550 551 icachePort->sendFunctional(pkt); 552 553 delete pkt; 554 555 // keep an instruction count 556 numInst++; 557 558 // decode the instruction 559 machInst = gtoh(machInst); 560 // Checks that the instruction matches what we expected it to be. 561 // Checks both the machine instruction and the PC. 562 validateInst(inst); 563 564 curStaticInst = StaticInst::decode(makeExtMI(machInst, 565 thread->readPC())); 566 567#if FULL_SYSTEM 568 thread->setInst(machInst); 569#endif // FULL_SYSTEM 570 571 fault = inst->getFault(); 572 } 573 574 // Discard fetch's memReq. 575 delete memReq; 576 memReq = NULL; 577 578 // Either the instruction was a fault and we should process the fault, 579 // or we should just go ahead execute the instruction. This assumes 580 // that the instruction is properly marked as a fault. 581 if (fault == NoFault) { 582 583 thread->funcExeInst++; 584 585 fault = curStaticInst->execute(this, NULL); 586 587 // Checks to make sure instrution results are correct. 588 validateExecution(inst); 589 590 if (curStaticInst->isLoad()) { 591 ++numLoad; 592 } 593 } 594 595 if (fault != NoFault) { 596#if FULL_SYSTEM 597 fault->invoke(tc); 598 willChangePC = true; 599 newPC = thread->readPC(); 600 DPRINTF(Checker, "Fault, PC is now %#x\n", newPC); 601#else // !FULL_SYSTEM 602 fatal("fault (%d) detected @ PC 0x%08p", fault, thread->readPC()); 603#endif // FULL_SYSTEM 604 } else { 605#if THE_ISA != MIPS_ISA 606 // go to the next instruction 607 thread->setPC(thread->readNextPC()); 608 thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); 609#else 610 // go to the next instruction 611 thread->setPC(thread->readNextPC()); 612 thread->setNextPC(thread->readNextNPC()); 613 thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); 614#endif 615 616 } 617 618#if FULL_SYSTEM 619 // @todo: Determine if these should happen only if the 620 // instruction hasn't faulted. In the SimpleCPU case this may 621 // not be true, but in the O3 or Ozone case this may be true. 622 Addr oldpc; 623 int count = 0; 624 do { 625 oldpc = thread->readPC(); 626 system->pcEventQueue.service(tc); 627 count++; 628 } while (oldpc != thread->readPC()); 629 if (count > 1) { 630 willChangePC = true; 631 newPC = thread->readPC(); 632 DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC); 633 } 634#endif 635 636 // @todo: Optionally can check all registers. (Or just those 637 // that have been modified). 638 validateState(); 639 640 if (memReq) { 641 delete memReq; 642 memReq = NULL; 643 } 644 645 // Continue verifying instructions if there's another completed 646 // instruction waiting to be verified. 647 if (instList.empty()) { 648 break; 649 } else if (instList.front()->isCompleted()) { 650 inst = instList.front(); 651 instList.pop_front(); 652 } else { 653 break; 654 } 655 } 656} 657 658template <class DynInstPtr> 659void 660Checker<DynInstPtr>::switchOut(Sampler *s) 661{ 662 instList.clear(); 663} 664 665template <class DynInstPtr> 666void 667Checker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU) 668{ 669} 670 671template <class DynInstPtr> 672void 673Checker<DynInstPtr>::validateInst(DynInstPtr &inst) 674{ 675 if (inst->readPC() != thread->readPC()) { 676 warn("%lli: PCs do not match! Inst: %#x, checker: %#x", 677 curTick, inst->readPC(), thread->readPC()); 678 if (changedPC) { 679 warn("%lli: Changed PCs recently, may not be an error", 680 curTick); 681 } else { 682 handleError(inst); 683 } 684 } 685 686 MachInst mi = static_cast<MachInst>(inst->staticInst->machInst); 687 688 if (mi != machInst) { 689 warn("%lli: Binary instructions do not match! Inst: %#x, " 690 "checker: %#x", 691 curTick, mi, machInst); 692 handleError(inst); 693 } 694} 695 696template <class DynInstPtr> 697void 698Checker<DynInstPtr>::validateExecution(DynInstPtr &inst) 699{ 700 bool result_mismatch = false; 701 if (inst->numDestRegs()) { 702 // @todo: Support more destination registers. 703 if (inst->isUnverifiable()) { 704 // Unverifiable instructions assume they were executed 705 // properly by the CPU. Grab the result from the 706 // instruction and write it to the register. 707 copyResult(inst); 708 } else if (result.integer != inst->readIntResult()) { 709 result_mismatch = true; 710 } 711 } 712 713 if (result_mismatch) { 714 warn("%lli: Instruction results do not match! (Values may not " 715 "actually be integers) Inst: %#x, checker: %#x", 716 curTick, inst->readIntResult(), result.integer); 717 718 // It's useful to verify load values from memory, but in MP 719 // systems the value obtained at execute may be different than 720 // the value obtained at completion. Similarly DMA can 721 // present the same problem on even UP systems. Thus there is 722 // the option to only warn on loads having a result error. 723 if (inst->isLoad() && warnOnlyOnLoadError) { 724 copyResult(inst); 725 } else { 726 handleError(inst); 727 } 728 } 729 730 if (inst->readNextPC() != thread->readNextPC()) { 731 warn("%lli: Instruction next PCs do not match! Inst: %#x, " 732 "checker: %#x", 733 curTick, inst->readNextPC(), thread->readNextPC()); 734 handleError(inst); 735 } 736 737 // Checking side effect registers can be difficult if they are not 738 // checked simultaneously with the execution of the instruction. 739 // This is because other valid instructions may have modified 740 // these registers in the meantime, and their values are not 741 // stored within the DynInst. 742 while (!miscRegIdxs.empty()) { 743 int misc_reg_idx = miscRegIdxs.front(); 744 miscRegIdxs.pop(); 745 746 if (inst->tcBase()->readMiscReg(misc_reg_idx) != 747 thread->readMiscReg(misc_reg_idx)) { 748 warn("%lli: Misc reg idx %i (side effect) does not match! " 749 "Inst: %#x, checker: %#x", 750 curTick, misc_reg_idx, 751 inst->tcBase()->readMiscReg(misc_reg_idx), 752 thread->readMiscReg(misc_reg_idx)); 753 handleError(inst); 754 } 755 } 756} 757 758template <class DynInstPtr> 759void 760Checker<DynInstPtr>::validateState() 761{ 762} 763 764template <class DynInstPtr> 765void 766Checker<DynInstPtr>::copyResult(DynInstPtr &inst) 767{ 768 RegIndex idx = inst->destRegIdx(0); 769 if (idx < TheISA::FP_Base_DepTag) { 770 thread->setIntReg(idx, inst->readIntResult()); 771 } else if (idx < TheISA::Fpcr_DepTag) { 772 thread->setFloatRegBits(idx, inst->readIntResult()); 773 } else { 774 thread->setMiscReg(idx, inst->readIntResult()); 775 } 776} 777 778template <class DynInstPtr> 779void 780Checker<DynInstPtr>::dumpAndExit(DynInstPtr &inst) 781{ 782 cprintf("Error detected, instruction information:\n"); 783 cprintf("PC:%#x, nextPC:%#x\n[sn:%lli]\n[tid:%i]\n" 784 "Completed:%i\n", 785 inst->readPC(), 786 inst->readNextPC(), 787 inst->seqNum, 788 inst->threadNumber, 789 inst->isCompleted()); 790 inst->dump(); 791 CheckerCPU::dumpAndExit(); 792} 793 794template <class DynInstPtr> 795void 796Checker<DynInstPtr>::dumpInsts() 797{ 798 int num = 0; 799 800 InstListIt inst_list_it = --(instList.end()); 801 802 cprintf("Inst list size: %i\n", instList.size()); 803 804 while (inst_list_it != instList.end()) 805 { 806 cprintf("Instruction:%i\n", 807 num); 808 809 cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" 810 "Completed:%i\n", 811 (*inst_list_it)->readPC(), 812 (*inst_list_it)->seqNum, 813 (*inst_list_it)->threadNumber, 814 (*inst_list_it)->isCompleted()); 815 816 cprintf("\n"); 817 818 inst_list_it--; 819 ++num; 820 } 821 822} 823