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