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