cpu.cc revision 12355:568ec3a0c614
110355SGeoffrey.Blake@arm.com/* 28839Sandreas.hansson@arm.com * Copyright (c) 2011,2013,2017 ARM Limited 38839Sandreas.hansson@arm.com * All rights reserved 48839Sandreas.hansson@arm.com * 58839Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 68839Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 78839Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 88839Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 98839Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 108839Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 118839Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 128839Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 133101Sstever@eecs.umich.edu * 148579Ssteve.reinhardt@amd.com * Copyright (c) 2006 The Regents of The University of Michigan 153101Sstever@eecs.umich.edu * All rights reserved. 163101Sstever@eecs.umich.edu * 173101Sstever@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 183101Sstever@eecs.umich.edu * modification, are permitted provided that the following conditions are 193101Sstever@eecs.umich.edu * met: redistributions of source code must retain the above copyright 203101Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 213101Sstever@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 223101Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 233101Sstever@eecs.umich.edu * documentation and/or other materials provided with the distribution; 243101Sstever@eecs.umich.edu * neither the name of the copyright holders nor the names of its 253101Sstever@eecs.umich.edu * contributors may be used to endorse or promote products derived from 263101Sstever@eecs.umich.edu * this software without specific prior written permission. 273101Sstever@eecs.umich.edu * 283101Sstever@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 293101Sstever@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 303101Sstever@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 313101Sstever@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 323101Sstever@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 333101Sstever@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 343101Sstever@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 353101Sstever@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 363101Sstever@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 373101Sstever@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 383101Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 393101Sstever@eecs.umich.edu * 403101Sstever@eecs.umich.edu * Authors: Kevin Lim 413101Sstever@eecs.umich.edu * Geoffrey Blake 427778Sgblack@eecs.umich.edu */ 438839Sandreas.hansson@arm.com 443101Sstever@eecs.umich.edu#include "cpu/checker/cpu.hh" 453101Sstever@eecs.umich.edu 463101Sstever@eecs.umich.edu#include <list> 473101Sstever@eecs.umich.edu#include <string> 483101Sstever@eecs.umich.edu 493101Sstever@eecs.umich.edu#include "arch/generic/tlb.hh" 503101Sstever@eecs.umich.edu#include "arch/kernel_stats.hh" 513101Sstever@eecs.umich.edu#include "arch/vtophys.hh" 523101Sstever@eecs.umich.edu#include "cpu/base.hh" 533101Sstever@eecs.umich.edu#include "cpu/simple_thread.hh" 543101Sstever@eecs.umich.edu#include "cpu/static_inst.hh" 553101Sstever@eecs.umich.edu#include "cpu/thread_context.hh" 563101Sstever@eecs.umich.edu#include "params/CheckerCPU.hh" 573101Sstever@eecs.umich.edu#include "sim/full_system.hh" 583101Sstever@eecs.umich.edu 593101Sstever@eecs.umich.eduusing namespace std; 603101Sstever@eecs.umich.eduusing namespace TheISA; 613101Sstever@eecs.umich.edu 623885Sbinkertn@umich.eduvoid 633885Sbinkertn@umich.eduCheckerCPU::init() 644762Snate@binkert.org{ 653885Sbinkertn@umich.edu masterId = systemPtr->getMasterId(name()); 663885Sbinkertn@umich.edu} 677528Ssteve.reinhardt@amd.com 683885Sbinkertn@umich.eduCheckerCPU::CheckerCPU(Params *p) 694380Sbinkertn@umich.edu : BaseCPU(p, true), systemPtr(NULL), icachePort(NULL), dcachePort(NULL), 704167Sbinkertn@umich.edu tc(NULL), thread(NULL) 713102Sstever@eecs.umich.edu{ 723101Sstever@eecs.umich.edu memReq = NULL; 734762Snate@binkert.org curStaticInst = NULL; 744762Snate@binkert.org curMacroStaticInst = NULL; 754762Snate@binkert.org 764762Snate@binkert.org numInst = 0; 774762Snate@binkert.org startNumInst = 0; 784762Snate@binkert.org numLoad = 0; 794762Snate@binkert.org startNumLoad = 0; 804762Snate@binkert.org youngestSN = 0; 814762Snate@binkert.org 825033Smilesck@eecs.umich.edu changedPC = willChangePC = false; 835033Smilesck@eecs.umich.edu 845033Smilesck@eecs.umich.edu exitOnError = p->exitOnError; 855033Smilesck@eecs.umich.edu warnOnlyOnLoadError = p->warnOnlyOnLoadError; 865033Smilesck@eecs.umich.edu itb = p->itb; 875033Smilesck@eecs.umich.edu dtb = p->dtb; 885033Smilesck@eecs.umich.edu workload = p->workload; 895033Smilesck@eecs.umich.edu 905033Smilesck@eecs.umich.edu updateOnError = true; 915033Smilesck@eecs.umich.edu} 923101Sstever@eecs.umich.edu 933101Sstever@eecs.umich.eduCheckerCPU::~CheckerCPU() 943101Sstever@eecs.umich.edu{ 955033Smilesck@eecs.umich.edu} 9610267SGeoffrey.Blake@arm.com 978596Ssteve.reinhardt@amd.comvoid 988596Ssteve.reinhardt@amd.comCheckerCPU::setSystem(System *system) 998596Ssteve.reinhardt@amd.com{ 1008596Ssteve.reinhardt@amd.com const Params *p(dynamic_cast<const Params *>(_params)); 1017673Snate@binkert.org 1027673Snate@binkert.org systemPtr = system; 1037673Snate@binkert.org 1047673Snate@binkert.org if (FullSystem) { 1058596Ssteve.reinhardt@amd.com thread = new SimpleThread(this, 0, systemPtr, itb, dtb, 1068596Ssteve.reinhardt@amd.com p->isa[0], false); 1078596Ssteve.reinhardt@amd.com } else { 1087673Snate@binkert.org thread = new SimpleThread(this, 0, systemPtr, 1097673Snate@binkert.org workload.size() ? workload[0] : NULL, 1107673Snate@binkert.org itb, dtb, p->isa[0]); 1113101Sstever@eecs.umich.edu } 1123101Sstever@eecs.umich.edu 1133101Sstever@eecs.umich.edu tc = thread->getTC(); 1143101Sstever@eecs.umich.edu threadContexts.push_back(tc); 1153101Sstever@eecs.umich.edu thread->kernelStats = NULL; 1163101Sstever@eecs.umich.edu // Thread should never be null after this 11710380SAndrew.Bardsley@arm.com assert(thread != NULL); 11810380SAndrew.Bardsley@arm.com} 11910380SAndrew.Bardsley@arm.com 12010380SAndrew.Bardsley@arm.comvoid 12110380SAndrew.Bardsley@arm.comCheckerCPU::setIcachePort(MasterPort *icache_port) 12210380SAndrew.Bardsley@arm.com{ 12310458Sandreas.hansson@arm.com icachePort = icache_port; 12410458Sandreas.hansson@arm.com} 12510458Sandreas.hansson@arm.com 12610458Sandreas.hansson@arm.comvoid 12710458Sandreas.hansson@arm.comCheckerCPU::setDcachePort(MasterPort *dcache_port) 12810458Sandreas.hansson@arm.com{ 12910458Sandreas.hansson@arm.com dcachePort = dcache_port; 13010458Sandreas.hansson@arm.com} 13110458Sandreas.hansson@arm.com 13210458Sandreas.hansson@arm.comvoid 13310458Sandreas.hansson@arm.comCheckerCPU::serialize(ostream &os) const 13410458Sandreas.hansson@arm.com{ 1353101Sstever@eecs.umich.edu} 1363101Sstever@eecs.umich.edu 1373101Sstever@eecs.umich.eduvoid 1383101Sstever@eecs.umich.eduCheckerCPU::unserialize(CheckpointIn &cp) 1393101Sstever@eecs.umich.edu{ 14010267SGeoffrey.Blake@arm.com} 14110267SGeoffrey.Blake@arm.com 14210267SGeoffrey.Blake@arm.comFault 14310267SGeoffrey.Blake@arm.comCheckerCPU::readMem(Addr addr, uint8_t *data, unsigned size, 1443101Sstever@eecs.umich.edu Request::Flags flags) 1453101Sstever@eecs.umich.edu{ 1463101Sstever@eecs.umich.edu Fault fault = NoFault; 1473101Sstever@eecs.umich.edu int fullSize = size; 1483101Sstever@eecs.umich.edu Addr secondAddr = roundDown(addr + size - 1, cacheLineSize()); 1493101Sstever@eecs.umich.edu bool checked_flags = false; 1503101Sstever@eecs.umich.edu bool flags_match = true; 1513101Sstever@eecs.umich.edu Addr pAddr = 0x0; 1523101Sstever@eecs.umich.edu 1533101Sstever@eecs.umich.edu 1543101Sstever@eecs.umich.edu if (secondAddr > addr) 1553101Sstever@eecs.umich.edu size = secondAddr - addr; 1563101Sstever@eecs.umich.edu 1573101Sstever@eecs.umich.edu // Need to account for multiple accesses like the Atomic and TimingSimple 1583101Sstever@eecs.umich.edu while (1) { 1593101Sstever@eecs.umich.edu memReq = new Request(0, addr, size, flags, masterId, 1603101Sstever@eecs.umich.edu thread->pcState().instAddr(), tc->contextId()); 1613101Sstever@eecs.umich.edu 1623101Sstever@eecs.umich.edu // translate to physical address 1633101Sstever@eecs.umich.edu fault = dtb->translateFunctional(memReq, tc, BaseTLB::Read); 1643101Sstever@eecs.umich.edu 1653101Sstever@eecs.umich.edu if (!checked_flags && fault == NoFault && unverifiedReq) { 1663101Sstever@eecs.umich.edu flags_match = checkFlags(unverifiedReq, memReq->getVaddr(), 1673101Sstever@eecs.umich.edu memReq->getPaddr(), memReq->getFlags()); 1683101Sstever@eecs.umich.edu pAddr = memReq->getPaddr(); 1693101Sstever@eecs.umich.edu checked_flags = true; 1703101Sstever@eecs.umich.edu } 1713101Sstever@eecs.umich.edu 1723101Sstever@eecs.umich.edu // Now do the access 1733101Sstever@eecs.umich.edu if (fault == NoFault && 1743101Sstever@eecs.umich.edu !memReq->getFlags().isSet(Request::NO_ACCESS)) { 1753101Sstever@eecs.umich.edu PacketPtr pkt = Packet::createRead(memReq); 1763101Sstever@eecs.umich.edu 1773101Sstever@eecs.umich.edu pkt->dataStatic(data); 1783101Sstever@eecs.umich.edu 1795033Smilesck@eecs.umich.edu if (!(memReq->isUncacheable() || memReq->isMmappedIpr())) { 1806656Snate@binkert.org // Access memory to see if we have the same data 1815033Smilesck@eecs.umich.edu dcachePort->sendFunctional(pkt); 1825033Smilesck@eecs.umich.edu } else { 1835033Smilesck@eecs.umich.edu // Assume the data is correct if it's an uncached access 1843101Sstever@eecs.umich.edu memcpy(data, unverifiedMemData, size); 1853101Sstever@eecs.umich.edu } 1863101Sstever@eecs.umich.edu 18710267SGeoffrey.Blake@arm.com delete memReq; 18810267SGeoffrey.Blake@arm.com memReq = NULL; 18910267SGeoffrey.Blake@arm.com delete pkt; 19010267SGeoffrey.Blake@arm.com } 19110267SGeoffrey.Blake@arm.com 19210267SGeoffrey.Blake@arm.com if (fault != NoFault) { 19310267SGeoffrey.Blake@arm.com if (memReq->isPrefetch()) { 19410267SGeoffrey.Blake@arm.com fault = NoFault; 19510267SGeoffrey.Blake@arm.com } 19610267SGeoffrey.Blake@arm.com delete memReq; 19710267SGeoffrey.Blake@arm.com memReq = NULL; 19810267SGeoffrey.Blake@arm.com break; 19910267SGeoffrey.Blake@arm.com } 2003101Sstever@eecs.umich.edu 2013101Sstever@eecs.umich.edu if (memReq != NULL) { 2023101Sstever@eecs.umich.edu delete memReq; 2033101Sstever@eecs.umich.edu } 2043101Sstever@eecs.umich.edu 2053101Sstever@eecs.umich.edu //If we don't need to access a second cache line, stop now. 2063101Sstever@eecs.umich.edu if (secondAddr <= addr) 2073101Sstever@eecs.umich.edu { 2083101Sstever@eecs.umich.edu break; 2093101Sstever@eecs.umich.edu } 2103102Sstever@eecs.umich.edu 2113101Sstever@eecs.umich.edu // Setup for accessing next cache line 2123101Sstever@eecs.umich.edu data += size; 2133101Sstever@eecs.umich.edu unverifiedMemData += size; 21410267SGeoffrey.Blake@arm.com size = addr + fullSize - secondAddr; 21510267SGeoffrey.Blake@arm.com addr = secondAddr; 21610267SGeoffrey.Blake@arm.com } 21710267SGeoffrey.Blake@arm.com 21810267SGeoffrey.Blake@arm.com if (!flags_match) { 21910267SGeoffrey.Blake@arm.com warn("%lli: Flags do not match CPU:%#x %#x %#x Checker:%#x %#x %#x\n", 22010267SGeoffrey.Blake@arm.com curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(), 2217673Snate@binkert.org unverifiedReq->getFlags(), addr, pAddr, flags); 2228607Sgblack@eecs.umich.edu handleError(); 2237673Snate@binkert.org } 2243101Sstever@eecs.umich.edu 2257673Snate@binkert.org return fault; 2267673Snate@binkert.org} 2273101Sstever@eecs.umich.edu 2287673Snate@binkert.orgFault 2297673Snate@binkert.orgCheckerCPU::writeMem(uint8_t *data, unsigned size, 2303101Sstever@eecs.umich.edu Addr addr, Request::Flags flags, uint64_t *res) 2313101Sstever@eecs.umich.edu{ 2323101Sstever@eecs.umich.edu Fault fault = NoFault; 2333101Sstever@eecs.umich.edu bool checked_flags = false; 2343101Sstever@eecs.umich.edu bool flags_match = true; 2353101Sstever@eecs.umich.edu Addr pAddr = 0x0; 2365033Smilesck@eecs.umich.edu static uint8_t zero_data[64] = {}; 2375475Snate@binkert.org 2385475Snate@binkert.org int fullSize = size; 2395475Snate@binkert.org 2405475Snate@binkert.org Addr secondAddr = roundDown(addr + size - 1, cacheLineSize()); 24110380SAndrew.Bardsley@arm.com 24210380SAndrew.Bardsley@arm.com if (secondAddr > addr) 24310380SAndrew.Bardsley@arm.com size = secondAddr - addr; 2443101Sstever@eecs.umich.edu 2453101Sstever@eecs.umich.edu // Need to account for a multiple access like Atomic and Timing CPUs 2463101Sstever@eecs.umich.edu while (1) { 2474762Snate@binkert.org memReq = new Request(0, addr, size, flags, masterId, 2484762Snate@binkert.org thread->pcState().instAddr(), tc->contextId()); 2494762Snate@binkert.org 2503101Sstever@eecs.umich.edu // translate to physical address 2518460SAli.Saidi@ARM.com fault = dtb->translateFunctional(memReq, tc, BaseTLB::Write); 2528459SAli.Saidi@ARM.com 2538459SAli.Saidi@ARM.com if (!checked_flags && fault == NoFault && unverifiedReq) { 2548459SAli.Saidi@ARM.com flags_match = checkFlags(unverifiedReq, memReq->getVaddr(), 2553101Sstever@eecs.umich.edu memReq->getPaddr(), memReq->getFlags()); 2567528Ssteve.reinhardt@amd.com pAddr = memReq->getPaddr(); 2577528Ssteve.reinhardt@amd.com checked_flags = true; 2587528Ssteve.reinhardt@amd.com } 2597528Ssteve.reinhardt@amd.com 2607528Ssteve.reinhardt@amd.com /* 2617528Ssteve.reinhardt@amd.com * We don't actually check memory for the store because there 2623101Sstever@eecs.umich.edu * is no guarantee it has left the lsq yet, and therefore we 2637528Ssteve.reinhardt@amd.com * can't verify the memory on stores without lsq snooping 2647528Ssteve.reinhardt@amd.com * enabled. This is left as future work for the Checker: LSQ snooping 2657528Ssteve.reinhardt@amd.com * and memory validation after stores have committed. 2667528Ssteve.reinhardt@amd.com */ 2677528Ssteve.reinhardt@amd.com bool was_prefetch = memReq->isPrefetch(); 2687528Ssteve.reinhardt@amd.com 2697528Ssteve.reinhardt@amd.com delete memReq; 2707528Ssteve.reinhardt@amd.com 2717528Ssteve.reinhardt@amd.com //If we don't need to access a second cache line, stop now. 2727528Ssteve.reinhardt@amd.com if (fault != NoFault || secondAddr <= addr) 2738321Ssteve.reinhardt@amd.com { 2748321Ssteve.reinhardt@amd.com if (fault != NoFault && was_prefetch) { 2757528Ssteve.reinhardt@amd.com fault = NoFault; 2767528Ssteve.reinhardt@amd.com } 2777528Ssteve.reinhardt@amd.com break; 2787528Ssteve.reinhardt@amd.com } 2797528Ssteve.reinhardt@amd.com 2807528Ssteve.reinhardt@amd.com //Update size and access address 2817528Ssteve.reinhardt@amd.com size = addr + fullSize - secondAddr; 2827528Ssteve.reinhardt@amd.com //And access the right address. 2837528Ssteve.reinhardt@amd.com addr = secondAddr; 2847528Ssteve.reinhardt@amd.com } 2857528Ssteve.reinhardt@amd.com 2867528Ssteve.reinhardt@amd.com if (!flags_match) { 2877528Ssteve.reinhardt@amd.com warn("%lli: Flags do not match CPU:%#x %#x Checker:%#x %#x %#x\n", 2883101Sstever@eecs.umich.edu curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(), 2898664SAli.Saidi@ARM.com unverifiedReq->getFlags(), addr, pAddr, flags); 2908664SAli.Saidi@ARM.com handleError(); 2918664SAli.Saidi@ARM.com } 2928664SAli.Saidi@ARM.com 2938664SAli.Saidi@ARM.com // Assume the result was the same as the one passed in. This checker 2948664SAli.Saidi@ARM.com // doesn't check if the SC should succeed or fail, it just checks the 2959953Sgeoffrey.blake@arm.com // value. 2969953Sgeoffrey.blake@arm.com if (unverifiedReq && res && unverifiedReq->extraDataValid()) 2979953Sgeoffrey.blake@arm.com *res = unverifiedReq->getExtraData(); 2989953Sgeoffrey.blake@arm.com 2999953Sgeoffrey.blake@arm.com // Entire purpose here is to make sure we are getting the 3009953Sgeoffrey.blake@arm.com // same data to send to the mem system as the CPU did. 3019953Sgeoffrey.blake@arm.com // Cannot check this is actually what went to memory because 3029953Sgeoffrey.blake@arm.com // there stores can be in ld/st queue or coherent operations 3039953Sgeoffrey.blake@arm.com // overwriting values. 3049953Sgeoffrey.blake@arm.com bool extraData = false; 3059953Sgeoffrey.blake@arm.com if (unverifiedReq) { 3069953Sgeoffrey.blake@arm.com extraData = unverifiedReq->extraDataValid() ? 3079953Sgeoffrey.blake@arm.com unverifiedReq->getExtraData() : true; 30810267SGeoffrey.Blake@arm.com } 30910267SGeoffrey.Blake@arm.com 31010267SGeoffrey.Blake@arm.com // If the request is to ZERO a cache block, there is no data to check 31110267SGeoffrey.Blake@arm.com // against, but it's all zero. We need something to compare to, so use a 31210267SGeoffrey.Blake@arm.com // const set of zeros. 31310267SGeoffrey.Blake@arm.com if (flags & Request::STORE_NO_DATA) { 31410267SGeoffrey.Blake@arm.com assert(!data); 31510267SGeoffrey.Blake@arm.com assert(sizeof(zero_data) <= fullSize); 31610267SGeoffrey.Blake@arm.com data = zero_data; 31710267SGeoffrey.Blake@arm.com } 31810267SGeoffrey.Blake@arm.com 31910267SGeoffrey.Blake@arm.com if (unverifiedReq && unverifiedMemData && 32010267SGeoffrey.Blake@arm.com memcmp(data, unverifiedMemData, fullSize) && extraData) { 32110267SGeoffrey.Blake@arm.com warn("%lli: Store value does not match value sent to memory! " 32210267SGeoffrey.Blake@arm.com "data: %#x inst_data: %#x", curTick(), data, 32310267SGeoffrey.Blake@arm.com unverifiedMemData); 32410267SGeoffrey.Blake@arm.com handleError(); 32510267SGeoffrey.Blake@arm.com } 32610267SGeoffrey.Blake@arm.com 32710267SGeoffrey.Blake@arm.com return fault; 3283101Sstever@eecs.umich.edu} 3293101Sstever@eecs.umich.edu 3303101Sstever@eecs.umich.eduAddr 3313101Sstever@eecs.umich.eduCheckerCPU::dbg_vtophys(Addr addr) 3323101Sstever@eecs.umich.edu{ 3333101Sstever@eecs.umich.edu return vtophys(tc, addr); 3343101Sstever@eecs.umich.edu} 33510364SGeoffrey.Blake@arm.com 33610364SGeoffrey.Blake@arm.com/** 33710364SGeoffrey.Blake@arm.com * Checks if the flags set by the Checker and Checkee match. 33810364SGeoffrey.Blake@arm.com */ 3393101Sstever@eecs.umich.edubool 3404762Snate@binkert.orgCheckerCPU::checkFlags(Request *unverified_req, Addr vAddr, 3414762Snate@binkert.org Addr pAddr, int flags) 3424762Snate@binkert.org{ 3434762Snate@binkert.org Addr unverifiedVAddr = unverified_req->getVaddr(); 3447528Ssteve.reinhardt@amd.com Addr unverifiedPAddr = unverified_req->getPaddr(); 3454762Snate@binkert.org int unverifiedFlags = unverified_req->getFlags(); 3464762Snate@binkert.org 3474762Snate@binkert.org if (unverifiedVAddr != vAddr || 34810267SGeoffrey.Blake@arm.com unverifiedPAddr != pAddr || 34910267SGeoffrey.Blake@arm.com unverifiedFlags != flags) { 35010267SGeoffrey.Blake@arm.com return false; 35110267SGeoffrey.Blake@arm.com } 35210267SGeoffrey.Blake@arm.com 35310267SGeoffrey.Blake@arm.com return true; 35410267SGeoffrey.Blake@arm.com} 35510267SGeoffrey.Blake@arm.com 35610267SGeoffrey.Blake@arm.comvoid 35710267SGeoffrey.Blake@arm.comCheckerCPU::dumpAndExit() 35810267SGeoffrey.Blake@arm.com{ 35910267SGeoffrey.Blake@arm.com warn("%lli: Checker PC:%s", 36010267SGeoffrey.Blake@arm.com curTick(), thread->pcState()); 36110267SGeoffrey.Blake@arm.com panic("Checker found an error!"); 36210267SGeoffrey.Blake@arm.com} 36310267SGeoffrey.Blake@arm.com