cpu.cc revision 3172
12789Sktlim@umich.edu/* 22789Sktlim@umich.edu * Copyright (c) 2006 The Regents of The University of Michigan 32789Sktlim@umich.edu * All rights reserved. 42789Sktlim@umich.edu * 52789Sktlim@umich.edu * Redistribution and use in source and binary forms, with or without 62789Sktlim@umich.edu * modification, are permitted provided that the following conditions are 72789Sktlim@umich.edu * met: redistributions of source code must retain the above copyright 82789Sktlim@umich.edu * notice, this list of conditions and the following disclaimer; 92789Sktlim@umich.edu * redistributions in binary form must reproduce the above copyright 102789Sktlim@umich.edu * notice, this list of conditions and the following disclaimer in the 112789Sktlim@umich.edu * documentation and/or other materials provided with the distribution; 122789Sktlim@umich.edu * neither the name of the copyright holders nor the names of its 132789Sktlim@umich.edu * contributors may be used to endorse or promote products derived from 142789Sktlim@umich.edu * this software without specific prior written permission. 152789Sktlim@umich.edu * 162789Sktlim@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172789Sktlim@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182789Sktlim@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192789Sktlim@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202789Sktlim@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212789Sktlim@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222789Sktlim@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232789Sktlim@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242789Sktlim@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252789Sktlim@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262789Sktlim@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272789Sktlim@umich.edu * 282789Sktlim@umich.edu * Authors: Kevin Lim 292789Sktlim@umich.edu */ 302789Sktlim@umich.edu 312789Sktlim@umich.edu#include <list> 322789Sktlim@umich.edu#include <string> 332789Sktlim@umich.edu 342789Sktlim@umich.edu#include "cpu/base.hh" 352789Sktlim@umich.edu#include "cpu/checker/cpu.hh" 362789Sktlim@umich.edu#include "cpu/simple_thread.hh" 372789Sktlim@umich.edu#include "cpu/thread_context.hh" 382789Sktlim@umich.edu#include "cpu/static_inst.hh" 392789Sktlim@umich.edu#include "mem/packet_impl.hh" 402789Sktlim@umich.edu#include "sim/byteswap.hh" 412789Sktlim@umich.edu 422789Sktlim@umich.edu#if FULL_SYSTEM 432789Sktlim@umich.edu#include "arch/vtophys.hh" 442789Sktlim@umich.edu#include "kern/kernel_stats.hh" 452789Sktlim@umich.edu#endif // FULL_SYSTEM 462789Sktlim@umich.edu 472789Sktlim@umich.eduusing namespace std; 482789Sktlim@umich.edu//The CheckerCPU does alpha only 492789Sktlim@umich.eduusing namespace AlphaISA; 502789Sktlim@umich.edu 512789Sktlim@umich.eduvoid 522789Sktlim@umich.eduCheckerCPU::init() 532789Sktlim@umich.edu{ 542789Sktlim@umich.edu} 552789Sktlim@umich.edu 562789Sktlim@umich.eduCheckerCPU::CheckerCPU(Params *p) 572789Sktlim@umich.edu : BaseCPU(p), thread(NULL), tc(NULL) 582789Sktlim@umich.edu{ 592789Sktlim@umich.edu memReq = NULL; 602789Sktlim@umich.edu 612789Sktlim@umich.edu numInst = 0; 622789Sktlim@umich.edu startNumInst = 0; 632789Sktlim@umich.edu numLoad = 0; 642789Sktlim@umich.edu startNumLoad = 0; 652789Sktlim@umich.edu youngestSN = 0; 662789Sktlim@umich.edu 672789Sktlim@umich.edu changedPC = willChangePC = changedNextPC = false; 682789Sktlim@umich.edu 692789Sktlim@umich.edu exitOnError = p->exitOnError; 702789Sktlim@umich.edu warnOnlyOnLoadError = p->warnOnlyOnLoadError; 712789Sktlim@umich.edu#if FULL_SYSTEM 722789Sktlim@umich.edu itb = p->itb; 732789Sktlim@umich.edu dtb = p->dtb; 742789Sktlim@umich.edu systemPtr = NULL; 752789Sktlim@umich.edu#else 762789Sktlim@umich.edu process = p->process; 772789Sktlim@umich.edu#endif 782789Sktlim@umich.edu 792789Sktlim@umich.edu result.integer = 0; 802789Sktlim@umich.edu} 812789Sktlim@umich.edu 822789Sktlim@umich.eduCheckerCPU::~CheckerCPU() 832789Sktlim@umich.edu{ 842789Sktlim@umich.edu} 852789Sktlim@umich.edu 862789Sktlim@umich.eduvoid 872789Sktlim@umich.eduCheckerCPU::setMemory(MemObject *mem) 882789Sktlim@umich.edu{ 892789Sktlim@umich.edu#if !FULL_SYSTEM 902789Sktlim@umich.edu memPtr = mem; 912789Sktlim@umich.edu thread = new SimpleThread(this, /* thread_num */ 0, process, 922789Sktlim@umich.edu /* asid */ 0, mem); 932789Sktlim@umich.edu 942789Sktlim@umich.edu thread->setStatus(ThreadContext::Suspended); 952789Sktlim@umich.edu tc = thread->getTC(); 962789Sktlim@umich.edu threadContexts.push_back(tc); 972789Sktlim@umich.edu#endif 982789Sktlim@umich.edu} 992789Sktlim@umich.edu 1002789Sktlim@umich.eduvoid 1012789Sktlim@umich.eduCheckerCPU::setSystem(System *system) 1022789Sktlim@umich.edu{ 1032789Sktlim@umich.edu#if FULL_SYSTEM 1042789Sktlim@umich.edu systemPtr = system; 1052789Sktlim@umich.edu 1062789Sktlim@umich.edu thread = new SimpleThread(this, 0, systemPtr, itb, dtb, false); 1072789Sktlim@umich.edu 1082789Sktlim@umich.edu thread->setStatus(ThreadContext::Suspended); 1092789Sktlim@umich.edu tc = thread->getTC(); 1102789Sktlim@umich.edu threadContexts.push_back(tc); 1112789Sktlim@umich.edu delete thread->kernelStats; 1122789Sktlim@umich.edu thread->kernelStats = NULL; 1132789Sktlim@umich.edu#endif 1142789Sktlim@umich.edu} 1152789Sktlim@umich.edu 1162789Sktlim@umich.eduvoid 1172789Sktlim@umich.eduCheckerCPU::setIcachePort(Port *icache_port) 1182789Sktlim@umich.edu{ 1192789Sktlim@umich.edu icachePort = icache_port; 1202789Sktlim@umich.edu} 1212789Sktlim@umich.edu 1222789Sktlim@umich.eduvoid 1232789Sktlim@umich.eduCheckerCPU::setDcachePort(Port *dcache_port) 1242789Sktlim@umich.edu{ 1252789Sktlim@umich.edu dcachePort = dcache_port; 1262789Sktlim@umich.edu} 1272789Sktlim@umich.edu 1282789Sktlim@umich.eduvoid 1292789Sktlim@umich.eduCheckerCPU::serialize(ostream &os) 1302789Sktlim@umich.edu{ 1312789Sktlim@umich.edu/* 1322789Sktlim@umich.edu BaseCPU::serialize(os); 1332789Sktlim@umich.edu SERIALIZE_SCALAR(inst); 1342789Sktlim@umich.edu nameOut(os, csprintf("%s.xc", name())); 1352789Sktlim@umich.edu thread->serialize(os); 1362789Sktlim@umich.edu cacheCompletionEvent.serialize(os); 1372789Sktlim@umich.edu*/ 1382789Sktlim@umich.edu} 1392789Sktlim@umich.edu 1402789Sktlim@umich.eduvoid 1412789Sktlim@umich.eduCheckerCPU::unserialize(Checkpoint *cp, const string §ion) 1422789Sktlim@umich.edu{ 1432789Sktlim@umich.edu/* 1442789Sktlim@umich.edu BaseCPU::unserialize(cp, section); 1452789Sktlim@umich.edu UNSERIALIZE_SCALAR(inst); 1462789Sktlim@umich.edu thread->unserialize(cp, csprintf("%s.xc", section)); 1472789Sktlim@umich.edu*/ 1482789Sktlim@umich.edu} 1492789Sktlim@umich.edu 1502789Sktlim@umich.eduFault 1512789Sktlim@umich.eduCheckerCPU::copySrcTranslate(Addr src) 1522789Sktlim@umich.edu{ 1532789Sktlim@umich.edu panic("Unimplemented!"); 1542789Sktlim@umich.edu} 1552789Sktlim@umich.edu 1562789Sktlim@umich.eduFault 1572789Sktlim@umich.eduCheckerCPU::copy(Addr dest) 1582789Sktlim@umich.edu{ 1592789Sktlim@umich.edu panic("Unimplemented!"); 1602789Sktlim@umich.edu} 1612789Sktlim@umich.edu 1622789Sktlim@umich.edutemplate <class T> 1632789Sktlim@umich.eduFault 1642789Sktlim@umich.eduCheckerCPU::read(Addr addr, T &data, unsigned flags) 1652789Sktlim@umich.edu{ 1662789Sktlim@umich.edu // need to fill in CPU & thread IDs here 1672789Sktlim@umich.edu memReq = new Request(); 1682789Sktlim@umich.edu 1692789Sktlim@umich.edu memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 1702789Sktlim@umich.edu 1712789Sktlim@umich.edu // translate to physical address 1722789Sktlim@umich.edu translateDataReadReq(memReq); 1732789Sktlim@umich.edu 1742789Sktlim@umich.edu Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); 1752789Sktlim@umich.edu 1762789Sktlim@umich.edu pkt->dataStatic(&data); 1772789Sktlim@umich.edu 1783172Sstever@eecs.umich.edu if (!(memReq->isUncacheable())) { 1792789Sktlim@umich.edu // Access memory to see if we have the same data 1802789Sktlim@umich.edu dcachePort->sendFunctional(pkt); 1812789Sktlim@umich.edu } else { 1822789Sktlim@umich.edu // Assume the data is correct if it's an uncached access 1832789Sktlim@umich.edu memcpy(&data, &unverifiedResult.integer, sizeof(T)); 1842789Sktlim@umich.edu } 1852789Sktlim@umich.edu 1862789Sktlim@umich.edu delete pkt; 1872789Sktlim@umich.edu 1882789Sktlim@umich.edu return NoFault; 1892789Sktlim@umich.edu} 1902789Sktlim@umich.edu 1912789Sktlim@umich.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS 1922789Sktlim@umich.edu 1932789Sktlim@umich.edutemplate 1942789Sktlim@umich.eduFault 1952789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint64_t &data, unsigned flags); 1962789Sktlim@umich.edu 1972789Sktlim@umich.edutemplate 1982789Sktlim@umich.eduFault 1992789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint32_t &data, unsigned flags); 2002789Sktlim@umich.edu 2012789Sktlim@umich.edutemplate 2022789Sktlim@umich.eduFault 2032789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint16_t &data, unsigned flags); 2042789Sktlim@umich.edu 2052789Sktlim@umich.edutemplate 2062789Sktlim@umich.eduFault 2072789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint8_t &data, unsigned flags); 2082789Sktlim@umich.edu 2092789Sktlim@umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS 2102789Sktlim@umich.edu 2112789Sktlim@umich.edutemplate<> 2122789Sktlim@umich.eduFault 2132789Sktlim@umich.eduCheckerCPU::read(Addr addr, double &data, unsigned flags) 2142789Sktlim@umich.edu{ 2152789Sktlim@umich.edu return read(addr, *(uint64_t*)&data, flags); 2162789Sktlim@umich.edu} 2172789Sktlim@umich.edu 2182789Sktlim@umich.edutemplate<> 2192789Sktlim@umich.eduFault 2202789Sktlim@umich.eduCheckerCPU::read(Addr addr, float &data, unsigned flags) 2212789Sktlim@umich.edu{ 2222789Sktlim@umich.edu return read(addr, *(uint32_t*)&data, flags); 2232789Sktlim@umich.edu} 2242789Sktlim@umich.edu 2252789Sktlim@umich.edutemplate<> 2262789Sktlim@umich.eduFault 2272789Sktlim@umich.eduCheckerCPU::read(Addr addr, int32_t &data, unsigned flags) 2282789Sktlim@umich.edu{ 2292789Sktlim@umich.edu return read(addr, (uint32_t&)data, flags); 2302789Sktlim@umich.edu} 2312789Sktlim@umich.edu 2322789Sktlim@umich.edutemplate <class T> 2332789Sktlim@umich.eduFault 2342789Sktlim@umich.eduCheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 2352789Sktlim@umich.edu{ 2362789Sktlim@umich.edu // need to fill in CPU & thread IDs here 2372789Sktlim@umich.edu memReq = new Request(); 2382789Sktlim@umich.edu 2392789Sktlim@umich.edu memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 2402789Sktlim@umich.edu 2412789Sktlim@umich.edu // translate to physical address 2422789Sktlim@umich.edu thread->translateDataWriteReq(memReq); 2432789Sktlim@umich.edu 2442789Sktlim@umich.edu // Can compare the write data and result only if it's cacheable, 2452789Sktlim@umich.edu // not a store conditional, or is a store conditional that 2462789Sktlim@umich.edu // succeeded. 2472789Sktlim@umich.edu // @todo: Verify that actual memory matches up with these values. 2482789Sktlim@umich.edu // Right now it only verifies that the instruction data is the 2492789Sktlim@umich.edu // same as what was in the request that got sent to memory; there 2502789Sktlim@umich.edu // is no verification that it is the same as what is in memory. 2512789Sktlim@umich.edu // This is because the LSQ would have to be snooped in the CPU to 2522789Sktlim@umich.edu // verify this data. 2532789Sktlim@umich.edu if (unverifiedReq && 2543172Sstever@eecs.umich.edu !(unverifiedReq->isUncacheable()) && 2553172Sstever@eecs.umich.edu (!(unverifiedReq->isLocked()) || 2563172Sstever@eecs.umich.edu ((unverifiedReq->isLocked()) && 2572789Sktlim@umich.edu unverifiedReq->getScResult() == 1))) { 2582789Sktlim@umich.edu T inst_data; 2592789Sktlim@umich.edu/* 2602789Sktlim@umich.edu // This code would work if the LSQ allowed for snooping. 2612789Sktlim@umich.edu Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); 2622789Sktlim@umich.edu pkt.dataStatic(&inst_data); 2632789Sktlim@umich.edu 2642789Sktlim@umich.edu dcachePort->sendFunctional(pkt); 2652789Sktlim@umich.edu 2662789Sktlim@umich.edu delete pkt; 2672789Sktlim@umich.edu*/ 2682789Sktlim@umich.edu memcpy(&inst_data, unverifiedMemData, sizeof(T)); 2692789Sktlim@umich.edu 2702789Sktlim@umich.edu if (data != inst_data) { 2712789Sktlim@umich.edu warn("%lli: Store value does not match value in memory! " 2722789Sktlim@umich.edu "Instruction: %#x, memory: %#x", 2732789Sktlim@umich.edu curTick, inst_data, data); 2742789Sktlim@umich.edu handleError(); 2752789Sktlim@umich.edu } 2762789Sktlim@umich.edu } 2772789Sktlim@umich.edu 2782789Sktlim@umich.edu // Assume the result was the same as the one passed in. This checker 2792789Sktlim@umich.edu // doesn't check if the SC should succeed or fail, it just checks the 2802789Sktlim@umich.edu // value. 2812789Sktlim@umich.edu if (res && unverifiedReq->scResultValid()) 2822789Sktlim@umich.edu *res = unverifiedReq->getScResult(); 2832789Sktlim@umich.edu 2842789Sktlim@umich.edu return NoFault; 2852789Sktlim@umich.edu} 2862789Sktlim@umich.edu 2872789Sktlim@umich.edu 2882789Sktlim@umich.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS 2892789Sktlim@umich.edutemplate 2902789Sktlim@umich.eduFault 2912789Sktlim@umich.eduCheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res); 2922789Sktlim@umich.edu 2932789Sktlim@umich.edutemplate 2942789Sktlim@umich.eduFault 2952789Sktlim@umich.eduCheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res); 2962789Sktlim@umich.edu 2972789Sktlim@umich.edutemplate 2982789Sktlim@umich.eduFault 2992789Sktlim@umich.eduCheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res); 3002789Sktlim@umich.edu 3012789Sktlim@umich.edutemplate 3022789Sktlim@umich.eduFault 3032789Sktlim@umich.eduCheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res); 3042789Sktlim@umich.edu 3052789Sktlim@umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS 3062789Sktlim@umich.edu 3072789Sktlim@umich.edutemplate<> 3082789Sktlim@umich.eduFault 3092789Sktlim@umich.eduCheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res) 3102789Sktlim@umich.edu{ 3112789Sktlim@umich.edu return write(*(uint64_t*)&data, addr, flags, res); 3122789Sktlim@umich.edu} 3132789Sktlim@umich.edu 3142789Sktlim@umich.edutemplate<> 3152789Sktlim@umich.eduFault 3162789Sktlim@umich.eduCheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res) 3172789Sktlim@umich.edu{ 3182789Sktlim@umich.edu return write(*(uint32_t*)&data, addr, flags, res); 3192789Sktlim@umich.edu} 3202789Sktlim@umich.edu 3212789Sktlim@umich.edutemplate<> 3222789Sktlim@umich.eduFault 3232789Sktlim@umich.eduCheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) 3242789Sktlim@umich.edu{ 3252789Sktlim@umich.edu return write((uint32_t)data, addr, flags, res); 3262789Sktlim@umich.edu} 3272789Sktlim@umich.edu 3282789Sktlim@umich.edu 3292789Sktlim@umich.edu#if FULL_SYSTEM 3302789Sktlim@umich.eduAddr 3312789Sktlim@umich.eduCheckerCPU::dbg_vtophys(Addr addr) 3322789Sktlim@umich.edu{ 3332789Sktlim@umich.edu return vtophys(tc, addr); 3342789Sktlim@umich.edu} 3352789Sktlim@umich.edu#endif // FULL_SYSTEM 3362789Sktlim@umich.edu 3372789Sktlim@umich.edubool 3382789Sktlim@umich.eduCheckerCPU::translateInstReq(Request *req) 3392789Sktlim@umich.edu{ 3402789Sktlim@umich.edu#if FULL_SYSTEM 3412789Sktlim@umich.edu return (thread->translateInstReq(req) == NoFault); 3422789Sktlim@umich.edu#else 3432789Sktlim@umich.edu thread->translateInstReq(req); 3442789Sktlim@umich.edu return true; 3452789Sktlim@umich.edu#endif 3462789Sktlim@umich.edu} 3472789Sktlim@umich.edu 3482789Sktlim@umich.eduvoid 3492789Sktlim@umich.eduCheckerCPU::translateDataReadReq(Request *req) 3502789Sktlim@umich.edu{ 3512789Sktlim@umich.edu thread->translateDataReadReq(req); 3522789Sktlim@umich.edu 3532789Sktlim@umich.edu if (req->getVaddr() != unverifiedReq->getVaddr()) { 3542789Sktlim@umich.edu warn("%lli: Request virtual addresses do not match! Inst: %#x, " 3552789Sktlim@umich.edu "checker: %#x", 3562789Sktlim@umich.edu curTick, unverifiedReq->getVaddr(), req->getVaddr()); 3572789Sktlim@umich.edu handleError(); 3582789Sktlim@umich.edu } 3592789Sktlim@umich.edu req->setPaddr(unverifiedReq->getPaddr()); 3602789Sktlim@umich.edu 3612789Sktlim@umich.edu if (checkFlags(req)) { 3622789Sktlim@umich.edu warn("%lli: Request flags do not match! Inst: %#x, checker: %#x", 3632789Sktlim@umich.edu curTick, unverifiedReq->getFlags(), req->getFlags()); 3642789Sktlim@umich.edu handleError(); 3652789Sktlim@umich.edu } 3662789Sktlim@umich.edu} 3672789Sktlim@umich.edu 3682789Sktlim@umich.eduvoid 3692789Sktlim@umich.eduCheckerCPU::translateDataWriteReq(Request *req) 3702789Sktlim@umich.edu{ 3712789Sktlim@umich.edu thread->translateDataWriteReq(req); 3722789Sktlim@umich.edu 3732789Sktlim@umich.edu if (req->getVaddr() != unverifiedReq->getVaddr()) { 3742789Sktlim@umich.edu warn("%lli: Request virtual addresses do not match! Inst: %#x, " 3752789Sktlim@umich.edu "checker: %#x", 3762789Sktlim@umich.edu curTick, unverifiedReq->getVaddr(), req->getVaddr()); 3772789Sktlim@umich.edu handleError(); 3782789Sktlim@umich.edu } 3792789Sktlim@umich.edu req->setPaddr(unverifiedReq->getPaddr()); 3802789Sktlim@umich.edu 3812789Sktlim@umich.edu if (checkFlags(req)) { 3822789Sktlim@umich.edu warn("%lli: Request flags do not match! Inst: %#x, checker: %#x", 3832789Sktlim@umich.edu curTick, unverifiedReq->getFlags(), req->getFlags()); 3842789Sktlim@umich.edu handleError(); 3852789Sktlim@umich.edu } 3862789Sktlim@umich.edu} 3872789Sktlim@umich.edu 3882789Sktlim@umich.edubool 3892789Sktlim@umich.eduCheckerCPU::checkFlags(Request *req) 3902789Sktlim@umich.edu{ 3912789Sktlim@umich.edu // Remove any dynamic flags that don't have to do with the request itself. 3922789Sktlim@umich.edu unsigned flags = unverifiedReq->getFlags(); 3932789Sktlim@umich.edu unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | NO_FAULT; 3942789Sktlim@umich.edu flags = flags & (mask); 3952789Sktlim@umich.edu if (flags == req->getFlags()) { 3962789Sktlim@umich.edu return false; 3972789Sktlim@umich.edu } else { 3982789Sktlim@umich.edu return true; 3992789Sktlim@umich.edu } 4002789Sktlim@umich.edu} 4012789Sktlim@umich.edu 4022789Sktlim@umich.eduvoid 4032789Sktlim@umich.eduCheckerCPU::dumpAndExit() 4042789Sktlim@umich.edu{ 4052789Sktlim@umich.edu warn("%lli: Checker PC:%#x, next PC:%#x", 4062789Sktlim@umich.edu curTick, thread->readPC(), thread->readNextPC()); 4072789Sktlim@umich.edu panic("Checker found an error!"); 4082789Sktlim@umich.edu} 409