cpu_impl.hh revision 9382
12315SN/A/* 22332SN/A * Copyright (c) 2011 ARM Limited 32315SN/A * All rights reserved 42315SN/A * 52315SN/A * The license below extends only to copyright in the software and shall 62315SN/A * not be construed as granting a license to any other intellectual 72315SN/A * property including but not limited to intellectual property relating 82315SN/A * to a hardware implementation of the functionality of the software 92315SN/A * licensed hereunder. You may use the software subject to the license 102315SN/A * terms below provided that you ensure that this notice is replicated 112315SN/A * unmodified and in its entirety in all distributions of the software, 122315SN/A * modified or unmodified, in source code or in binary form. 132315SN/A * 142315SN/A * Copyright (c) 2006 The Regents of The University of Michigan 152315SN/A * All rights reserved. 162315SN/A * 172315SN/A * Redistribution and use in source and binary forms, with or without 182315SN/A * modification, are permitted provided that the following conditions are 192315SN/A * met: redistributions of source code must retain the above copyright 202315SN/A * notice, this list of conditions and the following disclaimer; 212315SN/A * redistributions in binary form must reproduce the above copyright 222315SN/A * notice, this list of conditions and the following disclaimer in the 232315SN/A * documentation and/or other materials provided with the distribution; 242315SN/A * neither the name of the copyright holders nor the names of its 252315SN/A * contributors may be used to endorse or promote products derived from 262315SN/A * this software without specific prior written permission. 272689SN/A * 282689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292315SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302315SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 312315SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 322315SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332315SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 342315SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 352315SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362315SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 372683SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 382680SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392315SN/A * 402315SN/A * Authors: Kevin Lim 412315SN/A * Geoffrey Blake 422315SN/A */ 432315SN/A 442315SN/A#include <list> 452315SN/A#include <string> 462315SN/A 472315SN/A#include "arch/isa_traits.hh" 482315SN/A#include "arch/vtophys.hh" 492315SN/A#include "base/refcnt.hh" 502315SN/A#include "config/the_isa.hh" 512315SN/A#include "cpu/base_dyn_inst.hh" 522315SN/A#include "cpu/exetrace.hh" 532732SN/A#include "cpu/simple_thread.hh" 542315SN/A#include "cpu/static_inst.hh" 552315SN/A#include "cpu/thread_context.hh" 562315SN/A#include "cpu/checker/cpu.hh" 572332SN/A#include "debug/Checker.hh" 582332SN/A#include "sim/full_system.hh" 592332SN/A#include "sim/sim_object.hh" 602332SN/A#include "sim/stats.hh" 612332SN/A 622315SN/Ausing namespace std; 632315SN/Ausing namespace TheISA; 642315SN/A 652315SN/Atemplate <class Impl> 662315SN/Avoid 672315SN/AChecker<Impl>::advancePC(Fault fault) 682315SN/A{ 692315SN/A if (fault != NoFault) { 702315SN/A curMacroStaticInst = StaticInst::nullStaticInstPtr; 712315SN/A fault->invoke(tc, curStaticInst); 722315SN/A thread->decoder.reset(); 732315SN/A } else { 742315SN/A if (curStaticInst) { 752315SN/A if (curStaticInst->isLastMicroop()) 762315SN/A curMacroStaticInst = StaticInst::nullStaticInstPtr; 772315SN/A TheISA::PCState pcState = thread->pcState(); 782315SN/A TheISA::advancePC(pcState, curStaticInst); 792315SN/A thread->pcState(pcState); 802315SN/A DPRINTF(Checker, "Advancing PC to %s.\n", thread->pcState()); 812315SN/A } 822315SN/A } 832315SN/A} 842315SN/A////////////////////////////////////////////////// 852315SN/A 862315SN/Atemplate <class Impl> 872315SN/Avoid 882315SN/AChecker<Impl>::handlePendingInt() 892315SN/A{ 902315SN/A DPRINTF(Checker, "IRQ detected at PC: %s with %d insts in buffer\n", 912315SN/A thread->pcState(), instList.size()); 922315SN/A DynInstPtr boundaryInst = NULL; 932315SN/A if (!instList.empty()) { 942315SN/A // Set the instructions as completed and verify as much as possible. 952354SN/A DynInstPtr inst; 962354SN/A typename std::list<DynInstPtr>::iterator itr; 972332SN/A 982332SN/A for (itr = instList.begin(); itr != instList.end(); itr++) { 992332SN/A (*itr)->setCompleted(); 1002315SN/A } 1012315SN/A 1022315SN/A inst = instList.front(); 1032315SN/A boundaryInst = instList.back(); 1042315SN/A verify(inst); // verify the instructions 1052679SN/A inst = NULL; 1062315SN/A } 1072315SN/A if ((!boundaryInst && curMacroStaticInst && 1082315SN/A curStaticInst->isDelayedCommit() && 1092315SN/A !curStaticInst->isLastMicroop()) || 1102315SN/A (boundaryInst && boundaryInst->isDelayedCommit() && 1112683SN/A !boundaryInst->isLastMicroop())) { 1122315SN/A panic("%lli: Trying to take an interrupt in middle of " 1132683SN/A "a non-interuptable instruction!", curTick()); 1142315SN/A } 1152315SN/A boundaryInst = NULL; 1162332SN/A thread->decoder.reset(); 1172332SN/A curMacroStaticInst = StaticInst::nullStaticInstPtr; 1182332SN/A} 1192315SN/A 1202315SN/Atemplate <class Impl> 1212683SN/Avoid 1222315SN/AChecker<Impl>::verify(DynInstPtr &completed_inst) 1232683SN/A{ 1242315SN/A DynInstPtr inst; 1252315SN/A 1262332SN/A // Make sure serializing instructions are actually 1272332SN/A // seen as serializing to commit. instList should be 1282683SN/A // empty in these cases. 1292732SN/A if ((completed_inst->isSerializing() || 1302315SN/A completed_inst->isSerializeBefore()) && 1312315SN/A (!instList.empty() ? 1322315SN/A (instList.front()->seqNum != completed_inst->seqNum) : 0)) { 1332315SN/A panic("%lli: Instruction sn:%lli at PC %s is serializing before but is" 1342315SN/A " entering instList with other instructions\n", curTick(), 1352315SN/A completed_inst->seqNum, completed_inst->pcState()); 1362315SN/A } 1372683SN/A 1382315SN/A // Either check this instruction, or add it to a list of 1392315SN/A // instructions waiting to be checked. Instructions must be 1402315SN/A // checked in program order, so if a store has committed yet not 1412332SN/A // completed, there may be some instructions that are waiting 1422332SN/A // behind it that have completed and must be checked. 1432332SN/A if (!instList.empty()) { 1442332SN/A if (youngestSN < completed_inst->seqNum) { 1452332SN/A DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%s to list\n", 1462332SN/A completed_inst->seqNum, completed_inst->pcState()); 1472332SN/A instList.push_back(completed_inst); 1482332SN/A youngestSN = completed_inst->seqNum; 1492683SN/A } 1502679SN/A 1512332SN/A if (!instList.front()->isCompleted()) { 1522679SN/A return; 1532679SN/A } else { 1542683SN/A inst = instList.front(); 1552683SN/A instList.pop_front(); 1562315SN/A } 1572315SN/A } else { 1582315SN/A if (!completed_inst->isCompleted()) { 1592315SN/A if (youngestSN < completed_inst->seqNum) { 1602323SN/A DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%s to list\n", 1612332SN/A completed_inst->seqNum, completed_inst->pcState()); 1622332SN/A instList.push_back(completed_inst); 1632332SN/A youngestSN = completed_inst->seqNum; 1642332SN/A } 1652332SN/A return; 1662332SN/A } else { 1672683SN/A if (youngestSN < completed_inst->seqNum) { 1682732SN/A inst = completed_inst; 1692315SN/A youngestSN = completed_inst->seqNum; 1702323SN/A } else { 1712683SN/A return; 1722683SN/A } 1732315SN/A } 1742354SN/A } 1752323SN/A 1762332SN/A // Make sure a serializing instruction is actually seen as 1772332SN/A // serializing. instList should be empty here 1782332SN/A if (inst->isSerializeAfter() && !instList.empty()) { 1792323SN/A panic("%lli: Instruction sn:%lli at PC %s is serializing after but is" 1802323SN/A " exiting instList with other instructions\n", curTick(), 1812315SN/A completed_inst->seqNum, completed_inst->pcState()); 1822315SN/A } 1832323SN/A unverifiedInst = inst; 1843349Sbinkertn@umich.edu inst = NULL; 1852679SN/A 1862679SN/A // Try to check all instructions that are completed, ending if we 1872679SN/A // run out of instructions to check or if an instruction is not 1882679SN/A // yet completed. 1892679SN/A while (1) { 1902679SN/A DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%s.\n", 1912679SN/A unverifiedInst->seqNum, unverifiedInst->pcState()); 1922315SN/A unverifiedReq = NULL; 1932332SN/A unverifiedReq = unverifiedInst->reqToVerify; 1942323SN/A unverifiedMemData = unverifiedInst->memData; 1952315SN/A // Make sure results queue is empty 1962323SN/A while (!result.empty()) { 1972323SN/A result.pop(); 1982323SN/A } 1992323SN/A numCycles++; 2002323SN/A 2012315SN/A Fault fault = NoFault; 2022332SN/A 2032683SN/A // maintain $r0 semantics 2042315SN/A thread->setIntReg(ZeroReg, 0); 2052315SN/A#if THE_ISA == ALPHA_ISA 2062683SN/A thread->setFloatReg(ZeroReg, 0.0); 2072315SN/A#endif 2082315SN/A 2092323SN/A // Check if any recent PC changes match up with anything we 2102323SN/A // expect to happen. This is mostly to check if traps or 2112315SN/A // PC-based events have occurred in both the checker and CPU. 2122679SN/A if (changedPC) { 2132679SN/A DPRINTF(Checker, "Changed PC recently to %s\n", 2142679SN/A thread->pcState()); 2152679SN/A if (willChangePC) { 2162315SN/A if (newPCState == thread->pcState()) { 2172315SN/A DPRINTF(Checker, "Changed PC matches expected PC\n"); 2182315SN/A } else { 2192315SN/A warn("%lli: Changed PC does not match expected PC, " 2202315SN/A "changed: %s, expected: %s", 2212683SN/A curTick(), thread->pcState(), newPCState); 2222315SN/A CheckerCPU::handleError(); 2232354SN/A } 2242354SN/A willChangePC = false; 2252315SN/A } 2262315SN/A changedPC = false; 2272315SN/A } 2282315SN/A if (changedNextPC) { 2292315SN/A DPRINTF(Checker, "Changed NextPC recently to %#x\n", 2302315SN/A thread->nextInstAddr()); 2312315SN/A changedNextPC = false; 2322315SN/A } 2332315SN/A 2342315SN/A // Try to fetch the instruction 2352315SN/A uint64_t fetchOffset = 0; 2362690SN/A bool fetchDone = false; 2372315SN/A 2382683SN/A while (!fetchDone) { 2392315SN/A Addr fetch_PC = thread->instAddr(); 2402838Sktlim@umich.edu fetch_PC = (fetch_PC & PCMask) + fetchOffset; 2412315SN/A 2422315SN/A MachInst machInst; 2432315SN/A 2442683SN/A // If not in the middle of a macro instruction 2452683SN/A if (!curMacroStaticInst) { 2462315SN/A // set up memory request for instruction fetch 2472315SN/A memReq = new Request(unverifiedInst->threadNumber, fetch_PC, 2482683SN/A sizeof(MachInst), 2492683SN/A 0, 2502683SN/A masterId, 2512315SN/A fetch_PC, thread->contextId(), 2522315SN/A unverifiedInst->threadNumber); 2532315SN/A memReq->setVirt(0, fetch_PC, sizeof(MachInst), 2542315SN/A Request::INST_FETCH, masterId, thread->instAddr()); 2552315SN/A 2562332SN/A 2572332SN/A fault = itb->translateFunctional(memReq, tc, BaseTLB::Execute); 2582332SN/A 2592315SN/A if (fault != NoFault) { 2602315SN/A if (unverifiedInst->getFault() == NoFault) { 2612315SN/A // In this case the instruction was not a dummy 2622683SN/A // instruction carrying an ITB fault. In the single 2632690SN/A // threaded case the ITB should still be able to 2642315SN/A // translate this instruction; in the SMT case it's 2652683SN/A // possible that its ITB entry was kicked out. 2662315SN/A warn("%lli: Instruction PC %s was not found in the " 2672315SN/A "ITB!", curTick(), thread->pcState()); 2682683SN/A handleError(unverifiedInst); 2692315SN/A 2702315SN/A // go to the next instruction 2712315SN/A advancePC(NoFault); 2722315SN/A 2732332SN/A // Give up on an ITB fault.. 2742315SN/A delete memReq; 2752315SN/A unverifiedInst = NULL; 2762315SN/A return; 2772679SN/A } else { 2782679SN/A // The instruction is carrying an ITB fault. Handle 2792679SN/A // the fault and see if our results match the CPU on 2802679SN/A // the next tick(). 2812679SN/A fault = unverifiedInst->getFault(); 2822332SN/A delete memReq; 2832332SN/A break; 2842315SN/A } 2852315SN/A } else { 2862315SN/A PacketPtr pkt = new Packet(memReq, MemCmd::ReadReq); 2872315SN/A 2882315SN/A pkt->dataStatic(&machInst); 2892315SN/A icachePort->sendFunctional(pkt); 2902315SN/A machInst = gtoh(machInst); 2912315SN/A 2922315SN/A delete memReq; 2932354SN/A delete pkt; 2942315SN/A } 2952315SN/A } 2962315SN/A 2972315SN/A if (fault == NoFault) { 2982840Sktlim@umich.edu TheISA::PCState pcState = thread->pcState(); 2992315SN/A 3002315SN/A if (isRomMicroPC(pcState.microPC())) { 3012315SN/A fetchDone = true; 3022315SN/A curStaticInst = 3032315SN/A microcodeRom.fetchMicroop(pcState.microPC(), NULL); 3042315SN/A } else if (!curMacroStaticInst) { 3052315SN/A //We're not in the middle of a macro instruction 3062315SN/A StaticInstPtr instPtr = NULL; 3072315SN/A 3082315SN/A //Predecode, ie bundle up an ExtMachInst 3092315SN/A //If more fetch data is needed, pass it in. 3102315SN/A Addr fetchPC = (pcState.instAddr() & PCMask) + fetchOffset; 3112315SN/A thread->decoder.moreBytes(pcState, fetchPC, machInst); 3122315SN/A 3132683SN/A //If an instruction is ready, decode it. 3142332SN/A //Otherwise, we'll have to fetch beyond the 3152683SN/A //MachInst at the current pc. 3162315SN/A if (thread->decoder.instReady()) { 3172332SN/A fetchDone = true; 3182332SN/A instPtr = thread->decoder.decode(pcState); 3192315SN/A thread->pcState(pcState); 3202732SN/A } else { 3212315SN/A fetchDone = false; 3222315SN/A fetchOffset += sizeof(TheISA::MachInst); 3232315SN/A } 3242332SN/A 3252332SN/A //If we decoded an instruction and it's microcoded, 3262332SN/A //start pulling out micro ops 3272332SN/A if (instPtr && instPtr->isMacroop()) { 3282332SN/A curMacroStaticInst = instPtr; 3292332SN/A curStaticInst = 3302732SN/A instPtr->fetchMicroop(pcState.microPC()); 3312315SN/A } else { 3322315SN/A curStaticInst = instPtr; 3332315SN/A } 3342315SN/A } else { 3352315SN/A // Read the next micro op from the macro-op 3362315SN/A curStaticInst = 3372315SN/A curMacroStaticInst->fetchMicroop(pcState.microPC()); 3382732SN/A fetchDone = true; 3392315SN/A } 3402332SN/A } 3412315SN/A } 3422332SN/A // reset decoder on Checker 3432332SN/A thread->decoder.reset(); 3442332SN/A 3452732SN/A // Check Checker and CPU get same instruction, and record 3462315SN/A // any faults the CPU may have had. 3472732SN/A Fault unverifiedFault; 3482732SN/A if (fault == NoFault) { 3492732SN/A unverifiedFault = unverifiedInst->getFault(); 3502732SN/A 3512732SN/A // Checks that the instruction matches what we expected it to be. 3522732SN/A // Checks both the machine instruction and the PC. 3532732SN/A validateInst(unverifiedInst); 3542732SN/A } 3552732SN/A 3562732SN/A // keep an instruction count 3572732SN/A numInst++; 3582732SN/A 3592732SN/A 3602732SN/A // Either the instruction was a fault and we should process the fault, 3612732SN/A // or we should just go ahead execute the instruction. This assumes 3622732SN/A // that the instruction is properly marked as a fault. 3632732SN/A if (fault == NoFault) { 3642732SN/A // Execute Checker instruction and trace 3652315SN/A if (!unverifiedInst->isUnverifiable()) { 3662315SN/A Trace::InstRecord *traceData = tracer->getInstRecord(curTick(), 3672315SN/A tc, 3682683SN/A curStaticInst, 3692332SN/A pcState(), 3702332SN/A curMacroStaticInst); 3712683SN/A fault = curStaticInst->execute(this, traceData); 3722732SN/A if (traceData) { 3732315SN/A traceData->dump(); 3742315SN/A delete traceData; 3752315SN/A } 3762315SN/A } 3772315SN/A 3782315SN/A if (fault == NoFault && unverifiedFault == NoFault) { 3792315SN/A thread->funcExeInst++; 3802315SN/A // Checks to make sure instrution results are correct. 3812315SN/A validateExecution(unverifiedInst); 3822315SN/A 3832315SN/A if (curStaticInst->isLoad()) { 3842680SN/A ++numLoad; 3852683SN/A } 3862332SN/A } else if (fault != NoFault && unverifiedFault == NoFault) { 3872332SN/A panic("%lli: sn: %lli at PC: %s took a fault in checker " 3882332SN/A "but not in driver CPU\n", curTick(), 3892680SN/A unverifiedInst->seqNum, unverifiedInst->pcState()); 3902683SN/A } else if (fault == NoFault && unverifiedFault != NoFault) { 3912732SN/A panic("%lli: sn: %lli at PC: %s took a fault in driver " 3922315SN/A "CPU but not in checker\n", curTick(), 3932315SN/A unverifiedInst->seqNum, unverifiedInst->pcState()); 3942315SN/A } 3952315SN/A } 3962315SN/A 3972315SN/A // Take any faults here 3982315SN/A if (fault != NoFault) { 3992315SN/A if (FullSystem) { 4002354SN/A fault->invoke(tc, curStaticInst); 4012354SN/A willChangePC = true; 4022356SN/A newPCState = thread->pcState(); 4032354SN/A DPRINTF(Checker, "Fault, PC is now %s\n", newPCState); 4043126Sktlim@umich.edu curMacroStaticInst = StaticInst::nullStaticInstPtr; 4052356SN/A } 4062356SN/A } else { 4072356SN/A advancePC(fault); 4083126Sktlim@umich.edu } 4093126Sktlim@umich.edu 4102356SN/A if (FullSystem) { 4112356SN/A // @todo: Determine if these should happen only if the 4123126Sktlim@umich.edu // instruction hasn't faulted. In the SimpleCPU case this may 4133126Sktlim@umich.edu // not be true, but in the O3 or Ozone case this may be true. 4143126Sktlim@umich.edu Addr oldpc; 4152356SN/A int count = 0; 4162354SN/A do { 4173126Sktlim@umich.edu oldpc = thread->instAddr(); 4182315SN/A system->pcEventQueue.service(tc); 4192315SN/A count++; 4202315SN/A } while (oldpc != thread->instAddr()); 4212315SN/A if (count > 1) { 4222732SN/A willChangePC = true; 4232732SN/A newPCState = thread->pcState(); 4242732SN/A DPRINTF(Checker, "PC Event, PC is now %s\n", newPCState); 4252732SN/A } 4262732SN/A } 4272732SN/A 4282732SN/A // @todo: Optionally can check all registers. (Or just those 4292732SN/A // that have been modified). 4302732SN/A validateState(); 4312732SN/A 4322732SN/A // Continue verifying instructions if there's another completed 4332732SN/A // instruction waiting to be verified. 4342732SN/A if (instList.empty()) { 4352732SN/A break; 4362732SN/A } else if (instList.front()->isCompleted()) { 4372732SN/A unverifiedInst = NULL; 4382732SN/A unverifiedInst = instList.front(); 4392732SN/A instList.pop_front(); 4402732SN/A } else { 4412732SN/A break; 4422732SN/A } 4432732SN/A } 4442732SN/A unverifiedInst = NULL; 4452732SN/A} 4462732SN/A 4472732SN/Atemplate <class Impl> 4482732SN/Avoid 4492732SN/AChecker<Impl>::switchOut() 4502732SN/A{ 4512732SN/A instList.clear(); 4522315SN/A} 4532315SN/A 4542315SN/Atemplate <class Impl> 4552315SN/Avoid 4562315SN/AChecker<Impl>::takeOverFrom(BaseCPU *oldCPU) 4572315SN/A{ 4582315SN/A} 4592315SN/A 4602315SN/Atemplate <class Impl> 4612315SN/Avoid 4622315SN/AChecker<Impl>::validateInst(DynInstPtr &inst) 4632315SN/A{ 4642315SN/A if (inst->instAddr() != thread->instAddr()) { 4652315SN/A warn("%lli: PCs do not match! Inst: %s, checker: %s", 4662315SN/A curTick(), inst->pcState(), thread->pcState()); 4672315SN/A if (changedPC) { 4682315SN/A warn("%lli: Changed PCs recently, may not be an error", 4692315SN/A curTick()); 4702315SN/A } else { 4712315SN/A handleError(inst); 4722315SN/A } 4732315SN/A } 4742315SN/A 4752315SN/A if (curStaticInst != inst->staticInst) { 4762315SN/A warn("%lli: StaticInstPtrs don't match. (%s, %s).\n", curTick(), 4772315SN/A curStaticInst->getName(), inst->staticInst->getName()); 4782315SN/A } 479} 480 481template <class Impl> 482void 483Checker<Impl>::validateExecution(DynInstPtr &inst) 484{ 485 uint64_t checker_val; 486 uint64_t inst_val; 487 int idx = -1; 488 bool result_mismatch = false; 489 490 if (inst->isUnverifiable()) { 491 // Unverifiable instructions assume they were executed 492 // properly by the CPU. Grab the result from the 493 // instruction and write it to the register. 494 copyResult(inst, 0, idx); 495 } else if (inst->numDestRegs() > 0 && !result.empty()) { 496 DPRINTF(Checker, "Dest regs %d, number of checker dest regs %d\n", 497 inst->numDestRegs(), result.size()); 498 for (int i = 0; i < inst->numDestRegs() && !result.empty(); i++) { 499 result.front().get(checker_val); 500 result.pop(); 501 inst_val = 0; 502 inst->template popResult<uint64_t>(inst_val); 503 if (checker_val != inst_val) { 504 result_mismatch = true; 505 idx = i; 506 break; 507 } 508 } 509 } // Checker CPU checks all the saved results in the dyninst passed by 510 // the cpu model being checked against the saved results present in 511 // the static inst executed in the Checker. Sometimes the number 512 // of saved results differs between the dyninst and static inst, but 513 // this is ok and not a bug. May be worthwhile to try and correct this. 514 515 if (result_mismatch) { 516 warn("%lli: Instruction results do not match! (Values may not " 517 "actually be integers) Inst: %#x, checker: %#x", 518 curTick(), inst_val, checker_val); 519 520 // It's useful to verify load values from memory, but in MP 521 // systems the value obtained at execute may be different than 522 // the value obtained at completion. Similarly DMA can 523 // present the same problem on even UP systems. Thus there is 524 // the option to only warn on loads having a result error. 525 // The load/store queue in Detailed CPU can also cause problems 526 // if load/store forwarding is allowed. 527 if (inst->isLoad() && warnOnlyOnLoadError) { 528 copyResult(inst, inst_val, idx); 529 } else { 530 handleError(inst); 531 } 532 } 533 534 if (inst->nextInstAddr() != thread->nextInstAddr()) { 535 warn("%lli: Instruction next PCs do not match! Inst: %#x, " 536 "checker: %#x", 537 curTick(), inst->nextInstAddr(), thread->nextInstAddr()); 538 handleError(inst); 539 } 540 541 // Checking side effect registers can be difficult if they are not 542 // checked simultaneously with the execution of the instruction. 543 // This is because other valid instructions may have modified 544 // these registers in the meantime, and their values are not 545 // stored within the DynInst. 546 while (!miscRegIdxs.empty()) { 547 int misc_reg_idx = miscRegIdxs.front(); 548 miscRegIdxs.pop(); 549 550 if (inst->tcBase()->readMiscRegNoEffect(misc_reg_idx) != 551 thread->readMiscRegNoEffect(misc_reg_idx)) { 552 warn("%lli: Misc reg idx %i (side effect) does not match! " 553 "Inst: %#x, checker: %#x", 554 curTick(), misc_reg_idx, 555 inst->tcBase()->readMiscRegNoEffect(misc_reg_idx), 556 thread->readMiscRegNoEffect(misc_reg_idx)); 557 handleError(inst); 558 } 559 } 560} 561 562 563// This function is weird, if it is called it means the Checker and 564// O3 have diverged, so panic is called for now. It may be useful 565// to resynch states and continue if the divergence is a false positive 566template <class Impl> 567void 568Checker<Impl>::validateState() 569{ 570 if (updateThisCycle) { 571 // Change this back to warn if divergences end up being false positives 572 panic("%lli: Instruction PC %#x results didn't match up, copying all " 573 "registers from main CPU", curTick(), unverifiedInst->instAddr()); 574 575 // Terribly convoluted way to make sure O3 model does not implode 576 bool no_squash_from_TC = unverifiedInst->thread->noSquashFromTC; 577 unverifiedInst->thread->noSquashFromTC = true; 578 579 // Heavy-weight copying of all registers 580 thread->copyArchRegs(unverifiedInst->tcBase()); 581 unverifiedInst->thread->noSquashFromTC = no_squash_from_TC; 582 583 // Set curStaticInst to unverifiedInst->staticInst 584 curStaticInst = unverifiedInst->staticInst; 585 // Also advance the PC. Hopefully no PC-based events happened. 586 advancePC(NoFault); 587 updateThisCycle = false; 588 } 589} 590 591template <class Impl> 592void 593Checker<Impl>::copyResult(DynInstPtr &inst, uint64_t mismatch_val, 594 int start_idx) 595{ 596 // We've already popped one dest off the queue, 597 // so do the fix-up then start with the next dest reg; 598 if (start_idx >= 0) { 599 RegIndex idx = inst->destRegIdx(start_idx); 600 if (idx < TheISA::FP_Base_DepTag) { 601 thread->setIntReg(idx, mismatch_val); 602 } else if (idx < TheISA::Ctrl_Base_DepTag) { 603 thread->setFloatRegBits(idx, mismatch_val); 604 } else if (idx < TheISA::Max_DepTag) { 605 thread->setMiscReg(idx - TheISA::Ctrl_Base_DepTag, 606 mismatch_val); 607 } 608 } 609 start_idx++; 610 uint64_t res = 0; 611 for (int i = start_idx; i < inst->numDestRegs(); i++) { 612 RegIndex idx = inst->destRegIdx(i); 613 inst->template popResult<uint64_t>(res); 614 if (idx < TheISA::FP_Base_DepTag) { 615 thread->setIntReg(idx, res); 616 } else if (idx < TheISA::Ctrl_Base_DepTag) { 617 thread->setFloatRegBits(idx, res); 618 } else if (idx < TheISA::Max_DepTag) { 619 // Try to get the proper misc register index for ARM here... 620 thread->setMiscReg(idx - TheISA::Ctrl_Base_DepTag, res); 621 } // else Register is out of range... 622 } 623} 624 625template <class Impl> 626void 627Checker<Impl>::dumpAndExit(DynInstPtr &inst) 628{ 629 cprintf("Error detected, instruction information:\n"); 630 cprintf("PC:%s, nextPC:%#x\n[sn:%lli]\n[tid:%i]\n" 631 "Completed:%i\n", 632 inst->pcState(), 633 inst->nextInstAddr(), 634 inst->seqNum, 635 inst->threadNumber, 636 inst->isCompleted()); 637 inst->dump(); 638 CheckerCPU::dumpAndExit(); 639} 640 641template <class Impl> 642void 643Checker<Impl>::dumpInsts() 644{ 645 int num = 0; 646 647 InstListIt inst_list_it = --(instList.end()); 648 649 cprintf("Inst list size: %i\n", instList.size()); 650 651 while (inst_list_it != instList.end()) 652 { 653 cprintf("Instruction:%i\n", 654 num); 655 656 cprintf("PC:%s\n[sn:%lli]\n[tid:%i]\n" 657 "Completed:%i\n", 658 (*inst_list_it)->pcState(), 659 (*inst_list_it)->seqNum, 660 (*inst_list_it)->threadNumber, 661 (*inst_list_it)->isCompleted()); 662 663 cprintf("\n"); 664 665 inst_list_it--; 666 ++num; 667 } 668 669} 670