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