rename_impl.hh revision 3773:61c53465193d
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 * Korey Sewell 30 */ 31 32#include <list> 33 34#include "arch/isa_traits.hh" 35#include "arch/regfile.hh" 36#include "config/full_system.hh" 37#include "cpu/o3/rename.hh" 38 39template <class Impl> 40DefaultRename<Impl>::DefaultRename(Params *params) 41 : iewToRenameDelay(params->iewToRenameDelay), 42 decodeToRenameDelay(params->decodeToRenameDelay), 43 commitToRenameDelay(params->commitToRenameDelay), 44 renameWidth(params->renameWidth), 45 commitWidth(params->commitWidth), 46 numThreads(params->numberOfThreads), 47 maxPhysicalRegs(params->numPhysIntRegs + params->numPhysFloatRegs) 48{ 49 _status = Inactive; 50 51 for (int i=0; i< numThreads; i++) { 52 renameStatus[i] = Idle; 53 54 freeEntries[i].iqEntries = 0; 55 freeEntries[i].lsqEntries = 0; 56 freeEntries[i].robEntries = 0; 57 58 stalls[i].iew = false; 59 stalls[i].commit = false; 60 serializeInst[i] = NULL; 61 62 instsInProgress[i] = 0; 63 64 emptyROB[i] = true; 65 66 serializeOnNextInst[i] = false; 67 } 68 69 // @todo: Make into a parameter. 70 skidBufferMax = (2 * (iewToRenameDelay * params->decodeWidth)) + renameWidth; 71} 72 73template <class Impl> 74std::string 75DefaultRename<Impl>::name() const 76{ 77 return cpu->name() + ".rename"; 78} 79 80template <class Impl> 81void 82DefaultRename<Impl>::regStats() 83{ 84 renameSquashCycles 85 .name(name() + ".RENAME:SquashCycles") 86 .desc("Number of cycles rename is squashing") 87 .prereq(renameSquashCycles); 88 renameIdleCycles 89 .name(name() + ".RENAME:IdleCycles") 90 .desc("Number of cycles rename is idle") 91 .prereq(renameIdleCycles); 92 renameBlockCycles 93 .name(name() + ".RENAME:BlockCycles") 94 .desc("Number of cycles rename is blocking") 95 .prereq(renameBlockCycles); 96 renameSerializeStallCycles 97 .name(name() + ".RENAME:serializeStallCycles") 98 .desc("count of cycles rename stalled for serializing inst") 99 .flags(Stats::total); 100 renameRunCycles 101 .name(name() + ".RENAME:RunCycles") 102 .desc("Number of cycles rename is running") 103 .prereq(renameIdleCycles); 104 renameUnblockCycles 105 .name(name() + ".RENAME:UnblockCycles") 106 .desc("Number of cycles rename is unblocking") 107 .prereq(renameUnblockCycles); 108 renameRenamedInsts 109 .name(name() + ".RENAME:RenamedInsts") 110 .desc("Number of instructions processed by rename") 111 .prereq(renameRenamedInsts); 112 renameSquashedInsts 113 .name(name() + ".RENAME:SquashedInsts") 114 .desc("Number of squashed instructions processed by rename") 115 .prereq(renameSquashedInsts); 116 renameROBFullEvents 117 .name(name() + ".RENAME:ROBFullEvents") 118 .desc("Number of times rename has blocked due to ROB full") 119 .prereq(renameROBFullEvents); 120 renameIQFullEvents 121 .name(name() + ".RENAME:IQFullEvents") 122 .desc("Number of times rename has blocked due to IQ full") 123 .prereq(renameIQFullEvents); 124 renameLSQFullEvents 125 .name(name() + ".RENAME:LSQFullEvents") 126 .desc("Number of times rename has blocked due to LSQ full") 127 .prereq(renameLSQFullEvents); 128 renameFullRegistersEvents 129 .name(name() + ".RENAME:FullRegisterEvents") 130 .desc("Number of times there has been no free registers") 131 .prereq(renameFullRegistersEvents); 132 renameRenamedOperands 133 .name(name() + ".RENAME:RenamedOperands") 134 .desc("Number of destination operands rename has renamed") 135 .prereq(renameRenamedOperands); 136 renameRenameLookups 137 .name(name() + ".RENAME:RenameLookups") 138 .desc("Number of register rename lookups that rename has made") 139 .prereq(renameRenameLookups); 140 renameCommittedMaps 141 .name(name() + ".RENAME:CommittedMaps") 142 .desc("Number of HB maps that are committed") 143 .prereq(renameCommittedMaps); 144 renameUndoneMaps 145 .name(name() + ".RENAME:UndoneMaps") 146 .desc("Number of HB maps that are undone due to squashing") 147 .prereq(renameUndoneMaps); 148 renamedSerializing 149 .name(name() + ".RENAME:serializingInsts") 150 .desc("count of serializing insts renamed") 151 .flags(Stats::total) 152 ; 153 renamedTempSerializing 154 .name(name() + ".RENAME:tempSerializingInsts") 155 .desc("count of temporary serializing insts renamed") 156 .flags(Stats::total) 157 ; 158 renameSkidInsts 159 .name(name() + ".RENAME:skidInsts") 160 .desc("count of insts added to the skid buffer") 161 .flags(Stats::total) 162 ; 163} 164 165template <class Impl> 166void 167DefaultRename<Impl>::setCPU(O3CPU *cpu_ptr) 168{ 169 DPRINTF(Rename, "Setting CPU pointer.\n"); 170 cpu = cpu_ptr; 171} 172 173template <class Impl> 174void 175DefaultRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 176{ 177 DPRINTF(Rename, "Setting time buffer pointer.\n"); 178 timeBuffer = tb_ptr; 179 180 // Setup wire to read information from time buffer, from IEW stage. 181 fromIEW = timeBuffer->getWire(-iewToRenameDelay); 182 183 // Setup wire to read infromation from time buffer, from commit stage. 184 fromCommit = timeBuffer->getWire(-commitToRenameDelay); 185 186 // Setup wire to write information to previous stages. 187 toDecode = timeBuffer->getWire(0); 188} 189 190template <class Impl> 191void 192DefaultRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 193{ 194 DPRINTF(Rename, "Setting rename queue pointer.\n"); 195 renameQueue = rq_ptr; 196 197 // Setup wire to write information to future stages. 198 toIEW = renameQueue->getWire(0); 199} 200 201template <class Impl> 202void 203DefaultRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr) 204{ 205 DPRINTF(Rename, "Setting decode queue pointer.\n"); 206 decodeQueue = dq_ptr; 207 208 // Setup wire to get information from decode. 209 fromDecode = decodeQueue->getWire(-decodeToRenameDelay); 210} 211 212template <class Impl> 213void 214DefaultRename<Impl>::initStage() 215{ 216 // Grab the number of free entries directly from the stages. 217 for (int tid=0; tid < numThreads; tid++) { 218 freeEntries[tid].iqEntries = iew_ptr->instQueue.numFreeEntries(tid); 219 freeEntries[tid].lsqEntries = iew_ptr->ldstQueue.numFreeEntries(tid); 220 freeEntries[tid].robEntries = commit_ptr->numROBFreeEntries(tid); 221 emptyROB[tid] = true; 222 } 223} 224 225template<class Impl> 226void 227DefaultRename<Impl>::setActiveThreads(std::list<unsigned> *at_ptr) 228{ 229 DPRINTF(Rename, "Setting active threads list pointer.\n"); 230 activeThreads = at_ptr; 231} 232 233 234template <class Impl> 235void 236DefaultRename<Impl>::setRenameMap(RenameMap rm_ptr[]) 237{ 238 DPRINTF(Rename, "Setting rename map pointers.\n"); 239 240 for (int i=0; i<numThreads; i++) { 241 renameMap[i] = &rm_ptr[i]; 242 } 243} 244 245template <class Impl> 246void 247DefaultRename<Impl>::setFreeList(FreeList *fl_ptr) 248{ 249 DPRINTF(Rename, "Setting free list pointer.\n"); 250 freeList = fl_ptr; 251} 252 253template<class Impl> 254void 255DefaultRename<Impl>::setScoreboard(Scoreboard *_scoreboard) 256{ 257 DPRINTF(Rename, "Setting scoreboard pointer.\n"); 258 scoreboard = _scoreboard; 259} 260 261template <class Impl> 262bool 263DefaultRename<Impl>::drain() 264{ 265 // Rename is ready to switch out at any time. 266 cpu->signalDrained(); 267 return true; 268} 269 270template <class Impl> 271void 272DefaultRename<Impl>::switchOut() 273{ 274 // Clear any state, fix up the rename map. 275 for (int i = 0; i < numThreads; i++) { 276 typename std::list<RenameHistory>::iterator hb_it = 277 historyBuffer[i].begin(); 278 279 while (!historyBuffer[i].empty()) { 280 assert(hb_it != historyBuffer[i].end()); 281 282 DPRINTF(Rename, "[tid:%u]: Removing history entry with sequence " 283 "number %i.\n", i, (*hb_it).instSeqNum); 284 285 // Tell the rename map to set the architected register to the 286 // previous physical register that it was renamed to. 287 renameMap[i]->setEntry(hb_it->archReg, hb_it->prevPhysReg); 288 289 // Put the renamed physical register back on the free list. 290 freeList->addReg(hb_it->newPhysReg); 291 292 // Be sure to mark its register as ready if it's a misc register. 293 if (hb_it->newPhysReg >= maxPhysicalRegs) { 294 scoreboard->setReg(hb_it->newPhysReg); 295 } 296 297 historyBuffer[i].erase(hb_it++); 298 } 299 insts[i].clear(); 300 skidBuffer[i].clear(); 301 } 302} 303 304template <class Impl> 305void 306DefaultRename<Impl>::takeOverFrom() 307{ 308 _status = Inactive; 309 initStage(); 310 311 // Reset all state prior to taking over from the other CPU. 312 for (int i=0; i< numThreads; i++) { 313 renameStatus[i] = Idle; 314 315 stalls[i].iew = false; 316 stalls[i].commit = false; 317 serializeInst[i] = NULL; 318 319 instsInProgress[i] = 0; 320 321 emptyROB[i] = true; 322 323 serializeOnNextInst[i] = false; 324 } 325} 326 327template <class Impl> 328void 329DefaultRename<Impl>::squash(const InstSeqNum &squash_seq_num, unsigned tid) 330{ 331 DPRINTF(Rename, "[tid:%u]: Squashing instructions.\n",tid); 332 333 // Clear the stall signal if rename was blocked or unblocking before. 334 // If it still needs to block, the blocking should happen the next 335 // cycle and there should be space to hold everything due to the squash. 336 if (renameStatus[tid] == Blocked || 337 renameStatus[tid] == Unblocking || 338 renameStatus[tid] == SerializeStall) { 339 340 toDecode->renameUnblock[tid] = 1; 341 342 serializeInst[tid] = NULL; 343 } 344 345 // Set the status to Squashing. 346 renameStatus[tid] = Squashing; 347 348 // Squash any instructions from decode. 349 unsigned squashCount = 0; 350 351 for (int i=0; i<fromDecode->size; i++) { 352 if (fromDecode->insts[i]->threadNumber == tid && 353 fromDecode->insts[i]->seqNum > squash_seq_num) { 354 fromDecode->insts[i]->setSquashed(); 355 wroteToTimeBuffer = true; 356 squashCount++; 357 } 358 359 } 360 361 // Clear the instruction list and skid buffer in case they have any 362 // insts in them. Since we support multiple ISAs, we cant just: 363 // "insts[tid].clear();" or "skidBuffer[tid].clear()" since there is 364 // a possible delay slot inst for different architectures 365 // insts[tid].clear(); 366#if ISA_HAS_DELAY_SLOT 367 DPRINTF(Rename, "[tid:%i] Squashing incoming decode instructions until " 368 "[sn:%i].\n",tid, squash_seq_num); 369 ListIt ilist_it = insts[tid].begin(); 370 while (ilist_it != insts[tid].end()) { 371 if ((*ilist_it)->seqNum > squash_seq_num) { 372 (*ilist_it)->setSquashed(); 373 DPRINTF(Rename, "Squashing incoming decode instruction, " 374 "[tid:%i] [sn:%i] PC %08p.\n", tid, (*ilist_it)->seqNum, (*ilist_it)->PC); 375 } 376 ilist_it++; 377 } 378#else 379 insts[tid].clear(); 380#endif 381 382 // Clear the skid buffer in case it has any data in it. 383 // See comments above. 384 // skidBuffer[tid].clear(); 385#if ISA_HAS_DELAY_SLOT 386 DPRINTF(Rename, "[tid:%i] Squashing incoming skidbuffer instructions " 387 "until [sn:%i].\n", tid, squash_seq_num); 388 ListIt slist_it = skidBuffer[tid].begin(); 389 while (slist_it != skidBuffer[tid].end()) { 390 if ((*slist_it)->seqNum > squash_seq_num) { 391 (*slist_it)->setSquashed(); 392 DPRINTF(Rename, "Squashing skidbuffer instruction, [tid:%i] [sn:%i]" 393 "PC %08p.\n", tid, (*slist_it)->seqNum, (*slist_it)->PC); 394 } 395 slist_it++; 396 } 397#else 398 skidBuffer[tid].clear(); 399#endif 400 doSquash(squash_seq_num, tid); 401} 402 403template <class Impl> 404void 405DefaultRename<Impl>::tick() 406{ 407 wroteToTimeBuffer = false; 408 409 blockThisCycle = false; 410 411 bool status_change = false; 412 413 toIEWIndex = 0; 414 415 sortInsts(); 416 417 std::list<unsigned>::iterator threads = (*activeThreads).begin(); 418 419 // Check stall and squash signals. 420 while (threads != (*activeThreads).end()) { 421 unsigned tid = *threads++; 422 423 DPRINTF(Rename, "Processing [tid:%i]\n", tid); 424 425 status_change = checkSignalsAndUpdate(tid) || status_change; 426 427 rename(status_change, tid); 428 } 429 430 if (status_change) { 431 updateStatus(); 432 } 433 434 if (wroteToTimeBuffer) { 435 DPRINTF(Activity, "Activity this cycle.\n"); 436 cpu->activityThisCycle(); 437 } 438 439 threads = (*activeThreads).begin(); 440 441 while (threads != (*activeThreads).end()) { 442 unsigned tid = *threads++; 443 444 // If we committed this cycle then doneSeqNum will be > 0 445 if (fromCommit->commitInfo[tid].doneSeqNum != 0 && 446 !fromCommit->commitInfo[tid].squash && 447 renameStatus[tid] != Squashing) { 448 449 removeFromHistory(fromCommit->commitInfo[tid].doneSeqNum, 450 tid); 451 } 452 } 453 454 // @todo: make into updateProgress function 455 for (int tid=0; tid < numThreads; tid++) { 456 instsInProgress[tid] -= fromIEW->iewInfo[tid].dispatched; 457 458 assert(instsInProgress[tid] >=0); 459 } 460 461} 462 463template<class Impl> 464void 465DefaultRename<Impl>::rename(bool &status_change, unsigned tid) 466{ 467 // If status is Running or idle, 468 // call renameInsts() 469 // If status is Unblocking, 470 // buffer any instructions coming from decode 471 // continue trying to empty skid buffer 472 // check if stall conditions have passed 473 474 if (renameStatus[tid] == Blocked) { 475 ++renameBlockCycles; 476 } else if (renameStatus[tid] == Squashing) { 477 ++renameSquashCycles; 478 } else if (renameStatus[tid] == SerializeStall) { 479 ++renameSerializeStallCycles; 480 } 481 482 if (renameStatus[tid] == Running || 483 renameStatus[tid] == Idle) { 484 DPRINTF(Rename, "[tid:%u]: Not blocked, so attempting to run " 485 "stage.\n", tid); 486 487 renameInsts(tid); 488 } else if (renameStatus[tid] == Unblocking) { 489 renameInsts(tid); 490 491 if (validInsts()) { 492 // Add the current inputs to the skid buffer so they can be 493 // reprocessed when this stage unblocks. 494 skidInsert(tid); 495 } 496 497 // If we switched over to blocking, then there's a potential for 498 // an overall status change. 499 status_change = unblock(tid) || status_change || blockThisCycle; 500 } 501} 502 503template <class Impl> 504void 505DefaultRename<Impl>::renameInsts(unsigned tid) 506{ 507 // Instructions can be either in the skid buffer or the queue of 508 // instructions coming from decode, depending on the status. 509 int insts_available = renameStatus[tid] == Unblocking ? 510 skidBuffer[tid].size() : insts[tid].size(); 511 512 // Check the decode queue to see if instructions are available. 513 // If there are no available instructions to rename, then do nothing. 514 if (insts_available == 0) { 515 DPRINTF(Rename, "[tid:%u]: Nothing to do, breaking out early.\n", 516 tid); 517 // Should I change status to idle? 518 ++renameIdleCycles; 519 return; 520 } else if (renameStatus[tid] == Unblocking) { 521 ++renameUnblockCycles; 522 } else if (renameStatus[tid] == Running) { 523 ++renameRunCycles; 524 } 525 526 DynInstPtr inst; 527 528 // Will have to do a different calculation for the number of free 529 // entries. 530 int free_rob_entries = calcFreeROBEntries(tid); 531 int free_iq_entries = calcFreeIQEntries(tid); 532 int free_lsq_entries = calcFreeLSQEntries(tid); 533 int min_free_entries = free_rob_entries; 534 535 FullSource source = ROB; 536 537 if (free_iq_entries < min_free_entries) { 538 min_free_entries = free_iq_entries; 539 source = IQ; 540 } 541 542 if (free_lsq_entries < min_free_entries) { 543 min_free_entries = free_lsq_entries; 544 source = LSQ; 545 } 546 547 // Check if there's any space left. 548 if (min_free_entries <= 0) { 549 DPRINTF(Rename, "[tid:%u]: Blocking due to no free ROB/IQ/LSQ " 550 "entries.\n" 551 "ROB has %i free entries.\n" 552 "IQ has %i free entries.\n" 553 "LSQ has %i free entries.\n", 554 tid, 555 free_rob_entries, 556 free_iq_entries, 557 free_lsq_entries); 558 559 blockThisCycle = true; 560 561 block(tid); 562 563 incrFullStat(source); 564 565 return; 566 } else if (min_free_entries < insts_available) { 567 DPRINTF(Rename, "[tid:%u]: Will have to block this cycle." 568 "%i insts available, but only %i insts can be " 569 "renamed due to ROB/IQ/LSQ limits.\n", 570 tid, insts_available, min_free_entries); 571 572 insts_available = min_free_entries; 573 574 blockThisCycle = true; 575 576 incrFullStat(source); 577 } 578 579 InstQueue &insts_to_rename = renameStatus[tid] == Unblocking ? 580 skidBuffer[tid] : insts[tid]; 581 582 DPRINTF(Rename, "[tid:%u]: %i available instructions to " 583 "send iew.\n", tid, insts_available); 584 585 DPRINTF(Rename, "[tid:%u]: %i insts pipelining from Rename | %i insts " 586 "dispatched to IQ last cycle.\n", 587 tid, instsInProgress[tid], fromIEW->iewInfo[tid].dispatched); 588 589 // Handle serializing the next instruction if necessary. 590 if (serializeOnNextInst[tid]) { 591 if (emptyROB[tid] && instsInProgress[tid] == 0) { 592 // ROB already empty; no need to serialize. 593 serializeOnNextInst[tid] = false; 594 } else if (!insts_to_rename.empty()) { 595 insts_to_rename.front()->setSerializeBefore(); 596 } 597 } 598 599 int renamed_insts = 0; 600 601 while (insts_available > 0 && toIEWIndex < renameWidth) { 602 DPRINTF(Rename, "[tid:%u]: Sending instructions to IEW.\n", tid); 603 604 assert(!insts_to_rename.empty()); 605 606 inst = insts_to_rename.front(); 607 608 insts_to_rename.pop_front(); 609 610 if (renameStatus[tid] == Unblocking) { 611 DPRINTF(Rename,"[tid:%u]: Removing [sn:%lli] PC:%#x from rename " 612 "skidBuffer\n", 613 tid, inst->seqNum, inst->readPC()); 614 } 615 616 if (inst->isSquashed()) { 617 DPRINTF(Rename, "[tid:%u]: instruction %i with PC %#x is " 618 "squashed, skipping.\n", 619 tid, inst->seqNum, inst->readPC()); 620 621 ++renameSquashedInsts; 622 623 // Decrement how many instructions are available. 624 --insts_available; 625 626 continue; 627 } 628 629 DPRINTF(Rename, "[tid:%u]: Processing instruction [sn:%lli] with " 630 "PC %#x.\n", 631 tid, inst->seqNum, inst->readPC()); 632 633 // Handle serializeAfter/serializeBefore instructions. 634 // serializeAfter marks the next instruction as serializeBefore. 635 // serializeBefore makes the instruction wait in rename until the ROB 636 // is empty. 637 638 // In this model, IPR accesses are serialize before 639 // instructions, and store conditionals are serialize after 640 // instructions. This is mainly due to lack of support for 641 // out-of-order operations of either of those classes of 642 // instructions. 643 if ((inst->isIprAccess() || inst->isSerializeBefore()) && 644 !inst->isSerializeHandled()) { 645 DPRINTF(Rename, "Serialize before instruction encountered.\n"); 646 647 if (!inst->isTempSerializeBefore()) { 648 renamedSerializing++; 649 inst->setSerializeHandled(); 650 } else { 651 renamedTempSerializing++; 652 } 653 654 // Change status over to SerializeStall so that other stages know 655 // what this is blocked on. 656 renameStatus[tid] = SerializeStall; 657 658 serializeInst[tid] = inst; 659 660 blockThisCycle = true; 661 662 break; 663 } else if ((inst->isStoreConditional() || inst->isSerializeAfter()) && 664 !inst->isSerializeHandled()) { 665 DPRINTF(Rename, "Serialize after instruction encountered.\n"); 666 667 renamedSerializing++; 668 669 inst->setSerializeHandled(); 670 671 serializeAfter(insts_to_rename, tid); 672 } 673 674 // Check here to make sure there are enough destination registers 675 // to rename to. Otherwise block. 676 if (renameMap[tid]->numFreeEntries() < inst->numDestRegs()) { 677 DPRINTF(Rename, "Blocking due to lack of free " 678 "physical registers to rename to.\n"); 679 blockThisCycle = true; 680 681 ++renameFullRegistersEvents; 682 683 break; 684 } 685 686 renameSrcRegs(inst, inst->threadNumber); 687 688 renameDestRegs(inst, inst->threadNumber); 689 690 ++renamed_insts; 691 692 // Put instruction in rename queue. 693 toIEW->insts[toIEWIndex] = inst; 694 ++(toIEW->size); 695 696 // Increment which instruction we're on. 697 ++toIEWIndex; 698 699 // Decrement how many instructions are available. 700 --insts_available; 701 } 702 703 instsInProgress[tid] += renamed_insts; 704 renameRenamedInsts += renamed_insts; 705 706 // If we wrote to the time buffer, record this. 707 if (toIEWIndex) { 708 wroteToTimeBuffer = true; 709 } 710 711 // Check if there's any instructions left that haven't yet been renamed. 712 // If so then block. 713 if (insts_available) { 714 blockThisCycle = true; 715 } 716 717 if (blockThisCycle) { 718 block(tid); 719 toDecode->renameUnblock[tid] = false; 720 } 721} 722 723template<class Impl> 724void 725DefaultRename<Impl>::skidInsert(unsigned tid) 726{ 727 DynInstPtr inst = NULL; 728 729 while (!insts[tid].empty()) { 730 inst = insts[tid].front(); 731 732 insts[tid].pop_front(); 733 734 assert(tid == inst->threadNumber); 735 736 DPRINTF(Rename, "[tid:%u]: Inserting [sn:%lli] PC:%#x into Rename " 737 "skidBuffer\n", tid, inst->seqNum, inst->readPC()); 738 739 ++renameSkidInsts; 740 741 skidBuffer[tid].push_back(inst); 742 } 743 744 if (skidBuffer[tid].size() > skidBufferMax) 745 panic("Skidbuffer Exceeded Max Size"); 746} 747 748template <class Impl> 749void 750DefaultRename<Impl>::sortInsts() 751{ 752 int insts_from_decode = fromDecode->size; 753#ifdef DEBUG 754#if !ISA_HAS_DELAY_SLOT 755 for (int i=0; i < numThreads; i++) 756 assert(insts[i].empty()); 757#endif 758#endif 759 for (int i = 0; i < insts_from_decode; ++i) { 760 DynInstPtr inst = fromDecode->insts[i]; 761 insts[inst->threadNumber].push_back(inst); 762 } 763} 764 765template<class Impl> 766bool 767DefaultRename<Impl>::skidsEmpty() 768{ 769 std::list<unsigned>::iterator threads = (*activeThreads).begin(); 770 771 while (threads != (*activeThreads).end()) { 772 if (!skidBuffer[*threads++].empty()) 773 return false; 774 } 775 776 return true; 777} 778 779template<class Impl> 780void 781DefaultRename<Impl>::updateStatus() 782{ 783 bool any_unblocking = false; 784 785 std::list<unsigned>::iterator threads = (*activeThreads).begin(); 786 787 threads = (*activeThreads).begin(); 788 789 while (threads != (*activeThreads).end()) { 790 unsigned tid = *threads++; 791 792 if (renameStatus[tid] == Unblocking) { 793 any_unblocking = true; 794 break; 795 } 796 } 797 798 // Rename will have activity if it's unblocking. 799 if (any_unblocking) { 800 if (_status == Inactive) { 801 _status = Active; 802 803 DPRINTF(Activity, "Activating stage.\n"); 804 805 cpu->activateStage(O3CPU::RenameIdx); 806 } 807 } else { 808 // If it's not unblocking, then rename will not have any internal 809 // activity. Switch it to inactive. 810 if (_status == Active) { 811 _status = Inactive; 812 DPRINTF(Activity, "Deactivating stage.\n"); 813 814 cpu->deactivateStage(O3CPU::RenameIdx); 815 } 816 } 817} 818 819template <class Impl> 820bool 821DefaultRename<Impl>::block(unsigned tid) 822{ 823 DPRINTF(Rename, "[tid:%u]: Blocking.\n", tid); 824 825 // Add the current inputs onto the skid buffer, so they can be 826 // reprocessed when this stage unblocks. 827 skidInsert(tid); 828 829 // Only signal backwards to block if the previous stages do not think 830 // rename is already blocked. 831 if (renameStatus[tid] != Blocked) { 832 if (renameStatus[tid] != Unblocking) { 833 toDecode->renameBlock[tid] = true; 834 toDecode->renameUnblock[tid] = false; 835 wroteToTimeBuffer = true; 836 } 837 838 // Rename can not go from SerializeStall to Blocked, otherwise 839 // it would not know to complete the serialize stall. 840 if (renameStatus[tid] != SerializeStall) { 841 // Set status to Blocked. 842 renameStatus[tid] = Blocked; 843 return true; 844 } 845 } 846 847 return false; 848} 849 850template <class Impl> 851bool 852DefaultRename<Impl>::unblock(unsigned tid) 853{ 854 DPRINTF(Rename, "[tid:%u]: Trying to unblock.\n", tid); 855 856 // Rename is done unblocking if the skid buffer is empty. 857 if (skidBuffer[tid].empty() && renameStatus[tid] != SerializeStall) { 858 859 DPRINTF(Rename, "[tid:%u]: Done unblocking.\n", tid); 860 861 toDecode->renameUnblock[tid] = true; 862 wroteToTimeBuffer = true; 863 864 renameStatus[tid] = Running; 865 return true; 866 } 867 868 return false; 869} 870 871template <class Impl> 872void 873DefaultRename<Impl>::doSquash(const InstSeqNum &squashed_seq_num, unsigned tid) 874{ 875 typename std::list<RenameHistory>::iterator hb_it = 876 historyBuffer[tid].begin(); 877 878 // After a syscall squashes everything, the history buffer may be empty 879 // but the ROB may still be squashing instructions. 880 if (historyBuffer[tid].empty()) { 881 return; 882 } 883 884 // Go through the most recent instructions, undoing the mappings 885 // they did and freeing up the registers. 886 while (!historyBuffer[tid].empty() && 887 (*hb_it).instSeqNum > squashed_seq_num) { 888 assert(hb_it != historyBuffer[tid].end()); 889 890 DPRINTF(Rename, "[tid:%u]: Removing history entry with sequence " 891 "number %i.\n", tid, (*hb_it).instSeqNum); 892 893 // Tell the rename map to set the architected register to the 894 // previous physical register that it was renamed to. 895 renameMap[tid]->setEntry(hb_it->archReg, hb_it->prevPhysReg); 896 897 // Put the renamed physical register back on the free list. 898 freeList->addReg(hb_it->newPhysReg); 899 900 // Be sure to mark its register as ready if it's a misc register. 901 if (hb_it->newPhysReg >= maxPhysicalRegs) { 902 scoreboard->setReg(hb_it->newPhysReg); 903 } 904 905 historyBuffer[tid].erase(hb_it++); 906 907 ++renameUndoneMaps; 908 } 909} 910 911template<class Impl> 912void 913DefaultRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num, unsigned tid) 914{ 915 DPRINTF(Rename, "[tid:%u]: Removing a committed instruction from the " 916 "history buffer %u (size=%i), until [sn:%lli].\n", 917 tid, tid, historyBuffer[tid].size(), inst_seq_num); 918 919 typename std::list<RenameHistory>::iterator hb_it = 920 historyBuffer[tid].end(); 921 922 --hb_it; 923 924 if (historyBuffer[tid].empty()) { 925 DPRINTF(Rename, "[tid:%u]: History buffer is empty.\n", tid); 926 return; 927 } else if (hb_it->instSeqNum > inst_seq_num) { 928 DPRINTF(Rename, "[tid:%u]: Old sequence number encountered. Ensure " 929 "that a syscall happened recently.\n", tid); 930 return; 931 } 932 933 // Commit all the renames up until (and including) the committed sequence 934 // number. Some or even all of the committed instructions may not have 935 // rename histories if they did not have destination registers that were 936 // renamed. 937 while (!historyBuffer[tid].empty() && 938 hb_it != historyBuffer[tid].end() && 939 (*hb_it).instSeqNum <= inst_seq_num) { 940 941 DPRINTF(Rename, "[tid:%u]: Freeing up older rename of reg %i, " 942 "[sn:%lli].\n", 943 tid, (*hb_it).prevPhysReg, (*hb_it).instSeqNum); 944 945 freeList->addReg((*hb_it).prevPhysReg); 946 ++renameCommittedMaps; 947 948 historyBuffer[tid].erase(hb_it--); 949 } 950} 951 952template <class Impl> 953inline void 954DefaultRename<Impl>::renameSrcRegs(DynInstPtr &inst,unsigned tid) 955{ 956 assert(renameMap[tid] != 0); 957 958 unsigned num_src_regs = inst->numSrcRegs(); 959 960 // Get the architectual register numbers from the source and 961 // destination operands, and redirect them to the right register. 962 // Will need to mark dependencies though. 963 for (int src_idx = 0; src_idx < num_src_regs; src_idx++) { 964 RegIndex src_reg = inst->srcRegIdx(src_idx); 965 RegIndex flat_src_reg = src_reg; 966 if (src_reg < TheISA::FP_Base_DepTag) { 967 flat_src_reg = TheISA::flattenIntIndex(inst->tcBase(), src_reg); 968 DPRINTF(Rename, "Flattening index %d to %d.\n", (int)src_reg, (int)flat_src_reg); 969 } 970 inst->flattenSrcReg(src_idx, flat_src_reg); 971 972 // Look up the source registers to get the phys. register they've 973 // been renamed to, and set the sources to those registers. 974 PhysRegIndex renamed_reg = renameMap[tid]->lookup(flat_src_reg); 975 976 DPRINTF(Rename, "[tid:%u]: Looking up arch reg %i, got " 977 "physical reg %i.\n", tid, (int)flat_src_reg, 978 (int)renamed_reg); 979 980 inst->renameSrcReg(src_idx, renamed_reg); 981 982 // See if the register is ready or not. 983 if (scoreboard->getReg(renamed_reg) == true) { 984 DPRINTF(Rename, "[tid:%u]: Register is ready.\n", tid); 985 986 inst->markSrcRegReady(src_idx); 987 } 988 989 ++renameRenameLookups; 990 } 991} 992 993template <class Impl> 994inline void 995DefaultRename<Impl>::renameDestRegs(DynInstPtr &inst,unsigned tid) 996{ 997 typename RenameMap::RenameInfo rename_result; 998 999 unsigned num_dest_regs = inst->numDestRegs(); 1000 1001 // Rename the destination registers. 1002 for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++) { 1003 RegIndex dest_reg = inst->destRegIdx(dest_idx); 1004 RegIndex flat_dest_reg = dest_reg; 1005 if (dest_reg < TheISA::FP_Base_DepTag) { 1006 flat_dest_reg = TheISA::flattenIntIndex(inst->tcBase(), dest_reg); 1007 DPRINTF(Rename, "Flattening index %d to %d.\n", (int)dest_reg, (int)flat_dest_reg); 1008 } 1009 1010 inst->flattenDestReg(dest_idx, flat_dest_reg); 1011 1012 // Get the physical register that the destination will be 1013 // renamed to. 1014 rename_result = renameMap[tid]->rename(flat_dest_reg); 1015 1016 //Mark Scoreboard entry as not ready 1017 scoreboard->unsetReg(rename_result.first); 1018 1019 DPRINTF(Rename, "[tid:%u]: Renaming arch reg %i to physical " 1020 "reg %i.\n", tid, (int)flat_dest_reg, 1021 (int)rename_result.first); 1022 1023 // Record the rename information so that a history can be kept. 1024 RenameHistory hb_entry(inst->seqNum, flat_dest_reg, 1025 rename_result.first, 1026 rename_result.second); 1027 1028 historyBuffer[tid].push_front(hb_entry); 1029 1030 DPRINTF(Rename, "[tid:%u]: Adding instruction to history buffer " 1031 "(size=%i), [sn:%lli].\n",tid, 1032 historyBuffer[tid].size(), 1033 (*historyBuffer[tid].begin()).instSeqNum); 1034 1035 // Tell the instruction to rename the appropriate destination 1036 // register (dest_idx) to the new physical register 1037 // (rename_result.first), and record the previous physical 1038 // register that the same logical register was renamed to 1039 // (rename_result.second). 1040 inst->renameDestReg(dest_idx, 1041 rename_result.first, 1042 rename_result.second); 1043 1044 ++renameRenamedOperands; 1045 } 1046} 1047 1048template <class Impl> 1049inline int 1050DefaultRename<Impl>::calcFreeROBEntries(unsigned tid) 1051{ 1052 int num_free = freeEntries[tid].robEntries - 1053 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched); 1054 1055 //DPRINTF(Rename,"[tid:%i]: %i rob free\n",tid,num_free); 1056 1057 return num_free; 1058} 1059 1060template <class Impl> 1061inline int 1062DefaultRename<Impl>::calcFreeIQEntries(unsigned tid) 1063{ 1064 int num_free = freeEntries[tid].iqEntries - 1065 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched); 1066 1067 //DPRINTF(Rename,"[tid:%i]: %i iq free\n",tid,num_free); 1068 1069 return num_free; 1070} 1071 1072template <class Impl> 1073inline int 1074DefaultRename<Impl>::calcFreeLSQEntries(unsigned tid) 1075{ 1076 int num_free = freeEntries[tid].lsqEntries - 1077 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatchedToLSQ); 1078 1079 //DPRINTF(Rename,"[tid:%i]: %i lsq free\n",tid,num_free); 1080 1081 return num_free; 1082} 1083 1084template <class Impl> 1085unsigned 1086DefaultRename<Impl>::validInsts() 1087{ 1088 unsigned inst_count = 0; 1089 1090 for (int i=0; i<fromDecode->size; i++) { 1091 if (!fromDecode->insts[i]->isSquashed()) 1092 inst_count++; 1093 } 1094 1095 return inst_count; 1096} 1097 1098template <class Impl> 1099void 1100DefaultRename<Impl>::readStallSignals(unsigned tid) 1101{ 1102 if (fromIEW->iewBlock[tid]) { 1103 stalls[tid].iew = true; 1104 } 1105 1106 if (fromIEW->iewUnblock[tid]) { 1107 assert(stalls[tid].iew); 1108 stalls[tid].iew = false; 1109 } 1110 1111 if (fromCommit->commitBlock[tid]) { 1112 stalls[tid].commit = true; 1113 } 1114 1115 if (fromCommit->commitUnblock[tid]) { 1116 assert(stalls[tid].commit); 1117 stalls[tid].commit = false; 1118 } 1119} 1120 1121template <class Impl> 1122bool 1123DefaultRename<Impl>::checkStall(unsigned tid) 1124{ 1125 bool ret_val = false; 1126 1127 if (stalls[tid].iew) { 1128 DPRINTF(Rename,"[tid:%i]: Stall from IEW stage detected.\n", tid); 1129 ret_val = true; 1130 } else if (stalls[tid].commit) { 1131 DPRINTF(Rename,"[tid:%i]: Stall from Commit stage detected.\n", tid); 1132 ret_val = true; 1133 } else if (calcFreeROBEntries(tid) <= 0) { 1134 DPRINTF(Rename,"[tid:%i]: Stall: ROB has 0 free entries.\n", tid); 1135 ret_val = true; 1136 } else if (calcFreeIQEntries(tid) <= 0) { 1137 DPRINTF(Rename,"[tid:%i]: Stall: IQ has 0 free entries.\n", tid); 1138 ret_val = true; 1139 } else if (calcFreeLSQEntries(tid) <= 0) { 1140 DPRINTF(Rename,"[tid:%i]: Stall: LSQ has 0 free entries.\n", tid); 1141 ret_val = true; 1142 } else if (renameMap[tid]->numFreeEntries() <= 0) { 1143 DPRINTF(Rename,"[tid:%i]: Stall: RenameMap has 0 free entries.\n", tid); 1144 ret_val = true; 1145 } else if (renameStatus[tid] == SerializeStall && 1146 (!emptyROB[tid] || instsInProgress[tid])) { 1147 DPRINTF(Rename,"[tid:%i]: Stall: Serialize stall and ROB is not " 1148 "empty.\n", 1149 tid); 1150 ret_val = true; 1151 } 1152 1153 return ret_val; 1154} 1155 1156template <class Impl> 1157void 1158DefaultRename<Impl>::readFreeEntries(unsigned tid) 1159{ 1160 bool updated = false; 1161 if (fromIEW->iewInfo[tid].usedIQ) { 1162 freeEntries[tid].iqEntries = 1163 fromIEW->iewInfo[tid].freeIQEntries; 1164 updated = true; 1165 } 1166 1167 if (fromIEW->iewInfo[tid].usedLSQ) { 1168 freeEntries[tid].lsqEntries = 1169 fromIEW->iewInfo[tid].freeLSQEntries; 1170 updated = true; 1171 } 1172 1173 if (fromCommit->commitInfo[tid].usedROB) { 1174 freeEntries[tid].robEntries = 1175 fromCommit->commitInfo[tid].freeROBEntries; 1176 emptyROB[tid] = fromCommit->commitInfo[tid].emptyROB; 1177 updated = true; 1178 } 1179 1180 DPRINTF(Rename, "[tid:%i]: Free IQ: %i, Free ROB: %i, Free LSQ: %i\n", 1181 tid, 1182 freeEntries[tid].iqEntries, 1183 freeEntries[tid].robEntries, 1184 freeEntries[tid].lsqEntries); 1185 1186 DPRINTF(Rename, "[tid:%i]: %i instructions not yet in ROB\n", 1187 tid, instsInProgress[tid]); 1188} 1189 1190template <class Impl> 1191bool 1192DefaultRename<Impl>::checkSignalsAndUpdate(unsigned tid) 1193{ 1194 // Check if there's a squash signal, squash if there is 1195 // Check stall signals, block if necessary. 1196 // If status was blocked 1197 // check if stall conditions have passed 1198 // if so then go to unblocking 1199 // If status was Squashing 1200 // check if squashing is not high. Switch to running this cycle. 1201 // If status was serialize stall 1202 // check if ROB is empty and no insts are in flight to the ROB 1203 1204 readFreeEntries(tid); 1205 readStallSignals(tid); 1206 1207 if (fromCommit->commitInfo[tid].squash) { 1208 DPRINTF(Rename, "[tid:%u]: Squashing instructions due to squash from " 1209 "commit.\n", tid); 1210 1211#if ISA_HAS_DELAY_SLOT 1212 InstSeqNum squashed_seq_num = fromCommit->commitInfo[tid].bdelayDoneSeqNum; 1213#else 1214 InstSeqNum squashed_seq_num = fromCommit->commitInfo[tid].doneSeqNum; 1215#endif 1216 1217 squash(squashed_seq_num, tid); 1218 1219 return true; 1220 } 1221 1222 if (fromCommit->commitInfo[tid].robSquashing) { 1223 DPRINTF(Rename, "[tid:%u]: ROB is still squashing.\n", tid); 1224 1225 renameStatus[tid] = Squashing; 1226 1227 return true; 1228 } 1229 1230 if (checkStall(tid)) { 1231 return block(tid); 1232 } 1233 1234 if (renameStatus[tid] == Blocked) { 1235 DPRINTF(Rename, "[tid:%u]: Done blocking, switching to unblocking.\n", 1236 tid); 1237 1238 renameStatus[tid] = Unblocking; 1239 1240 unblock(tid); 1241 1242 return true; 1243 } 1244 1245 if (renameStatus[tid] == Squashing) { 1246 // Switch status to running if rename isn't being told to block or 1247 // squash this cycle. 1248 DPRINTF(Rename, "[tid:%u]: Done squashing, switching to running.\n", 1249 tid); 1250 1251 renameStatus[tid] = Running; 1252 1253 return false; 1254 } 1255 1256 if (renameStatus[tid] == SerializeStall) { 1257 // Stall ends once the ROB is free. 1258 DPRINTF(Rename, "[tid:%u]: Done with serialize stall, switching to " 1259 "unblocking.\n", tid); 1260 1261 DynInstPtr serial_inst = serializeInst[tid]; 1262 1263 renameStatus[tid] = Unblocking; 1264 1265 unblock(tid); 1266 1267 DPRINTF(Rename, "[tid:%u]: Processing instruction [%lli] with " 1268 "PC %#x.\n", 1269 tid, serial_inst->seqNum, serial_inst->readPC()); 1270 1271 // Put instruction into queue here. 1272 serial_inst->clearSerializeBefore(); 1273 1274 if (!skidBuffer[tid].empty()) { 1275 skidBuffer[tid].push_front(serial_inst); 1276 } else { 1277 insts[tid].push_front(serial_inst); 1278 } 1279 1280 DPRINTF(Rename, "[tid:%u]: Instruction must be processed by rename." 1281 " Adding to front of list.\n", tid); 1282 1283 serializeInst[tid] = NULL; 1284 1285 return true; 1286 } 1287 1288 // If we've reached this point, we have not gotten any signals that 1289 // cause rename to change its status. Rename remains the same as before. 1290 return false; 1291} 1292 1293template<class Impl> 1294void 1295DefaultRename<Impl>::serializeAfter(InstQueue &inst_list, 1296 unsigned tid) 1297{ 1298 if (inst_list.empty()) { 1299 // Mark a bit to say that I must serialize on the next instruction. 1300 serializeOnNextInst[tid] = true; 1301 return; 1302 } 1303 1304 // Set the next instruction as serializing. 1305 inst_list.front()->setSerializeBefore(); 1306} 1307 1308template <class Impl> 1309inline void 1310DefaultRename<Impl>::incrFullStat(const FullSource &source) 1311{ 1312 switch (source) { 1313 case ROB: 1314 ++renameROBFullEvents; 1315 break; 1316 case IQ: 1317 ++renameIQFullEvents; 1318 break; 1319 case LSQ: 1320 ++renameLSQFullEvents; 1321 break; 1322 default: 1323 panic("Rename full stall stat should be incremented for a reason!"); 1324 break; 1325 } 1326} 1327 1328template <class Impl> 1329void 1330DefaultRename<Impl>::dumpHistory() 1331{ 1332 typename std::list<RenameHistory>::iterator buf_it; 1333 1334 for (int i = 0; i < numThreads; i++) { 1335 1336 buf_it = historyBuffer[i].begin(); 1337 1338 while (buf_it != historyBuffer[i].end()) { 1339 cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys " 1340 "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg, 1341 (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg); 1342 1343 buf_it++; 1344 } 1345 } 1346} 1347