cpu.cc revision 4052
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"
373348Sbinkertn@umich.edu#include "cpu/static_inst.hh"
382789Sktlim@umich.edu#include "cpu/thread_context.hh"
392789Sktlim@umich.edu
402789Sktlim@umich.edu#if FULL_SYSTEM
413565Sgblack@eecs.umich.edu#include "arch/kernel_stats.hh"
422789Sktlim@umich.edu#include "arch/vtophys.hh"
432789Sktlim@umich.edu#endif // FULL_SYSTEM
442789Sktlim@umich.edu
452789Sktlim@umich.eduusing namespace std;
462789Sktlim@umich.edu//The CheckerCPU does alpha only
472789Sktlim@umich.eduusing namespace AlphaISA;
482789Sktlim@umich.edu
492789Sktlim@umich.eduvoid
502789Sktlim@umich.eduCheckerCPU::init()
512789Sktlim@umich.edu{
522789Sktlim@umich.edu}
532789Sktlim@umich.edu
542789Sktlim@umich.eduCheckerCPU::CheckerCPU(Params *p)
552789Sktlim@umich.edu    : BaseCPU(p), thread(NULL), tc(NULL)
562789Sktlim@umich.edu{
572789Sktlim@umich.edu    memReq = NULL;
582789Sktlim@umich.edu
592789Sktlim@umich.edu    numInst = 0;
602789Sktlim@umich.edu    startNumInst = 0;
612789Sktlim@umich.edu    numLoad = 0;
622789Sktlim@umich.edu    startNumLoad = 0;
632789Sktlim@umich.edu    youngestSN = 0;
642789Sktlim@umich.edu
652789Sktlim@umich.edu    changedPC = willChangePC = changedNextPC = false;
662789Sktlim@umich.edu
672789Sktlim@umich.edu    exitOnError = p->exitOnError;
682789Sktlim@umich.edu    warnOnlyOnLoadError = p->warnOnlyOnLoadError;
692789Sktlim@umich.edu#if FULL_SYSTEM
702789Sktlim@umich.edu    itb = p->itb;
712789Sktlim@umich.edu    dtb = p->dtb;
722789Sktlim@umich.edu    systemPtr = NULL;
732789Sktlim@umich.edu#else
742789Sktlim@umich.edu    process = p->process;
753402Sktlim@umich.edu    thread = new SimpleThread(this, /* thread_num */ 0, process,
763402Sktlim@umich.edu                              /* asid */ 0);
773402Sktlim@umich.edu
783402Sktlim@umich.edu    thread->setStatus(ThreadContext::Suspended);
793402Sktlim@umich.edu    tc = thread->getTC();
803402Sktlim@umich.edu    threadContexts.push_back(tc);
812789Sktlim@umich.edu#endif
822789Sktlim@umich.edu
832789Sktlim@umich.edu    result.integer = 0;
842789Sktlim@umich.edu}
852789Sktlim@umich.edu
862789Sktlim@umich.eduCheckerCPU::~CheckerCPU()
872789Sktlim@umich.edu{
882789Sktlim@umich.edu}
892789Sktlim@umich.edu
902789Sktlim@umich.eduvoid
912789Sktlim@umich.eduCheckerCPU::setSystem(System *system)
922789Sktlim@umich.edu{
932789Sktlim@umich.edu#if FULL_SYSTEM
942789Sktlim@umich.edu    systemPtr = system;
952789Sktlim@umich.edu
962789Sktlim@umich.edu    thread = new SimpleThread(this, 0, systemPtr, itb, dtb, false);
972789Sktlim@umich.edu
982789Sktlim@umich.edu    thread->setStatus(ThreadContext::Suspended);
992789Sktlim@umich.edu    tc = thread->getTC();
1002789Sktlim@umich.edu    threadContexts.push_back(tc);
1012789Sktlim@umich.edu    delete thread->kernelStats;
1022789Sktlim@umich.edu    thread->kernelStats = NULL;
1032789Sktlim@umich.edu#endif
1042789Sktlim@umich.edu}
1052789Sktlim@umich.edu
1062789Sktlim@umich.eduvoid
1072789Sktlim@umich.eduCheckerCPU::setIcachePort(Port *icache_port)
1082789Sktlim@umich.edu{
1092789Sktlim@umich.edu    icachePort = icache_port;
1102789Sktlim@umich.edu}
1112789Sktlim@umich.edu
1122789Sktlim@umich.eduvoid
1132789Sktlim@umich.eduCheckerCPU::setDcachePort(Port *dcache_port)
1142789Sktlim@umich.edu{
1152789Sktlim@umich.edu    dcachePort = dcache_port;
1162789Sktlim@umich.edu}
1172789Sktlim@umich.edu
1182789Sktlim@umich.eduvoid
1192789Sktlim@umich.eduCheckerCPU::serialize(ostream &os)
1202789Sktlim@umich.edu{
1212789Sktlim@umich.edu/*
1222789Sktlim@umich.edu    BaseCPU::serialize(os);
1232789Sktlim@umich.edu    SERIALIZE_SCALAR(inst);
1242789Sktlim@umich.edu    nameOut(os, csprintf("%s.xc", name()));
1252789Sktlim@umich.edu    thread->serialize(os);
1262789Sktlim@umich.edu    cacheCompletionEvent.serialize(os);
1272789Sktlim@umich.edu*/
1282789Sktlim@umich.edu}
1292789Sktlim@umich.edu
1302789Sktlim@umich.eduvoid
1312789Sktlim@umich.eduCheckerCPU::unserialize(Checkpoint *cp, const string &section)
1322789Sktlim@umich.edu{
1332789Sktlim@umich.edu/*
1342789Sktlim@umich.edu    BaseCPU::unserialize(cp, section);
1352789Sktlim@umich.edu    UNSERIALIZE_SCALAR(inst);
1362789Sktlim@umich.edu    thread->unserialize(cp, csprintf("%s.xc", section));
1372789Sktlim@umich.edu*/
1382789Sktlim@umich.edu}
1392789Sktlim@umich.edu
1402789Sktlim@umich.eduFault
1412789Sktlim@umich.eduCheckerCPU::copySrcTranslate(Addr src)
1422789Sktlim@umich.edu{
1432789Sktlim@umich.edu    panic("Unimplemented!");
1442789Sktlim@umich.edu}
1452789Sktlim@umich.edu
1462789Sktlim@umich.eduFault
1472789Sktlim@umich.eduCheckerCPU::copy(Addr dest)
1482789Sktlim@umich.edu{
1492789Sktlim@umich.edu    panic("Unimplemented!");
1502789Sktlim@umich.edu}
1512789Sktlim@umich.edu
1522789Sktlim@umich.edutemplate <class T>
1532789Sktlim@umich.eduFault
1542789Sktlim@umich.eduCheckerCPU::read(Addr addr, T &data, unsigned flags)
1552789Sktlim@umich.edu{
1562789Sktlim@umich.edu    // need to fill in CPU & thread IDs here
1572789Sktlim@umich.edu    memReq = new Request();
1582789Sktlim@umich.edu
1592789Sktlim@umich.edu    memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
1602789Sktlim@umich.edu
1612789Sktlim@umich.edu    // translate to physical address
1622789Sktlim@umich.edu    translateDataReadReq(memReq);
1632789Sktlim@umich.edu
1643349Sbinkertn@umich.edu    PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
1652789Sktlim@umich.edu
1662789Sktlim@umich.edu    pkt->dataStatic(&data);
1672789Sktlim@umich.edu
1683172Sstever@eecs.umich.edu    if (!(memReq->isUncacheable())) {
1692789Sktlim@umich.edu        // Access memory to see if we have the same data
1702789Sktlim@umich.edu        dcachePort->sendFunctional(pkt);
1712789Sktlim@umich.edu    } else {
1722789Sktlim@umich.edu        // Assume the data is correct if it's an uncached access
1732789Sktlim@umich.edu        memcpy(&data, &unverifiedResult.integer, sizeof(T));
1742789Sktlim@umich.edu    }
1752789Sktlim@umich.edu
1762789Sktlim@umich.edu    delete pkt;
1772789Sktlim@umich.edu
1782789Sktlim@umich.edu    return NoFault;
1792789Sktlim@umich.edu}
1802789Sktlim@umich.edu
1812789Sktlim@umich.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS
1822789Sktlim@umich.edu
1832789Sktlim@umich.edutemplate
1842789Sktlim@umich.eduFault
1852789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint64_t &data, unsigned flags);
1862789Sktlim@umich.edu
1872789Sktlim@umich.edutemplate
1882789Sktlim@umich.eduFault
1892789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint32_t &data, unsigned flags);
1902789Sktlim@umich.edu
1912789Sktlim@umich.edutemplate
1922789Sktlim@umich.eduFault
1932789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint16_t &data, unsigned flags);
1942789Sktlim@umich.edu
1952789Sktlim@umich.edutemplate
1962789Sktlim@umich.eduFault
1972789Sktlim@umich.eduCheckerCPU::read(Addr addr, uint8_t &data, unsigned flags);
1982789Sktlim@umich.edu
1992789Sktlim@umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS
2002789Sktlim@umich.edu
2012789Sktlim@umich.edutemplate<>
2022789Sktlim@umich.eduFault
2032789Sktlim@umich.eduCheckerCPU::read(Addr addr, double &data, unsigned flags)
2042789Sktlim@umich.edu{
2052789Sktlim@umich.edu    return read(addr, *(uint64_t*)&data, flags);
2062789Sktlim@umich.edu}
2072789Sktlim@umich.edu
2082789Sktlim@umich.edutemplate<>
2092789Sktlim@umich.eduFault
2102789Sktlim@umich.eduCheckerCPU::read(Addr addr, float &data, unsigned flags)
2112789Sktlim@umich.edu{
2122789Sktlim@umich.edu    return read(addr, *(uint32_t*)&data, flags);
2132789Sktlim@umich.edu}
2142789Sktlim@umich.edu
2152789Sktlim@umich.edutemplate<>
2162789Sktlim@umich.eduFault
2172789Sktlim@umich.eduCheckerCPU::read(Addr addr, int32_t &data, unsigned flags)
2182789Sktlim@umich.edu{
2192789Sktlim@umich.edu    return read(addr, (uint32_t&)data, flags);
2202789Sktlim@umich.edu}
2212789Sktlim@umich.edu
2222789Sktlim@umich.edutemplate <class T>
2232789Sktlim@umich.eduFault
2242789Sktlim@umich.eduCheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
2252789Sktlim@umich.edu{
2262789Sktlim@umich.edu    // need to fill in CPU & thread IDs here
2272789Sktlim@umich.edu    memReq = new Request();
2282789Sktlim@umich.edu
2292789Sktlim@umich.edu    memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
2302789Sktlim@umich.edu
2312789Sktlim@umich.edu    // translate to physical address
2322789Sktlim@umich.edu    thread->translateDataWriteReq(memReq);
2332789Sktlim@umich.edu
2342789Sktlim@umich.edu    // Can compare the write data and result only if it's cacheable,
2352789Sktlim@umich.edu    // not a store conditional, or is a store conditional that
2362789Sktlim@umich.edu    // succeeded.
2372789Sktlim@umich.edu    // @todo: Verify that actual memory matches up with these values.
2382789Sktlim@umich.edu    // Right now it only verifies that the instruction data is the
2392789Sktlim@umich.edu    // same as what was in the request that got sent to memory; there
2402789Sktlim@umich.edu    // is no verification that it is the same as what is in memory.
2412789Sktlim@umich.edu    // This is because the LSQ would have to be snooped in the CPU to
2422789Sktlim@umich.edu    // verify this data.
2432789Sktlim@umich.edu    if (unverifiedReq &&
2443172Sstever@eecs.umich.edu        !(unverifiedReq->isUncacheable()) &&
2453172Sstever@eecs.umich.edu        (!(unverifiedReq->isLocked()) ||
2463172Sstever@eecs.umich.edu         ((unverifiedReq->isLocked()) &&
2474052Ssaidi@eecs.umich.edu          unverifiedReq->getExtraData() == 1))) {
2482789Sktlim@umich.edu        T inst_data;
2492789Sktlim@umich.edu/*
2502789Sktlim@umich.edu        // This code would work if the LSQ allowed for snooping.
2513349Sbinkertn@umich.edu        PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
2522789Sktlim@umich.edu        pkt.dataStatic(&inst_data);
2532789Sktlim@umich.edu
2542789Sktlim@umich.edu        dcachePort->sendFunctional(pkt);
2552789Sktlim@umich.edu
2562789Sktlim@umich.edu        delete pkt;
2572789Sktlim@umich.edu*/
2582789Sktlim@umich.edu        memcpy(&inst_data, unverifiedMemData, sizeof(T));
2592789Sktlim@umich.edu
2602789Sktlim@umich.edu        if (data != inst_data) {
2612789Sktlim@umich.edu            warn("%lli: Store value does not match value in memory! "
2622789Sktlim@umich.edu                 "Instruction: %#x, memory: %#x",
2632789Sktlim@umich.edu                 curTick, inst_data, data);
2642789Sktlim@umich.edu            handleError();
2652789Sktlim@umich.edu        }
2662789Sktlim@umich.edu    }
2672789Sktlim@umich.edu
2682789Sktlim@umich.edu    // Assume the result was the same as the one passed in.  This checker
2692789Sktlim@umich.edu    // doesn't check if the SC should succeed or fail, it just checks the
2702789Sktlim@umich.edu    // value.
2712789Sktlim@umich.edu    if (res && unverifiedReq->scResultValid())
2724052Ssaidi@eecs.umich.edu        *res = unverifiedReq->getExtraData();
2732789Sktlim@umich.edu
2742789Sktlim@umich.edu    return NoFault;
2752789Sktlim@umich.edu}
2762789Sktlim@umich.edu
2772789Sktlim@umich.edu
2782789Sktlim@umich.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS
2792789Sktlim@umich.edutemplate
2802789Sktlim@umich.eduFault
2812789Sktlim@umich.eduCheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
2822789Sktlim@umich.edu
2832789Sktlim@umich.edutemplate
2842789Sktlim@umich.eduFault
2852789Sktlim@umich.eduCheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);
2862789Sktlim@umich.edu
2872789Sktlim@umich.edutemplate
2882789Sktlim@umich.eduFault
2892789Sktlim@umich.eduCheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);
2902789Sktlim@umich.edu
2912789Sktlim@umich.edutemplate
2922789Sktlim@umich.eduFault
2932789Sktlim@umich.eduCheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);
2942789Sktlim@umich.edu
2952789Sktlim@umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS
2962789Sktlim@umich.edu
2972789Sktlim@umich.edutemplate<>
2982789Sktlim@umich.eduFault
2992789Sktlim@umich.eduCheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
3002789Sktlim@umich.edu{
3012789Sktlim@umich.edu    return write(*(uint64_t*)&data, addr, flags, res);
3022789Sktlim@umich.edu}
3032789Sktlim@umich.edu
3042789Sktlim@umich.edutemplate<>
3052789Sktlim@umich.eduFault
3062789Sktlim@umich.eduCheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
3072789Sktlim@umich.edu{
3082789Sktlim@umich.edu    return write(*(uint32_t*)&data, addr, flags, res);
3092789Sktlim@umich.edu}
3102789Sktlim@umich.edu
3112789Sktlim@umich.edutemplate<>
3122789Sktlim@umich.eduFault
3132789Sktlim@umich.eduCheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
3142789Sktlim@umich.edu{
3152789Sktlim@umich.edu    return write((uint32_t)data, addr, flags, res);
3162789Sktlim@umich.edu}
3172789Sktlim@umich.edu
3182789Sktlim@umich.edu
3192789Sktlim@umich.edu#if FULL_SYSTEM
3202789Sktlim@umich.eduAddr
3212789Sktlim@umich.eduCheckerCPU::dbg_vtophys(Addr addr)
3222789Sktlim@umich.edu{
3232789Sktlim@umich.edu    return vtophys(tc, addr);
3242789Sktlim@umich.edu}
3252789Sktlim@umich.edu#endif // FULL_SYSTEM
3262789Sktlim@umich.edu
3272789Sktlim@umich.edubool
3282789Sktlim@umich.eduCheckerCPU::translateInstReq(Request *req)
3292789Sktlim@umich.edu{
3302789Sktlim@umich.edu#if FULL_SYSTEM
3312789Sktlim@umich.edu    return (thread->translateInstReq(req) == NoFault);
3322789Sktlim@umich.edu#else
3332789Sktlim@umich.edu    thread->translateInstReq(req);
3342789Sktlim@umich.edu    return true;
3352789Sktlim@umich.edu#endif
3362789Sktlim@umich.edu}
3372789Sktlim@umich.edu
3382789Sktlim@umich.eduvoid
3392789Sktlim@umich.eduCheckerCPU::translateDataReadReq(Request *req)
3402789Sktlim@umich.edu{
3412789Sktlim@umich.edu    thread->translateDataReadReq(req);
3422789Sktlim@umich.edu
3432789Sktlim@umich.edu    if (req->getVaddr() != unverifiedReq->getVaddr()) {
3442789Sktlim@umich.edu        warn("%lli: Request virtual addresses do not match! Inst: %#x, "
3452789Sktlim@umich.edu             "checker: %#x",
3462789Sktlim@umich.edu             curTick, unverifiedReq->getVaddr(), req->getVaddr());
3472789Sktlim@umich.edu        handleError();
3482789Sktlim@umich.edu    }
3492789Sktlim@umich.edu    req->setPaddr(unverifiedReq->getPaddr());
3502789Sktlim@umich.edu
3512789Sktlim@umich.edu    if (checkFlags(req)) {
3522789Sktlim@umich.edu        warn("%lli: Request flags do not match! Inst: %#x, checker: %#x",
3532789Sktlim@umich.edu             curTick, unverifiedReq->getFlags(), req->getFlags());
3542789Sktlim@umich.edu        handleError();
3552789Sktlim@umich.edu    }
3562789Sktlim@umich.edu}
3572789Sktlim@umich.edu
3582789Sktlim@umich.eduvoid
3592789Sktlim@umich.eduCheckerCPU::translateDataWriteReq(Request *req)
3602789Sktlim@umich.edu{
3612789Sktlim@umich.edu    thread->translateDataWriteReq(req);
3622789Sktlim@umich.edu
3632789Sktlim@umich.edu    if (req->getVaddr() != unverifiedReq->getVaddr()) {
3642789Sktlim@umich.edu        warn("%lli: Request virtual addresses do not match! Inst: %#x, "
3652789Sktlim@umich.edu             "checker: %#x",
3662789Sktlim@umich.edu             curTick, unverifiedReq->getVaddr(), req->getVaddr());
3672789Sktlim@umich.edu        handleError();
3682789Sktlim@umich.edu    }
3692789Sktlim@umich.edu    req->setPaddr(unverifiedReq->getPaddr());
3702789Sktlim@umich.edu
3712789Sktlim@umich.edu    if (checkFlags(req)) {
3722789Sktlim@umich.edu        warn("%lli: Request flags do not match! Inst: %#x, checker: %#x",
3732789Sktlim@umich.edu             curTick, unverifiedReq->getFlags(), req->getFlags());
3742789Sktlim@umich.edu        handleError();
3752789Sktlim@umich.edu    }
3762789Sktlim@umich.edu}
3772789Sktlim@umich.edu
3782789Sktlim@umich.edubool
3792789Sktlim@umich.eduCheckerCPU::checkFlags(Request *req)
3802789Sktlim@umich.edu{
3812789Sktlim@umich.edu    // Remove any dynamic flags that don't have to do with the request itself.
3822789Sktlim@umich.edu    unsigned flags = unverifiedReq->getFlags();
3832789Sktlim@umich.edu    unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | NO_FAULT;
3842789Sktlim@umich.edu    flags = flags & (mask);
3852789Sktlim@umich.edu    if (flags == req->getFlags()) {
3862789Sktlim@umich.edu        return false;
3872789Sktlim@umich.edu    } else {
3882789Sktlim@umich.edu        return true;
3892789Sktlim@umich.edu    }
3902789Sktlim@umich.edu}
3912789Sktlim@umich.edu
3922789Sktlim@umich.eduvoid
3932789Sktlim@umich.eduCheckerCPU::dumpAndExit()
3942789Sktlim@umich.edu{
3952789Sktlim@umich.edu    warn("%lli: Checker PC:%#x, next PC:%#x",
3962789Sktlim@umich.edu         curTick, thread->readPC(), thread->readNextPC());
3972789Sktlim@umich.edu    panic("Checker found an error!");
3982789Sktlim@umich.edu}
399