cpu_impl.hh revision 5891:73084c6bb183
112855Sgabeblack@google.com/* 212855Sgabeblack@google.com * Copyright (c) 2006 The Regents of The University of Michigan 312855Sgabeblack@google.com * All rights reserved. 412855Sgabeblack@google.com * 512855Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 612855Sgabeblack@google.com * modification, are permitted provided that the following conditions are 712855Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 812855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 912855Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 1012855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1112855Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1212855Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1312855Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1412855Sgabeblack@google.com * this software without specific prior written permission. 1512855Sgabeblack@google.com * 1612855Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712855Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812855Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912855Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012855Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112855Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212855Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312855Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412855Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512855Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612855Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712855Sgabeblack@google.com * 2812855Sgabeblack@google.com * Authors: Kevin Lim 2912855Sgabeblack@google.com */ 3012855Sgabeblack@google.com 3112855Sgabeblack@google.com#include <list> 3212855Sgabeblack@google.com#include <string> 3312855Sgabeblack@google.com 3412855Sgabeblack@google.com#include "base/refcnt.hh" 3512855Sgabeblack@google.com#include "cpu/base_dyn_inst.hh" 3612855Sgabeblack@google.com#include "cpu/checker/cpu.hh" 3712855Sgabeblack@google.com#include "cpu/simple_thread.hh" 3812855Sgabeblack@google.com#include "cpu/thread_context.hh" 3912855Sgabeblack@google.com#include "cpu/static_inst.hh" 4012855Sgabeblack@google.com#include "sim/sim_object.hh" 4112855Sgabeblack@google.com#include "sim/stats.hh" 4212855Sgabeblack@google.com 4312855Sgabeblack@google.com#if FULL_SYSTEM 4412855Sgabeblack@google.com#include "arch/vtophys.hh" 4512855Sgabeblack@google.com#endif // FULL_SYSTEM 4612855Sgabeblack@google.com 4712855Sgabeblack@google.comusing namespace std; 4812855Sgabeblack@google.com//The CheckerCPU does alpha only 4912855Sgabeblack@google.comusing namespace AlphaISA; 5012855Sgabeblack@google.com 5112855Sgabeblack@google.comtemplate <class DynInstPtr> 5212855Sgabeblack@google.comvoid 5312855Sgabeblack@google.comChecker<DynInstPtr>::verify(DynInstPtr &completed_inst) 5412855Sgabeblack@google.com{ 5512855Sgabeblack@google.com DynInstPtr inst; 5612855Sgabeblack@google.com 5712855Sgabeblack@google.com // Either check this instruction, or add it to a list of 5812855Sgabeblack@google.com // instructions waiting to be checked. Instructions must be 5912855Sgabeblack@google.com // checked in program order, so if a store has committed yet not 6012855Sgabeblack@google.com // completed, there may be some instructions that are waiting 6112855Sgabeblack@google.com // behind it that have completed and must be checked. 6212855Sgabeblack@google.com if (!instList.empty()) { 6312855Sgabeblack@google.com if (youngestSN < completed_inst->seqNum) { 6412855Sgabeblack@google.com DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n", 6512855Sgabeblack@google.com completed_inst->seqNum, completed_inst->readPC()); 6612855Sgabeblack@google.com instList.push_back(completed_inst); 6712855Sgabeblack@google.com youngestSN = completed_inst->seqNum; 6812855Sgabeblack@google.com } 69 70 if (!instList.front()->isCompleted()) { 71 return; 72 } else { 73 inst = instList.front(); 74 instList.pop_front(); 75 } 76 } else { 77 if (!completed_inst->isCompleted()) { 78 if (youngestSN < completed_inst->seqNum) { 79 DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n", 80 completed_inst->seqNum, completed_inst->readPC()); 81 instList.push_back(completed_inst); 82 youngestSN = completed_inst->seqNum; 83 } 84 return; 85 } else { 86 if (youngestSN < completed_inst->seqNum) { 87 inst = completed_inst; 88 youngestSN = completed_inst->seqNum; 89 } else { 90 return; 91 } 92 } 93 } 94 95 unverifiedInst = inst; 96 97 // Try to check all instructions that are completed, ending if we 98 // run out of instructions to check or if an instruction is not 99 // yet completed. 100 while (1) { 101 DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n", 102 inst->seqNum, inst->readPC()); 103 unverifiedResult.integer = inst->readIntResult(); 104 unverifiedReq = inst->req; 105 unverifiedMemData = inst->memData; 106 numCycles++; 107 108 Fault fault = NoFault; 109 110 // maintain $r0 semantics 111 thread->setIntReg(ZeroReg, 0); 112#ifdef TARGET_ALPHA 113 thread->setFloatRegDouble(ZeroReg, 0.0); 114#endif // TARGET_ALPHA 115 116 // Check if any recent PC changes match up with anything we 117 // expect to happen. This is mostly to check if traps or 118 // PC-based events have occurred in both the checker and CPU. 119 if (changedPC) { 120 DPRINTF(Checker, "Changed PC recently to %#x\n", 121 thread->readPC()); 122 if (willChangePC) { 123 if (newPC == thread->readPC()) { 124 DPRINTF(Checker, "Changed PC matches expected PC\n"); 125 } else { 126 warn("%lli: Changed PC does not match expected PC, " 127 "changed: %#x, expected: %#x", 128 curTick, thread->readPC(), newPC); 129 CheckerCPU::handleError(); 130 } 131 willChangePC = false; 132 } 133 changedPC = false; 134 } 135 if (changedNextPC) { 136 DPRINTF(Checker, "Changed NextPC recently to %#x\n", 137 thread->readNextPC()); 138 changedNextPC = false; 139 } 140 141 // Try to fetch the instruction 142 143#if FULL_SYSTEM 144#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0 145#else 146#define IFETCH_FLAGS(pc) 0 147#endif 148 149 uint64_t fetch_PC = thread->readPC() & ~3; 150 151 // set up memory request for instruction fetch 152 memReq = new Request(inst->threadNumber, fetch_PC, 153 sizeof(uint32_t), 154 IFETCH_FLAGS(thread->readPC()), 155 fetch_PC, thread->contextId(), 156 inst->threadNumber); 157 158 bool succeeded = itb->translateAtomic(memReq, thread); 159 160 if (!succeeded) { 161 if (inst->getFault() == NoFault) { 162 // In this case the instruction was not a dummy 163 // instruction carrying an ITB fault. In the single 164 // threaded case the ITB should still be able to 165 // translate this instruction; in the SMT case it's 166 // possible that its ITB entry was kicked out. 167 warn("%lli: Instruction PC %#x was not found in the ITB!", 168 curTick, thread->readPC()); 169 handleError(inst); 170 171 // go to the next instruction 172 thread->setPC(thread->readNextPC()); 173 thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); 174 175 break; 176 } else { 177 // The instruction is carrying an ITB fault. Handle 178 // the fault and see if our results match the CPU on 179 // the next tick(). 180 fault = inst->getFault(); 181 } 182 } 183 184 if (fault == NoFault) { 185 PacketPtr pkt = new Packet(memReq, Packet::ReadReq, 186 Packet::Broadcast); 187 188 pkt->dataStatic(&machInst); 189 190 icachePort->sendFunctional(pkt); 191 192 delete pkt; 193 194 // keep an instruction count 195 numInst++; 196 197 // decode the instruction 198 machInst = gtoh(machInst); 199 // Checks that the instruction matches what we expected it to be. 200 // Checks both the machine instruction and the PC. 201 validateInst(inst); 202 203#if THE_ISA == ALPHA_ISA 204 curStaticInst = StaticInst::decode(makeExtMI(machInst, 205 thread->readPC())); 206#elif THE_ISA == SPARC_ISA 207 curStaticInst = StaticInst::decode(makeExtMI(machInst, 208 thread->getTC())); 209#endif 210 211#if FULL_SYSTEM 212 thread->setInst(machInst); 213#endif // FULL_SYSTEM 214 215 fault = inst->getFault(); 216 } 217 218 // Discard fetch's memReq. 219 delete memReq; 220 memReq = NULL; 221 222 // Either the instruction was a fault and we should process the fault, 223 // or we should just go ahead execute the instruction. This assumes 224 // that the instruction is properly marked as a fault. 225 if (fault == NoFault) { 226 227 thread->funcExeInst++; 228 229 if (!inst->isUnverifiable()) 230 fault = curStaticInst->execute(this, NULL); 231 232 // Checks to make sure instrution results are correct. 233 validateExecution(inst); 234 235 if (curStaticInst->isLoad()) { 236 ++numLoad; 237 } 238 } 239 240 if (fault != NoFault) { 241#if FULL_SYSTEM 242 fault->invoke(tc); 243 willChangePC = true; 244 newPC = thread->readPC(); 245 DPRINTF(Checker, "Fault, PC is now %#x\n", newPC); 246#endif 247 } else { 248#if THE_ISA != MIPS_ISA 249 // go to the next instruction 250 thread->setPC(thread->readNextPC()); 251 thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); 252#else 253 // go to the next instruction 254 thread->setPC(thread->readNextPC()); 255 thread->setNextPC(thread->readNextNPC()); 256 thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); 257#endif 258 259 } 260 261#if FULL_SYSTEM 262 // @todo: Determine if these should happen only if the 263 // instruction hasn't faulted. In the SimpleCPU case this may 264 // not be true, but in the O3 or Ozone case this may be true. 265 Addr oldpc; 266 int count = 0; 267 do { 268 oldpc = thread->readPC(); 269 system->pcEventQueue.service(tc); 270 count++; 271 } while (oldpc != thread->readPC()); 272 if (count > 1) { 273 willChangePC = true; 274 newPC = thread->readPC(); 275 DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC); 276 } 277#endif 278 279 // @todo: Optionally can check all registers. (Or just those 280 // that have been modified). 281 validateState(); 282 283 if (memReq) { 284 delete memReq; 285 memReq = NULL; 286 } 287 288 // Continue verifying instructions if there's another completed 289 // instruction waiting to be verified. 290 if (instList.empty()) { 291 break; 292 } else if (instList.front()->isCompleted()) { 293 inst = instList.front(); 294 instList.pop_front(); 295 } else { 296 break; 297 } 298 } 299 unverifiedInst = NULL; 300} 301 302template <class DynInstPtr> 303void 304Checker<DynInstPtr>::switchOut() 305{ 306 instList.clear(); 307} 308 309template <class DynInstPtr> 310void 311Checker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU) 312{ 313} 314 315template <class DynInstPtr> 316void 317Checker<DynInstPtr>::validateInst(DynInstPtr &inst) 318{ 319 if (inst->readPC() != thread->readPC()) { 320 warn("%lli: PCs do not match! Inst: %#x, checker: %#x", 321 curTick, inst->readPC(), thread->readPC()); 322 if (changedPC) { 323 warn("%lli: Changed PCs recently, may not be an error", 324 curTick); 325 } else { 326 handleError(inst); 327 } 328 } 329 330 MachInst mi = static_cast<MachInst>(inst->staticInst->machInst); 331 332 if (mi != machInst) { 333 warn("%lli: Binary instructions do not match! Inst: %#x, " 334 "checker: %#x", 335 curTick, mi, machInst); 336 handleError(inst); 337 } 338} 339 340template <class DynInstPtr> 341void 342Checker<DynInstPtr>::validateExecution(DynInstPtr &inst) 343{ 344 bool result_mismatch = false; 345 if (inst->numDestRegs()) { 346 // @todo: Support more destination registers. 347 if (inst->isUnverifiable()) { 348 // Unverifiable instructions assume they were executed 349 // properly by the CPU. Grab the result from the 350 // instruction and write it to the register. 351 copyResult(inst); 352 } else if (result.integer != inst->readIntResult()) { 353 result_mismatch = true; 354 } 355 } 356 357 if (result_mismatch) { 358 warn("%lli: Instruction results do not match! (Values may not " 359 "actually be integers) Inst: %#x, checker: %#x", 360 curTick, inst->readIntResult(), result.integer); 361 362 // It's useful to verify load values from memory, but in MP 363 // systems the value obtained at execute may be different than 364 // the value obtained at completion. Similarly DMA can 365 // present the same problem on even UP systems. Thus there is 366 // the option to only warn on loads having a result error. 367 if (inst->isLoad() && warnOnlyOnLoadError) { 368 copyResult(inst); 369 } else { 370 handleError(inst); 371 } 372 } 373 374 if (inst->readNextPC() != thread->readNextPC()) { 375 warn("%lli: Instruction next PCs do not match! Inst: %#x, " 376 "checker: %#x", 377 curTick, inst->readNextPC(), thread->readNextPC()); 378 handleError(inst); 379 } 380 381 // Checking side effect registers can be difficult if they are not 382 // checked simultaneously with the execution of the instruction. 383 // This is because other valid instructions may have modified 384 // these registers in the meantime, and their values are not 385 // stored within the DynInst. 386 while (!miscRegIdxs.empty()) { 387 int misc_reg_idx = miscRegIdxs.front(); 388 miscRegIdxs.pop(); 389 390 if (inst->tcBase()->readMiscRegNoEffect(misc_reg_idx) != 391 thread->readMiscRegNoEffect(misc_reg_idx)) { 392 warn("%lli: Misc reg idx %i (side effect) does not match! " 393 "Inst: %#x, checker: %#x", 394 curTick, misc_reg_idx, 395 inst->tcBase()->readMiscRegNoEffect(misc_reg_idx), 396 thread->readMiscRegNoEffect(misc_reg_idx)); 397 handleError(inst); 398 } 399 } 400} 401 402template <class DynInstPtr> 403void 404Checker<DynInstPtr>::validateState() 405{ 406 if (updateThisCycle) { 407 warn("%lli: Instruction PC %#x results didn't match up, copying all " 408 "registers from main CPU", curTick, unverifiedInst->readPC()); 409 // Heavy-weight copying of all registers 410 thread->copyArchRegs(unverifiedInst->tcBase()); 411 // Also advance the PC. Hopefully no PC-based events happened. 412#if THE_ISA != MIPS_ISA 413 // go to the next instruction 414 thread->setPC(thread->readNextPC()); 415 thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); 416#else 417 // go to the next instruction 418 thread->setPC(thread->readNextPC()); 419 thread->setNextPC(thread->readNextNPC()); 420 thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); 421#endif 422 updateThisCycle = false; 423 } 424} 425 426template <class DynInstPtr> 427void 428Checker<DynInstPtr>::copyResult(DynInstPtr &inst) 429{ 430 RegIndex idx = inst->destRegIdx(0); 431 if (idx < TheISA::FP_Base_DepTag) { 432 thread->setIntReg(idx, inst->readIntResult()); 433 } else if (idx < TheISA::Fpcr_DepTag) { 434 thread->setFloatRegBits(idx, inst->readIntResult()); 435 } else { 436 thread->setMiscRegNoEffect(idx, inst->readIntResult()); 437 } 438} 439 440template <class DynInstPtr> 441void 442Checker<DynInstPtr>::dumpAndExit(DynInstPtr &inst) 443{ 444 cprintf("Error detected, instruction information:\n"); 445 cprintf("PC:%#x, nextPC:%#x\n[sn:%lli]\n[tid:%i]\n" 446 "Completed:%i\n", 447 inst->readPC(), 448 inst->readNextPC(), 449 inst->seqNum, 450 inst->threadNumber, 451 inst->isCompleted()); 452 inst->dump(); 453 CheckerCPU::dumpAndExit(); 454} 455 456template <class DynInstPtr> 457void 458Checker<DynInstPtr>::dumpInsts() 459{ 460 int num = 0; 461 462 InstListIt inst_list_it = --(instList.end()); 463 464 cprintf("Inst list size: %i\n", instList.size()); 465 466 while (inst_list_it != instList.end()) 467 { 468 cprintf("Instruction:%i\n", 469 num); 470 471 cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" 472 "Completed:%i\n", 473 (*inst_list_it)->readPC(), 474 (*inst_list_it)->seqNum, 475 (*inst_list_it)->threadNumber, 476 (*inst_list_it)->isCompleted()); 477 478 cprintf("\n"); 479 480 inst_list_it--; 481 ++num; 482 } 483 484} 485