decode_impl.hh revision 2348
1/* 2 * Copyright (c) 2004-2006 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include "cpu/o3/decode.hh" 30 31using namespace std; 32 33template<class Impl> 34DefaultDecode<Impl>::DefaultDecode(Params *params) 35 : renameToDecodeDelay(params->renameToDecodeDelay), 36 iewToDecodeDelay(params->iewToDecodeDelay), 37 commitToDecodeDelay(params->commitToDecodeDelay), 38 fetchToDecodeDelay(params->fetchToDecodeDelay), 39 decodeWidth(params->decodeWidth), 40 numThreads(params->numberOfThreads) 41{ 42 _status = Inactive; 43 44 // Setup status, make sure stall signals are clear. 45 for (int i = 0; i < numThreads; ++i) { 46 decodeStatus[i] = Idle; 47 48 stalls[i].rename = false; 49 stalls[i].iew = false; 50 stalls[i].commit = false; 51 } 52 53 // @todo: Make into a parameter 54 skidBufferMax = (fetchToDecodeDelay * params->fetchWidth) + decodeWidth; 55} 56 57template <class Impl> 58std::string 59DefaultDecode<Impl>::name() const 60{ 61 return cpu->name() + ".decode"; 62} 63 64template <class Impl> 65void 66DefaultDecode<Impl>::regStats() 67{ 68 decodeIdleCycles 69 .name(name() + ".DECODE:IdleCycles") 70 .desc("Number of cycles decode is idle") 71 .prereq(decodeIdleCycles); 72 decodeBlockedCycles 73 .name(name() + ".DECODE:BlockedCycles") 74 .desc("Number of cycles decode is blocked") 75 .prereq(decodeBlockedCycles); 76 decodeRunCycles 77 .name(name() + ".DECODE:RunCycles") 78 .desc("Number of cycles decode is running") 79 .prereq(decodeRunCycles); 80 decodeUnblockCycles 81 .name(name() + ".DECODE:UnblockCycles") 82 .desc("Number of cycles decode is unblocking") 83 .prereq(decodeUnblockCycles); 84 decodeSquashCycles 85 .name(name() + ".DECODE:SquashCycles") 86 .desc("Number of cycles decode is squashing") 87 .prereq(decodeSquashCycles); 88 decodeBranchResolved 89 .name(name() + ".DECODE:BranchResolved") 90 .desc("Number of times decode resolved a branch") 91 .prereq(decodeBranchResolved); 92 decodeBranchMispred 93 .name(name() + ".DECODE:BranchMispred") 94 .desc("Number of times decode detected a branch misprediction") 95 .prereq(decodeBranchMispred); 96 decodeControlMispred 97 .name(name() + ".DECODE:ControlMispred") 98 .desc("Number of times decode detected an instruction incorrectly" 99 " predicted as a control") 100 .prereq(decodeControlMispred); 101 decodeDecodedInsts 102 .name(name() + ".DECODE:DecodedInsts") 103 .desc("Number of instructions handled by decode") 104 .prereq(decodeDecodedInsts); 105 decodeSquashedInsts 106 .name(name() + ".DECODE:SquashedInsts") 107 .desc("Number of squashed instructions handled by decode") 108 .prereq(decodeSquashedInsts); 109} 110 111template<class Impl> 112void 113DefaultDecode<Impl>::setCPU(FullCPU *cpu_ptr) 114{ 115 DPRINTF(Decode, "Setting CPU pointer.\n"); 116 cpu = cpu_ptr; 117} 118 119template<class Impl> 120void 121DefaultDecode<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 122{ 123 DPRINTF(Decode, "Setting time buffer pointer.\n"); 124 timeBuffer = tb_ptr; 125 126 // Setup wire to write information back to fetch. 127 toFetch = timeBuffer->getWire(0); 128 129 // Create wires to get information from proper places in time buffer. 130 fromRename = timeBuffer->getWire(-renameToDecodeDelay); 131 fromIEW = timeBuffer->getWire(-iewToDecodeDelay); 132 fromCommit = timeBuffer->getWire(-commitToDecodeDelay); 133} 134 135template<class Impl> 136void 137DefaultDecode<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr) 138{ 139 DPRINTF(Decode, "Setting decode queue pointer.\n"); 140 decodeQueue = dq_ptr; 141 142 // Setup wire to write information to proper place in decode queue. 143 toRename = decodeQueue->getWire(0); 144} 145 146template<class Impl> 147void 148DefaultDecode<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr) 149{ 150 DPRINTF(Decode, "Setting fetch queue pointer.\n"); 151 fetchQueue = fq_ptr; 152 153 // Setup wire to read information from fetch queue. 154 fromFetch = fetchQueue->getWire(-fetchToDecodeDelay); 155} 156 157template<class Impl> 158void 159DefaultDecode<Impl>::setActiveThreads(list<unsigned> *at_ptr) 160{ 161 DPRINTF(Decode, "Setting active threads list pointer.\n"); 162 activeThreads = at_ptr; 163} 164 165template <class Impl> 166void 167DefaultDecode<Impl>::switchOut() 168{ 169 // Decode can immediately switch out. 170 cpu->signalSwitched(); 171} 172 173template <class Impl> 174void 175DefaultDecode<Impl>::takeOverFrom() 176{ 177 _status = Inactive; 178 179 // Be sure to reset state and clear out any old instructions. 180 for (int i = 0; i < numThreads; ++i) { 181 decodeStatus[i] = Idle; 182 183 stalls[i].rename = false; 184 stalls[i].iew = false; 185 stalls[i].commit = false; 186 while (!insts[i].empty()) 187 insts[i].pop(); 188 while (!skidBuffer[i].empty()) 189 skidBuffer[i].pop(); 190 branchCount[i] = 0; 191 } 192 wroteToTimeBuffer = false; 193} 194 195template<class Impl> 196bool 197DefaultDecode<Impl>::checkStall(unsigned tid) const 198{ 199 bool ret_val = false; 200 201 if (stalls[tid].rename) { 202 DPRINTF(Decode,"[tid:%i]: Stall fom Rename stage detected.\n", tid); 203 ret_val = true; 204 } else if (stalls[tid].iew) { 205 DPRINTF(Decode,"[tid:%i]: Stall fom IEW stage detected.\n", tid); 206 ret_val = true; 207 } else if (stalls[tid].commit) { 208 DPRINTF(Decode,"[tid:%i]: Stall fom Commit stage detected.\n", tid); 209 ret_val = true; 210 } 211 212 return ret_val; 213} 214 215template<class Impl> 216inline bool 217DefaultDecode<Impl>::fetchInstsValid() 218{ 219 return fromFetch->size > 0; 220} 221 222template<class Impl> 223bool 224DefaultDecode<Impl>::block(unsigned tid) 225{ 226 DPRINTF(Decode, "[tid:%u]: Blocking.\n", tid); 227 228 // Add the current inputs to the skid buffer so they can be 229 // reprocessed when this stage unblocks. 230 skidInsert(tid); 231 232 // If the decode status is blocked or unblocking then decode has not yet 233 // signalled fetch to unblock. In that case, there is no need to tell 234 // fetch to block. 235 if (decodeStatus[tid] != Blocked) { 236 // Set the status to Blocked. 237 decodeStatus[tid] = Blocked; 238 239 if (decodeStatus[tid] != Unblocking) { 240 toFetch->decodeBlock[tid] = true; 241 wroteToTimeBuffer = true; 242 } 243 244 return true; 245 } 246 247 return false; 248} 249 250template<class Impl> 251bool 252DefaultDecode<Impl>::unblock(unsigned tid) 253{ 254 // Decode is done unblocking only if the skid buffer is empty. 255 if (skidBuffer[tid].empty()) { 256 DPRINTF(Decode, "[tid:%u]: Done unblocking.\n", tid); 257 toFetch->decodeUnblock[tid] = true; 258 wroteToTimeBuffer = true; 259 260 decodeStatus[tid] = Running; 261 return true; 262 } 263 264 DPRINTF(Decode, "[tid:%u]: Currently unblocking.\n", tid); 265 266 return false; 267} 268 269template<class Impl> 270void 271DefaultDecode<Impl>::squash(DynInstPtr &inst, unsigned tid) 272{ 273 DPRINTF(Decode, "[tid:%i]: Squashing due to incorrect branch prediction " 274 "detected at decode.\n", tid); 275 276 // Send back mispredict information. 277 toFetch->decodeInfo[tid].branchMispredict = true; 278 toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum; 279 toFetch->decodeInfo[tid].predIncorrect = true; 280 toFetch->decodeInfo[tid].squash = true; 281 toFetch->decodeInfo[tid].nextPC = inst->readNextPC(); 282 toFetch->decodeInfo[tid].branchTaken = 283 inst->readNextPC() != (inst->readPC() + sizeof(TheISA::MachInst)); 284 285 // Might have to tell fetch to unblock. 286 if (decodeStatus[tid] == Blocked || 287 decodeStatus[tid] == Unblocking) { 288 toFetch->decodeUnblock[tid] = 1; 289 } 290 291 // Set status to squashing. 292 decodeStatus[tid] = Squashing; 293 294 for (int i=0; i<fromFetch->size; i++) { 295 if (fromFetch->insts[i]->threadNumber == tid && 296 fromFetch->insts[i]->seqNum > inst->seqNum) { 297 fromFetch->insts[i]->squashed = true; 298 } 299 } 300 301 // Clear the instruction list and skid buffer in case they have any 302 // insts in them. 303 while (!insts[tid].empty()) { 304 insts[tid].pop(); 305 } 306 307 while (!skidBuffer[tid].empty()) { 308 skidBuffer[tid].pop(); 309 } 310 311 // Squash instructions up until this one 312 cpu->removeInstsUntil(inst->seqNum, tid); 313} 314 315template<class Impl> 316unsigned 317DefaultDecode<Impl>::squash(unsigned tid) 318{ 319 DPRINTF(Decode, "[tid:%i]: Squashing.\n",tid); 320 321 if (decodeStatus[tid] == Blocked || 322 decodeStatus[tid] == Unblocking) { 323#if !FULL_SYSTEM 324 // In syscall emulation, we can have both a block and a squash due 325 // to a syscall in the same cycle. This would cause both signals to 326 // be high. This shouldn't happen in full system. 327 // @todo: Determine if this still happens. 328 if (toFetch->decodeBlock[tid]) { 329 toFetch->decodeBlock[tid] = 0; 330 } else { 331 toFetch->decodeUnblock[tid] = 1; 332 } 333#else 334 toFetch->decodeUnblock[tid] = 1; 335#endif 336 } 337 338 // Set status to squashing. 339 decodeStatus[tid] = Squashing; 340 341 // Go through incoming instructions from fetch and squash them. 342 unsigned squash_count = 0; 343 344 for (int i=0; i<fromFetch->size; i++) { 345 if (fromFetch->insts[i]->threadNumber == tid) { 346 fromFetch->insts[i]->squashed = true; 347 squash_count++; 348 } 349 } 350 351 // Clear the instruction list and skid buffer in case they have any 352 // insts in them. 353 while (!insts[tid].empty()) { 354 insts[tid].pop(); 355 } 356 357 while (!skidBuffer[tid].empty()) { 358 skidBuffer[tid].pop(); 359 } 360 361 return squash_count; 362} 363 364template<class Impl> 365void 366DefaultDecode<Impl>::skidInsert(unsigned tid) 367{ 368 DynInstPtr inst = NULL; 369 370 while (!insts[tid].empty()) { 371 inst = insts[tid].front(); 372 373 insts[tid].pop(); 374 375 assert(tid == inst->threadNumber); 376 377 DPRINTF(Decode,"Inserting [sn:%lli] PC:%#x into decode skidBuffer %i\n", 378 inst->seqNum, inst->readPC(), inst->threadNumber); 379 380 skidBuffer[tid].push(inst); 381 } 382 383 // @todo: Eventually need to enforce this by not letting a thread 384 // fetch past its skidbuffer 385 assert(skidBuffer[tid].size() <= skidBufferMax); 386} 387 388template<class Impl> 389bool 390DefaultDecode<Impl>::skidsEmpty() 391{ 392 list<unsigned>::iterator threads = (*activeThreads).begin(); 393 394 while (threads != (*activeThreads).end()) { 395 if (!skidBuffer[*threads++].empty()) 396 return false; 397 } 398 399 return true; 400} 401 402template<class Impl> 403void 404DefaultDecode<Impl>::updateStatus() 405{ 406 bool any_unblocking = false; 407 408 list<unsigned>::iterator threads = (*activeThreads).begin(); 409 410 threads = (*activeThreads).begin(); 411 412 while (threads != (*activeThreads).end()) { 413 unsigned tid = *threads++; 414 415 if (decodeStatus[tid] == Unblocking) { 416 any_unblocking = true; 417 break; 418 } 419 } 420 421 // Decode will have activity if it's unblocking. 422 if (any_unblocking) { 423 if (_status == Inactive) { 424 _status = Active; 425 426 DPRINTF(Activity, "Activating stage.\n"); 427 428 cpu->activateStage(FullCPU::DecodeIdx); 429 } 430 } else { 431 // If it's not unblocking, then decode will not have any internal 432 // activity. Switch it to inactive. 433 if (_status == Active) { 434 _status = Inactive; 435 DPRINTF(Activity, "Deactivating stage.\n"); 436 437 cpu->deactivateStage(FullCPU::DecodeIdx); 438 } 439 } 440} 441 442template <class Impl> 443void 444DefaultDecode<Impl>::sortInsts() 445{ 446 int insts_from_fetch = fromFetch->size; 447#ifdef DEBUG 448 for (int i=0; i < numThreads; i++) 449 assert(insts[i].empty()); 450#endif 451 for (int i = 0; i < insts_from_fetch; ++i) { 452 insts[fromFetch->insts[i]->threadNumber].push(fromFetch->insts[i]); 453 } 454} 455 456template<class Impl> 457void 458DefaultDecode<Impl>::readStallSignals(unsigned tid) 459{ 460 if (fromRename->renameBlock[tid]) { 461 stalls[tid].rename = true; 462 } 463 464 if (fromRename->renameUnblock[tid]) { 465 assert(stalls[tid].rename); 466 stalls[tid].rename = false; 467 } 468 469 if (fromIEW->iewBlock[tid]) { 470 stalls[tid].iew = true; 471 } 472 473 if (fromIEW->iewUnblock[tid]) { 474 assert(stalls[tid].iew); 475 stalls[tid].iew = false; 476 } 477 478 if (fromCommit->commitBlock[tid]) { 479 stalls[tid].commit = true; 480 } 481 482 if (fromCommit->commitUnblock[tid]) { 483 assert(stalls[tid].commit); 484 stalls[tid].commit = false; 485 } 486} 487 488template <class Impl> 489bool 490DefaultDecode<Impl>::checkSignalsAndUpdate(unsigned tid) 491{ 492 // Check if there's a squash signal, squash if there is. 493 // Check stall signals, block if necessary. 494 // If status was blocked 495 // Check if stall conditions have passed 496 // if so then go to unblocking 497 // If status was Squashing 498 // check if squashing is not high. Switch to running this cycle. 499 500 // Update the per thread stall statuses. 501 readStallSignals(tid); 502 503 // Check squash signals from commit. 504 if (fromCommit->commitInfo[tid].squash) { 505 506 DPRINTF(Decode, "[tid:%u]: Squashing instructions due to squash " 507 "from commit.\n", tid); 508 509 squash(tid); 510 511 return true; 512 } 513 514 // Check ROB squash signals from commit. 515 if (fromCommit->commitInfo[tid].robSquashing) { 516 DPRINTF(Decode, "[tid:%]: ROB is still squashing.\n",tid); 517 518 // Continue to squash. 519 decodeStatus[tid] = Squashing; 520 521 return true; 522 } 523 524 if (checkStall(tid)) { 525 return block(tid); 526 } 527 528 if (decodeStatus[tid] == Blocked) { 529 DPRINTF(Decode, "[tid:%u]: Done blocking, switching to unblocking.\n", 530 tid); 531 532 decodeStatus[tid] = Unblocking; 533 534 unblock(tid); 535 536 return true; 537 } 538 539 if (decodeStatus[tid] == Squashing) { 540 // Switch status to running if decode isn't being told to block or 541 // squash this cycle. 542 DPRINTF(Decode, "[tid:%u]: Done squashing, switching to running.\n", 543 tid); 544 545 decodeStatus[tid] = Running; 546 547 return false; 548 } 549 550 // If we've reached this point, we have not gotten any signals that 551 // cause decode to change its status. Decode remains the same as before. 552 return false; 553} 554 555template<class Impl> 556void 557DefaultDecode<Impl>::tick() 558{ 559 wroteToTimeBuffer = false; 560 561 bool status_change = false; 562 563 toRenameIndex = 0; 564 565 list<unsigned>::iterator threads = (*activeThreads).begin(); 566 567 sortInsts(); 568 569 //Check stall and squash signals. 570 while (threads != (*activeThreads).end()) { 571 unsigned tid = *threads++; 572 573 DPRINTF(Decode,"Processing [tid:%i]\n",tid); 574 status_change = checkSignalsAndUpdate(tid) || status_change; 575 576 decode(status_change, tid); 577 } 578 579 if (status_change) { 580 updateStatus(); 581 } 582 583 if (wroteToTimeBuffer) { 584 DPRINTF(Activity, "Activity this cycle.\n"); 585 586 cpu->activityThisCycle(); 587 } 588} 589 590template<class Impl> 591void 592DefaultDecode<Impl>::decode(bool &status_change, unsigned tid) 593{ 594 // If status is Running or idle, 595 // call decodeInsts() 596 // If status is Unblocking, 597 // buffer any instructions coming from fetch 598 // continue trying to empty skid buffer 599 // check if stall conditions have passed 600 601 if (decodeStatus[tid] == Blocked) { 602 ++decodeBlockedCycles; 603 } else if (decodeStatus[tid] == Squashing) { 604 ++decodeSquashCycles; 605 } 606 607 // Decode should try to decode as many instructions as its bandwidth 608 // will allow, as long as it is not currently blocked. 609 if (decodeStatus[tid] == Running || 610 decodeStatus[tid] == Idle) { 611 DPRINTF(Decode, "[tid:%u] Not blocked, so attempting to run " 612 "stage.\n",tid); 613 614 decodeInsts(tid); 615 } else if (decodeStatus[tid] == Unblocking) { 616 // Make sure that the skid buffer has something in it if the 617 // status is unblocking. 618 assert(!skidsEmpty()); 619 620 // If the status was unblocking, then instructions from the skid 621 // buffer were used. Remove those instructions and handle 622 // the rest of unblocking. 623 decodeInsts(tid); 624 625 if (fetchInstsValid()) { 626 // Add the current inputs to the skid buffer so they can be 627 // reprocessed when this stage unblocks. 628 skidInsert(tid); 629 } 630 631 status_change = unblock(tid) || status_change; 632 } 633} 634 635template <class Impl> 636void 637DefaultDecode<Impl>::decodeInsts(unsigned tid) 638{ 639 // Instructions can come either from the skid buffer or the list of 640 // instructions coming from fetch, depending on decode's status. 641 int insts_available = decodeStatus[tid] == Unblocking ? 642 skidBuffer[tid].size() : insts[tid].size(); 643 644 if (insts_available == 0) { 645 DPRINTF(Decode, "[tid:%u] Nothing to do, breaking out" 646 " early.\n",tid); 647 // Should I change the status to idle? 648 ++decodeIdleCycles; 649 return; 650 } else if (decodeStatus[tid] == Unblocking) { 651 DPRINTF(Decode, "[tid:%u] Unblocking, removing insts from skid " 652 "buffer.\n",tid); 653 ++decodeUnblockCycles; 654 } else if (decodeStatus[tid] == Running) { 655 ++decodeRunCycles; 656 } 657 658 DynInstPtr inst; 659 660 std::queue<DynInstPtr> 661 &insts_to_decode = decodeStatus[tid] == Unblocking ? 662 skidBuffer[tid] : insts[tid]; 663 664 DPRINTF(Decode, "[tid:%u]: Sending instruction to rename.\n",tid); 665 666 while (insts_available > 0 && toRenameIndex < decodeWidth) { 667 assert(!insts_to_decode.empty()); 668 669 inst = insts_to_decode.front(); 670 671 insts_to_decode.pop(); 672 673 DPRINTF(Decode, "[tid:%u]: Processing instruction [sn:%lli] with " 674 "PC %#x\n", 675 tid, inst->seqNum, inst->readPC()); 676 677 if (inst->isSquashed()) { 678 DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %#x is " 679 "squashed, skipping.\n", 680 tid, inst->seqNum, inst->readPC()); 681 682 ++decodeSquashedInsts; 683 684 --insts_available; 685 686 continue; 687 } 688 689 // Also check if instructions have no source registers. Mark 690 // them as ready to issue at any time. Not sure if this check 691 // should exist here or at a later stage; however it doesn't matter 692 // too much for function correctness. 693 if (inst->numSrcRegs() == 0) { 694 inst->setCanIssue(); 695 } 696 697 // This current instruction is valid, so add it into the decode 698 // queue. The next instruction may not be valid, so check to 699 // see if branches were predicted correctly. 700 toRename->insts[toRenameIndex] = inst; 701 702 ++(toRename->size); 703 ++toRenameIndex; 704 ++decodeDecodedInsts; 705 --insts_available; 706 707 // Ensure that if it was predicted as a branch, it really is a 708 // branch. 709 if (inst->predTaken() && !inst->isControl()) { 710 panic("Instruction predicted as a branch!"); 711 712 ++decodeControlMispred; 713 714 // Might want to set some sort of boolean and just do 715 // a check at the end 716 squash(inst, inst->threadNumber); 717 718 break; 719 } 720 721 // Go ahead and compute any PC-relative branches. 722 if (inst->isDirectCtrl() && inst->isUncondCtrl()) { 723 ++decodeBranchResolved; 724 inst->setNextPC(inst->branchTarget()); 725 726 if (inst->mispredicted()) { 727 ++decodeBranchMispred; 728 729 // Might want to set some sort of boolean and just do 730 // a check at the end 731 squash(inst, inst->threadNumber); 732 inst->setPredTarg(inst->branchTarget()); 733 734 break; 735 } 736 } 737 } 738 739 // If we didn't process all instructions, then we will need to block 740 // and put all those instructions into the skid buffer. 741 if (!insts_to_decode.empty()) { 742 block(tid); 743 } 744 745 // Record that decode has written to the time buffer for activity 746 // tracking. 747 if (toRenameIndex) { 748 wroteToTimeBuffer = true; 749 } 750} 751