cpu_impl.hh revision 8887
1/* 2 * Copyright (c) 2011 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2006 The Regents of The University of Michigan 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Kevin Lim 41 * Geoffrey Blake 42 */ 43 44#include <list> 45#include <string> 46 47#include "arch/vtophys.hh" 48#include "base/refcnt.hh" 49#include "config/the_isa.hh" 50#include "cpu/base_dyn_inst.hh" 51#include "cpu/exetrace.hh" 52#include "cpu/simple_thread.hh" 53#include "cpu/static_inst.hh" 54#include "cpu/thread_context.hh" 55#include "cpu/checker/cpu.hh" 56#include "debug/Checker.hh" 57#include "sim/full_system.hh" 58#include "sim/sim_object.hh" 59#include "sim/stats.hh" 60 61using namespace std; 62using namespace TheISA; 63 64template <class Impl> 65void 66Checker<Impl>::advancePC(Fault fault) 67{ 68 if (fault != NoFault) { 69 curMacroStaticInst = StaticInst::nullStaticInstPtr; 70 fault->invoke(tc, curStaticInst); 71 predecoder.reset(); 72 } else { 73 if (curStaticInst) { 74 if (curStaticInst->isLastMicroop()) 75 curMacroStaticInst = StaticInst::nullStaticInstPtr; 76 TheISA::PCState pcState = thread->pcState(); 77 TheISA::advancePC(pcState, curStaticInst); 78 thread->pcState(pcState); 79 DPRINTF(Checker, "Advancing PC to %s.\n", thread->pcState()); 80 } 81 } 82} 83////////////////////////////////////////////////// 84 85template <class Impl> 86void 87Checker<Impl>::handlePendingInt() 88{ 89 DPRINTF(Checker, "IRQ detected at PC: %s with %d insts in buffer\n", 90 thread->pcState(), instList.size()); 91 DynInstPtr boundaryInst = NULL; 92 if (!instList.empty()) { 93 // Set the instructions as completed and verify as much as possible. 94 DynInstPtr inst; 95 typename std::list<DynInstPtr>::iterator itr; 96 97 for (itr = instList.begin(); itr != instList.end(); itr++) { 98 (*itr)->setCompleted(); 99 } 100 101 inst = instList.front(); 102 boundaryInst = instList.back(); 103 verify(inst); // verify the instructions 104 inst = NULL; 105 } 106 if ((!boundaryInst && curMacroStaticInst && 107 curStaticInst->isDelayedCommit() && 108 !curStaticInst->isLastMicroop()) || 109 (boundaryInst && boundaryInst->isDelayedCommit() && 110 !boundaryInst->isLastMicroop())) { 111 panic("%lli: Trying to take an interrupt in middle of " 112 "a non-interuptable instruction!", curTick()); 113 } 114 boundaryInst = NULL; 115 predecoder.reset(); 116 curMacroStaticInst = StaticInst::nullStaticInstPtr; 117} 118 119template <class Impl> 120void 121Checker<Impl>::verify(DynInstPtr &completed_inst) 122{ 123 DynInstPtr inst; 124 125 // Make sure serializing instructions are actually 126 // seen as serializing to commit. instList should be 127 // empty in these cases. 128 if ((completed_inst->isSerializing() || 129 completed_inst->isSerializeBefore()) && 130 (!instList.empty() ? 131 (instList.front()->seqNum != completed_inst->seqNum) : 0)) { 132 panic("%lli: Instruction sn:%lli at PC %s is serializing before but is" 133 " entering instList with other instructions\n", curTick(), 134 completed_inst->seqNum, completed_inst->pcState()); 135 } 136 137 // Either check this instruction, or add it to a list of 138 // instructions waiting to be checked. Instructions must be 139 // checked in program order, so if a store has committed yet not 140 // completed, there may be some instructions that are waiting 141 // behind it that have completed and must be checked. 142 if (!instList.empty()) { 143 if (youngestSN < completed_inst->seqNum) { 144 DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%s to list\n", 145 completed_inst->seqNum, completed_inst->pcState()); 146 instList.push_back(completed_inst); 147 youngestSN = completed_inst->seqNum; 148 } 149 150 if (!instList.front()->isCompleted()) { 151 return; 152 } else { 153 inst = instList.front(); 154 instList.pop_front(); 155 } 156 } else { 157 if (!completed_inst->isCompleted()) { 158 if (youngestSN < completed_inst->seqNum) { 159 DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%s to list\n", 160 completed_inst->seqNum, completed_inst->pcState()); 161 instList.push_back(completed_inst); 162 youngestSN = completed_inst->seqNum; 163 } 164 return; 165 } else { 166 if (youngestSN < completed_inst->seqNum) { 167 inst = completed_inst; 168 youngestSN = completed_inst->seqNum; 169 } else { 170 return; 171 } 172 } 173 } 174 175 // Make sure a serializing instruction is actually seen as 176 // serializing. instList should be empty here 177 if (inst->isSerializeAfter() && !instList.empty()) { 178 panic("%lli: Instruction sn:%lli at PC %s is serializing after but is" 179 " exiting instList with other instructions\n", curTick(), 180 completed_inst->seqNum, completed_inst->pcState()); 181 } 182 unverifiedInst = inst; 183 inst = NULL; 184 185 // Try to check all instructions that are completed, ending if we 186 // run out of instructions to check or if an instruction is not 187 // yet completed. 188 while (1) { 189 DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%s.\n", 190 unverifiedInst->seqNum, unverifiedInst->pcState()); 191 unverifiedReq = NULL; 192 unverifiedReq = unverifiedInst->reqToVerify; 193 unverifiedMemData = unverifiedInst->memData; 194 // Make sure results queue is empty 195 while (!result.empty()) { 196 result.pop(); 197 } 198 numCycles++; 199 200 Fault fault = NoFault; 201 202 // maintain $r0 semantics 203 thread->setIntReg(ZeroReg, 0); 204#ifdef TARGET_ALPHA 205 thread->setFloatRegDouble(ZeroReg, 0.0); 206#endif // TARGET_ALPHA 207 208 // Check if any recent PC changes match up with anything we 209 // expect to happen. This is mostly to check if traps or 210 // PC-based events have occurred in both the checker and CPU. 211 if (changedPC) { 212 DPRINTF(Checker, "Changed PC recently to %s\n", 213 thread->pcState()); 214 if (willChangePC) { 215 if (newPCState == thread->pcState()) { 216 DPRINTF(Checker, "Changed PC matches expected PC\n"); 217 } else { 218 warn("%lli: Changed PC does not match expected PC, " 219 "changed: %s, expected: %s", 220 curTick(), thread->pcState(), newPCState); 221 CheckerCPU::handleError(); 222 } 223 willChangePC = false; 224 } 225 changedPC = false; 226 } 227 if (changedNextPC) { 228 DPRINTF(Checker, "Changed NextPC recently to %#x\n", 229 thread->nextInstAddr()); 230 changedNextPC = false; 231 } 232 233 // Try to fetch the instruction 234 uint64_t fetchOffset = 0; 235 bool fetchDone = false; 236 237 while (!fetchDone) { 238 Addr fetch_PC = thread->instAddr(); 239 fetch_PC = (fetch_PC & PCMask) + fetchOffset; 240 241 // If not in the middle of a macro instruction 242 if (!curMacroStaticInst) { 243 // set up memory request for instruction fetch 244 memReq = new Request(unverifiedInst->threadNumber, fetch_PC, 245 sizeof(MachInst), 246 0, 247 masterId, 248 fetch_PC, thread->contextId(), 249 unverifiedInst->threadNumber); 250 memReq->setVirt(0, fetch_PC, sizeof(MachInst), 251 Request::INST_FETCH, masterId, thread->instAddr()); 252 253 254 fault = itb->translateFunctional(memReq, tc, BaseTLB::Execute); 255 256 if (fault != NoFault) { 257 if (unverifiedInst->getFault() == NoFault) { 258 // In this case the instruction was not a dummy 259 // instruction carrying an ITB fault. In the single 260 // threaded case the ITB should still be able to 261 // translate this instruction; in the SMT case it's 262 // possible that its ITB entry was kicked out. 263 warn("%lli: Instruction PC %s was not found in the " 264 "ITB!", curTick(), thread->pcState()); 265 handleError(unverifiedInst); 266 267 // go to the next instruction 268 advancePC(NoFault); 269 270 // Give up on an ITB fault.. 271 delete memReq; 272 unverifiedInst = NULL; 273 return; 274 } else { 275 // The instruction is carrying an ITB fault. Handle 276 // the fault and see if our results match the CPU on 277 // the next tick(). 278 fault = unverifiedInst->getFault(); 279 delete memReq; 280 break; 281 } 282 } else { 283 PacketPtr pkt = new Packet(memReq, 284 MemCmd::ReadReq, 285 Packet::Broadcast); 286 287 pkt->dataStatic(&machInst); 288 icachePort->sendFunctional(pkt); 289 machInst = gtoh(machInst); 290 291 delete memReq; 292 delete pkt; 293 } 294 } 295 296 if (fault == NoFault) { 297 TheISA::PCState pcState = thread->pcState(); 298 299 if (isRomMicroPC(pcState.microPC())) { 300 fetchDone = true; 301 curStaticInst = 302 microcodeRom.fetchMicroop(pcState.microPC(), NULL); 303 } else if (!curMacroStaticInst) { 304 //We're not in the middle of a macro instruction 305 StaticInstPtr instPtr = NULL; 306 307 //Predecode, ie bundle up an ExtMachInst 308 predecoder.setTC(thread->getTC()); 309 //If more fetch data is needed, pass it in. 310 Addr fetchPC = (pcState.instAddr() & PCMask) + fetchOffset; 311 predecoder.moreBytes(pcState, fetchPC, machInst); 312 313 //If an instruction is ready, decode it. 314 //Otherwise, we'll have to fetch beyond the 315 //MachInst at the current pc. 316 if (predecoder.extMachInstReady()) { 317 fetchDone = true; 318 ExtMachInst newMachInst = 319 predecoder.getExtMachInst(pcState); 320 thread->pcState(pcState); 321 instPtr = thread->decoder.decode(newMachInst, 322 pcState.instAddr()); 323 machInst = newMachInst; 324 } else { 325 fetchDone = false; 326 fetchOffset += sizeof(TheISA::MachInst); 327 } 328 329 //If we decoded an instruction and it's microcoded, 330 //start pulling out micro ops 331 if (instPtr && instPtr->isMacroop()) { 332 curMacroStaticInst = instPtr; 333 curStaticInst = 334 instPtr->fetchMicroop(pcState.microPC()); 335 } else { 336 curStaticInst = instPtr; 337 } 338 } else { 339 // Read the next micro op from the macro-op 340 curStaticInst = 341 curMacroStaticInst->fetchMicroop(pcState.microPC()); 342 fetchDone = true; 343 } 344 } 345 } 346 // reset predecoder on Checker 347 predecoder.reset(); 348 349 // Check Checker and CPU get same instruction, and record 350 // any faults the CPU may have had. 351 Fault unverifiedFault; 352 if (fault == NoFault) { 353 unverifiedFault = unverifiedInst->getFault(); 354 355 // Checks that the instruction matches what we expected it to be. 356 // Checks both the machine instruction and the PC. 357 validateInst(unverifiedInst); 358 } 359 360 // keep an instruction count 361 numInst++; 362 363 364 // Either the instruction was a fault and we should process the fault, 365 // or we should just go ahead execute the instruction. This assumes 366 // that the instruction is properly marked as a fault. 367 if (fault == NoFault) { 368 // Execute Checker instruction and trace 369 if (!unverifiedInst->isUnverifiable()) { 370 Trace::InstRecord *traceData = tracer->getInstRecord(curTick(), 371 tc, 372 curStaticInst, 373 pcState(), 374 curMacroStaticInst); 375 fault = curStaticInst->execute(this, traceData); 376 if (traceData) { 377 traceData->dump(); 378 delete traceData; 379 } 380 } 381 382 if (fault == NoFault && unverifiedFault == NoFault) { 383 thread->funcExeInst++; 384 // Checks to make sure instrution results are correct. 385 validateExecution(unverifiedInst); 386 387 if (curStaticInst->isLoad()) { 388 ++numLoad; 389 } 390 } else if (fault != NoFault && unverifiedFault == NoFault) { 391 panic("%lli: sn: %lli at PC: %s took a fault in checker " 392 "but not in driver CPU\n", curTick(), 393 unverifiedInst->seqNum, unverifiedInst->pcState()); 394 } else if (fault == NoFault && unverifiedFault != NoFault) { 395 panic("%lli: sn: %lli at PC: %s took a fault in driver " 396 "CPU but not in checker\n", curTick(), 397 unverifiedInst->seqNum, unverifiedInst->pcState()); 398 } 399 } 400 401 // Take any faults here 402 if (fault != NoFault) { 403 if (FullSystem) { 404 fault->invoke(tc, curStaticInst); 405 willChangePC = true; 406 newPCState = thread->pcState(); 407 DPRINTF(Checker, "Fault, PC is now %s\n", newPCState); 408 curMacroStaticInst = StaticInst::nullStaticInstPtr; 409 } 410 } else { 411 advancePC(fault); 412 } 413 414 if (FullSystem) { 415 // @todo: Determine if these should happen only if the 416 // instruction hasn't faulted. In the SimpleCPU case this may 417 // not be true, but in the O3 or Ozone case this may be true. 418 Addr oldpc; 419 int count = 0; 420 do { 421 oldpc = thread->instAddr(); 422 system->pcEventQueue.service(tc); 423 count++; 424 } while (oldpc != thread->instAddr()); 425 if (count > 1) { 426 willChangePC = true; 427 newPCState = thread->pcState(); 428 DPRINTF(Checker, "PC Event, PC is now %s\n", newPCState); 429 } 430 } 431 432 // @todo: Optionally can check all registers. (Or just those 433 // that have been modified). 434 validateState(); 435 436 // Continue verifying instructions if there's another completed 437 // instruction waiting to be verified. 438 if (instList.empty()) { 439 break; 440 } else if (instList.front()->isCompleted()) { 441 unverifiedInst = NULL; 442 unverifiedInst = instList.front(); 443 instList.pop_front(); 444 } else { 445 break; 446 } 447 } 448 unverifiedInst = NULL; 449} 450 451template <class Impl> 452void 453Checker<Impl>::switchOut() 454{ 455 instList.clear(); 456} 457 458template <class Impl> 459void 460Checker<Impl>::takeOverFrom(BaseCPU *oldCPU) 461{ 462} 463 464template <class Impl> 465void 466Checker<Impl>::validateInst(DynInstPtr &inst) 467{ 468 if (inst->instAddr() != thread->instAddr()) { 469 warn("%lli: PCs do not match! Inst: %s, checker: %s", 470 curTick(), inst->pcState(), thread->pcState()); 471 if (changedPC) { 472 warn("%lli: Changed PCs recently, may not be an error", 473 curTick()); 474 } else { 475 handleError(inst); 476 } 477 } 478 479 MachInst mi = static_cast<MachInst>(inst->staticInst->machInst); 480 481 if (mi != machInst) { 482 panic("%lli: Binary instructions do not match! Inst: %#x, " 483 "checker: %#x", 484 curTick(), mi, machInst); 485 handleError(inst); 486 } 487} 488 489template <class Impl> 490void 491Checker<Impl>::validateExecution(DynInstPtr &inst) 492{ 493 uint64_t checker_val; 494 uint64_t inst_val; 495 int idx = -1; 496 bool result_mismatch = false; 497 498 if (inst->isUnverifiable()) { 499 // Unverifiable instructions assume they were executed 500 // properly by the CPU. Grab the result from the 501 // instruction and write it to the register. 502 copyResult(inst, 0, idx); 503 } else if (inst->numDestRegs() > 0 && !result.empty()) { 504 DPRINTF(Checker, "Dest regs %d, number of checker dest regs %d\n", 505 inst->numDestRegs(), result.size()); 506 for (int i = 0; i < inst->numDestRegs() && !result.empty(); i++) { 507 result.front().get(checker_val); 508 result.pop(); 509 inst_val = 0; 510 inst->template popResult<uint64_t>(inst_val); 511 if (checker_val != inst_val) { 512 result_mismatch = true; 513 idx = i; 514 break; 515 } 516 } 517 } // Checker CPU checks all the saved results in the dyninst passed by 518 // the cpu model being checked against the saved results present in 519 // the static inst executed in the Checker. Sometimes the number 520 // of saved results differs between the dyninst and static inst, but 521 // this is ok and not a bug. May be worthwhile to try and correct this. 522 523 if (result_mismatch) { 524 warn("%lli: Instruction results do not match! (Values may not " 525 "actually be integers) Inst: %#x, checker: %#x", 526 curTick(), inst_val, checker_val); 527 528 // It's useful to verify load values from memory, but in MP 529 // systems the value obtained at execute may be different than 530 // the value obtained at completion. Similarly DMA can 531 // present the same problem on even UP systems. Thus there is 532 // the option to only warn on loads having a result error. 533 // The load/store queue in Detailed CPU can also cause problems 534 // if load/store forwarding is allowed. 535 if (inst->isLoad() && warnOnlyOnLoadError) { 536 copyResult(inst, inst_val, idx); 537 } else { 538 handleError(inst); 539 } 540 } 541 542 if (inst->nextInstAddr() != thread->nextInstAddr()) { 543 warn("%lli: Instruction next PCs do not match! Inst: %#x, " 544 "checker: %#x", 545 curTick(), inst->nextInstAddr(), thread->nextInstAddr()); 546 handleError(inst); 547 } 548 549 // Checking side effect registers can be difficult if they are not 550 // checked simultaneously with the execution of the instruction. 551 // This is because other valid instructions may have modified 552 // these registers in the meantime, and their values are not 553 // stored within the DynInst. 554 while (!miscRegIdxs.empty()) { 555 int misc_reg_idx = miscRegIdxs.front(); 556 miscRegIdxs.pop(); 557 558 if (inst->tcBase()->readMiscRegNoEffect(misc_reg_idx) != 559 thread->readMiscRegNoEffect(misc_reg_idx)) { 560 warn("%lli: Misc reg idx %i (side effect) does not match! " 561 "Inst: %#x, checker: %#x", 562 curTick(), misc_reg_idx, 563 inst->tcBase()->readMiscRegNoEffect(misc_reg_idx), 564 thread->readMiscRegNoEffect(misc_reg_idx)); 565 handleError(inst); 566 } 567 } 568} 569 570 571// This function is weird, if it is called it means the Checker and 572// O3 have diverged, so panic is called for now. It may be useful 573// to resynch states and continue if the divergence is a false positive 574template <class Impl> 575void 576Checker<Impl>::validateState() 577{ 578 if (updateThisCycle) { 579 // Change this back to warn if divergences end up being false positives 580 panic("%lli: Instruction PC %#x results didn't match up, copying all " 581 "registers from main CPU", curTick(), unverifiedInst->instAddr()); 582 583 // Terribly convoluted way to make sure O3 model does not implode 584 bool inSyscall = unverifiedInst->thread->inSyscall; 585 unverifiedInst->thread->inSyscall = true; 586 587 // Heavy-weight copying of all registers 588 thread->copyArchRegs(unverifiedInst->tcBase()); 589 unverifiedInst->thread->inSyscall = inSyscall; 590 591 // Set curStaticInst to unverifiedInst->staticInst 592 curStaticInst = unverifiedInst->staticInst; 593 // Also advance the PC. Hopefully no PC-based events happened. 594 advancePC(NoFault); 595 updateThisCycle = false; 596 } 597} 598 599template <class Impl> 600void 601Checker<Impl>::copyResult(DynInstPtr &inst, uint64_t mismatch_val, 602 int start_idx) 603{ 604 // We've already popped one dest off the queue, 605 // so do the fix-up then start with the next dest reg; 606 if (start_idx >= 0) { 607 RegIndex idx = inst->destRegIdx(start_idx); 608 if (idx < TheISA::FP_Base_DepTag) { 609 thread->setIntReg(idx, mismatch_val); 610 } else if (idx < TheISA::Ctrl_Base_DepTag) { 611 thread->setFloatRegBits(idx, mismatch_val); 612 } else if (idx < TheISA::Max_DepTag) { 613 thread->setMiscReg(idx - TheISA::Ctrl_Base_DepTag, 614 mismatch_val); 615 } 616 } 617 start_idx++; 618 uint64_t res = 0; 619 for (int i = start_idx; i < inst->numDestRegs(); i++) { 620 RegIndex idx = inst->destRegIdx(i); 621 inst->template popResult<uint64_t>(res); 622 if (idx < TheISA::FP_Base_DepTag) { 623 thread->setIntReg(idx, res); 624 } else if (idx < TheISA::Ctrl_Base_DepTag) { 625 thread->setFloatRegBits(idx, res); 626 } else if (idx < TheISA::Max_DepTag) { 627 // Try to get the proper misc register index for ARM here... 628 thread->setMiscReg(idx - TheISA::Ctrl_Base_DepTag, res); 629 } // else Register is out of range... 630 } 631} 632 633template <class Impl> 634void 635Checker<Impl>::dumpAndExit(DynInstPtr &inst) 636{ 637 cprintf("Error detected, instruction information:\n"); 638 cprintf("PC:%s, nextPC:%#x\n[sn:%lli]\n[tid:%i]\n" 639 "Completed:%i\n", 640 inst->pcState(), 641 inst->nextInstAddr(), 642 inst->seqNum, 643 inst->threadNumber, 644 inst->isCompleted()); 645 inst->dump(); 646 CheckerCPU::dumpAndExit(); 647} 648 649template <class Impl> 650void 651Checker<Impl>::dumpInsts() 652{ 653 int num = 0; 654 655 InstListIt inst_list_it = --(instList.end()); 656 657 cprintf("Inst list size: %i\n", instList.size()); 658 659 while (inst_list_it != instList.end()) 660 { 661 cprintf("Instruction:%i\n", 662 num); 663 664 cprintf("PC:%s\n[sn:%lli]\n[tid:%i]\n" 665 "Completed:%i\n", 666 (*inst_list_it)->pcState(), 667 (*inst_list_it)->seqNum, 668 (*inst_list_it)->threadNumber, 669 (*inst_list_it)->isCompleted()); 670 671 cprintf("\n"); 672 673 inst_list_it--; 674 ++num; 675 } 676 677} 678