decode_impl.hh revision 3967
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 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 squashAfterDelaySlot[i] = 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(std::list<unsigned> *at_ptr) 162{ 163 DPRINTF(Decode, "Setting active threads list pointer.\n"); 164 activeThreads = at_ptr; 165} 166 167template <class Impl> 168bool 169DefaultDecode<Impl>::drain() 170{ 171 // Decode is done draining at any time. 172 cpu->signalDrained(); 173 return true; 174} 175 176template <class Impl> 177void 178DefaultDecode<Impl>::takeOverFrom() 179{ 180 _status = Inactive; 181 182 // Be sure to reset state and clear out any old instructions. 183 for (int i = 0; i < numThreads; ++i) { 184 decodeStatus[i] = Idle; 185 186 stalls[i].rename = false; 187 stalls[i].iew = false; 188 stalls[i].commit = false; 189 while (!insts[i].empty()) 190 insts[i].pop(); 191 while (!skidBuffer[i].empty()) 192 skidBuffer[i].pop(); 193 branchCount[i] = 0; 194 } 195 wroteToTimeBuffer = false; 196} 197 198template<class Impl> 199bool 200DefaultDecode<Impl>::checkStall(unsigned tid) const 201{ 202 bool ret_val = false; 203 204 if (stalls[tid].rename) { 205 DPRINTF(Decode,"[tid:%i]: Stall fom Rename stage detected.\n", tid); 206 ret_val = true; 207 } else if (stalls[tid].iew) { 208 DPRINTF(Decode,"[tid:%i]: Stall fom IEW stage detected.\n", tid); 209 ret_val = true; 210 } else if (stalls[tid].commit) { 211 DPRINTF(Decode,"[tid:%i]: Stall fom Commit stage detected.\n", tid); 212 ret_val = true; 213 } 214 215 return ret_val; 216} 217 218template<class Impl> 219inline bool 220DefaultDecode<Impl>::fetchInstsValid() 221{ 222 return fromFetch->size > 0; 223} 224 225template<class Impl> 226bool 227DefaultDecode<Impl>::block(unsigned tid) 228{ 229 DPRINTF(Decode, "[tid:%u]: Blocking.\n", tid); 230 231 // Add the current inputs to the skid buffer so they can be 232 // reprocessed when this stage unblocks. 233 skidInsert(tid); 234 235 // If the decode status is blocked or unblocking then decode has not yet 236 // signalled fetch to unblock. In that case, there is no need to tell 237 // fetch to block. 238 if (decodeStatus[tid] != Blocked) { 239 // Set the status to Blocked. 240 decodeStatus[tid] = Blocked; 241 242 if (decodeStatus[tid] != Unblocking) { 243 toFetch->decodeBlock[tid] = true; 244 wroteToTimeBuffer = true; 245 } 246 247 return true; 248 } 249 250 return false; 251} 252 253template<class Impl> 254bool 255DefaultDecode<Impl>::unblock(unsigned tid) 256{ 257 // Decode is done unblocking only if the skid buffer is empty. 258 if (skidBuffer[tid].empty()) { 259 DPRINTF(Decode, "[tid:%u]: Done unblocking.\n", tid); 260 toFetch->decodeUnblock[tid] = true; 261 wroteToTimeBuffer = true; 262 263 decodeStatus[tid] = Running; 264 return true; 265 } 266 267 DPRINTF(Decode, "[tid:%u]: Currently unblocking.\n", tid); 268 269 return false; 270} 271 272template<class Impl> 273void 274DefaultDecode<Impl>::squash(DynInstPtr &inst, unsigned tid) 275{ 276 DPRINTF(Decode, "[tid:%i]: Squashing due to incorrect branch prediction " 277 "detected at decode.\n", tid); 278 279 // Send back mispredict information. 280 toFetch->decodeInfo[tid].branchMispredict = true; 281 toFetch->decodeInfo[tid].predIncorrect = true; 282 toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum; 283 toFetch->decodeInfo[tid].squash = true; 284 toFetch->decodeInfo[tid].nextPC = inst->branchTarget(); 285 ///FIXME There needs to be a way to set the nextPC and nextNPC 286 ///explicitly for ISAs with delay slots. 287 toFetch->decodeInfo[tid].nextNPC = 288 inst->branchTarget() + sizeof(TheISA::MachInst); 289#if ISA_HAS_DELAY_SLOT 290 toFetch->decodeInfo[tid].branchTaken = inst->readNextNPC() != 291 (inst->readNextPC() + sizeof(TheISA::MachInst)); 292 293 toFetch->decodeInfo[tid].bdelayDoneSeqNum = bdelayDoneSeqNum[tid]; 294 squashAfterDelaySlot[tid] = false; 295 296 InstSeqNum squash_seq_num = bdelayDoneSeqNum[tid]; 297#else 298 toFetch->decodeInfo[tid].branchTaken = 299 inst->readNextPC() != (inst->readPC() + sizeof(TheISA::MachInst)); 300 301 InstSeqNum squash_seq_num = inst->seqNum; 302#endif 303 304 // Might have to tell fetch to unblock. 305 if (decodeStatus[tid] == Blocked || 306 decodeStatus[tid] == Unblocking) { 307 toFetch->decodeUnblock[tid] = 1; 308 } 309 310 // Set status to squashing. 311 decodeStatus[tid] = Squashing; 312 313 for (int i=0; i<fromFetch->size; i++) { 314 if (fromFetch->insts[i]->threadNumber == tid && 315 fromFetch->insts[i]->seqNum > squash_seq_num) { 316 fromFetch->insts[i]->setSquashed(); 317 } 318 } 319 320 // Clear the instruction list and skid buffer in case they have any 321 // insts in them. 322 while (!insts[tid].empty()) { 323 324#if ISA_HAS_DELAY_SLOT 325 if (insts[tid].front()->seqNum <= squash_seq_num) { 326 DPRINTF(Decode, "[tid:%i]: Cannot remove incoming decode " 327 "instructions before delay slot [sn:%i]. %i insts" 328 "left in decode.\n", tid, squash_seq_num, 329 insts[tid].size()); 330 break; 331 } 332#endif 333 insts[tid].pop(); 334 } 335 336 while (!skidBuffer[tid].empty()) { 337 338#if ISA_HAS_DELAY_SLOT 339 if (skidBuffer[tid].front()->seqNum <= squash_seq_num) { 340 DPRINTF(Decode, "[tid:%i]: Cannot remove skidBuffer " 341 "instructions before delay slot [sn:%i]. %i insts" 342 "left in decode.\n", tid, squash_seq_num, 343 insts[tid].size()); 344 break; 345 } 346#endif 347 skidBuffer[tid].pop(); 348 } 349 350 // Squash instructions up until this one 351 cpu->removeInstsUntil(squash_seq_num, tid); 352} 353 354template<class Impl> 355unsigned 356DefaultDecode<Impl>::squash(unsigned tid) 357{ 358 DPRINTF(Decode, "[tid:%i]: Squashing.\n",tid); 359 360 if (decodeStatus[tid] == Blocked || 361 decodeStatus[tid] == Unblocking) { 362#if !FULL_SYSTEM 363 // In syscall emulation, we can have both a block and a squash due 364 // to a syscall in the same cycle. This would cause both signals to 365 // be high. This shouldn't happen in full system. 366 // @todo: Determine if this still happens. 367 if (toFetch->decodeBlock[tid]) { 368 toFetch->decodeBlock[tid] = 0; 369 } else { 370 toFetch->decodeUnblock[tid] = 1; 371 } 372#else 373 toFetch->decodeUnblock[tid] = 1; 374#endif 375 } 376 377 // Set status to squashing. 378 decodeStatus[tid] = Squashing; 379 380 // Go through incoming instructions from fetch and squash them. 381 unsigned squash_count = 0; 382 383 for (int i=0; i<fromFetch->size; i++) { 384 if (fromFetch->insts[i]->threadNumber == tid) { 385 fromFetch->insts[i]->setSquashed(); 386 squash_count++; 387 } 388 } 389 390 // Clear the instruction list and skid buffer in case they have any 391 // insts in them. 392 while (!insts[tid].empty()) { 393 insts[tid].pop(); 394 } 395 396 while (!skidBuffer[tid].empty()) { 397 skidBuffer[tid].pop(); 398 } 399 400 return squash_count; 401} 402 403template<class Impl> 404void 405DefaultDecode<Impl>::skidInsert(unsigned tid) 406{ 407 DynInstPtr inst = NULL; 408 409 while (!insts[tid].empty()) { 410 inst = insts[tid].front(); 411 412 insts[tid].pop(); 413 414 assert(tid == inst->threadNumber); 415 416 DPRINTF(Decode,"Inserting [sn:%lli] PC:%#x into decode skidBuffer %i\n", 417 inst->seqNum, inst->readPC(), inst->threadNumber); 418 419 skidBuffer[tid].push(inst); 420 } 421 422 // @todo: Eventually need to enforce this by not letting a thread 423 // fetch past its skidbuffer 424 assert(skidBuffer[tid].size() <= skidBufferMax); 425} 426 427template<class Impl> 428bool 429DefaultDecode<Impl>::skidsEmpty() 430{ 431 std::list<unsigned>::iterator threads = (*activeThreads).begin(); 432 433 while (threads != (*activeThreads).end()) { 434 if (!skidBuffer[*threads++].empty()) 435 return false; 436 } 437 438 return true; 439} 440 441template<class Impl> 442void 443DefaultDecode<Impl>::updateStatus() 444{ 445 bool any_unblocking = false; 446 447 std::list<unsigned>::iterator threads = (*activeThreads).begin(); 448 449 threads = (*activeThreads).begin(); 450 451 while (threads != (*activeThreads).end()) { 452 unsigned tid = *threads++; 453 454 if (decodeStatus[tid] == Unblocking) { 455 any_unblocking = true; 456 break; 457 } 458 } 459 460 // Decode will have activity if it's unblocking. 461 if (any_unblocking) { 462 if (_status == Inactive) { 463 _status = Active; 464 465 DPRINTF(Activity, "Activating stage.\n"); 466 467 cpu->activateStage(O3CPU::DecodeIdx); 468 } 469 } else { 470 // If it's not unblocking, then decode will not have any internal 471 // activity. Switch it to inactive. 472 if (_status == Active) { 473 _status = Inactive; 474 DPRINTF(Activity, "Deactivating stage.\n"); 475 476 cpu->deactivateStage(O3CPU::DecodeIdx); 477 } 478 } 479} 480 481template <class Impl> 482void 483DefaultDecode<Impl>::sortInsts() 484{ 485 int insts_from_fetch = fromFetch->size; 486#ifdef DEBUG 487 for (int i=0; i < numThreads; i++) 488 assert(insts[i].empty()); 489#endif 490 for (int i = 0; i < insts_from_fetch; ++i) { 491 insts[fromFetch->insts[i]->threadNumber].push(fromFetch->insts[i]); 492 } 493} 494 495template<class Impl> 496void 497DefaultDecode<Impl>::readStallSignals(unsigned tid) 498{ 499 if (fromRename->renameBlock[tid]) { 500 stalls[tid].rename = true; 501 } 502 503 if (fromRename->renameUnblock[tid]) { 504 assert(stalls[tid].rename); 505 stalls[tid].rename = false; 506 } 507 508 if (fromIEW->iewBlock[tid]) { 509 stalls[tid].iew = true; 510 } 511 512 if (fromIEW->iewUnblock[tid]) { 513 assert(stalls[tid].iew); 514 stalls[tid].iew = false; 515 } 516 517 if (fromCommit->commitBlock[tid]) { 518 stalls[tid].commit = true; 519 } 520 521 if (fromCommit->commitUnblock[tid]) { 522 assert(stalls[tid].commit); 523 stalls[tid].commit = false; 524 } 525} 526 527template <class Impl> 528bool 529DefaultDecode<Impl>::checkSignalsAndUpdate(unsigned tid) 530{ 531 // Check if there's a squash signal, squash if there is. 532 // Check stall signals, block if necessary. 533 // If status was blocked 534 // Check if stall conditions have passed 535 // if so then go to unblocking 536 // If status was Squashing 537 // check if squashing is not high. Switch to running this cycle. 538 539 // Update the per thread stall statuses. 540 readStallSignals(tid); 541 542 // Check squash signals from commit. 543 if (fromCommit->commitInfo[tid].squash) { 544 545 DPRINTF(Decode, "[tid:%u]: Squashing instructions due to squash " 546 "from commit.\n", tid); 547 548 squash(tid); 549 550 return true; 551 } 552 553 // Check ROB squash signals from commit. 554 if (fromCommit->commitInfo[tid].robSquashing) { 555 DPRINTF(Decode, "[tid:%u]: ROB is still squashing.\n", tid); 556 557 // Continue to squash. 558 decodeStatus[tid] = Squashing; 559 560 return true; 561 } 562 563 if (checkStall(tid)) { 564 return block(tid); 565 } 566 567 if (decodeStatus[tid] == Blocked) { 568 DPRINTF(Decode, "[tid:%u]: Done blocking, switching to unblocking.\n", 569 tid); 570 571 decodeStatus[tid] = Unblocking; 572 573 unblock(tid); 574 575 return true; 576 } 577 578 if (decodeStatus[tid] == Squashing) { 579 // Switch status to running if decode isn't being told to block or 580 // squash this cycle. 581 DPRINTF(Decode, "[tid:%u]: Done squashing, switching to running.\n", 582 tid); 583 584 decodeStatus[tid] = Running; 585 586 return false; 587 } 588 589 // If we've reached this point, we have not gotten any signals that 590 // cause decode to change its status. Decode remains the same as before. 591 return false; 592} 593 594template<class Impl> 595void 596DefaultDecode<Impl>::tick() 597{ 598 wroteToTimeBuffer = false; 599 600 bool status_change = false; 601 602 toRenameIndex = 0; 603 604 std::list<unsigned>::iterator threads = (*activeThreads).begin(); 605 606 sortInsts(); 607 608 //Check stall and squash signals. 609 while (threads != (*activeThreads).end()) { 610 unsigned tid = *threads++; 611 612 DPRINTF(Decode,"Processing [tid:%i]\n",tid); 613 status_change = checkSignalsAndUpdate(tid) || status_change; 614 615 decode(status_change, tid); 616 } 617 618 if (status_change) { 619 updateStatus(); 620 } 621 622 if (wroteToTimeBuffer) { 623 DPRINTF(Activity, "Activity this cycle.\n"); 624 625 cpu->activityThisCycle(); 626 } 627} 628 629template<class Impl> 630void 631DefaultDecode<Impl>::decode(bool &status_change, unsigned tid) 632{ 633 // If status is Running or idle, 634 // call decodeInsts() 635 // If status is Unblocking, 636 // buffer any instructions coming from fetch 637 // continue trying to empty skid buffer 638 // check if stall conditions have passed 639 640 if (decodeStatus[tid] == Blocked) { 641 ++decodeBlockedCycles; 642 } else if (decodeStatus[tid] == Squashing) { 643 ++decodeSquashCycles; 644 } 645 646 // Decode should try to decode as many instructions as its bandwidth 647 // will allow, as long as it is not currently blocked. 648 if (decodeStatus[tid] == Running || 649 decodeStatus[tid] == Idle) { 650 DPRINTF(Decode, "[tid:%u]: Not blocked, so attempting to run " 651 "stage.\n",tid); 652 653 decodeInsts(tid); 654 } else if (decodeStatus[tid] == Unblocking) { 655 // Make sure that the skid buffer has something in it if the 656 // status is unblocking. 657 assert(!skidsEmpty()); 658 659 // If the status was unblocking, then instructions from the skid 660 // buffer were used. Remove those instructions and handle 661 // the rest of unblocking. 662 decodeInsts(tid); 663 664 if (fetchInstsValid()) { 665 // Add the current inputs to the skid buffer so they can be 666 // reprocessed when this stage unblocks. 667 skidInsert(tid); 668 } 669 670 status_change = unblock(tid) || status_change; 671 } 672} 673 674template <class Impl> 675void 676DefaultDecode<Impl>::decodeInsts(unsigned tid) 677{ 678 // Instructions can come either from the skid buffer or the list of 679 // instructions coming from fetch, depending on decode's status. 680 int insts_available = decodeStatus[tid] == Unblocking ? 681 skidBuffer[tid].size() : insts[tid].size(); 682 683 if (insts_available == 0) { 684 DPRINTF(Decode, "[tid:%u] Nothing to do, breaking out" 685 " early.\n",tid); 686 // Should I change the status to idle? 687 ++decodeIdleCycles; 688 return; 689 } else if (decodeStatus[tid] == Unblocking) { 690 DPRINTF(Decode, "[tid:%u] Unblocking, removing insts from skid " 691 "buffer.\n",tid); 692 ++decodeUnblockCycles; 693 } else if (decodeStatus[tid] == Running) { 694 ++decodeRunCycles; 695 } 696 697 DynInstPtr inst; 698 699 std::queue<DynInstPtr> 700 &insts_to_decode = decodeStatus[tid] == Unblocking ? 701 skidBuffer[tid] : insts[tid]; 702 703 DPRINTF(Decode, "[tid:%u]: Sending instruction to rename.\n",tid); 704 705 while (insts_available > 0 && toRenameIndex < decodeWidth) { 706 assert(!insts_to_decode.empty()); 707 708 inst = insts_to_decode.front(); 709 710 insts_to_decode.pop(); 711 712 DPRINTF(Decode, "[tid:%u]: Processing instruction [sn:%lli] with " 713 "PC %#x\n", 714 tid, inst->seqNum, inst->readPC()); 715 716 if (inst->isSquashed()) { 717 DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %#x is " 718 "squashed, skipping.\n", 719 tid, inst->seqNum, inst->readPC()); 720 721 ++decodeSquashedInsts; 722 723 --insts_available; 724 725 continue; 726 } 727 728 // Also check if instructions have no source registers. Mark 729 // them as ready to issue at any time. Not sure if this check 730 // should exist here or at a later stage; however it doesn't matter 731 // too much for function correctness. 732 if (inst->numSrcRegs() == 0) { 733 inst->setCanIssue(); 734 } 735 736 // This current instruction is valid, so add it into the decode 737 // queue. The next instruction may not be valid, so check to 738 // see if branches were predicted correctly. 739 toRename->insts[toRenameIndex] = inst; 740 741 ++(toRename->size); 742 ++toRenameIndex; 743 ++decodeDecodedInsts; 744 --insts_available; 745 746 // Ensure that if it was predicted as a branch, it really is a 747 // branch. 748 if (inst->readPredTaken() && !inst->isControl()) { 749 DPRINTF(Decode, "PredPC : %#x != NextPC: %#x\n", 750 inst->readPredPC(), inst->readNextPC() + 4); 751 752 panic("Instruction predicted as a branch!"); 753 754 ++decodeControlMispred; 755 756 // Might want to set some sort of boolean and just do 757 // a check at the end 758 squash(inst, inst->threadNumber); 759 760 break; 761 } 762 763 // Go ahead and compute any PC-relative branches. 764 if (inst->isDirectCtrl() && inst->isUncondCtrl()) { 765 ++decodeBranchResolved; 766 767 if (inst->branchTarget() != inst->readPredPC()) { 768 ++decodeBranchMispred; 769 770 // Might want to set some sort of boolean and just do 771 // a check at the end 772#if !ISA_HAS_DELAY_SLOT 773 squash(inst, inst->threadNumber); 774 Addr target = inst->branchTarget(); 775 inst->setPredTarg(target, target + sizeof(TheISA::MachInst)); 776 break; 777#else 778 // If mispredicted as taken, then ignore delay slot 779 // instruction... else keep delay slot and squash 780 // after it is sent to rename 781 if (inst->readPredTaken() && inst->isCondDelaySlot()) { 782 DPRINTF(Decode, "[tid:%i]: Conditional delay slot inst." 783 "[sn:%i] PC %#x mispredicted as taken.\n", tid, 784 inst->seqNum, inst->PC); 785 bdelayDoneSeqNum[tid] = inst->seqNum; 786 squash(inst, inst->threadNumber); 787 Addr target = inst->branchTarget(); 788 inst->setPredTarg(target, 789 target + sizeof(TheISA::MachInst)); 790 break; 791 } else { 792 DPRINTF(Decode, "[tid:%i]: Misprediction detected at " 793 "[sn:%i] PC %#x, will squash after delay slot " 794 "inst. is sent to Rename\n", 795 tid, inst->seqNum, inst->PC); 796 bdelayDoneSeqNum[tid] = inst->seqNum + 1; 797 squashAfterDelaySlot[tid] = true; 798 squashInst[tid] = inst; 799 continue; 800 } 801#endif 802 } 803 } 804 805 if (squashAfterDelaySlot[tid]) { 806 assert(!inst->isSquashed()); 807 squash(squashInst[tid], squashInst[tid]->threadNumber); 808 Addr target = squashInst[tid]->branchTarget(); 809 squashInst[tid]->setPredTarg(target, 810 target + sizeof(TheISA::MachInst)); 811 assert(!inst->isSquashed()); 812 break; 813 } 814 } 815 816 // If we didn't process all instructions, then we will need to block 817 // and put all those instructions into the skid buffer. 818 if (!insts_to_decode.empty()) { 819 block(tid); 820 } 821 822 // Record that decode has written to the time buffer for activity 823 // tracking. 824 if (toRenameIndex) { 825 wroteToTimeBuffer = true; 826 } 827} 828