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