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