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