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