1/* 2 * Copyright (c) 2010-2012, 2014-2015 ARM Limited 3 * Copyright (c) 2013 Advanced Micro Devices, Inc. 4 * All rights reserved. 5 * 6 * The license below extends only to copyright in the software and shall 7 * not be construed as granting a license to any other intellectual 8 * property including but not limited to intellectual property relating 9 * to a hardware implementation of the functionality of the software 10 * licensed hereunder. You may use the software subject to the license 11 * terms below provided that you ensure that this notice is replicated 12 * unmodified and in its entirety in all distributions of the software, 13 * modified or unmodified, in source code or in binary form. 14 * 15 * Copyright (c) 2004-2006 The Regents of The University of Michigan 16 * All rights reserved. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions are 20 * met: redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer; 22 * redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution; 25 * neither the name of the copyright holders nor the names of its 26 * contributors may be used to endorse or promote products derived from 27 * this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Authors: Kevin Lim 42 * Korey Sewell 43 */ 44 45#ifndef __CPU_O3_RENAME_IMPL_HH__ 46#define __CPU_O3_RENAME_IMPL_HH__ 47 48#include <list> 49 50#include "arch/isa_traits.hh" 51#include "arch/registers.hh" 52#include "config/the_isa.hh" 53#include "cpu/o3/rename.hh" 54#include "cpu/reg_class.hh" 55#include "debug/Activity.hh" 56#include "debug/Rename.hh" 57#include "debug/O3PipeView.hh" 58#include "params/DerivO3CPU.hh" 59 60using namespace std; 61 62template <class Impl> 63DefaultRename<Impl>::DefaultRename(O3CPU *_cpu, DerivO3CPUParams *params) 64 : cpu(_cpu), 65 iewToRenameDelay(params->iewToRenameDelay), 66 decodeToRenameDelay(params->decodeToRenameDelay), 67 commitToRenameDelay(params->commitToRenameDelay), 68 renameWidth(params->renameWidth), 69 commitWidth(params->commitWidth), 70 numThreads(params->numThreads), 71 maxPhysicalRegs(params->numPhysIntRegs + params->numPhysFloatRegs
| 1/* 2 * Copyright (c) 2010-2012, 2014-2015 ARM Limited 3 * Copyright (c) 2013 Advanced Micro Devices, Inc. 4 * All rights reserved. 5 * 6 * The license below extends only to copyright in the software and shall 7 * not be construed as granting a license to any other intellectual 8 * property including but not limited to intellectual property relating 9 * to a hardware implementation of the functionality of the software 10 * licensed hereunder. You may use the software subject to the license 11 * terms below provided that you ensure that this notice is replicated 12 * unmodified and in its entirety in all distributions of the software, 13 * modified or unmodified, in source code or in binary form. 14 * 15 * Copyright (c) 2004-2006 The Regents of The University of Michigan 16 * All rights reserved. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions are 20 * met: redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer; 22 * redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution; 25 * neither the name of the copyright holders nor the names of its 26 * contributors may be used to endorse or promote products derived from 27 * this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Authors: Kevin Lim 42 * Korey Sewell 43 */ 44 45#ifndef __CPU_O3_RENAME_IMPL_HH__ 46#define __CPU_O3_RENAME_IMPL_HH__ 47 48#include <list> 49 50#include "arch/isa_traits.hh" 51#include "arch/registers.hh" 52#include "config/the_isa.hh" 53#include "cpu/o3/rename.hh" 54#include "cpu/reg_class.hh" 55#include "debug/Activity.hh" 56#include "debug/Rename.hh" 57#include "debug/O3PipeView.hh" 58#include "params/DerivO3CPU.hh" 59 60using namespace std; 61 62template <class Impl> 63DefaultRename<Impl>::DefaultRename(O3CPU *_cpu, DerivO3CPUParams *params) 64 : cpu(_cpu), 65 iewToRenameDelay(params->iewToRenameDelay), 66 decodeToRenameDelay(params->decodeToRenameDelay), 67 commitToRenameDelay(params->commitToRenameDelay), 68 renameWidth(params->renameWidth), 69 commitWidth(params->commitWidth), 70 numThreads(params->numThreads), 71 maxPhysicalRegs(params->numPhysIntRegs + params->numPhysFloatRegs
|
72 + params->numPhysCCRegs + params->numPhysVectorRegs)
| 72 + params->numPhysCCRegs)
|
73{ 74 if (renameWidth > Impl::MaxWidth) 75 fatal("renameWidth (%d) is larger than compiled limit (%d),\n" 76 "\tincrease MaxWidth in src/cpu/o3/impl.hh\n", 77 renameWidth, static_cast<int>(Impl::MaxWidth)); 78 79 // @todo: Make into a parameter. 80 skidBufferMax = (decodeToRenameDelay + 1) * params->decodeWidth; 81} 82 83template <class Impl> 84std::string 85DefaultRename<Impl>::name() const 86{ 87 return cpu->name() + ".rename"; 88} 89 90template <class Impl> 91void 92DefaultRename<Impl>::regStats() 93{ 94 renameSquashCycles 95 .name(name() + ".SquashCycles") 96 .desc("Number of cycles rename is squashing") 97 .prereq(renameSquashCycles); 98 renameIdleCycles 99 .name(name() + ".IdleCycles") 100 .desc("Number of cycles rename is idle") 101 .prereq(renameIdleCycles); 102 renameBlockCycles 103 .name(name() + ".BlockCycles") 104 .desc("Number of cycles rename is blocking") 105 .prereq(renameBlockCycles); 106 renameSerializeStallCycles 107 .name(name() + ".serializeStallCycles") 108 .desc("count of cycles rename stalled for serializing inst") 109 .flags(Stats::total); 110 renameRunCycles 111 .name(name() + ".RunCycles") 112 .desc("Number of cycles rename is running") 113 .prereq(renameIdleCycles); 114 renameUnblockCycles 115 .name(name() + ".UnblockCycles") 116 .desc("Number of cycles rename is unblocking") 117 .prereq(renameUnblockCycles); 118 renameRenamedInsts 119 .name(name() + ".RenamedInsts") 120 .desc("Number of instructions processed by rename") 121 .prereq(renameRenamedInsts); 122 renameSquashedInsts 123 .name(name() + ".SquashedInsts") 124 .desc("Number of squashed instructions processed by rename") 125 .prereq(renameSquashedInsts); 126 renameROBFullEvents 127 .name(name() + ".ROBFullEvents") 128 .desc("Number of times rename has blocked due to ROB full") 129 .prereq(renameROBFullEvents); 130 renameIQFullEvents 131 .name(name() + ".IQFullEvents") 132 .desc("Number of times rename has blocked due to IQ full") 133 .prereq(renameIQFullEvents); 134 renameLQFullEvents 135 .name(name() + ".LQFullEvents") 136 .desc("Number of times rename has blocked due to LQ full") 137 .prereq(renameLQFullEvents); 138 renameSQFullEvents 139 .name(name() + ".SQFullEvents") 140 .desc("Number of times rename has blocked due to SQ full") 141 .prereq(renameSQFullEvents); 142 renameFullRegistersEvents 143 .name(name() + ".FullRegisterEvents") 144 .desc("Number of times there has been no free registers") 145 .prereq(renameFullRegistersEvents); 146 renameRenamedOperands 147 .name(name() + ".RenamedOperands") 148 .desc("Number of destination operands rename has renamed") 149 .prereq(renameRenamedOperands); 150 renameRenameLookups 151 .name(name() + ".RenameLookups") 152 .desc("Number of register rename lookups that rename has made") 153 .prereq(renameRenameLookups); 154 renameCommittedMaps 155 .name(name() + ".CommittedMaps") 156 .desc("Number of HB maps that are committed") 157 .prereq(renameCommittedMaps); 158 renameUndoneMaps 159 .name(name() + ".UndoneMaps") 160 .desc("Number of HB maps that are undone due to squashing") 161 .prereq(renameUndoneMaps); 162 renamedSerializing 163 .name(name() + ".serializingInsts") 164 .desc("count of serializing insts renamed") 165 .flags(Stats::total) 166 ; 167 renamedTempSerializing 168 .name(name() + ".tempSerializingInsts") 169 .desc("count of temporary serializing insts renamed") 170 .flags(Stats::total) 171 ; 172 renameSkidInsts 173 .name(name() + ".skidInsts") 174 .desc("count of insts added to the skid buffer") 175 .flags(Stats::total) 176 ; 177 intRenameLookups 178 .name(name() + ".int_rename_lookups") 179 .desc("Number of integer rename lookups") 180 .prereq(intRenameLookups); 181 fpRenameLookups 182 .name(name() + ".fp_rename_lookups") 183 .desc("Number of floating rename lookups") 184 .prereq(fpRenameLookups); 185} 186 187template <class Impl> 188void 189DefaultRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 190{ 191 timeBuffer = tb_ptr; 192 193 // Setup wire to read information from time buffer, from IEW stage. 194 fromIEW = timeBuffer->getWire(-iewToRenameDelay); 195 196 // Setup wire to read infromation from time buffer, from commit stage. 197 fromCommit = timeBuffer->getWire(-commitToRenameDelay); 198 199 // Setup wire to write information to previous stages. 200 toDecode = timeBuffer->getWire(0); 201} 202 203template <class Impl> 204void 205DefaultRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 206{ 207 renameQueue = rq_ptr; 208 209 // Setup wire to write information to future stages. 210 toIEW = renameQueue->getWire(0); 211} 212 213template <class Impl> 214void 215DefaultRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr) 216{ 217 decodeQueue = dq_ptr; 218 219 // Setup wire to get information from decode. 220 fromDecode = decodeQueue->getWire(-decodeToRenameDelay); 221} 222 223template <class Impl> 224void 225DefaultRename<Impl>::startupStage() 226{ 227 resetStage(); 228} 229 230template <class Impl> 231void 232DefaultRename<Impl>::resetStage() 233{ 234 _status = Inactive; 235 236 resumeSerialize = false; 237 resumeUnblocking = false; 238 239 // Grab the number of free entries directly from the stages. 240 for (ThreadID tid = 0; tid < numThreads; tid++) { 241 renameStatus[tid] = Idle; 242 243 freeEntries[tid].iqEntries = iew_ptr->instQueue.numFreeEntries(tid); 244 freeEntries[tid].lqEntries = iew_ptr->ldstQueue.numFreeLoadEntries(tid); 245 freeEntries[tid].sqEntries = iew_ptr->ldstQueue.numFreeStoreEntries(tid); 246 freeEntries[tid].robEntries = commit_ptr->numROBFreeEntries(tid); 247 emptyROB[tid] = true; 248 249 stalls[tid].iew = false; 250 serializeInst[tid] = NULL; 251 252 instsInProgress[tid] = 0; 253 loadsInProgress[tid] = 0; 254 storesInProgress[tid] = 0; 255 256 serializeOnNextInst[tid] = false; 257 } 258} 259 260template<class Impl> 261void 262DefaultRename<Impl>::setActiveThreads(list<ThreadID> *at_ptr) 263{ 264 activeThreads = at_ptr; 265} 266 267 268template <class Impl> 269void 270DefaultRename<Impl>::setRenameMap(RenameMap rm_ptr[]) 271{ 272 for (ThreadID tid = 0; tid < numThreads; tid++) 273 renameMap[tid] = &rm_ptr[tid]; 274} 275 276template <class Impl> 277void 278DefaultRename<Impl>::setFreeList(FreeList *fl_ptr) 279{ 280 freeList = fl_ptr; 281} 282 283template<class Impl> 284void 285DefaultRename<Impl>::setScoreboard(Scoreboard *_scoreboard) 286{ 287 scoreboard = _scoreboard; 288} 289 290template <class Impl> 291bool 292DefaultRename<Impl>::isDrained() const 293{ 294 for (ThreadID tid = 0; tid < numThreads; tid++) { 295 if (instsInProgress[tid] != 0 || 296 !historyBuffer[tid].empty() || 297 !skidBuffer[tid].empty() || 298 !insts[tid].empty()) 299 return false; 300 } 301 return true; 302} 303 304template <class Impl> 305void 306DefaultRename<Impl>::takeOverFrom() 307{ 308 resetStage(); 309} 310 311template <class Impl> 312void 313DefaultRename<Impl>::drainSanityCheck() const 314{ 315 for (ThreadID tid = 0; tid < numThreads; tid++) { 316 assert(historyBuffer[tid].empty()); 317 assert(insts[tid].empty()); 318 assert(skidBuffer[tid].empty()); 319 assert(instsInProgress[tid] == 0); 320 } 321} 322 323template <class Impl> 324void 325DefaultRename<Impl>::squash(const InstSeqNum &squash_seq_num, ThreadID tid) 326{ 327 DPRINTF(Rename, "[tid:%u]: Squashing instructions.\n",tid); 328 329 // Clear the stall signal if rename was blocked or unblocking before. 330 // If it still needs to block, the blocking should happen the next 331 // cycle and there should be space to hold everything due to the squash. 332 if (renameStatus[tid] == Blocked || 333 renameStatus[tid] == Unblocking) { 334 toDecode->renameUnblock[tid] = 1; 335 336 resumeSerialize = false; 337 serializeInst[tid] = NULL; 338 } else if (renameStatus[tid] == SerializeStall) { 339 if (serializeInst[tid]->seqNum <= squash_seq_num) { 340 DPRINTF(Rename, "Rename will resume serializing after squash\n"); 341 resumeSerialize = true; 342 assert(serializeInst[tid]); 343 } else { 344 resumeSerialize = false; 345 toDecode->renameUnblock[tid] = 1; 346 347 serializeInst[tid] = NULL; 348 } 349 } 350 351 // Set the status to Squashing. 352 renameStatus[tid] = Squashing; 353 354 // Squash any instructions from decode. 355 for (int i=0; i<fromDecode->size; i++) { 356 if (fromDecode->insts[i]->threadNumber == tid && 357 fromDecode->insts[i]->seqNum > squash_seq_num) { 358 fromDecode->insts[i]->setSquashed(); 359 wroteToTimeBuffer = true; 360 } 361 362 } 363 364 // Clear the instruction list and skid buffer in case they have any 365 // insts in them. 366 insts[tid].clear(); 367 368 // Clear the skid buffer in case it has any data in it. 369 skidBuffer[tid].clear(); 370 371 doSquash(squash_seq_num, tid); 372} 373 374template <class Impl> 375void 376DefaultRename<Impl>::tick() 377{ 378 wroteToTimeBuffer = false; 379 380 blockThisCycle = false; 381 382 bool status_change = false; 383 384 toIEWIndex = 0; 385 386 sortInsts(); 387 388 list<ThreadID>::iterator threads = activeThreads->begin(); 389 list<ThreadID>::iterator end = activeThreads->end(); 390 391 // Check stall and squash signals. 392 while (threads != end) { 393 ThreadID tid = *threads++; 394 395 DPRINTF(Rename, "Processing [tid:%i]\n", tid); 396 397 status_change = checkSignalsAndUpdate(tid) || status_change; 398 399 rename(status_change, tid); 400 } 401 402 if (status_change) { 403 updateStatus(); 404 } 405 406 if (wroteToTimeBuffer) { 407 DPRINTF(Activity, "Activity this cycle.\n"); 408 cpu->activityThisCycle(); 409 } 410 411 threads = activeThreads->begin(); 412 413 while (threads != end) { 414 ThreadID tid = *threads++; 415 416 // If we committed this cycle then doneSeqNum will be > 0 417 if (fromCommit->commitInfo[tid].doneSeqNum != 0 && 418 !fromCommit->commitInfo[tid].squash && 419 renameStatus[tid] != Squashing) { 420 421 removeFromHistory(fromCommit->commitInfo[tid].doneSeqNum, 422 tid); 423 } 424 } 425 426 // @todo: make into updateProgress function 427 for (ThreadID tid = 0; tid < numThreads; tid++) { 428 instsInProgress[tid] -= fromIEW->iewInfo[tid].dispatched; 429 loadsInProgress[tid] -= fromIEW->iewInfo[tid].dispatchedToLQ; 430 storesInProgress[tid] -= fromIEW->iewInfo[tid].dispatchedToSQ; 431 assert(loadsInProgress[tid] >= 0); 432 assert(storesInProgress[tid] >= 0); 433 assert(instsInProgress[tid] >=0); 434 } 435 436} 437 438template<class Impl> 439void 440DefaultRename<Impl>::rename(bool &status_change, ThreadID tid) 441{ 442 // If status is Running or idle, 443 // call renameInsts() 444 // If status is Unblocking, 445 // buffer any instructions coming from decode 446 // continue trying to empty skid buffer 447 // check if stall conditions have passed 448 449 if (renameStatus[tid] == Blocked) { 450 ++renameBlockCycles; 451 } else if (renameStatus[tid] == Squashing) { 452 ++renameSquashCycles; 453 } else if (renameStatus[tid] == SerializeStall) { 454 ++renameSerializeStallCycles; 455 // If we are currently in SerializeStall and resumeSerialize 456 // was set, then that means that we are resuming serializing 457 // this cycle. Tell the previous stages to block. 458 if (resumeSerialize) { 459 resumeSerialize = false; 460 block(tid); 461 toDecode->renameUnblock[tid] = false; 462 } 463 } else if (renameStatus[tid] == Unblocking) { 464 if (resumeUnblocking) { 465 block(tid); 466 resumeUnblocking = false; 467 toDecode->renameUnblock[tid] = false; 468 } 469 } 470 471 if (renameStatus[tid] == Running || 472 renameStatus[tid] == Idle) { 473 DPRINTF(Rename, "[tid:%u]: Not blocked, so attempting to run " 474 "stage.\n", tid); 475 476 renameInsts(tid); 477 } else if (renameStatus[tid] == Unblocking) { 478 renameInsts(tid); 479 480 if (validInsts()) { 481 // Add the current inputs to the skid buffer so they can be 482 // reprocessed when this stage unblocks. 483 skidInsert(tid); 484 } 485 486 // If we switched over to blocking, then there's a potential for 487 // an overall status change. 488 status_change = unblock(tid) || status_change || blockThisCycle; 489 } 490} 491 492template <class Impl> 493void 494DefaultRename<Impl>::renameInsts(ThreadID tid) 495{ 496 // Instructions can be either in the skid buffer or the queue of 497 // instructions coming from decode, depending on the status. 498 int insts_available = renameStatus[tid] == Unblocking ? 499 skidBuffer[tid].size() : insts[tid].size(); 500 501 // Check the decode queue to see if instructions are available. 502 // If there are no available instructions to rename, then do nothing. 503 if (insts_available == 0) { 504 DPRINTF(Rename, "[tid:%u]: Nothing to do, breaking out early.\n", 505 tid); 506 // Should I change status to idle? 507 ++renameIdleCycles; 508 return; 509 } else if (renameStatus[tid] == Unblocking) { 510 ++renameUnblockCycles; 511 } else if (renameStatus[tid] == Running) { 512 ++renameRunCycles; 513 } 514 515 DynInstPtr inst; 516 517 // Will have to do a different calculation for the number of free 518 // entries. 519 int free_rob_entries = calcFreeROBEntries(tid); 520 int free_iq_entries = calcFreeIQEntries(tid); 521 int min_free_entries = free_rob_entries; 522 523 FullSource source = ROB; 524 525 if (free_iq_entries < min_free_entries) { 526 min_free_entries = free_iq_entries; 527 source = IQ; 528 } 529 530 // Check if there's any space left. 531 if (min_free_entries <= 0) { 532 DPRINTF(Rename, "[tid:%u]: Blocking due to no free ROB/IQ/ " 533 "entries.\n" 534 "ROB has %i free entries.\n" 535 "IQ has %i free entries.\n", 536 tid, 537 free_rob_entries, 538 free_iq_entries); 539 540 blockThisCycle = true; 541 542 block(tid); 543 544 incrFullStat(source); 545 546 return; 547 } else if (min_free_entries < insts_available) { 548 DPRINTF(Rename, "[tid:%u]: Will have to block this cycle." 549 "%i insts available, but only %i insts can be " 550 "renamed due to ROB/IQ/LSQ limits.\n", 551 tid, insts_available, min_free_entries); 552 553 insts_available = min_free_entries; 554 555 blockThisCycle = true; 556 557 incrFullStat(source); 558 } 559 560 InstQueue &insts_to_rename = renameStatus[tid] == Unblocking ? 561 skidBuffer[tid] : insts[tid]; 562 563 DPRINTF(Rename, "[tid:%u]: %i available instructions to " 564 "send iew.\n", tid, insts_available); 565 566 DPRINTF(Rename, "[tid:%u]: %i insts pipelining from Rename | %i insts " 567 "dispatched to IQ last cycle.\n", 568 tid, instsInProgress[tid], fromIEW->iewInfo[tid].dispatched); 569 570 // Handle serializing the next instruction if necessary. 571 if (serializeOnNextInst[tid]) { 572 if (emptyROB[tid] && instsInProgress[tid] == 0) { 573 // ROB already empty; no need to serialize. 574 serializeOnNextInst[tid] = false; 575 } else if (!insts_to_rename.empty()) { 576 insts_to_rename.front()->setSerializeBefore(); 577 } 578 } 579 580 int renamed_insts = 0; 581 582 while (insts_available > 0 && toIEWIndex < renameWidth) { 583 DPRINTF(Rename, "[tid:%u]: Sending instructions to IEW.\n", tid); 584 585 assert(!insts_to_rename.empty()); 586 587 inst = insts_to_rename.front(); 588 589 //For all kind of instructions, check ROB and IQ first 590 //For load instruction, check LQ size and take into account the inflight loads 591 //For store instruction, check SQ size and take into account the inflight stores 592 593 if (inst->isLoad()) { 594 if (calcFreeLQEntries(tid) <= 0) { 595 DPRINTF(Rename, "[tid:%u]: Cannot rename due to no free LQ\n"); 596 source = LQ; 597 incrFullStat(source); 598 break; 599 } 600 } 601 602 if (inst->isStore()) { 603 if (calcFreeSQEntries(tid) <= 0) { 604 DPRINTF(Rename, "[tid:%u]: Cannot rename due to no free SQ\n"); 605 source = SQ; 606 incrFullStat(source); 607 break; 608 } 609 } 610 611 insts_to_rename.pop_front(); 612 613 if (renameStatus[tid] == Unblocking) { 614 DPRINTF(Rename,"[tid:%u]: Removing [sn:%lli] PC:%s from rename " 615 "skidBuffer\n", tid, inst->seqNum, inst->pcState()); 616 } 617 618 if (inst->isSquashed()) { 619 DPRINTF(Rename, "[tid:%u]: instruction %i with PC %s is " 620 "squashed, skipping.\n", tid, inst->seqNum, 621 inst->pcState()); 622 623 ++renameSquashedInsts; 624 625 // Decrement how many instructions are available. 626 --insts_available; 627 628 continue; 629 } 630 631 DPRINTF(Rename, "[tid:%u]: Processing instruction [sn:%lli] with " 632 "PC %s.\n", tid, inst->seqNum, inst->pcState()); 633 634 // Check here to make sure there are enough destination registers 635 // to rename to. Otherwise block. 636 if (!renameMap[tid]->canRename(inst->numIntDestRegs(), 637 inst->numFPDestRegs(),
| 73{ 74 if (renameWidth > Impl::MaxWidth) 75 fatal("renameWidth (%d) is larger than compiled limit (%d),\n" 76 "\tincrease MaxWidth in src/cpu/o3/impl.hh\n", 77 renameWidth, static_cast<int>(Impl::MaxWidth)); 78 79 // @todo: Make into a parameter. 80 skidBufferMax = (decodeToRenameDelay + 1) * params->decodeWidth; 81} 82 83template <class Impl> 84std::string 85DefaultRename<Impl>::name() const 86{ 87 return cpu->name() + ".rename"; 88} 89 90template <class Impl> 91void 92DefaultRename<Impl>::regStats() 93{ 94 renameSquashCycles 95 .name(name() + ".SquashCycles") 96 .desc("Number of cycles rename is squashing") 97 .prereq(renameSquashCycles); 98 renameIdleCycles 99 .name(name() + ".IdleCycles") 100 .desc("Number of cycles rename is idle") 101 .prereq(renameIdleCycles); 102 renameBlockCycles 103 .name(name() + ".BlockCycles") 104 .desc("Number of cycles rename is blocking") 105 .prereq(renameBlockCycles); 106 renameSerializeStallCycles 107 .name(name() + ".serializeStallCycles") 108 .desc("count of cycles rename stalled for serializing inst") 109 .flags(Stats::total); 110 renameRunCycles 111 .name(name() + ".RunCycles") 112 .desc("Number of cycles rename is running") 113 .prereq(renameIdleCycles); 114 renameUnblockCycles 115 .name(name() + ".UnblockCycles") 116 .desc("Number of cycles rename is unblocking") 117 .prereq(renameUnblockCycles); 118 renameRenamedInsts 119 .name(name() + ".RenamedInsts") 120 .desc("Number of instructions processed by rename") 121 .prereq(renameRenamedInsts); 122 renameSquashedInsts 123 .name(name() + ".SquashedInsts") 124 .desc("Number of squashed instructions processed by rename") 125 .prereq(renameSquashedInsts); 126 renameROBFullEvents 127 .name(name() + ".ROBFullEvents") 128 .desc("Number of times rename has blocked due to ROB full") 129 .prereq(renameROBFullEvents); 130 renameIQFullEvents 131 .name(name() + ".IQFullEvents") 132 .desc("Number of times rename has blocked due to IQ full") 133 .prereq(renameIQFullEvents); 134 renameLQFullEvents 135 .name(name() + ".LQFullEvents") 136 .desc("Number of times rename has blocked due to LQ full") 137 .prereq(renameLQFullEvents); 138 renameSQFullEvents 139 .name(name() + ".SQFullEvents") 140 .desc("Number of times rename has blocked due to SQ full") 141 .prereq(renameSQFullEvents); 142 renameFullRegistersEvents 143 .name(name() + ".FullRegisterEvents") 144 .desc("Number of times there has been no free registers") 145 .prereq(renameFullRegistersEvents); 146 renameRenamedOperands 147 .name(name() + ".RenamedOperands") 148 .desc("Number of destination operands rename has renamed") 149 .prereq(renameRenamedOperands); 150 renameRenameLookups 151 .name(name() + ".RenameLookups") 152 .desc("Number of register rename lookups that rename has made") 153 .prereq(renameRenameLookups); 154 renameCommittedMaps 155 .name(name() + ".CommittedMaps") 156 .desc("Number of HB maps that are committed") 157 .prereq(renameCommittedMaps); 158 renameUndoneMaps 159 .name(name() + ".UndoneMaps") 160 .desc("Number of HB maps that are undone due to squashing") 161 .prereq(renameUndoneMaps); 162 renamedSerializing 163 .name(name() + ".serializingInsts") 164 .desc("count of serializing insts renamed") 165 .flags(Stats::total) 166 ; 167 renamedTempSerializing 168 .name(name() + ".tempSerializingInsts") 169 .desc("count of temporary serializing insts renamed") 170 .flags(Stats::total) 171 ; 172 renameSkidInsts 173 .name(name() + ".skidInsts") 174 .desc("count of insts added to the skid buffer") 175 .flags(Stats::total) 176 ; 177 intRenameLookups 178 .name(name() + ".int_rename_lookups") 179 .desc("Number of integer rename lookups") 180 .prereq(intRenameLookups); 181 fpRenameLookups 182 .name(name() + ".fp_rename_lookups") 183 .desc("Number of floating rename lookups") 184 .prereq(fpRenameLookups); 185} 186 187template <class Impl> 188void 189DefaultRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 190{ 191 timeBuffer = tb_ptr; 192 193 // Setup wire to read information from time buffer, from IEW stage. 194 fromIEW = timeBuffer->getWire(-iewToRenameDelay); 195 196 // Setup wire to read infromation from time buffer, from commit stage. 197 fromCommit = timeBuffer->getWire(-commitToRenameDelay); 198 199 // Setup wire to write information to previous stages. 200 toDecode = timeBuffer->getWire(0); 201} 202 203template <class Impl> 204void 205DefaultRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 206{ 207 renameQueue = rq_ptr; 208 209 // Setup wire to write information to future stages. 210 toIEW = renameQueue->getWire(0); 211} 212 213template <class Impl> 214void 215DefaultRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr) 216{ 217 decodeQueue = dq_ptr; 218 219 // Setup wire to get information from decode. 220 fromDecode = decodeQueue->getWire(-decodeToRenameDelay); 221} 222 223template <class Impl> 224void 225DefaultRename<Impl>::startupStage() 226{ 227 resetStage(); 228} 229 230template <class Impl> 231void 232DefaultRename<Impl>::resetStage() 233{ 234 _status = Inactive; 235 236 resumeSerialize = false; 237 resumeUnblocking = false; 238 239 // Grab the number of free entries directly from the stages. 240 for (ThreadID tid = 0; tid < numThreads; tid++) { 241 renameStatus[tid] = Idle; 242 243 freeEntries[tid].iqEntries = iew_ptr->instQueue.numFreeEntries(tid); 244 freeEntries[tid].lqEntries = iew_ptr->ldstQueue.numFreeLoadEntries(tid); 245 freeEntries[tid].sqEntries = iew_ptr->ldstQueue.numFreeStoreEntries(tid); 246 freeEntries[tid].robEntries = commit_ptr->numROBFreeEntries(tid); 247 emptyROB[tid] = true; 248 249 stalls[tid].iew = false; 250 serializeInst[tid] = NULL; 251 252 instsInProgress[tid] = 0; 253 loadsInProgress[tid] = 0; 254 storesInProgress[tid] = 0; 255 256 serializeOnNextInst[tid] = false; 257 } 258} 259 260template<class Impl> 261void 262DefaultRename<Impl>::setActiveThreads(list<ThreadID> *at_ptr) 263{ 264 activeThreads = at_ptr; 265} 266 267 268template <class Impl> 269void 270DefaultRename<Impl>::setRenameMap(RenameMap rm_ptr[]) 271{ 272 for (ThreadID tid = 0; tid < numThreads; tid++) 273 renameMap[tid] = &rm_ptr[tid]; 274} 275 276template <class Impl> 277void 278DefaultRename<Impl>::setFreeList(FreeList *fl_ptr) 279{ 280 freeList = fl_ptr; 281} 282 283template<class Impl> 284void 285DefaultRename<Impl>::setScoreboard(Scoreboard *_scoreboard) 286{ 287 scoreboard = _scoreboard; 288} 289 290template <class Impl> 291bool 292DefaultRename<Impl>::isDrained() const 293{ 294 for (ThreadID tid = 0; tid < numThreads; tid++) { 295 if (instsInProgress[tid] != 0 || 296 !historyBuffer[tid].empty() || 297 !skidBuffer[tid].empty() || 298 !insts[tid].empty()) 299 return false; 300 } 301 return true; 302} 303 304template <class Impl> 305void 306DefaultRename<Impl>::takeOverFrom() 307{ 308 resetStage(); 309} 310 311template <class Impl> 312void 313DefaultRename<Impl>::drainSanityCheck() const 314{ 315 for (ThreadID tid = 0; tid < numThreads; tid++) { 316 assert(historyBuffer[tid].empty()); 317 assert(insts[tid].empty()); 318 assert(skidBuffer[tid].empty()); 319 assert(instsInProgress[tid] == 0); 320 } 321} 322 323template <class Impl> 324void 325DefaultRename<Impl>::squash(const InstSeqNum &squash_seq_num, ThreadID tid) 326{ 327 DPRINTF(Rename, "[tid:%u]: Squashing instructions.\n",tid); 328 329 // Clear the stall signal if rename was blocked or unblocking before. 330 // If it still needs to block, the blocking should happen the next 331 // cycle and there should be space to hold everything due to the squash. 332 if (renameStatus[tid] == Blocked || 333 renameStatus[tid] == Unblocking) { 334 toDecode->renameUnblock[tid] = 1; 335 336 resumeSerialize = false; 337 serializeInst[tid] = NULL; 338 } else if (renameStatus[tid] == SerializeStall) { 339 if (serializeInst[tid]->seqNum <= squash_seq_num) { 340 DPRINTF(Rename, "Rename will resume serializing after squash\n"); 341 resumeSerialize = true; 342 assert(serializeInst[tid]); 343 } else { 344 resumeSerialize = false; 345 toDecode->renameUnblock[tid] = 1; 346 347 serializeInst[tid] = NULL; 348 } 349 } 350 351 // Set the status to Squashing. 352 renameStatus[tid] = Squashing; 353 354 // Squash any instructions from decode. 355 for (int i=0; i<fromDecode->size; i++) { 356 if (fromDecode->insts[i]->threadNumber == tid && 357 fromDecode->insts[i]->seqNum > squash_seq_num) { 358 fromDecode->insts[i]->setSquashed(); 359 wroteToTimeBuffer = true; 360 } 361 362 } 363 364 // Clear the instruction list and skid buffer in case they have any 365 // insts in them. 366 insts[tid].clear(); 367 368 // Clear the skid buffer in case it has any data in it. 369 skidBuffer[tid].clear(); 370 371 doSquash(squash_seq_num, tid); 372} 373 374template <class Impl> 375void 376DefaultRename<Impl>::tick() 377{ 378 wroteToTimeBuffer = false; 379 380 blockThisCycle = false; 381 382 bool status_change = false; 383 384 toIEWIndex = 0; 385 386 sortInsts(); 387 388 list<ThreadID>::iterator threads = activeThreads->begin(); 389 list<ThreadID>::iterator end = activeThreads->end(); 390 391 // Check stall and squash signals. 392 while (threads != end) { 393 ThreadID tid = *threads++; 394 395 DPRINTF(Rename, "Processing [tid:%i]\n", tid); 396 397 status_change = checkSignalsAndUpdate(tid) || status_change; 398 399 rename(status_change, tid); 400 } 401 402 if (status_change) { 403 updateStatus(); 404 } 405 406 if (wroteToTimeBuffer) { 407 DPRINTF(Activity, "Activity this cycle.\n"); 408 cpu->activityThisCycle(); 409 } 410 411 threads = activeThreads->begin(); 412 413 while (threads != end) { 414 ThreadID tid = *threads++; 415 416 // If we committed this cycle then doneSeqNum will be > 0 417 if (fromCommit->commitInfo[tid].doneSeqNum != 0 && 418 !fromCommit->commitInfo[tid].squash && 419 renameStatus[tid] != Squashing) { 420 421 removeFromHistory(fromCommit->commitInfo[tid].doneSeqNum, 422 tid); 423 } 424 } 425 426 // @todo: make into updateProgress function 427 for (ThreadID tid = 0; tid < numThreads; tid++) { 428 instsInProgress[tid] -= fromIEW->iewInfo[tid].dispatched; 429 loadsInProgress[tid] -= fromIEW->iewInfo[tid].dispatchedToLQ; 430 storesInProgress[tid] -= fromIEW->iewInfo[tid].dispatchedToSQ; 431 assert(loadsInProgress[tid] >= 0); 432 assert(storesInProgress[tid] >= 0); 433 assert(instsInProgress[tid] >=0); 434 } 435 436} 437 438template<class Impl> 439void 440DefaultRename<Impl>::rename(bool &status_change, ThreadID tid) 441{ 442 // If status is Running or idle, 443 // call renameInsts() 444 // If status is Unblocking, 445 // buffer any instructions coming from decode 446 // continue trying to empty skid buffer 447 // check if stall conditions have passed 448 449 if (renameStatus[tid] == Blocked) { 450 ++renameBlockCycles; 451 } else if (renameStatus[tid] == Squashing) { 452 ++renameSquashCycles; 453 } else if (renameStatus[tid] == SerializeStall) { 454 ++renameSerializeStallCycles; 455 // If we are currently in SerializeStall and resumeSerialize 456 // was set, then that means that we are resuming serializing 457 // this cycle. Tell the previous stages to block. 458 if (resumeSerialize) { 459 resumeSerialize = false; 460 block(tid); 461 toDecode->renameUnblock[tid] = false; 462 } 463 } else if (renameStatus[tid] == Unblocking) { 464 if (resumeUnblocking) { 465 block(tid); 466 resumeUnblocking = false; 467 toDecode->renameUnblock[tid] = false; 468 } 469 } 470 471 if (renameStatus[tid] == Running || 472 renameStatus[tid] == Idle) { 473 DPRINTF(Rename, "[tid:%u]: Not blocked, so attempting to run " 474 "stage.\n", tid); 475 476 renameInsts(tid); 477 } else if (renameStatus[tid] == Unblocking) { 478 renameInsts(tid); 479 480 if (validInsts()) { 481 // Add the current inputs to the skid buffer so they can be 482 // reprocessed when this stage unblocks. 483 skidInsert(tid); 484 } 485 486 // If we switched over to blocking, then there's a potential for 487 // an overall status change. 488 status_change = unblock(tid) || status_change || blockThisCycle; 489 } 490} 491 492template <class Impl> 493void 494DefaultRename<Impl>::renameInsts(ThreadID tid) 495{ 496 // Instructions can be either in the skid buffer or the queue of 497 // instructions coming from decode, depending on the status. 498 int insts_available = renameStatus[tid] == Unblocking ? 499 skidBuffer[tid].size() : insts[tid].size(); 500 501 // Check the decode queue to see if instructions are available. 502 // If there are no available instructions to rename, then do nothing. 503 if (insts_available == 0) { 504 DPRINTF(Rename, "[tid:%u]: Nothing to do, breaking out early.\n", 505 tid); 506 // Should I change status to idle? 507 ++renameIdleCycles; 508 return; 509 } else if (renameStatus[tid] == Unblocking) { 510 ++renameUnblockCycles; 511 } else if (renameStatus[tid] == Running) { 512 ++renameRunCycles; 513 } 514 515 DynInstPtr inst; 516 517 // Will have to do a different calculation for the number of free 518 // entries. 519 int free_rob_entries = calcFreeROBEntries(tid); 520 int free_iq_entries = calcFreeIQEntries(tid); 521 int min_free_entries = free_rob_entries; 522 523 FullSource source = ROB; 524 525 if (free_iq_entries < min_free_entries) { 526 min_free_entries = free_iq_entries; 527 source = IQ; 528 } 529 530 // Check if there's any space left. 531 if (min_free_entries <= 0) { 532 DPRINTF(Rename, "[tid:%u]: Blocking due to no free ROB/IQ/ " 533 "entries.\n" 534 "ROB has %i free entries.\n" 535 "IQ has %i free entries.\n", 536 tid, 537 free_rob_entries, 538 free_iq_entries); 539 540 blockThisCycle = true; 541 542 block(tid); 543 544 incrFullStat(source); 545 546 return; 547 } else if (min_free_entries < insts_available) { 548 DPRINTF(Rename, "[tid:%u]: Will have to block this cycle." 549 "%i insts available, but only %i insts can be " 550 "renamed due to ROB/IQ/LSQ limits.\n", 551 tid, insts_available, min_free_entries); 552 553 insts_available = min_free_entries; 554 555 blockThisCycle = true; 556 557 incrFullStat(source); 558 } 559 560 InstQueue &insts_to_rename = renameStatus[tid] == Unblocking ? 561 skidBuffer[tid] : insts[tid]; 562 563 DPRINTF(Rename, "[tid:%u]: %i available instructions to " 564 "send iew.\n", tid, insts_available); 565 566 DPRINTF(Rename, "[tid:%u]: %i insts pipelining from Rename | %i insts " 567 "dispatched to IQ last cycle.\n", 568 tid, instsInProgress[tid], fromIEW->iewInfo[tid].dispatched); 569 570 // Handle serializing the next instruction if necessary. 571 if (serializeOnNextInst[tid]) { 572 if (emptyROB[tid] && instsInProgress[tid] == 0) { 573 // ROB already empty; no need to serialize. 574 serializeOnNextInst[tid] = false; 575 } else if (!insts_to_rename.empty()) { 576 insts_to_rename.front()->setSerializeBefore(); 577 } 578 } 579 580 int renamed_insts = 0; 581 582 while (insts_available > 0 && toIEWIndex < renameWidth) { 583 DPRINTF(Rename, "[tid:%u]: Sending instructions to IEW.\n", tid); 584 585 assert(!insts_to_rename.empty()); 586 587 inst = insts_to_rename.front(); 588 589 //For all kind of instructions, check ROB and IQ first 590 //For load instruction, check LQ size and take into account the inflight loads 591 //For store instruction, check SQ size and take into account the inflight stores 592 593 if (inst->isLoad()) { 594 if (calcFreeLQEntries(tid) <= 0) { 595 DPRINTF(Rename, "[tid:%u]: Cannot rename due to no free LQ\n"); 596 source = LQ; 597 incrFullStat(source); 598 break; 599 } 600 } 601 602 if (inst->isStore()) { 603 if (calcFreeSQEntries(tid) <= 0) { 604 DPRINTF(Rename, "[tid:%u]: Cannot rename due to no free SQ\n"); 605 source = SQ; 606 incrFullStat(source); 607 break; 608 } 609 } 610 611 insts_to_rename.pop_front(); 612 613 if (renameStatus[tid] == Unblocking) { 614 DPRINTF(Rename,"[tid:%u]: Removing [sn:%lli] PC:%s from rename " 615 "skidBuffer\n", tid, inst->seqNum, inst->pcState()); 616 } 617 618 if (inst->isSquashed()) { 619 DPRINTF(Rename, "[tid:%u]: instruction %i with PC %s is " 620 "squashed, skipping.\n", tid, inst->seqNum, 621 inst->pcState()); 622 623 ++renameSquashedInsts; 624 625 // Decrement how many instructions are available. 626 --insts_available; 627 628 continue; 629 } 630 631 DPRINTF(Rename, "[tid:%u]: Processing instruction [sn:%lli] with " 632 "PC %s.\n", tid, inst->seqNum, inst->pcState()); 633 634 // Check here to make sure there are enough destination registers 635 // to rename to. Otherwise block. 636 if (!renameMap[tid]->canRename(inst->numIntDestRegs(), 637 inst->numFPDestRegs(),
|
638 inst->numCCDestRegs(), 639 inst->numVectorDestRegs())) {
| 638 inst->numCCDestRegs())) {
|
640 DPRINTF(Rename, "Blocking due to lack of free " 641 "physical registers to rename to.\n"); 642 blockThisCycle = true; 643 insts_to_rename.push_front(inst); 644 ++renameFullRegistersEvents; 645 646 break; 647 } 648 649 // Handle serializeAfter/serializeBefore instructions. 650 // serializeAfter marks the next instruction as serializeBefore. 651 // serializeBefore makes the instruction wait in rename until the ROB 652 // is empty. 653 654 // In this model, IPR accesses are serialize before 655 // instructions, and store conditionals are serialize after 656 // instructions. This is mainly due to lack of support for 657 // out-of-order operations of either of those classes of 658 // instructions. 659 if ((inst->isIprAccess() || inst->isSerializeBefore()) && 660 !inst->isSerializeHandled()) { 661 DPRINTF(Rename, "Serialize before instruction encountered.\n"); 662 663 if (!inst->isTempSerializeBefore()) { 664 renamedSerializing++; 665 inst->setSerializeHandled(); 666 } else { 667 renamedTempSerializing++; 668 } 669 670 // Change status over to SerializeStall so that other stages know 671 // what this is blocked on. 672 renameStatus[tid] = SerializeStall; 673 674 serializeInst[tid] = inst; 675 676 blockThisCycle = true; 677 678 break; 679 } else if ((inst->isStoreConditional() || inst->isSerializeAfter()) && 680 !inst->isSerializeHandled()) { 681 DPRINTF(Rename, "Serialize after instruction encountered.\n"); 682 683 renamedSerializing++; 684 685 inst->setSerializeHandled(); 686 687 serializeAfter(insts_to_rename, tid); 688 } 689 690 renameSrcRegs(inst, inst->threadNumber); 691 692 renameDestRegs(inst, inst->threadNumber); 693 694 if (inst->isLoad()) { 695 loadsInProgress[tid]++; 696 } 697 if (inst->isStore()) { 698 storesInProgress[tid]++; 699 } 700 ++renamed_insts; 701 702 703 // Put instruction in rename queue. 704 toIEW->insts[toIEWIndex] = inst; 705 ++(toIEW->size); 706 707 // Increment which instruction we're on. 708 ++toIEWIndex; 709 710 // Decrement how many instructions are available. 711 --insts_available; 712 } 713 714 instsInProgress[tid] += renamed_insts; 715 renameRenamedInsts += renamed_insts; 716 717 // If we wrote to the time buffer, record this. 718 if (toIEWIndex) { 719 wroteToTimeBuffer = true; 720 } 721 722 // Check if there's any instructions left that haven't yet been renamed. 723 // If so then block. 724 if (insts_available) { 725 blockThisCycle = true; 726 } 727 728 if (blockThisCycle) { 729 block(tid); 730 toDecode->renameUnblock[tid] = false; 731 } 732} 733 734template<class Impl> 735void 736DefaultRename<Impl>::skidInsert(ThreadID tid) 737{ 738 DynInstPtr inst = NULL; 739 740 while (!insts[tid].empty()) { 741 inst = insts[tid].front(); 742 743 insts[tid].pop_front(); 744 745 assert(tid == inst->threadNumber); 746 747 DPRINTF(Rename, "[tid:%u]: Inserting [sn:%lli] PC: %s into Rename " 748 "skidBuffer\n", tid, inst->seqNum, inst->pcState()); 749 750 ++renameSkidInsts; 751 752 skidBuffer[tid].push_back(inst); 753 } 754 755 if (skidBuffer[tid].size() > skidBufferMax) 756 { 757 typename InstQueue::iterator it; 758 warn("Skidbuffer contents:\n"); 759 for(it = skidBuffer[tid].begin(); it != skidBuffer[tid].end(); it++) 760 { 761 warn("[tid:%u]: %s [sn:%i].\n", tid, 762 (*it)->staticInst->disassemble(inst->instAddr()), 763 (*it)->seqNum); 764 } 765 panic("Skidbuffer Exceeded Max Size"); 766 } 767} 768 769template <class Impl> 770void 771DefaultRename<Impl>::sortInsts() 772{ 773 int insts_from_decode = fromDecode->size; 774 for (int i = 0; i < insts_from_decode; ++i) { 775 DynInstPtr inst = fromDecode->insts[i]; 776 insts[inst->threadNumber].push_back(inst); 777#if TRACING_ON 778 if (DTRACE(O3PipeView)) { 779 inst->renameTick = curTick() - inst->fetchTick; 780 } 781#endif 782 } 783} 784 785template<class Impl> 786bool 787DefaultRename<Impl>::skidsEmpty() 788{ 789 list<ThreadID>::iterator threads = activeThreads->begin(); 790 list<ThreadID>::iterator end = activeThreads->end(); 791 792 while (threads != end) { 793 ThreadID tid = *threads++; 794 795 if (!skidBuffer[tid].empty()) 796 return false; 797 } 798 799 return true; 800} 801 802template<class Impl> 803void 804DefaultRename<Impl>::updateStatus() 805{ 806 bool any_unblocking = false; 807 808 list<ThreadID>::iterator threads = activeThreads->begin(); 809 list<ThreadID>::iterator end = activeThreads->end(); 810 811 while (threads != end) { 812 ThreadID tid = *threads++; 813 814 if (renameStatus[tid] == Unblocking) { 815 any_unblocking = true; 816 break; 817 } 818 } 819 820 // Rename will have activity if it's unblocking. 821 if (any_unblocking) { 822 if (_status == Inactive) { 823 _status = Active; 824 825 DPRINTF(Activity, "Activating stage.\n"); 826 827 cpu->activateStage(O3CPU::RenameIdx); 828 } 829 } else { 830 // If it's not unblocking, then rename will not have any internal 831 // activity. Switch it to inactive. 832 if (_status == Active) { 833 _status = Inactive; 834 DPRINTF(Activity, "Deactivating stage.\n"); 835 836 cpu->deactivateStage(O3CPU::RenameIdx); 837 } 838 } 839} 840 841template <class Impl> 842bool 843DefaultRename<Impl>::block(ThreadID tid) 844{ 845 DPRINTF(Rename, "[tid:%u]: Blocking.\n", tid); 846 847 // Add the current inputs onto the skid buffer, so they can be 848 // reprocessed when this stage unblocks. 849 skidInsert(tid); 850 851 // Only signal backwards to block if the previous stages do not think 852 // rename is already blocked. 853 if (renameStatus[tid] != Blocked) { 854 // If resumeUnblocking is set, we unblocked during the squash, 855 // but now we're have unblocking status. We need to tell earlier 856 // stages to block. 857 if (resumeUnblocking || renameStatus[tid] != Unblocking) { 858 toDecode->renameBlock[tid] = true; 859 toDecode->renameUnblock[tid] = false; 860 wroteToTimeBuffer = true; 861 } 862 863 // Rename can not go from SerializeStall to Blocked, otherwise 864 // it would not know to complete the serialize stall. 865 if (renameStatus[tid] != SerializeStall) { 866 // Set status to Blocked. 867 renameStatus[tid] = Blocked; 868 return true; 869 } 870 } 871 872 return false; 873} 874 875template <class Impl> 876bool 877DefaultRename<Impl>::unblock(ThreadID tid) 878{ 879 DPRINTF(Rename, "[tid:%u]: Trying to unblock.\n", tid); 880 881 // Rename is done unblocking if the skid buffer is empty. 882 if (skidBuffer[tid].empty() && renameStatus[tid] != SerializeStall) { 883 884 DPRINTF(Rename, "[tid:%u]: Done unblocking.\n", tid); 885 886 toDecode->renameUnblock[tid] = true; 887 wroteToTimeBuffer = true; 888 889 renameStatus[tid] = Running; 890 return true; 891 } 892 893 return false; 894} 895 896template <class Impl> 897void 898DefaultRename<Impl>::doSquash(const InstSeqNum &squashed_seq_num, ThreadID tid) 899{ 900 typename std::list<RenameHistory>::iterator hb_it = 901 historyBuffer[tid].begin(); 902 903 // After a syscall squashes everything, the history buffer may be empty 904 // but the ROB may still be squashing instructions. 905 if (historyBuffer[tid].empty()) { 906 return; 907 } 908 909 // Go through the most recent instructions, undoing the mappings 910 // they did and freeing up the registers. 911 while (!historyBuffer[tid].empty() && 912 hb_it->instSeqNum > squashed_seq_num) { 913 assert(hb_it != historyBuffer[tid].end()); 914 915 DPRINTF(Rename, "[tid:%u]: Removing history entry with sequence " 916 "number %i.\n", tid, hb_it->instSeqNum); 917 918 // Undo the rename mapping only if it was really a change. 919 // Special regs that are not really renamed (like misc regs 920 // and the zero reg) can be recognized because the new mapping 921 // is the same as the old one. While it would be merely a 922 // waste of time to update the rename table, we definitely 923 // don't want to put these on the free list. 924 if (hb_it->newPhysReg != hb_it->prevPhysReg) { 925 // Tell the rename map to set the architected register to the 926 // previous physical register that it was renamed to. 927 renameMap[tid]->setEntry(hb_it->archReg, hb_it->prevPhysReg); 928 929 // Put the renamed physical register back on the free list. 930 freeList->addReg(hb_it->newPhysReg); 931 } 932 933 historyBuffer[tid].erase(hb_it++); 934 935 ++renameUndoneMaps; 936 } 937} 938 939template<class Impl> 940void 941DefaultRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num, ThreadID tid) 942{ 943 DPRINTF(Rename, "[tid:%u]: Removing a committed instruction from the " 944 "history buffer %u (size=%i), until [sn:%lli].\n", 945 tid, tid, historyBuffer[tid].size(), inst_seq_num); 946 947 typename std::list<RenameHistory>::iterator hb_it = 948 historyBuffer[tid].end(); 949 950 --hb_it; 951 952 if (historyBuffer[tid].empty()) { 953 DPRINTF(Rename, "[tid:%u]: History buffer is empty.\n", tid); 954 return; 955 } else if (hb_it->instSeqNum > inst_seq_num) { 956 DPRINTF(Rename, "[tid:%u]: Old sequence number encountered. Ensure " 957 "that a syscall happened recently.\n", tid); 958 return; 959 } 960 961 // Commit all the renames up until (and including) the committed sequence 962 // number. Some or even all of the committed instructions may not have 963 // rename histories if they did not have destination registers that were 964 // renamed. 965 while (!historyBuffer[tid].empty() && 966 hb_it != historyBuffer[tid].end() && 967 hb_it->instSeqNum <= inst_seq_num) { 968 969 DPRINTF(Rename, "[tid:%u]: Freeing up older rename of reg %i, " 970 "[sn:%lli].\n", 971 tid, hb_it->prevPhysReg, hb_it->instSeqNum); 972 973 // Don't free special phys regs like misc and zero regs, which 974 // can be recognized because the new mapping is the same as 975 // the old one. 976 if (hb_it->newPhysReg != hb_it->prevPhysReg) { 977 freeList->addReg(hb_it->prevPhysReg); 978 } 979 980 ++renameCommittedMaps; 981 982 historyBuffer[tid].erase(hb_it--); 983 } 984} 985 986template <class Impl> 987inline void 988DefaultRename<Impl>::renameSrcRegs(DynInstPtr &inst, ThreadID tid) 989{ 990 ThreadContext *tc = inst->tcBase(); 991 RenameMap *map = renameMap[tid]; 992 unsigned num_src_regs = inst->numSrcRegs(); 993 994 // Get the architectual register numbers from the source and 995 // operands, and redirect them to the right physical register. 996 for (int src_idx = 0; src_idx < num_src_regs; src_idx++) { 997 RegIndex src_reg = inst->srcRegIdx(src_idx); 998 RegIndex rel_src_reg; 999 RegIndex flat_rel_src_reg; 1000 PhysRegIndex renamed_reg; 1001 1002 switch (regIdxToClass(src_reg, &rel_src_reg)) { 1003 case IntRegClass: 1004 flat_rel_src_reg = tc->flattenIntIndex(rel_src_reg); 1005 renamed_reg = map->lookupInt(flat_rel_src_reg); 1006 intRenameLookups++; 1007 break; 1008 1009 case FloatRegClass: 1010 flat_rel_src_reg = tc->flattenFloatIndex(rel_src_reg); 1011 renamed_reg = map->lookupFloat(flat_rel_src_reg); 1012 fpRenameLookups++; 1013 break; 1014 1015 case CCRegClass: 1016 flat_rel_src_reg = tc->flattenCCIndex(rel_src_reg); 1017 renamed_reg = map->lookupCC(flat_rel_src_reg); 1018 break; 1019
| 639 DPRINTF(Rename, "Blocking due to lack of free " 640 "physical registers to rename to.\n"); 641 blockThisCycle = true; 642 insts_to_rename.push_front(inst); 643 ++renameFullRegistersEvents; 644 645 break; 646 } 647 648 // Handle serializeAfter/serializeBefore instructions. 649 // serializeAfter marks the next instruction as serializeBefore. 650 // serializeBefore makes the instruction wait in rename until the ROB 651 // is empty. 652 653 // In this model, IPR accesses are serialize before 654 // instructions, and store conditionals are serialize after 655 // instructions. This is mainly due to lack of support for 656 // out-of-order operations of either of those classes of 657 // instructions. 658 if ((inst->isIprAccess() || inst->isSerializeBefore()) && 659 !inst->isSerializeHandled()) { 660 DPRINTF(Rename, "Serialize before instruction encountered.\n"); 661 662 if (!inst->isTempSerializeBefore()) { 663 renamedSerializing++; 664 inst->setSerializeHandled(); 665 } else { 666 renamedTempSerializing++; 667 } 668 669 // Change status over to SerializeStall so that other stages know 670 // what this is blocked on. 671 renameStatus[tid] = SerializeStall; 672 673 serializeInst[tid] = inst; 674 675 blockThisCycle = true; 676 677 break; 678 } else if ((inst->isStoreConditional() || inst->isSerializeAfter()) && 679 !inst->isSerializeHandled()) { 680 DPRINTF(Rename, "Serialize after instruction encountered.\n"); 681 682 renamedSerializing++; 683 684 inst->setSerializeHandled(); 685 686 serializeAfter(insts_to_rename, tid); 687 } 688 689 renameSrcRegs(inst, inst->threadNumber); 690 691 renameDestRegs(inst, inst->threadNumber); 692 693 if (inst->isLoad()) { 694 loadsInProgress[tid]++; 695 } 696 if (inst->isStore()) { 697 storesInProgress[tid]++; 698 } 699 ++renamed_insts; 700 701 702 // Put instruction in rename queue. 703 toIEW->insts[toIEWIndex] = inst; 704 ++(toIEW->size); 705 706 // Increment which instruction we're on. 707 ++toIEWIndex; 708 709 // Decrement how many instructions are available. 710 --insts_available; 711 } 712 713 instsInProgress[tid] += renamed_insts; 714 renameRenamedInsts += renamed_insts; 715 716 // If we wrote to the time buffer, record this. 717 if (toIEWIndex) { 718 wroteToTimeBuffer = true; 719 } 720 721 // Check if there's any instructions left that haven't yet been renamed. 722 // If so then block. 723 if (insts_available) { 724 blockThisCycle = true; 725 } 726 727 if (blockThisCycle) { 728 block(tid); 729 toDecode->renameUnblock[tid] = false; 730 } 731} 732 733template<class Impl> 734void 735DefaultRename<Impl>::skidInsert(ThreadID tid) 736{ 737 DynInstPtr inst = NULL; 738 739 while (!insts[tid].empty()) { 740 inst = insts[tid].front(); 741 742 insts[tid].pop_front(); 743 744 assert(tid == inst->threadNumber); 745 746 DPRINTF(Rename, "[tid:%u]: Inserting [sn:%lli] PC: %s into Rename " 747 "skidBuffer\n", tid, inst->seqNum, inst->pcState()); 748 749 ++renameSkidInsts; 750 751 skidBuffer[tid].push_back(inst); 752 } 753 754 if (skidBuffer[tid].size() > skidBufferMax) 755 { 756 typename InstQueue::iterator it; 757 warn("Skidbuffer contents:\n"); 758 for(it = skidBuffer[tid].begin(); it != skidBuffer[tid].end(); it++) 759 { 760 warn("[tid:%u]: %s [sn:%i].\n", tid, 761 (*it)->staticInst->disassemble(inst->instAddr()), 762 (*it)->seqNum); 763 } 764 panic("Skidbuffer Exceeded Max Size"); 765 } 766} 767 768template <class Impl> 769void 770DefaultRename<Impl>::sortInsts() 771{ 772 int insts_from_decode = fromDecode->size; 773 for (int i = 0; i < insts_from_decode; ++i) { 774 DynInstPtr inst = fromDecode->insts[i]; 775 insts[inst->threadNumber].push_back(inst); 776#if TRACING_ON 777 if (DTRACE(O3PipeView)) { 778 inst->renameTick = curTick() - inst->fetchTick; 779 } 780#endif 781 } 782} 783 784template<class Impl> 785bool 786DefaultRename<Impl>::skidsEmpty() 787{ 788 list<ThreadID>::iterator threads = activeThreads->begin(); 789 list<ThreadID>::iterator end = activeThreads->end(); 790 791 while (threads != end) { 792 ThreadID tid = *threads++; 793 794 if (!skidBuffer[tid].empty()) 795 return false; 796 } 797 798 return true; 799} 800 801template<class Impl> 802void 803DefaultRename<Impl>::updateStatus() 804{ 805 bool any_unblocking = false; 806 807 list<ThreadID>::iterator threads = activeThreads->begin(); 808 list<ThreadID>::iterator end = activeThreads->end(); 809 810 while (threads != end) { 811 ThreadID tid = *threads++; 812 813 if (renameStatus[tid] == Unblocking) { 814 any_unblocking = true; 815 break; 816 } 817 } 818 819 // Rename will have activity if it's unblocking. 820 if (any_unblocking) { 821 if (_status == Inactive) { 822 _status = Active; 823 824 DPRINTF(Activity, "Activating stage.\n"); 825 826 cpu->activateStage(O3CPU::RenameIdx); 827 } 828 } else { 829 // If it's not unblocking, then rename will not have any internal 830 // activity. Switch it to inactive. 831 if (_status == Active) { 832 _status = Inactive; 833 DPRINTF(Activity, "Deactivating stage.\n"); 834 835 cpu->deactivateStage(O3CPU::RenameIdx); 836 } 837 } 838} 839 840template <class Impl> 841bool 842DefaultRename<Impl>::block(ThreadID tid) 843{ 844 DPRINTF(Rename, "[tid:%u]: Blocking.\n", tid); 845 846 // Add the current inputs onto the skid buffer, so they can be 847 // reprocessed when this stage unblocks. 848 skidInsert(tid); 849 850 // Only signal backwards to block if the previous stages do not think 851 // rename is already blocked. 852 if (renameStatus[tid] != Blocked) { 853 // If resumeUnblocking is set, we unblocked during the squash, 854 // but now we're have unblocking status. We need to tell earlier 855 // stages to block. 856 if (resumeUnblocking || renameStatus[tid] != Unblocking) { 857 toDecode->renameBlock[tid] = true; 858 toDecode->renameUnblock[tid] = false; 859 wroteToTimeBuffer = true; 860 } 861 862 // Rename can not go from SerializeStall to Blocked, otherwise 863 // it would not know to complete the serialize stall. 864 if (renameStatus[tid] != SerializeStall) { 865 // Set status to Blocked. 866 renameStatus[tid] = Blocked; 867 return true; 868 } 869 } 870 871 return false; 872} 873 874template <class Impl> 875bool 876DefaultRename<Impl>::unblock(ThreadID tid) 877{ 878 DPRINTF(Rename, "[tid:%u]: Trying to unblock.\n", tid); 879 880 // Rename is done unblocking if the skid buffer is empty. 881 if (skidBuffer[tid].empty() && renameStatus[tid] != SerializeStall) { 882 883 DPRINTF(Rename, "[tid:%u]: Done unblocking.\n", tid); 884 885 toDecode->renameUnblock[tid] = true; 886 wroteToTimeBuffer = true; 887 888 renameStatus[tid] = Running; 889 return true; 890 } 891 892 return false; 893} 894 895template <class Impl> 896void 897DefaultRename<Impl>::doSquash(const InstSeqNum &squashed_seq_num, ThreadID tid) 898{ 899 typename std::list<RenameHistory>::iterator hb_it = 900 historyBuffer[tid].begin(); 901 902 // After a syscall squashes everything, the history buffer may be empty 903 // but the ROB may still be squashing instructions. 904 if (historyBuffer[tid].empty()) { 905 return; 906 } 907 908 // Go through the most recent instructions, undoing the mappings 909 // they did and freeing up the registers. 910 while (!historyBuffer[tid].empty() && 911 hb_it->instSeqNum > squashed_seq_num) { 912 assert(hb_it != historyBuffer[tid].end()); 913 914 DPRINTF(Rename, "[tid:%u]: Removing history entry with sequence " 915 "number %i.\n", tid, hb_it->instSeqNum); 916 917 // Undo the rename mapping only if it was really a change. 918 // Special regs that are not really renamed (like misc regs 919 // and the zero reg) can be recognized because the new mapping 920 // is the same as the old one. While it would be merely a 921 // waste of time to update the rename table, we definitely 922 // don't want to put these on the free list. 923 if (hb_it->newPhysReg != hb_it->prevPhysReg) { 924 // Tell the rename map to set the architected register to the 925 // previous physical register that it was renamed to. 926 renameMap[tid]->setEntry(hb_it->archReg, hb_it->prevPhysReg); 927 928 // Put the renamed physical register back on the free list. 929 freeList->addReg(hb_it->newPhysReg); 930 } 931 932 historyBuffer[tid].erase(hb_it++); 933 934 ++renameUndoneMaps; 935 } 936} 937 938template<class Impl> 939void 940DefaultRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num, ThreadID tid) 941{ 942 DPRINTF(Rename, "[tid:%u]: Removing a committed instruction from the " 943 "history buffer %u (size=%i), until [sn:%lli].\n", 944 tid, tid, historyBuffer[tid].size(), inst_seq_num); 945 946 typename std::list<RenameHistory>::iterator hb_it = 947 historyBuffer[tid].end(); 948 949 --hb_it; 950 951 if (historyBuffer[tid].empty()) { 952 DPRINTF(Rename, "[tid:%u]: History buffer is empty.\n", tid); 953 return; 954 } else if (hb_it->instSeqNum > inst_seq_num) { 955 DPRINTF(Rename, "[tid:%u]: Old sequence number encountered. Ensure " 956 "that a syscall happened recently.\n", tid); 957 return; 958 } 959 960 // Commit all the renames up until (and including) the committed sequence 961 // number. Some or even all of the committed instructions may not have 962 // rename histories if they did not have destination registers that were 963 // renamed. 964 while (!historyBuffer[tid].empty() && 965 hb_it != historyBuffer[tid].end() && 966 hb_it->instSeqNum <= inst_seq_num) { 967 968 DPRINTF(Rename, "[tid:%u]: Freeing up older rename of reg %i, " 969 "[sn:%lli].\n", 970 tid, hb_it->prevPhysReg, hb_it->instSeqNum); 971 972 // Don't free special phys regs like misc and zero regs, which 973 // can be recognized because the new mapping is the same as 974 // the old one. 975 if (hb_it->newPhysReg != hb_it->prevPhysReg) { 976 freeList->addReg(hb_it->prevPhysReg); 977 } 978 979 ++renameCommittedMaps; 980 981 historyBuffer[tid].erase(hb_it--); 982 } 983} 984 985template <class Impl> 986inline void 987DefaultRename<Impl>::renameSrcRegs(DynInstPtr &inst, ThreadID tid) 988{ 989 ThreadContext *tc = inst->tcBase(); 990 RenameMap *map = renameMap[tid]; 991 unsigned num_src_regs = inst->numSrcRegs(); 992 993 // Get the architectual register numbers from the source and 994 // operands, and redirect them to the right physical register. 995 for (int src_idx = 0; src_idx < num_src_regs; src_idx++) { 996 RegIndex src_reg = inst->srcRegIdx(src_idx); 997 RegIndex rel_src_reg; 998 RegIndex flat_rel_src_reg; 999 PhysRegIndex renamed_reg; 1000 1001 switch (regIdxToClass(src_reg, &rel_src_reg)) { 1002 case IntRegClass: 1003 flat_rel_src_reg = tc->flattenIntIndex(rel_src_reg); 1004 renamed_reg = map->lookupInt(flat_rel_src_reg); 1005 intRenameLookups++; 1006 break; 1007 1008 case FloatRegClass: 1009 flat_rel_src_reg = tc->flattenFloatIndex(rel_src_reg); 1010 renamed_reg = map->lookupFloat(flat_rel_src_reg); 1011 fpRenameLookups++; 1012 break; 1013 1014 case CCRegClass: 1015 flat_rel_src_reg = tc->flattenCCIndex(rel_src_reg); 1016 renamed_reg = map->lookupCC(flat_rel_src_reg); 1017 break; 1018
|
1020 case VectorRegClass: 1021 flat_rel_src_reg = tc->flattenVectorIndex(rel_src_reg); 1022 renamed_reg = map->lookupVector(flat_rel_src_reg); 1023 break; 1024
| |
1025 case MiscRegClass: 1026 // misc regs don't get flattened 1027 flat_rel_src_reg = rel_src_reg; 1028 renamed_reg = map->lookupMisc(flat_rel_src_reg); 1029 break; 1030 1031 default: 1032 panic("Reg index is out of bound: %d.", src_reg); 1033 } 1034 1035 DPRINTF(Rename, "[tid:%u]: Looking up %s arch reg %i (flattened %i), " 1036 "got phys reg %i\n", tid, RegClassStrings[regIdxToClass(src_reg)], 1037 (int)src_reg, (int)flat_rel_src_reg, (int)renamed_reg); 1038 1039 inst->renameSrcReg(src_idx, renamed_reg); 1040 1041 // See if the register is ready or not. 1042 if (scoreboard->getReg(renamed_reg)) { 1043 DPRINTF(Rename, "[tid:%u]: Register %d is ready.\n", 1044 tid, renamed_reg); 1045 1046 inst->markSrcRegReady(src_idx); 1047 } else { 1048 DPRINTF(Rename, "[tid:%u]: Register %d is not ready.\n", 1049 tid, renamed_reg); 1050 } 1051 1052 ++renameRenameLookups; 1053 } 1054} 1055 1056template <class Impl> 1057inline void 1058DefaultRename<Impl>::renameDestRegs(DynInstPtr &inst, ThreadID tid) 1059{ 1060 ThreadContext *tc = inst->tcBase(); 1061 RenameMap *map = renameMap[tid]; 1062 unsigned num_dest_regs = inst->numDestRegs(); 1063 1064 // Rename the destination registers. 1065 for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++) { 1066 RegIndex dest_reg = inst->destRegIdx(dest_idx); 1067 RegIndex rel_dest_reg; 1068 RegIndex flat_rel_dest_reg; 1069 RegIndex flat_uni_dest_reg; 1070 typename RenameMap::RenameInfo rename_result; 1071 1072 switch (regIdxToClass(dest_reg, &rel_dest_reg)) { 1073 case IntRegClass: 1074 flat_rel_dest_reg = tc->flattenIntIndex(rel_dest_reg); 1075 rename_result = map->renameInt(flat_rel_dest_reg); 1076 flat_uni_dest_reg = flat_rel_dest_reg; // 1:1 mapping 1077 break; 1078 1079 case FloatRegClass: 1080 flat_rel_dest_reg = tc->flattenFloatIndex(rel_dest_reg); 1081 rename_result = map->renameFloat(flat_rel_dest_reg); 1082 flat_uni_dest_reg = flat_rel_dest_reg + TheISA::FP_Reg_Base; 1083 break; 1084 1085 case CCRegClass: 1086 flat_rel_dest_reg = tc->flattenCCIndex(rel_dest_reg); 1087 rename_result = map->renameCC(flat_rel_dest_reg); 1088 flat_uni_dest_reg = flat_rel_dest_reg + TheISA::CC_Reg_Base; 1089 break; 1090
| 1019 case MiscRegClass: 1020 // misc regs don't get flattened 1021 flat_rel_src_reg = rel_src_reg; 1022 renamed_reg = map->lookupMisc(flat_rel_src_reg); 1023 break; 1024 1025 default: 1026 panic("Reg index is out of bound: %d.", src_reg); 1027 } 1028 1029 DPRINTF(Rename, "[tid:%u]: Looking up %s arch reg %i (flattened %i), " 1030 "got phys reg %i\n", tid, RegClassStrings[regIdxToClass(src_reg)], 1031 (int)src_reg, (int)flat_rel_src_reg, (int)renamed_reg); 1032 1033 inst->renameSrcReg(src_idx, renamed_reg); 1034 1035 // See if the register is ready or not. 1036 if (scoreboard->getReg(renamed_reg)) { 1037 DPRINTF(Rename, "[tid:%u]: Register %d is ready.\n", 1038 tid, renamed_reg); 1039 1040 inst->markSrcRegReady(src_idx); 1041 } else { 1042 DPRINTF(Rename, "[tid:%u]: Register %d is not ready.\n", 1043 tid, renamed_reg); 1044 } 1045 1046 ++renameRenameLookups; 1047 } 1048} 1049 1050template <class Impl> 1051inline void 1052DefaultRename<Impl>::renameDestRegs(DynInstPtr &inst, ThreadID tid) 1053{ 1054 ThreadContext *tc = inst->tcBase(); 1055 RenameMap *map = renameMap[tid]; 1056 unsigned num_dest_regs = inst->numDestRegs(); 1057 1058 // Rename the destination registers. 1059 for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++) { 1060 RegIndex dest_reg = inst->destRegIdx(dest_idx); 1061 RegIndex rel_dest_reg; 1062 RegIndex flat_rel_dest_reg; 1063 RegIndex flat_uni_dest_reg; 1064 typename RenameMap::RenameInfo rename_result; 1065 1066 switch (regIdxToClass(dest_reg, &rel_dest_reg)) { 1067 case IntRegClass: 1068 flat_rel_dest_reg = tc->flattenIntIndex(rel_dest_reg); 1069 rename_result = map->renameInt(flat_rel_dest_reg); 1070 flat_uni_dest_reg = flat_rel_dest_reg; // 1:1 mapping 1071 break; 1072 1073 case FloatRegClass: 1074 flat_rel_dest_reg = tc->flattenFloatIndex(rel_dest_reg); 1075 rename_result = map->renameFloat(flat_rel_dest_reg); 1076 flat_uni_dest_reg = flat_rel_dest_reg + TheISA::FP_Reg_Base; 1077 break; 1078 1079 case CCRegClass: 1080 flat_rel_dest_reg = tc->flattenCCIndex(rel_dest_reg); 1081 rename_result = map->renameCC(flat_rel_dest_reg); 1082 flat_uni_dest_reg = flat_rel_dest_reg + TheISA::CC_Reg_Base; 1083 break; 1084
|
1091 case VectorRegClass: 1092 flat_rel_dest_reg = tc->flattenVectorIndex(rel_dest_reg); 1093 rename_result = map->renameVector(flat_rel_dest_reg); 1094 flat_uni_dest_reg = flat_rel_dest_reg + TheISA::Vector_Reg_Base; 1095 break; 1096
| |
1097 case MiscRegClass: 1098 // misc regs don't get flattened 1099 flat_rel_dest_reg = rel_dest_reg; 1100 rename_result = map->renameMisc(flat_rel_dest_reg); 1101 flat_uni_dest_reg = flat_rel_dest_reg + TheISA::Misc_Reg_Base; 1102 break; 1103 1104 default: 1105 panic("Reg index is out of bound: %d.", dest_reg); 1106 } 1107 1108 inst->flattenDestReg(dest_idx, flat_uni_dest_reg); 1109 1110 // Mark Scoreboard entry as not ready 1111 scoreboard->unsetReg(rename_result.first); 1112 1113 DPRINTF(Rename, "[tid:%u]: Renaming arch reg %i to physical " 1114 "reg %i.\n", tid, (int)flat_rel_dest_reg, 1115 (int)rename_result.first); 1116 1117 // Record the rename information so that a history can be kept. 1118 RenameHistory hb_entry(inst->seqNum, flat_uni_dest_reg, 1119 rename_result.first, 1120 rename_result.second); 1121 1122 historyBuffer[tid].push_front(hb_entry); 1123 1124 DPRINTF(Rename, "[tid:%u]: Adding instruction to history buffer " 1125 "(size=%i), [sn:%lli].\n",tid, 1126 historyBuffer[tid].size(), 1127 (*historyBuffer[tid].begin()).instSeqNum); 1128 1129 // Tell the instruction to rename the appropriate destination 1130 // register (dest_idx) to the new physical register 1131 // (rename_result.first), and record the previous physical 1132 // register that the same logical register was renamed to 1133 // (rename_result.second). 1134 inst->renameDestReg(dest_idx, 1135 rename_result.first, 1136 rename_result.second); 1137 1138 ++renameRenamedOperands; 1139 } 1140} 1141 1142template <class Impl> 1143inline int 1144DefaultRename<Impl>::calcFreeROBEntries(ThreadID tid) 1145{ 1146 int num_free = freeEntries[tid].robEntries - 1147 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched); 1148 1149 //DPRINTF(Rename,"[tid:%i]: %i rob free\n",tid,num_free); 1150 1151 return num_free; 1152} 1153 1154template <class Impl> 1155inline int 1156DefaultRename<Impl>::calcFreeIQEntries(ThreadID tid) 1157{ 1158 int num_free = freeEntries[tid].iqEntries - 1159 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched); 1160 1161 //DPRINTF(Rename,"[tid:%i]: %i iq free\n",tid,num_free); 1162 1163 return num_free; 1164} 1165 1166template <class Impl> 1167inline int 1168DefaultRename<Impl>::calcFreeLQEntries(ThreadID tid) 1169{ 1170 int num_free = freeEntries[tid].lqEntries -
| 1085 case MiscRegClass: 1086 // misc regs don't get flattened 1087 flat_rel_dest_reg = rel_dest_reg; 1088 rename_result = map->renameMisc(flat_rel_dest_reg); 1089 flat_uni_dest_reg = flat_rel_dest_reg + TheISA::Misc_Reg_Base; 1090 break; 1091 1092 default: 1093 panic("Reg index is out of bound: %d.", dest_reg); 1094 } 1095 1096 inst->flattenDestReg(dest_idx, flat_uni_dest_reg); 1097 1098 // Mark Scoreboard entry as not ready 1099 scoreboard->unsetReg(rename_result.first); 1100 1101 DPRINTF(Rename, "[tid:%u]: Renaming arch reg %i to physical " 1102 "reg %i.\n", tid, (int)flat_rel_dest_reg, 1103 (int)rename_result.first); 1104 1105 // Record the rename information so that a history can be kept. 1106 RenameHistory hb_entry(inst->seqNum, flat_uni_dest_reg, 1107 rename_result.first, 1108 rename_result.second); 1109 1110 historyBuffer[tid].push_front(hb_entry); 1111 1112 DPRINTF(Rename, "[tid:%u]: Adding instruction to history buffer " 1113 "(size=%i), [sn:%lli].\n",tid, 1114 historyBuffer[tid].size(), 1115 (*historyBuffer[tid].begin()).instSeqNum); 1116 1117 // Tell the instruction to rename the appropriate destination 1118 // register (dest_idx) to the new physical register 1119 // (rename_result.first), and record the previous physical 1120 // register that the same logical register was renamed to 1121 // (rename_result.second). 1122 inst->renameDestReg(dest_idx, 1123 rename_result.first, 1124 rename_result.second); 1125 1126 ++renameRenamedOperands; 1127 } 1128} 1129 1130template <class Impl> 1131inline int 1132DefaultRename<Impl>::calcFreeROBEntries(ThreadID tid) 1133{ 1134 int num_free = freeEntries[tid].robEntries - 1135 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched); 1136 1137 //DPRINTF(Rename,"[tid:%i]: %i rob free\n",tid,num_free); 1138 1139 return num_free; 1140} 1141 1142template <class Impl> 1143inline int 1144DefaultRename<Impl>::calcFreeIQEntries(ThreadID tid) 1145{ 1146 int num_free = freeEntries[tid].iqEntries - 1147 (instsInProgress[tid] - fromIEW->iewInfo[tid].dispatched); 1148 1149 //DPRINTF(Rename,"[tid:%i]: %i iq free\n",tid,num_free); 1150 1151 return num_free; 1152} 1153 1154template <class Impl> 1155inline int 1156DefaultRename<Impl>::calcFreeLQEntries(ThreadID tid) 1157{ 1158 int num_free = freeEntries[tid].lqEntries -
|
1171 (loadsInProgress[tid] - fromIEW->iewInfo[tid].dispatchedToLQ);
| 1159 (loadsInProgress[tid] - fromIEW->iewInfo[tid].dispatchedToLQ);
|
1172 DPRINTF(Rename, "calcFreeLQEntries: free lqEntries: %d, loadsInProgress: %d, " 1173 "loads dispatchedToLQ: %d\n", freeEntries[tid].lqEntries, 1174 loadsInProgress[tid], fromIEW->iewInfo[tid].dispatchedToLQ); 1175 return num_free; 1176} 1177 1178template <class Impl> 1179inline int 1180DefaultRename<Impl>::calcFreeSQEntries(ThreadID tid) 1181{ 1182 int num_free = freeEntries[tid].sqEntries -
| 1160 DPRINTF(Rename, "calcFreeLQEntries: free lqEntries: %d, loadsInProgress: %d, " 1161 "loads dispatchedToLQ: %d\n", freeEntries[tid].lqEntries, 1162 loadsInProgress[tid], fromIEW->iewInfo[tid].dispatchedToLQ); 1163 return num_free; 1164} 1165 1166template <class Impl> 1167inline int 1168DefaultRename<Impl>::calcFreeSQEntries(ThreadID tid) 1169{ 1170 int num_free = freeEntries[tid].sqEntries -
|
1183 (storesInProgress[tid] - fromIEW->iewInfo[tid].dispatchedToSQ);
| 1171 (storesInProgress[tid] - fromIEW->iewInfo[tid].dispatchedToSQ);
|
1184 DPRINTF(Rename, "calcFreeSQEntries: free sqEntries: %d, storesInProgress: %d, " 1185 "stores dispatchedToSQ: %d\n", freeEntries[tid].sqEntries, 1186 storesInProgress[tid], fromIEW->iewInfo[tid].dispatchedToSQ); 1187 return num_free; 1188} 1189 1190template <class Impl> 1191unsigned 1192DefaultRename<Impl>::validInsts() 1193{ 1194 unsigned inst_count = 0; 1195 1196 for (int i=0; i<fromDecode->size; i++) { 1197 if (!fromDecode->insts[i]->isSquashed()) 1198 inst_count++; 1199 } 1200 1201 return inst_count; 1202} 1203 1204template <class Impl> 1205void 1206DefaultRename<Impl>::readStallSignals(ThreadID tid) 1207{ 1208 if (fromIEW->iewBlock[tid]) { 1209 stalls[tid].iew = true; 1210 } 1211 1212 if (fromIEW->iewUnblock[tid]) { 1213 assert(stalls[tid].iew); 1214 stalls[tid].iew = false; 1215 } 1216} 1217 1218template <class Impl> 1219bool 1220DefaultRename<Impl>::checkStall(ThreadID tid) 1221{ 1222 bool ret_val = false; 1223 1224 if (stalls[tid].iew) { 1225 DPRINTF(Rename,"[tid:%i]: Stall from IEW stage detected.\n", tid); 1226 ret_val = true; 1227 } else if (calcFreeROBEntries(tid) <= 0) { 1228 DPRINTF(Rename,"[tid:%i]: Stall: ROB has 0 free entries.\n", tid); 1229 ret_val = true; 1230 } else if (calcFreeIQEntries(tid) <= 0) { 1231 DPRINTF(Rename,"[tid:%i]: Stall: IQ has 0 free entries.\n", tid); 1232 ret_val = true; 1233 } else if (calcFreeLQEntries(tid) <= 0 && calcFreeSQEntries(tid) <= 0) { 1234 DPRINTF(Rename,"[tid:%i]: Stall: LSQ has 0 free entries.\n", tid); 1235 ret_val = true; 1236 } else if (renameMap[tid]->numFreeEntries() <= 0) { 1237 DPRINTF(Rename,"[tid:%i]: Stall: RenameMap has 0 free entries.\n", tid); 1238 ret_val = true; 1239 } else if (renameStatus[tid] == SerializeStall && 1240 (!emptyROB[tid] || instsInProgress[tid])) { 1241 DPRINTF(Rename,"[tid:%i]: Stall: Serialize stall and ROB is not " 1242 "empty.\n", 1243 tid); 1244 ret_val = true; 1245 } 1246 1247 return ret_val; 1248} 1249 1250template <class Impl> 1251void 1252DefaultRename<Impl>::readFreeEntries(ThreadID tid) 1253{ 1254 if (fromIEW->iewInfo[tid].usedIQ) 1255 freeEntries[tid].iqEntries = fromIEW->iewInfo[tid].freeIQEntries; 1256 1257 if (fromIEW->iewInfo[tid].usedLSQ) { 1258 freeEntries[tid].lqEntries = fromIEW->iewInfo[tid].freeLQEntries; 1259 freeEntries[tid].sqEntries = fromIEW->iewInfo[tid].freeSQEntries; 1260 } 1261 1262 if (fromCommit->commitInfo[tid].usedROB) { 1263 freeEntries[tid].robEntries = 1264 fromCommit->commitInfo[tid].freeROBEntries; 1265 emptyROB[tid] = fromCommit->commitInfo[tid].emptyROB; 1266 } 1267 1268 DPRINTF(Rename, "[tid:%i]: Free IQ: %i, Free ROB: %i, " 1269 "Free LQ: %i, Free SQ: %i\n", 1270 tid, 1271 freeEntries[tid].iqEntries, 1272 freeEntries[tid].robEntries, 1273 freeEntries[tid].lqEntries, 1274 freeEntries[tid].sqEntries); 1275 1276 DPRINTF(Rename, "[tid:%i]: %i instructions not yet in ROB\n", 1277 tid, instsInProgress[tid]); 1278} 1279 1280template <class Impl> 1281bool 1282DefaultRename<Impl>::checkSignalsAndUpdate(ThreadID tid) 1283{ 1284 // Check if there's a squash signal, squash if there is 1285 // Check stall signals, block if necessary. 1286 // If status was blocked 1287 // check if stall conditions have passed 1288 // if so then go to unblocking 1289 // If status was Squashing 1290 // check if squashing is not high. Switch to running this cycle. 1291 // If status was serialize stall 1292 // check if ROB is empty and no insts are in flight to the ROB 1293 1294 readFreeEntries(tid); 1295 readStallSignals(tid); 1296 1297 if (fromCommit->commitInfo[tid].squash) { 1298 DPRINTF(Rename, "[tid:%u]: Squashing instructions due to squash from " 1299 "commit.\n", tid); 1300 1301 squash(fromCommit->commitInfo[tid].doneSeqNum, tid); 1302 1303 return true; 1304 } 1305 1306 if (checkStall(tid)) { 1307 return block(tid); 1308 } 1309 1310 if (renameStatus[tid] == Blocked) { 1311 DPRINTF(Rename, "[tid:%u]: Done blocking, switching to unblocking.\n", 1312 tid); 1313 1314 renameStatus[tid] = Unblocking; 1315 1316 unblock(tid); 1317 1318 return true; 1319 } 1320 1321 if (renameStatus[tid] == Squashing) { 1322 // Switch status to running if rename isn't being told to block or 1323 // squash this cycle. 1324 if (resumeSerialize) { 1325 DPRINTF(Rename, "[tid:%u]: Done squashing, switching to serialize.\n", 1326 tid); 1327 1328 renameStatus[tid] = SerializeStall; 1329 return true; 1330 } else if (resumeUnblocking) { 1331 DPRINTF(Rename, "[tid:%u]: Done squashing, switching to unblocking.\n", 1332 tid); 1333 renameStatus[tid] = Unblocking; 1334 return true; 1335 } else { 1336 DPRINTF(Rename, "[tid:%u]: Done squashing, switching to running.\n", 1337 tid); 1338 1339 renameStatus[tid] = Running; 1340 return false; 1341 } 1342 } 1343 1344 if (renameStatus[tid] == SerializeStall) { 1345 // Stall ends once the ROB is free. 1346 DPRINTF(Rename, "[tid:%u]: Done with serialize stall, switching to " 1347 "unblocking.\n", tid); 1348 1349 DynInstPtr serial_inst = serializeInst[tid]; 1350 1351 renameStatus[tid] = Unblocking; 1352 1353 unblock(tid); 1354 1355 DPRINTF(Rename, "[tid:%u]: Processing instruction [%lli] with " 1356 "PC %s.\n", tid, serial_inst->seqNum, serial_inst->pcState()); 1357 1358 // Put instruction into queue here. 1359 serial_inst->clearSerializeBefore(); 1360 1361 if (!skidBuffer[tid].empty()) { 1362 skidBuffer[tid].push_front(serial_inst); 1363 } else { 1364 insts[tid].push_front(serial_inst); 1365 } 1366 1367 DPRINTF(Rename, "[tid:%u]: Instruction must be processed by rename." 1368 " Adding to front of list.\n", tid); 1369 1370 serializeInst[tid] = NULL; 1371 1372 return true; 1373 } 1374 1375 // If we've reached this point, we have not gotten any signals that 1376 // cause rename to change its status. Rename remains the same as before. 1377 return false; 1378} 1379 1380template<class Impl> 1381void 1382DefaultRename<Impl>::serializeAfter(InstQueue &inst_list, ThreadID tid) 1383{ 1384 if (inst_list.empty()) { 1385 // Mark a bit to say that I must serialize on the next instruction. 1386 serializeOnNextInst[tid] = true; 1387 return; 1388 } 1389 1390 // Set the next instruction as serializing. 1391 inst_list.front()->setSerializeBefore(); 1392} 1393 1394template <class Impl> 1395inline void 1396DefaultRename<Impl>::incrFullStat(const FullSource &source) 1397{ 1398 switch (source) { 1399 case ROB: 1400 ++renameROBFullEvents; 1401 break; 1402 case IQ: 1403 ++renameIQFullEvents; 1404 break; 1405 case LQ: 1406 ++renameLQFullEvents; 1407 break; 1408 case SQ: 1409 ++renameSQFullEvents; 1410 break; 1411 default: 1412 panic("Rename full stall stat should be incremented for a reason!"); 1413 break; 1414 } 1415} 1416 1417template <class Impl> 1418void 1419DefaultRename<Impl>::dumpHistory() 1420{ 1421 typename std::list<RenameHistory>::iterator buf_it; 1422 1423 for (ThreadID tid = 0; tid < numThreads; tid++) { 1424 1425 buf_it = historyBuffer[tid].begin(); 1426 1427 while (buf_it != historyBuffer[tid].end()) { 1428 cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys " 1429 "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg, 1430 (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg); 1431 1432 buf_it++; 1433 } 1434 } 1435} 1436 1437#endif//__CPU_O3_RENAME_IMPL_HH__
| 1172 DPRINTF(Rename, "calcFreeSQEntries: free sqEntries: %d, storesInProgress: %d, " 1173 "stores dispatchedToSQ: %d\n", freeEntries[tid].sqEntries, 1174 storesInProgress[tid], fromIEW->iewInfo[tid].dispatchedToSQ); 1175 return num_free; 1176} 1177 1178template <class Impl> 1179unsigned 1180DefaultRename<Impl>::validInsts() 1181{ 1182 unsigned inst_count = 0; 1183 1184 for (int i=0; i<fromDecode->size; i++) { 1185 if (!fromDecode->insts[i]->isSquashed()) 1186 inst_count++; 1187 } 1188 1189 return inst_count; 1190} 1191 1192template <class Impl> 1193void 1194DefaultRename<Impl>::readStallSignals(ThreadID tid) 1195{ 1196 if (fromIEW->iewBlock[tid]) { 1197 stalls[tid].iew = true; 1198 } 1199 1200 if (fromIEW->iewUnblock[tid]) { 1201 assert(stalls[tid].iew); 1202 stalls[tid].iew = false; 1203 } 1204} 1205 1206template <class Impl> 1207bool 1208DefaultRename<Impl>::checkStall(ThreadID tid) 1209{ 1210 bool ret_val = false; 1211 1212 if (stalls[tid].iew) { 1213 DPRINTF(Rename,"[tid:%i]: Stall from IEW stage detected.\n", tid); 1214 ret_val = true; 1215 } else if (calcFreeROBEntries(tid) <= 0) { 1216 DPRINTF(Rename,"[tid:%i]: Stall: ROB has 0 free entries.\n", tid); 1217 ret_val = true; 1218 } else if (calcFreeIQEntries(tid) <= 0) { 1219 DPRINTF(Rename,"[tid:%i]: Stall: IQ has 0 free entries.\n", tid); 1220 ret_val = true; 1221 } else if (calcFreeLQEntries(tid) <= 0 && calcFreeSQEntries(tid) <= 0) { 1222 DPRINTF(Rename,"[tid:%i]: Stall: LSQ has 0 free entries.\n", tid); 1223 ret_val = true; 1224 } else if (renameMap[tid]->numFreeEntries() <= 0) { 1225 DPRINTF(Rename,"[tid:%i]: Stall: RenameMap has 0 free entries.\n", tid); 1226 ret_val = true; 1227 } else if (renameStatus[tid] == SerializeStall && 1228 (!emptyROB[tid] || instsInProgress[tid])) { 1229 DPRINTF(Rename,"[tid:%i]: Stall: Serialize stall and ROB is not " 1230 "empty.\n", 1231 tid); 1232 ret_val = true; 1233 } 1234 1235 return ret_val; 1236} 1237 1238template <class Impl> 1239void 1240DefaultRename<Impl>::readFreeEntries(ThreadID tid) 1241{ 1242 if (fromIEW->iewInfo[tid].usedIQ) 1243 freeEntries[tid].iqEntries = fromIEW->iewInfo[tid].freeIQEntries; 1244 1245 if (fromIEW->iewInfo[tid].usedLSQ) { 1246 freeEntries[tid].lqEntries = fromIEW->iewInfo[tid].freeLQEntries; 1247 freeEntries[tid].sqEntries = fromIEW->iewInfo[tid].freeSQEntries; 1248 } 1249 1250 if (fromCommit->commitInfo[tid].usedROB) { 1251 freeEntries[tid].robEntries = 1252 fromCommit->commitInfo[tid].freeROBEntries; 1253 emptyROB[tid] = fromCommit->commitInfo[tid].emptyROB; 1254 } 1255 1256 DPRINTF(Rename, "[tid:%i]: Free IQ: %i, Free ROB: %i, " 1257 "Free LQ: %i, Free SQ: %i\n", 1258 tid, 1259 freeEntries[tid].iqEntries, 1260 freeEntries[tid].robEntries, 1261 freeEntries[tid].lqEntries, 1262 freeEntries[tid].sqEntries); 1263 1264 DPRINTF(Rename, "[tid:%i]: %i instructions not yet in ROB\n", 1265 tid, instsInProgress[tid]); 1266} 1267 1268template <class Impl> 1269bool 1270DefaultRename<Impl>::checkSignalsAndUpdate(ThreadID tid) 1271{ 1272 // Check if there's a squash signal, squash if there is 1273 // Check stall signals, block if necessary. 1274 // If status was blocked 1275 // check if stall conditions have passed 1276 // if so then go to unblocking 1277 // If status was Squashing 1278 // check if squashing is not high. Switch to running this cycle. 1279 // If status was serialize stall 1280 // check if ROB is empty and no insts are in flight to the ROB 1281 1282 readFreeEntries(tid); 1283 readStallSignals(tid); 1284 1285 if (fromCommit->commitInfo[tid].squash) { 1286 DPRINTF(Rename, "[tid:%u]: Squashing instructions due to squash from " 1287 "commit.\n", tid); 1288 1289 squash(fromCommit->commitInfo[tid].doneSeqNum, tid); 1290 1291 return true; 1292 } 1293 1294 if (checkStall(tid)) { 1295 return block(tid); 1296 } 1297 1298 if (renameStatus[tid] == Blocked) { 1299 DPRINTF(Rename, "[tid:%u]: Done blocking, switching to unblocking.\n", 1300 tid); 1301 1302 renameStatus[tid] = Unblocking; 1303 1304 unblock(tid); 1305 1306 return true; 1307 } 1308 1309 if (renameStatus[tid] == Squashing) { 1310 // Switch status to running if rename isn't being told to block or 1311 // squash this cycle. 1312 if (resumeSerialize) { 1313 DPRINTF(Rename, "[tid:%u]: Done squashing, switching to serialize.\n", 1314 tid); 1315 1316 renameStatus[tid] = SerializeStall; 1317 return true; 1318 } else if (resumeUnblocking) { 1319 DPRINTF(Rename, "[tid:%u]: Done squashing, switching to unblocking.\n", 1320 tid); 1321 renameStatus[tid] = Unblocking; 1322 return true; 1323 } else { 1324 DPRINTF(Rename, "[tid:%u]: Done squashing, switching to running.\n", 1325 tid); 1326 1327 renameStatus[tid] = Running; 1328 return false; 1329 } 1330 } 1331 1332 if (renameStatus[tid] == SerializeStall) { 1333 // Stall ends once the ROB is free. 1334 DPRINTF(Rename, "[tid:%u]: Done with serialize stall, switching to " 1335 "unblocking.\n", tid); 1336 1337 DynInstPtr serial_inst = serializeInst[tid]; 1338 1339 renameStatus[tid] = Unblocking; 1340 1341 unblock(tid); 1342 1343 DPRINTF(Rename, "[tid:%u]: Processing instruction [%lli] with " 1344 "PC %s.\n", tid, serial_inst->seqNum, serial_inst->pcState()); 1345 1346 // Put instruction into queue here. 1347 serial_inst->clearSerializeBefore(); 1348 1349 if (!skidBuffer[tid].empty()) { 1350 skidBuffer[tid].push_front(serial_inst); 1351 } else { 1352 insts[tid].push_front(serial_inst); 1353 } 1354 1355 DPRINTF(Rename, "[tid:%u]: Instruction must be processed by rename." 1356 " Adding to front of list.\n", tid); 1357 1358 serializeInst[tid] = NULL; 1359 1360 return true; 1361 } 1362 1363 // If we've reached this point, we have not gotten any signals that 1364 // cause rename to change its status. Rename remains the same as before. 1365 return false; 1366} 1367 1368template<class Impl> 1369void 1370DefaultRename<Impl>::serializeAfter(InstQueue &inst_list, ThreadID tid) 1371{ 1372 if (inst_list.empty()) { 1373 // Mark a bit to say that I must serialize on the next instruction. 1374 serializeOnNextInst[tid] = true; 1375 return; 1376 } 1377 1378 // Set the next instruction as serializing. 1379 inst_list.front()->setSerializeBefore(); 1380} 1381 1382template <class Impl> 1383inline void 1384DefaultRename<Impl>::incrFullStat(const FullSource &source) 1385{ 1386 switch (source) { 1387 case ROB: 1388 ++renameROBFullEvents; 1389 break; 1390 case IQ: 1391 ++renameIQFullEvents; 1392 break; 1393 case LQ: 1394 ++renameLQFullEvents; 1395 break; 1396 case SQ: 1397 ++renameSQFullEvents; 1398 break; 1399 default: 1400 panic("Rename full stall stat should be incremented for a reason!"); 1401 break; 1402 } 1403} 1404 1405template <class Impl> 1406void 1407DefaultRename<Impl>::dumpHistory() 1408{ 1409 typename std::list<RenameHistory>::iterator buf_it; 1410 1411 for (ThreadID tid = 0; tid < numThreads; tid++) { 1412 1413 buf_it = historyBuffer[tid].begin(); 1414 1415 while (buf_it != historyBuffer[tid].end()) { 1416 cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys " 1417 "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg, 1418 (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg); 1419 1420 buf_it++; 1421 } 1422 } 1423} 1424 1425#endif//__CPU_O3_RENAME_IMPL_HH__
|