cpu_impl.hh revision 8793
12315SN/A/* 22332SN/A * Copyright (c) 2006 The Regents of The University of Michigan 32315SN/A * All rights reserved. 42315SN/A * 52315SN/A * Redistribution and use in source and binary forms, with or without 62315SN/A * modification, are permitted provided that the following conditions are 72315SN/A * met: redistributions of source code must retain the above copyright 82315SN/A * notice, this list of conditions and the following disclaimer; 92315SN/A * redistributions in binary form must reproduce the above copyright 102315SN/A * notice, this list of conditions and the following disclaimer in the 112315SN/A * documentation and/or other materials provided with the distribution; 122315SN/A * neither the name of the copyright holders nor the names of its 132315SN/A * contributors may be used to endorse or promote products derived from 142315SN/A * this software without specific prior written permission. 152315SN/A * 162315SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172315SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182315SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192315SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202315SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212315SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222315SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232315SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242315SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252315SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262315SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272689SN/A * 282689SN/A * Authors: Kevin Lim 292315SN/A */ 302315SN/A 312315SN/A#include <list> 322315SN/A#include <string> 332315SN/A 348793Sgblack@eecs.umich.edu#include "arch/vtophys.hh" 352315SN/A#include "base/refcnt.hh" 366658Snate@binkert.org#include "config/the_isa.hh" 378229Snate@binkert.org#include "cpu/checker/cpu.hh" 382315SN/A#include "cpu/base_dyn_inst.hh" 392683SN/A#include "cpu/simple_thread.hh" 408229Snate@binkert.org#include "cpu/static_inst.hh" 412680SN/A#include "cpu/thread_context.hh" 428793Sgblack@eecs.umich.edu#include "sim/full_system.hh" 432315SN/A#include "sim/sim_object.hh" 442315SN/A#include "sim/stats.hh" 452315SN/A 462315SN/Ausing namespace std; 472315SN/A//The CheckerCPU does alpha only 482315SN/Ausing namespace AlphaISA; 492315SN/A 502315SN/Atemplate <class DynInstPtr> 512315SN/Avoid 522732SN/AChecker<DynInstPtr>::verify(DynInstPtr &completed_inst) 532315SN/A{ 542315SN/A DynInstPtr inst; 552315SN/A 562332SN/A // Either check this instruction, or add it to a list of 572332SN/A // instructions waiting to be checked. Instructions must be 582332SN/A // checked in program order, so if a store has committed yet not 592332SN/A // completed, there may be some instructions that are waiting 602332SN/A // behind it that have completed and must be checked. 612315SN/A if (!instList.empty()) { 622315SN/A if (youngestSN < completed_inst->seqNum) { 632315SN/A DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n", 642315SN/A completed_inst->seqNum, completed_inst->readPC()); 652315SN/A instList.push_back(completed_inst); 662315SN/A youngestSN = completed_inst->seqNum; 672315SN/A } 682315SN/A 692315SN/A if (!instList.front()->isCompleted()) { 702315SN/A return; 712315SN/A } else { 722315SN/A inst = instList.front(); 732315SN/A instList.pop_front(); 742315SN/A } 752315SN/A } else { 762315SN/A if (!completed_inst->isCompleted()) { 772315SN/A if (youngestSN < completed_inst->seqNum) { 782315SN/A DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n", 792315SN/A completed_inst->seqNum, completed_inst->readPC()); 802315SN/A instList.push_back(completed_inst); 812315SN/A youngestSN = completed_inst->seqNum; 822315SN/A } 832315SN/A return; 842315SN/A } else { 852315SN/A if (youngestSN < completed_inst->seqNum) { 862315SN/A inst = completed_inst; 872315SN/A youngestSN = completed_inst->seqNum; 882315SN/A } else { 892315SN/A return; 902315SN/A } 912315SN/A } 922315SN/A } 932315SN/A 942354SN/A unverifiedInst = inst; 952354SN/A 962332SN/A // Try to check all instructions that are completed, ending if we 972332SN/A // run out of instructions to check or if an instruction is not 982332SN/A // yet completed. 992315SN/A while (1) { 1002315SN/A DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n", 1012315SN/A inst->seqNum, inst->readPC()); 1022315SN/A unverifiedResult.integer = inst->readIntResult(); 1032315SN/A unverifiedReq = inst->req; 1042679SN/A unverifiedMemData = inst->memData; 1052315SN/A numCycles++; 1062315SN/A 1072315SN/A Fault fault = NoFault; 1082315SN/A 1092315SN/A // maintain $r0 semantics 1102683SN/A thread->setIntReg(ZeroReg, 0); 1112315SN/A#ifdef TARGET_ALPHA 1122683SN/A thread->setFloatRegDouble(ZeroReg, 0.0); 1132315SN/A#endif // TARGET_ALPHA 1142315SN/A 1152332SN/A // Check if any recent PC changes match up with anything we 1162332SN/A // expect to happen. This is mostly to check if traps or 1172332SN/A // PC-based events have occurred in both the checker and CPU. 1182315SN/A if (changedPC) { 1192315SN/A DPRINTF(Checker, "Changed PC recently to %#x\n", 1202683SN/A thread->readPC()); 1212315SN/A if (willChangePC) { 1222683SN/A if (newPC == thread->readPC()) { 1232315SN/A DPRINTF(Checker, "Changed PC matches expected PC\n"); 1242315SN/A } else { 1252332SN/A warn("%lli: Changed PC does not match expected PC, " 1262332SN/A "changed: %#x, expected: %#x", 1277823Ssteve.reinhardt@amd.com curTick(), thread->readPC(), newPC); 1282732SN/A CheckerCPU::handleError(); 1292315SN/A } 1302315SN/A willChangePC = false; 1312315SN/A } 1322315SN/A changedPC = false; 1332315SN/A } 1342315SN/A if (changedNextPC) { 1352315SN/A DPRINTF(Checker, "Changed NextPC recently to %#x\n", 1362683SN/A thread->readNextPC()); 1372315SN/A changedNextPC = false; 1382315SN/A } 1392315SN/A 1402332SN/A // Try to fetch the instruction 1412332SN/A 1428793Sgblack@eecs.umich.edu#define IFETCH_FLAGS(pc) (FullSystem ? 0 : ((pc) & 1) ? PHYSICAL : 0) 1432332SN/A 1442683SN/A uint64_t fetch_PC = thread->readPC() & ~3; 1452679SN/A 1462332SN/A // set up memory request for instruction fetch 1472679SN/A memReq = new Request(inst->threadNumber, fetch_PC, 1482679SN/A sizeof(uint32_t), 1492683SN/A IFETCH_FLAGS(thread->readPC()), 1505714Shsul@eecs.umich.edu fetch_PC, thread->contextId(), 1515714Shsul@eecs.umich.edu inst->threadNumber); 1522315SN/A 1535891Sgblack@eecs.umich.edu bool succeeded = itb->translateAtomic(memReq, thread); 1542315SN/A 1552315SN/A if (!succeeded) { 1562323SN/A if (inst->getFault() == NoFault) { 1572332SN/A // In this case the instruction was not a dummy 1582332SN/A // instruction carrying an ITB fault. In the single 1592332SN/A // threaded case the ITB should still be able to 1602332SN/A // translate this instruction; in the SMT case it's 1612332SN/A // possible that its ITB entry was kicked out. 1622332SN/A warn("%lli: Instruction PC %#x was not found in the ITB!", 1637823Ssteve.reinhardt@amd.com curTick(), thread->readPC()); 1642732SN/A handleError(inst); 1652315SN/A 1662323SN/A // go to the next instruction 1672683SN/A thread->setPC(thread->readNextPC()); 1682683SN/A thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); 1692315SN/A 1702354SN/A break; 1712323SN/A } else { 1722332SN/A // The instruction is carrying an ITB fault. Handle 1732332SN/A // the fault and see if our results match the CPU on 1742332SN/A // the next tick(). 1752323SN/A fault = inst->getFault(); 1762323SN/A } 1772315SN/A } 1782315SN/A 1792323SN/A if (fault == NoFault) { 1803349Sbinkertn@umich.edu PacketPtr pkt = new Packet(memReq, Packet::ReadReq, 1812679SN/A Packet::Broadcast); 1822679SN/A 1832679SN/A pkt->dataStatic(&machInst); 1842679SN/A 1852679SN/A icachePort->sendFunctional(pkt); 1862679SN/A 1872679SN/A delete pkt; 1882315SN/A 1892332SN/A // keep an instruction count 1902323SN/A numInst++; 1912315SN/A 1922323SN/A // decode the instruction 1932323SN/A machInst = gtoh(machInst); 1942323SN/A // Checks that the instruction matches what we expected it to be. 1952323SN/A // Checks both the machine instruction and the PC. 1962323SN/A validateInst(inst); 1972315SN/A 1983484Sktlim@umich.edu#if THE_ISA == ALPHA_ISA 1993484Sktlim@umich.edu curStaticInst = StaticInst::decode(makeExtMI(machInst, 2003484Sktlim@umich.edu thread->readPC())); 2013484Sktlim@umich.edu#elif THE_ISA == SPARC_ISA 2022332SN/A curStaticInst = StaticInst::decode(makeExtMI(machInst, 2033120Sgblack@eecs.umich.edu thread->getTC())); 2043484Sktlim@umich.edu#endif 2052315SN/A 2062323SN/A fault = inst->getFault(); 2072323SN/A } 2082315SN/A 2092679SN/A // Discard fetch's memReq. 2102679SN/A delete memReq; 2112679SN/A memReq = NULL; 2122679SN/A 2132315SN/A // Either the instruction was a fault and we should process the fault, 2142315SN/A // or we should just go ahead execute the instruction. This assumes 2152315SN/A // that the instruction is properly marked as a fault. 2162315SN/A if (fault == NoFault) { 2172315SN/A 2182683SN/A thread->funcExeInst++; 2192315SN/A 2202354SN/A if (!inst->isUnverifiable()) 2212354SN/A fault = curStaticInst->execute(this, NULL); 2222315SN/A 2232315SN/A // Checks to make sure instrution results are correct. 2242315SN/A validateExecution(inst); 2252315SN/A 2262315SN/A if (curStaticInst->isLoad()) { 2272315SN/A ++numLoad; 2282315SN/A } 2292315SN/A } 2302315SN/A 2312315SN/A if (fault != NoFault) { 2327678Sgblack@eecs.umich.edu fault->invoke(tc, curStaticInst); 2332315SN/A willChangePC = true; 2342683SN/A newPC = thread->readPC(); 2352315SN/A DPRINTF(Checker, "Fault, PC is now %#x\n", newPC); 2362315SN/A } else { 2372315SN/A#if THE_ISA != MIPS_ISA 2382315SN/A // go to the next instruction 2392683SN/A thread->setPC(thread->readNextPC()); 2402683SN/A thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); 2412315SN/A#else 2422315SN/A // go to the next instruction 2432683SN/A thread->setPC(thread->readNextPC()); 2442683SN/A thread->setNextPC(thread->readNextNPC()); 2452683SN/A thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); 2462315SN/A#endif 2472315SN/A 2482315SN/A } 2492315SN/A 2508793Sgblack@eecs.umich.edu if (FullSystem) { 2518793Sgblack@eecs.umich.edu // @todo: Determine if these should happen only if the 2528793Sgblack@eecs.umich.edu // instruction hasn't faulted. In the SimpleCPU case this may 2538793Sgblack@eecs.umich.edu // not be true, but in the O3 or Ozone case this may be true. 2548793Sgblack@eecs.umich.edu Addr oldpc; 2558793Sgblack@eecs.umich.edu int count = 0; 2568793Sgblack@eecs.umich.edu do { 2578793Sgblack@eecs.umich.edu oldpc = thread->readPC(); 2588793Sgblack@eecs.umich.edu system->pcEventQueue.service(tc); 2598793Sgblack@eecs.umich.edu count++; 2608793Sgblack@eecs.umich.edu } while (oldpc != thread->readPC()); 2618793Sgblack@eecs.umich.edu if (count > 1) { 2628793Sgblack@eecs.umich.edu willChangePC = true; 2638793Sgblack@eecs.umich.edu newPC = thread->readPC(); 2648793Sgblack@eecs.umich.edu DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC); 2658793Sgblack@eecs.umich.edu } 2662315SN/A } 2672315SN/A 2682332SN/A // @todo: Optionally can check all registers. (Or just those 2692315SN/A // that have been modified). 2702315SN/A validateState(); 2712315SN/A 2722679SN/A if (memReq) { 2732679SN/A delete memReq; 2742679SN/A memReq = NULL; 2752679SN/A } 2762679SN/A 2772332SN/A // Continue verifying instructions if there's another completed 2782332SN/A // instruction waiting to be verified. 2792315SN/A if (instList.empty()) { 2802315SN/A break; 2812315SN/A } else if (instList.front()->isCompleted()) { 2822315SN/A inst = instList.front(); 2832315SN/A instList.pop_front(); 2842315SN/A } else { 2852315SN/A break; 2862315SN/A } 2872315SN/A } 2882354SN/A unverifiedInst = NULL; 2892315SN/A} 2902315SN/A 2912315SN/Atemplate <class DynInstPtr> 2922315SN/Avoid 2932840Sktlim@umich.eduChecker<DynInstPtr>::switchOut() 2942315SN/A{ 2952315SN/A instList.clear(); 2962315SN/A} 2972315SN/A 2982315SN/Atemplate <class DynInstPtr> 2992315SN/Avoid 3002315SN/AChecker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU) 3012315SN/A{ 3022315SN/A} 3032315SN/A 3042315SN/Atemplate <class DynInstPtr> 3052315SN/Avoid 3062315SN/AChecker<DynInstPtr>::validateInst(DynInstPtr &inst) 3072315SN/A{ 3082683SN/A if (inst->readPC() != thread->readPC()) { 3092332SN/A warn("%lli: PCs do not match! Inst: %#x, checker: %#x", 3107823Ssteve.reinhardt@amd.com curTick(), inst->readPC(), thread->readPC()); 3112315SN/A if (changedPC) { 3122332SN/A warn("%lli: Changed PCs recently, may not be an error", 3137823Ssteve.reinhardt@amd.com curTick()); 3142315SN/A } else { 3152732SN/A handleError(inst); 3162315SN/A } 3172315SN/A } 3182315SN/A 3192332SN/A MachInst mi = static_cast<MachInst>(inst->staticInst->machInst); 3202332SN/A 3212332SN/A if (mi != machInst) { 3222332SN/A warn("%lli: Binary instructions do not match! Inst: %#x, " 3232332SN/A "checker: %#x", 3247823Ssteve.reinhardt@amd.com curTick(), mi, machInst); 3252732SN/A handleError(inst); 3262315SN/A } 3272315SN/A} 3282315SN/A 3292315SN/Atemplate <class DynInstPtr> 3302315SN/Avoid 3312315SN/AChecker<DynInstPtr>::validateExecution(DynInstPtr &inst) 3322315SN/A{ 3332732SN/A bool result_mismatch = false; 3342315SN/A if (inst->numDestRegs()) { 3352332SN/A // @todo: Support more destination registers. 3362315SN/A if (inst->isUnverifiable()) { 3372332SN/A // Unverifiable instructions assume they were executed 3382332SN/A // properly by the CPU. Grab the result from the 3392332SN/A // instruction and write it to the register. 3402732SN/A copyResult(inst); 3412315SN/A } else if (result.integer != inst->readIntResult()) { 3422732SN/A result_mismatch = true; 3432732SN/A } 3442732SN/A } 3452732SN/A 3462732SN/A if (result_mismatch) { 3472732SN/A warn("%lli: Instruction results do not match! (Values may not " 3482732SN/A "actually be integers) Inst: %#x, checker: %#x", 3497823Ssteve.reinhardt@amd.com curTick(), inst->readIntResult(), result.integer); 3502732SN/A 3512732SN/A // It's useful to verify load values from memory, but in MP 3522732SN/A // systems the value obtained at execute may be different than 3532732SN/A // the value obtained at completion. Similarly DMA can 3542732SN/A // present the same problem on even UP systems. Thus there is 3552732SN/A // the option to only warn on loads having a result error. 3562732SN/A if (inst->isLoad() && warnOnlyOnLoadError) { 3572732SN/A copyResult(inst); 3582732SN/A } else { 3592732SN/A handleError(inst); 3602315SN/A } 3612315SN/A } 3622315SN/A 3632683SN/A if (inst->readNextPC() != thread->readNextPC()) { 3642332SN/A warn("%lli: Instruction next PCs do not match! Inst: %#x, " 3652332SN/A "checker: %#x", 3667823Ssteve.reinhardt@amd.com curTick(), inst->readNextPC(), thread->readNextPC()); 3672732SN/A handleError(inst); 3682315SN/A } 3692315SN/A 3702315SN/A // Checking side effect registers can be difficult if they are not 3712315SN/A // checked simultaneously with the execution of the instruction. 3722315SN/A // This is because other valid instructions may have modified 3732315SN/A // these registers in the meantime, and their values are not 3742315SN/A // stored within the DynInst. 3752315SN/A while (!miscRegIdxs.empty()) { 3762315SN/A int misc_reg_idx = miscRegIdxs.front(); 3772315SN/A miscRegIdxs.pop(); 3782315SN/A 3794172Ssaidi@eecs.umich.edu if (inst->tcBase()->readMiscRegNoEffect(misc_reg_idx) != 3804172Ssaidi@eecs.umich.edu thread->readMiscRegNoEffect(misc_reg_idx)) { 3812332SN/A warn("%lli: Misc reg idx %i (side effect) does not match! " 3822332SN/A "Inst: %#x, checker: %#x", 3837823Ssteve.reinhardt@amd.com curTick(), misc_reg_idx, 3844172Ssaidi@eecs.umich.edu inst->tcBase()->readMiscRegNoEffect(misc_reg_idx), 3854172Ssaidi@eecs.umich.edu thread->readMiscRegNoEffect(misc_reg_idx)); 3862732SN/A handleError(inst); 3872315SN/A } 3882315SN/A } 3892315SN/A} 3902315SN/A 3912315SN/Atemplate <class DynInstPtr> 3922315SN/Avoid 3932315SN/AChecker<DynInstPtr>::validateState() 3942315SN/A{ 3952354SN/A if (updateThisCycle) { 3962354SN/A warn("%lli: Instruction PC %#x results didn't match up, copying all " 3977823Ssteve.reinhardt@amd.com "registers from main CPU", curTick(), unverifiedInst->readPC()); 3982354SN/A // Heavy-weight copying of all registers 3993126Sktlim@umich.edu thread->copyArchRegs(unverifiedInst->tcBase()); 4002356SN/A // Also advance the PC. Hopefully no PC-based events happened. 4012356SN/A#if THE_ISA != MIPS_ISA 4022356SN/A // go to the next instruction 4033126Sktlim@umich.edu thread->setPC(thread->readNextPC()); 4043126Sktlim@umich.edu thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); 4052356SN/A#else 4062356SN/A // go to the next instruction 4073126Sktlim@umich.edu thread->setPC(thread->readNextPC()); 4083126Sktlim@umich.edu thread->setNextPC(thread->readNextNPC()); 4093126Sktlim@umich.edu thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); 4102356SN/A#endif 4112354SN/A updateThisCycle = false; 4123126Sktlim@umich.edu } 4132315SN/A} 4142315SN/A 4152315SN/Atemplate <class DynInstPtr> 4162315SN/Avoid 4172732SN/AChecker<DynInstPtr>::copyResult(DynInstPtr &inst) 4182732SN/A{ 4192732SN/A RegIndex idx = inst->destRegIdx(0); 4202732SN/A if (idx < TheISA::FP_Base_DepTag) { 4212732SN/A thread->setIntReg(idx, inst->readIntResult()); 4222732SN/A } else if (idx < TheISA::Fpcr_DepTag) { 4232732SN/A thread->setFloatRegBits(idx, inst->readIntResult()); 4242732SN/A } else { 4254172Ssaidi@eecs.umich.edu thread->setMiscRegNoEffect(idx, inst->readIntResult()); 4262732SN/A } 4272732SN/A} 4282732SN/A 4292732SN/Atemplate <class DynInstPtr> 4302732SN/Avoid 4312732SN/AChecker<DynInstPtr>::dumpAndExit(DynInstPtr &inst) 4322732SN/A{ 4332732SN/A cprintf("Error detected, instruction information:\n"); 4342732SN/A cprintf("PC:%#x, nextPC:%#x\n[sn:%lli]\n[tid:%i]\n" 4352732SN/A "Completed:%i\n", 4362732SN/A inst->readPC(), 4372732SN/A inst->readNextPC(), 4382732SN/A inst->seqNum, 4392732SN/A inst->threadNumber, 4402732SN/A inst->isCompleted()); 4412732SN/A inst->dump(); 4422732SN/A CheckerCPU::dumpAndExit(); 4432732SN/A} 4442732SN/A 4452732SN/Atemplate <class DynInstPtr> 4462732SN/Avoid 4472315SN/AChecker<DynInstPtr>::dumpInsts() 4482315SN/A{ 4492315SN/A int num = 0; 4502315SN/A 4512315SN/A InstListIt inst_list_it = --(instList.end()); 4522315SN/A 4532315SN/A cprintf("Inst list size: %i\n", instList.size()); 4542315SN/A 4552315SN/A while (inst_list_it != instList.end()) 4562315SN/A { 4572315SN/A cprintf("Instruction:%i\n", 4582315SN/A num); 4592315SN/A 4602315SN/A cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" 4612315SN/A "Completed:%i\n", 4622315SN/A (*inst_list_it)->readPC(), 4632315SN/A (*inst_list_it)->seqNum, 4642315SN/A (*inst_list_it)->threadNumber, 4652315SN/A (*inst_list_it)->isCompleted()); 4662315SN/A 4672315SN/A cprintf("\n"); 4682315SN/A 4692315SN/A inst_list_it--; 4702315SN/A ++num; 4712315SN/A } 4722315SN/A 4732315SN/A} 474