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