cpu_impl.hh revision 2323
1/* 2 * Copyright (c) 2002-2005 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 <cmath> 30#include <cstdio> 31//#include <cstdlib> 32#include <iostream> 33#include <iomanip> 34#include <list> 35//#include <sstream> 36#include <string> 37 38//#include "base/cprintf.hh" 39//#include "base/inifile.hh" 40//#include "base/loader/symtab.hh" 41#include "base/misc.hh" 42//#include "base/pollevent.hh" 43//#include "base/range.hh" 44#include "base/refcnt.hh" 45//#include "base/stats/events.hh" 46#include "cpu/base.hh" 47#include "cpu/base_dyn_inst.hh" 48#include "cpu/checker/cpu.hh" 49#include "cpu/cpu_exec_context.hh" 50#include "cpu/exec_context.hh" 51//#include "cpu/exetrace.hh" 52//#include "cpu/profile.hh" 53#include "cpu/sampler/sampler.hh" 54//#include "cpu/smt.hh" 55#include "cpu/static_inst.hh" 56//#include "kern/kernel_stats.hh" 57#include "mem/base_mem.hh" 58#include "mem/mem_interface.hh" 59#include "sim/byteswap.hh" 60#include "sim/builder.hh" 61//#include "sim/debug.hh" 62//#include "sim/host.hh" 63//#include "sim/sim_events.hh" 64#include "sim/sim_object.hh" 65#include "sim/stats.hh" 66 67#include "cpu/o3/alpha_dyn_inst.hh" 68#include "cpu/o3/alpha_impl.hh" 69 70#include "cpu/ozone/dyn_inst.hh" 71#include "cpu/ozone/ozone_impl.hh" 72#include "cpu/ozone/simple_impl.hh" 73 74#if FULL_SYSTEM 75#include "base/remote_gdb.hh" 76#include "mem/functional/memory_control.hh" 77#include "mem/functional/physical.hh" 78#include "sim/system.hh" 79#include "arch/tlb.hh" 80#include "arch/stacktrace.hh" 81#include "arch/vtophys.hh" 82#else // !FULL_SYSTEM 83#include "mem/functional/functional.hh" 84#endif // FULL_SYSTEM 85 86using namespace std; 87//The CheckerCPU does alpha only 88using namespace AlphaISA; 89 90void 91CheckerCPU::init() 92{ 93/* 94 BaseCPU::init(); 95#if FULL_SYSTEM 96 for (int i = 0; i < execContexts.size(); ++i) { 97 ExecContext *xc = execContexts[i]; 98 99 // initialize CPU, including PC 100 TheISA::initCPU(xc, xc->readCpuId()); 101 } 102#endif 103*/ 104} 105 106CheckerCPU::CheckerCPU(Params *p) 107 : BaseCPU(p), cpuXC(NULL), xcProxy(NULL) 108{ 109 memReq = new MemReq(); 110 memReq->xc = xcProxy; 111 memReq->asid = 0; 112 memReq->data = new uint8_t[64]; 113 114 numInst = 0; 115 startNumInst = 0; 116 numLoad = 0; 117 startNumLoad = 0; 118 youngestSN = 0; 119 120 changedPC = willChangePC = changedNextPC = false; 121 122 exitOnError = p->exitOnError; 123#if FULL_SYSTEM 124 itb = p->itb; 125 dtb = p->dtb; 126 systemPtr = NULL; 127 memPtr = NULL; 128#endif 129} 130 131CheckerCPU::~CheckerCPU() 132{ 133} 134 135void 136CheckerCPU::setMemory(FunctionalMemory *mem) 137{ 138 memPtr = mem; 139#if !FULL_SYSTEM 140 cpuXC = new CPUExecContext(this, /* thread_num */ 0, mem, 141 /* asid */ 0); 142 143 cpuXC->setStatus(ExecContext::Suspended); 144 xcProxy = cpuXC->getProxy(); 145 execContexts.push_back(xcProxy); 146#else 147 if (systemPtr) { 148 cpuXC = new CPUExecContext(this, 0, systemPtr, itb, dtb, memPtr); 149 150 cpuXC->setStatus(ExecContext::Suspended); 151 xcProxy = cpuXC->getProxy(); 152 execContexts.push_back(xcProxy); 153 memReq->xc = xcProxy; 154 } 155#endif 156} 157 158#if FULL_SYSTEM 159void 160CheckerCPU::setSystem(System *system) 161{ 162 systemPtr = system; 163 164 if (memPtr) { 165 cpuXC = new CPUExecContext(this, 0, systemPtr, itb, dtb, memPtr); 166 167 cpuXC->setStatus(ExecContext::Suspended); 168 xcProxy = cpuXC->getProxy(); 169 execContexts.push_back(xcProxy); 170 memReq->xc = xcProxy; 171 } 172} 173#endif 174 175void 176CheckerCPU::serialize(ostream &os) 177{ 178/* 179 BaseCPU::serialize(os); 180 SERIALIZE_SCALAR(inst); 181 nameOut(os, csprintf("%s.xc", name())); 182 cpuXC->serialize(os); 183 cacheCompletionEvent.serialize(os); 184*/ 185} 186 187void 188CheckerCPU::unserialize(Checkpoint *cp, const string §ion) 189{ 190/* 191 BaseCPU::unserialize(cp, section); 192 UNSERIALIZE_SCALAR(inst); 193 cpuXC->unserialize(cp, csprintf("%s.xc", section)); 194*/ 195} 196 197Fault 198CheckerCPU::copySrcTranslate(Addr src) 199{ 200 static bool no_warn = true; 201 int blk_size = 64; 202 // Only support block sizes of 64 atm. 203 assert(blk_size == 64); 204 int offset = src & (blk_size - 1); 205 206 // Make sure block doesn't span page 207 if (no_warn && 208 (src & PageMask) != ((src + blk_size) & PageMask) && 209 (src >> 40) != 0xfffffc) { 210 warn("Copied block source spans pages %x.", src); 211 no_warn = false; 212 } 213 214 memReq->reset(src & ~(blk_size - 1), blk_size); 215 216 // translate to physical address 217 Fault fault = cpuXC->translateDataReadReq(memReq); 218 219 if (fault == NoFault) { 220 cpuXC->copySrcAddr = src; 221 cpuXC->copySrcPhysAddr = memReq->paddr + offset; 222 } else { 223 assert(!fault->isAlignmentFault()); 224 225 cpuXC->copySrcAddr = 0; 226 cpuXC->copySrcPhysAddr = 0; 227 } 228 return fault; 229} 230 231Fault 232CheckerCPU::copy(Addr dest) 233{ 234 static bool no_warn = true; 235 int blk_size = 64; 236 // Only support block sizes of 64 atm. 237 assert(blk_size == 64); 238 uint8_t data[blk_size]; 239 //assert(cpuXC->copySrcAddr); 240 int offset = dest & (blk_size - 1); 241 242 // Make sure block doesn't span page 243 if (no_warn && 244 (dest & PageMask) != ((dest + blk_size) & PageMask) && 245 (dest >> 40) != 0xfffffc) { 246 no_warn = false; 247 warn("Copied block destination spans pages %x. ", dest); 248 } 249 250 memReq->reset(dest & ~(blk_size -1), blk_size); 251 // translate to physical address 252 Fault fault = cpuXC->translateDataWriteReq(memReq); 253 254 if (fault == NoFault) { 255 Addr dest_addr = memReq->paddr + offset; 256 // Need to read straight from memory since we have more than 8 bytes. 257 memReq->paddr = cpuXC->copySrcPhysAddr; 258 cpuXC->mem->read(memReq, data); 259 memReq->paddr = dest_addr; 260 cpuXC->mem->write(memReq, data); 261 memReq->cmd = Copy; 262 memReq->completionEvent = NULL; 263 memReq->paddr = cpuXC->copySrcPhysAddr; 264 memReq->dest = dest_addr; 265 memReq->size = 64; 266 memReq->time = curTick; 267 memReq->flags &= ~INST_READ; 268 } 269 else 270 assert(!fault->isAlignmentFault()); 271 272 return fault; 273} 274 275// precise architected memory state accessor macros 276template <class T> 277Fault 278CheckerCPU::read(Addr addr, T &data, unsigned flags) 279{ 280 memReq->reset(addr, sizeof(T), flags); 281 282 // translate to physical address 283 // Should I probe the DTB? Or should I just take the physical address 284 // and assume correct translation? 285 translateDataReadReq(memReq); 286 287 // if we have a cache, do cache access too 288 memReq->cmd = Read; 289 memReq->completionEvent = NULL; 290 memReq->time = curTick; 291 memReq->flags &= ~INST_READ; 292 293 if (!(memReq->flags & UNCACHEABLE)) { 294 cpuXC->read(memReq, data); 295 } else { 296 // Assume the data is correct if it's an uncached access 297 memcpy(&data, &unverifiedResult.integer, sizeof(T)); 298 } 299 300 return NoFault; 301} 302 303#ifndef DOXYGEN_SHOULD_SKIP_THIS 304 305template 306Fault 307CheckerCPU::read(Addr addr, uint64_t &data, unsigned flags); 308 309template 310Fault 311CheckerCPU::read(Addr addr, uint32_t &data, unsigned flags); 312 313template 314Fault 315CheckerCPU::read(Addr addr, uint16_t &data, unsigned flags); 316 317template 318Fault 319CheckerCPU::read(Addr addr, uint8_t &data, unsigned flags); 320 321#endif //DOXYGEN_SHOULD_SKIP_THIS 322 323template<> 324Fault 325CheckerCPU::read(Addr addr, double &data, unsigned flags) 326{ 327 return read(addr, *(uint64_t*)&data, flags); 328} 329 330template<> 331Fault 332CheckerCPU::read(Addr addr, float &data, unsigned flags) 333{ 334 return read(addr, *(uint32_t*)&data, flags); 335} 336 337template<> 338Fault 339CheckerCPU::read(Addr addr, int32_t &data, unsigned flags) 340{ 341 return read(addr, (uint32_t&)data, flags); 342} 343 344template <class T> 345Fault 346CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 347{ 348 memReq->reset(addr, sizeof(T), flags); 349 350 // translate to physical address 351 cpuXC->translateDataWriteReq(memReq); 352 353 if ((!(unverifiedReq->flags & LOCKED) || 354 ((unverifiedReq->flags & LOCKED) && 355 unverifiedReq->result == 1)) && 356 !(unverifiedReq->flags & UNCACHEABLE)) { 357 // do functional access 358// cpuXC->read(memReq, data); 359 360 memReq->cmd = Write; 361// memcpy(memReq->data,(uint8_t *)&data,memReq->size); 362 T inst_data; 363 memcpy(&inst_data, unverifiedReq->data, sizeof(T)); 364 memReq->completionEvent = NULL; 365 memReq->time = curTick; 366 memReq->flags &= ~INST_READ; 367 368 // Hard to verify this as the data writes back after the 369 // instruction commits. May only be able to check that the 370 // value produced from execute() matches the value produced 371 // from the instruction's first execution. 372 if (data != inst_data) { 373 warn("Store value does not match value in memory! " 374 "Instruction: %#x, memory: %#x", 375 inst_data, data); 376 handleError(); 377 } 378 } 379 380 // Assume the result was the same as the one passed in. This checker 381 // doesn't check if the SC should succeed or fail, it just checks the 382 // value. 383 if (res) 384 *res = unverifiedReq->result; 385 386 return NoFault; 387} 388 389 390#ifndef DOXYGEN_SHOULD_SKIP_THIS 391template 392Fault 393CheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res); 394 395template 396Fault 397CheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res); 398 399template 400Fault 401CheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res); 402 403template 404Fault 405CheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res); 406 407#endif //DOXYGEN_SHOULD_SKIP_THIS 408 409template<> 410Fault 411CheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res) 412{ 413 return write(*(uint64_t*)&data, addr, flags, res); 414} 415 416template<> 417Fault 418CheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res) 419{ 420 return write(*(uint32_t*)&data, addr, flags, res); 421} 422 423template<> 424Fault 425CheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) 426{ 427 return write((uint32_t)data, addr, flags, res); 428} 429 430 431#if FULL_SYSTEM 432Addr 433CheckerCPU::dbg_vtophys(Addr addr) 434{ 435 return vtophys(xcProxy, addr); 436} 437#endif // FULL_SYSTEM 438 439#if FULL_SYSTEM 440void 441CheckerCPU::post_interrupt(int int_num, int index) 442{ 443 BaseCPU::post_interrupt(int_num, index); 444 445 if (cpuXC->status() == ExecContext::Suspended) { 446 DPRINTF(IPI,"Suspended Processor awoke\n"); 447 cpuXC->activate(); 448 } 449} 450#endif // FULL_SYSTEM 451 452bool 453CheckerCPU::translateInstReq(MemReqPtr &req) 454{ 455#if FULL_SYSTEM 456 return (cpuXC->translateInstReq(req) == NoFault); 457#else 458 cpuXC->translateInstReq(req); 459 return true; 460#endif 461} 462 463void 464CheckerCPU::translateDataReadReq(MemReqPtr &req) 465{ 466 cpuXC->translateDataReadReq(req); 467 468 if (req->vaddr != unverifiedReq->vaddr) { 469 warn("Request virtual addresses do not match! Inst: %#x, checker:" 470 " %#x", 471 unverifiedReq->vaddr, req->vaddr); 472 } 473 req->paddr = unverifiedReq->paddr; 474 475 if (checkFlags(req)) { 476 warn("Request flags do not match! Inst: %#x, checker: %#x", 477 unverifiedReq->flags, req->flags); 478 handleError(); 479 } 480} 481 482void 483CheckerCPU::translateDataWriteReq(MemReqPtr &req) 484{ 485 cpuXC->translateDataWriteReq(req); 486 487 if (req->vaddr != unverifiedReq->vaddr) { 488 warn("Request virtual addresses do not match! Inst: %#x, checker:" 489 " %#x", 490 unverifiedReq->vaddr, req->vaddr); 491 } 492 req->paddr = unverifiedReq->paddr; 493 494 if (checkFlags(req)) { 495 warn("Request flags do not match! Inst: %#x, checker: %#x", 496 unverifiedReq->flags, req->flags); 497 handleError(); 498 } 499} 500 501bool 502CheckerCPU::checkFlags(MemReqPtr &req) 503{ 504 // Remove any dynamic flags that don't have to do with the request itself. 505 unsigned flags = unverifiedReq->flags; 506 unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | NO_FAULT; 507 flags = flags & (mask); 508 if (flags == req->flags) { 509 return false; 510 } else { 511 return true; 512 } 513} 514 515/* start simulation, program loaded, processor precise state initialized */ 516template <class DynInstPtr> 517void 518Checker<DynInstPtr>::tick(DynInstPtr &completed_inst) 519{ 520 DynInstPtr inst; 521 522 if (!instList.empty()) { 523 if (youngestSN < completed_inst->seqNum) { 524 DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n", 525 completed_inst->seqNum, completed_inst->readPC()); 526 instList.push_back(completed_inst); 527 youngestSN = completed_inst->seqNum; 528 } 529 530 if (!instList.front()->isCompleted()) { 531 return; 532 } else { 533 inst = instList.front(); 534 instList.pop_front(); 535 } 536 } else { 537 if (!completed_inst->isCompleted()) { 538 if (youngestSN < completed_inst->seqNum) { 539 DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n", 540 completed_inst->seqNum, completed_inst->readPC()); 541 instList.push_back(completed_inst); 542 youngestSN = completed_inst->seqNum; 543 } 544 return; 545 } else { 546 if (youngestSN < completed_inst->seqNum) { 547 inst = completed_inst; 548 youngestSN = completed_inst->seqNum; 549 } else { 550// panic("SN already seen yet the list is empty!"); 551 return; 552 } 553 } 554 } 555 556 while (1) { 557 DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n", 558 inst->seqNum, inst->readPC()); 559// verifyInst = completed_inst; 560 unverifiedResult.integer = inst->readIntResult(); 561 unverifiedReq = inst->req; 562 numCycles++; 563 564 Fault fault = NoFault; 565 566 // maintain $r0 semantics 567 cpuXC->setIntReg(ZeroReg, 0); 568#ifdef TARGET_ALPHA 569 cpuXC->setFloatRegDouble(ZeroReg, 0.0); 570#endif // TARGET_ALPHA 571 572 // Try to fetch an instruction 573 574 // set up memory request for instruction fetch 575#if FULL_SYSTEM 576#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0 577#else 578#define IFETCH_FLAGS(pc) 0 579#endif 580 581 if (changedPC) { 582 DPRINTF(Checker, "Changed PC recently to %#x\n", 583 cpuXC->readPC()); 584 if (willChangePC) { 585 if (newPC == cpuXC->readPC()) { 586 DPRINTF(Checker, "Changed PC matches expected PC\n"); 587 } else { 588 warn("Changed PC does not match expected PC, changed: %#x, " 589 "expected: %#x", 590 cpuXC->readPC(), newPC); 591 handleError(); 592 } 593 willChangePC = false; 594 } 595 changedPC = false; 596 } 597 if (changedNextPC) { 598 DPRINTF(Checker, "Changed NextPC recently to %#x\n", 599 cpuXC->readNextPC()); 600 changedNextPC = false; 601 } 602 603 memReq->cmd = Read; 604 memReq->reset(cpuXC->readPC() & ~3, sizeof(uint32_t), 605 IFETCH_FLAGS(cpuXC->readPC())); 606 607 bool succeeded = translateInstReq(memReq); 608 609 if (!succeeded) { 610 if (inst->getFault() == NoFault) { 611 warn("Instruction PC %#x was not found in the ITB!", 612 cpuXC->readPC()); 613 handleError(); 614 615 // go to the next instruction 616 cpuXC->setPC(cpuXC->readNextPC()); 617 cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst)); 618 619 return; 620 } else { 621 fault = inst->getFault(); 622 } 623 } 624 625 if (fault == NoFault) { 626// fault = cpuXC->mem->read(memReq, machInst); 627 cpuXC->mem->read(memReq, machInst); 628 629 // If we've got a valid instruction (i.e., no fault on instruction 630 // fetch), then execute it. 631 632 // keep an instruction count 633 numInst++; 634// numInsts++; 635 636 // decode the instruction 637 machInst = gtoh(machInst); 638 // Checks that the instruction matches what we expected it to be. 639 // Checks both the machine instruction and the PC. 640 validateInst(inst); 641 642 curStaticInst = StaticInst::decode(makeExtMI(machInst, cpuXC->readPC())); 643 644#if FULL_SYSTEM 645 cpuXC->setInst(machInst); 646#endif // FULL_SYSTEM 647 648 fault = inst->getFault(); 649 } 650 651 // Either the instruction was a fault and we should process the fault, 652 // or we should just go ahead execute the instruction. This assumes 653 // that the instruction is properly marked as a fault. 654 if (fault == NoFault) { 655 656 cpuXC->func_exe_inst++; 657 658 fault = curStaticInst->execute(this, NULL); 659 660 // Checks to make sure instrution results are correct. 661 validateExecution(inst); 662 663// if (curStaticInst->isMemRef()) { 664// numMemRefs++; 665// } 666 667 if (curStaticInst->isLoad()) { 668 ++numLoad; 669 } 670 } 671 672 if (fault != NoFault) { 673#if FULL_SYSTEM 674 fault->invoke(xcProxy); 675 willChangePC = true; 676 newPC = cpuXC->readPC(); 677 DPRINTF(Checker, "Fault, PC is now %#x\n", newPC); 678#else // !FULL_SYSTEM 679 fatal("fault (%d) detected @ PC 0x%08p", fault, cpuXC->readPC()); 680#endif // FULL_SYSTEM 681 } else { 682#if THE_ISA != MIPS_ISA 683 // go to the next instruction 684 cpuXC->setPC(cpuXC->readNextPC()); 685 cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst)); 686#else 687 // go to the next instruction 688 cpuXC->setPC(cpuXC->readNextPC()); 689 cpuXC->setNextPC(cpuXC->readNextNPC()); 690 cpuXC->setNextNPC(cpuXC->readNextNPC() + sizeof(MachInst)); 691#endif 692 693 } 694 695#if FULL_SYSTEM 696 Addr oldpc; 697 int count = 0; 698 do { 699 oldpc = cpuXC->readPC(); 700 system->pcEventQueue.service(xcProxy); 701 count++; 702 } while (oldpc != cpuXC->readPC()); 703 if (count > 1) { 704 willChangePC = true; 705 newPC = cpuXC->readPC(); 706 DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC); 707 } 708#endif 709 710 // Checks PC, next PC. Optionally can check all registers. (Or just those 711 // that have been modified). 712 validateState(); 713 714 if (instList.empty()) { 715 break; 716 } else if (instList.front()->isCompleted()) { 717 inst = instList.front(); 718 instList.pop_front(); 719 } else { 720 break; 721 } 722 } 723} 724 725template <class DynInstPtr> 726void 727Checker<DynInstPtr>::switchOut(Sampler *s) 728{ 729 sampler = s; 730 instList.clear(); 731} 732 733template <class DynInstPtr> 734void 735Checker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU) 736{ 737// BaseCPU::takeOverFrom(oldCPU); 738 739 // if any of this CPU's ExecContexts are active, mark the CPU as 740 // running and schedule its tick event. 741/* 742 for (int i = 0; i < execContexts.size(); ++i) { 743 ExecContext *xc = execContexts[i]; 744 } 745*/ 746} 747 748template <class DynInstPtr> 749void 750Checker<DynInstPtr>::validateInst(DynInstPtr &inst) 751{ 752 if (inst->readPC() != cpuXC->readPC()) { 753 warn("PCs do not match! Inst: %#x, checker: %#x", 754 inst->readPC(), cpuXC->readPC()); 755 if (changedPC) { 756 warn("Changed PCs recently, may not be an error"); 757 } else { 758 handleError(); 759 } 760 } 761 762 if (static_cast<MachInst>(inst->staticInst->machInst) != 763 machInst) { 764 warn("Binary instructions do not match! Inst: %#x, checker: %#x", 765 static_cast<MachInst>(inst->staticInst->machInst), 766 machInst); 767 handleError(); 768 } 769} 770 771template <class DynInstPtr> 772void 773Checker<DynInstPtr>::validateExecution(DynInstPtr &inst) 774{ 775 if (inst->numDestRegs()) { 776 if (inst->isUnverifiable()) { 777 // @todo: Support more destination registers. 778 // Grab the result from the instruction and write it to the 779 // register. 780 RegIndex idx = inst->destRegIdx(0); 781 if (idx < TheISA::FP_Base_DepTag) { 782 cpuXC->setIntReg(idx, inst->readIntResult()); 783 } else if (idx < TheISA::Fpcr_DepTag) { 784 cpuXC->setFloatRegInt(idx, inst->readIntResult()); 785 } else { 786 cpuXC->setMiscReg(idx, inst->readIntResult()); 787 } 788 } else if (result.integer != inst->readIntResult()) { 789 warn("Instruction results do not match! (May not be integer results) " 790 "Inst: %#x, checker: %#x", 791 inst->readIntResult(), result.integer); 792 handleError(); 793 } 794 } 795 796 if (inst->readNextPC() != cpuXC->readNextPC()) { 797 warn("Instruction next PCs do not match! Inst: %#x, checker: %#x", 798 inst->readNextPC(), cpuXC->readNextPC()); 799 handleError(); 800 } 801 802 // Checking side effect registers can be difficult if they are not 803 // checked simultaneously with the execution of the instruction. 804 // This is because other valid instructions may have modified 805 // these registers in the meantime, and their values are not 806 // stored within the DynInst. 807 while (!miscRegIdxs.empty()) { 808 int misc_reg_idx = miscRegIdxs.front(); 809 miscRegIdxs.pop(); 810 811 if (inst->xcBase()->readMiscReg(misc_reg_idx) != 812 cpuXC->readMiscReg(misc_reg_idx)) { 813 warn("Misc reg idx %i (side effect) does not match! Inst: %#x, " 814 "checker: %#x", 815 misc_reg_idx, inst->xcBase()->readMiscReg(misc_reg_idx), 816 cpuXC->readMiscReg(misc_reg_idx)); 817 handleError(); 818 } 819 } 820} 821 822template <class DynInstPtr> 823void 824Checker<DynInstPtr>::validateState() 825{ 826} 827 828template <class DynInstPtr> 829void 830Checker<DynInstPtr>::dumpInsts() 831{ 832 int num = 0; 833 834 InstListIt inst_list_it = --(instList.end()); 835 836 cprintf("Inst list size: %i\n", instList.size()); 837 838 while (inst_list_it != instList.end()) 839 { 840 cprintf("Instruction:%i\n", 841 num); 842 843 cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" 844 "Completed:%i\n", 845 (*inst_list_it)->readPC(), 846 (*inst_list_it)->seqNum, 847 (*inst_list_it)->threadNumber, 848 (*inst_list_it)->isCompleted()); 849 850 cprintf("\n"); 851 852 inst_list_it--; 853 ++num; 854 } 855 856} 857 858template 859class Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >; 860 861template 862class Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >; 863