iew_impl.hh revision 10164:2d2c60bda8b2
1/* 2 * Copyright (c) 2010-2013 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 */ 42 43#ifndef __CPU_O3_IEW_IMPL_IMPL_HH__ 44#define __CPU_O3_IEW_IMPL_IMPL_HH__ 45 46// @todo: Fix the instantaneous communication among all the stages within 47// iew. There's a clear delay between issue and execute, yet backwards 48// communication happens simultaneously. 49 50#include <queue> 51 52#include "arch/utility.hh" 53#include "config/the_isa.hh" 54#include "cpu/checker/cpu.hh" 55#include "cpu/o3/fu_pool.hh" 56#include "cpu/o3/iew.hh" 57#include "cpu/timebuf.hh" 58#include "debug/Activity.hh" 59#include "debug/Drain.hh" 60#include "debug/IEW.hh" 61#include "debug/O3PipeView.hh" 62#include "params/DerivO3CPU.hh" 63 64using namespace std; 65 66template<class Impl> 67DefaultIEW<Impl>::DefaultIEW(O3CPU *_cpu, DerivO3CPUParams *params) 68 : issueToExecQueue(params->backComSize, params->forwardComSize), 69 cpu(_cpu), 70 instQueue(_cpu, this, params), 71 ldstQueue(_cpu, this, params), 72 fuPool(params->fuPool), 73 commitToIEWDelay(params->commitToIEWDelay), 74 renameToIEWDelay(params->renameToIEWDelay), 75 issueToExecuteDelay(params->issueToExecuteDelay), 76 dispatchWidth(params->dispatchWidth), 77 issueWidth(params->issueWidth), 78 wbOutstanding(0), 79 wbWidth(params->wbWidth), 80 numThreads(params->numThreads) 81{ 82 _status = Active; 83 exeStatus = Running; 84 wbStatus = Idle; 85 86 // Setup wire to read instructions coming from issue. 87 fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay); 88 89 // Instruction queue needs the queue between issue and execute. 90 instQueue.setIssueToExecuteQueue(&issueToExecQueue); 91 92 for (ThreadID tid = 0; tid < numThreads; tid++) { 93 dispatchStatus[tid] = Running; 94 stalls[tid].commit = false; 95 fetchRedirect[tid] = false; 96 } 97 98 wbMax = wbWidth * params->wbDepth; 99 100 updateLSQNextCycle = false; 101 102 ableToIssue = true; 103 104 skidBufferMax = (3 * (renameToIEWDelay * params->renameWidth)) + issueWidth; 105} 106 107template <class Impl> 108std::string 109DefaultIEW<Impl>::name() const 110{ 111 return cpu->name() + ".iew"; 112} 113 114template <class Impl> 115void 116DefaultIEW<Impl>::regProbePoints() 117{ 118 ppDispatch = new ProbePointArg<DynInstPtr>(cpu->getProbeManager(), "Dispatch"); 119 ppMispredict = new ProbePointArg<DynInstPtr>(cpu->getProbeManager(), "Mispredict"); 120} 121 122template <class Impl> 123void 124DefaultIEW<Impl>::regStats() 125{ 126 using namespace Stats; 127 128 instQueue.regStats(); 129 ldstQueue.regStats(); 130 131 iewIdleCycles 132 .name(name() + ".iewIdleCycles") 133 .desc("Number of cycles IEW is idle"); 134 135 iewSquashCycles 136 .name(name() + ".iewSquashCycles") 137 .desc("Number of cycles IEW is squashing"); 138 139 iewBlockCycles 140 .name(name() + ".iewBlockCycles") 141 .desc("Number of cycles IEW is blocking"); 142 143 iewUnblockCycles 144 .name(name() + ".iewUnblockCycles") 145 .desc("Number of cycles IEW is unblocking"); 146 147 iewDispatchedInsts 148 .name(name() + ".iewDispatchedInsts") 149 .desc("Number of instructions dispatched to IQ"); 150 151 iewDispSquashedInsts 152 .name(name() + ".iewDispSquashedInsts") 153 .desc("Number of squashed instructions skipped by dispatch"); 154 155 iewDispLoadInsts 156 .name(name() + ".iewDispLoadInsts") 157 .desc("Number of dispatched load instructions"); 158 159 iewDispStoreInsts 160 .name(name() + ".iewDispStoreInsts") 161 .desc("Number of dispatched store instructions"); 162 163 iewDispNonSpecInsts 164 .name(name() + ".iewDispNonSpecInsts") 165 .desc("Number of dispatched non-speculative instructions"); 166 167 iewIQFullEvents 168 .name(name() + ".iewIQFullEvents") 169 .desc("Number of times the IQ has become full, causing a stall"); 170 171 iewLSQFullEvents 172 .name(name() + ".iewLSQFullEvents") 173 .desc("Number of times the LSQ has become full, causing a stall"); 174 175 memOrderViolationEvents 176 .name(name() + ".memOrderViolationEvents") 177 .desc("Number of memory order violations"); 178 179 predictedTakenIncorrect 180 .name(name() + ".predictedTakenIncorrect") 181 .desc("Number of branches that were predicted taken incorrectly"); 182 183 predictedNotTakenIncorrect 184 .name(name() + ".predictedNotTakenIncorrect") 185 .desc("Number of branches that were predicted not taken incorrectly"); 186 187 branchMispredicts 188 .name(name() + ".branchMispredicts") 189 .desc("Number of branch mispredicts detected at execute"); 190 191 branchMispredicts = predictedTakenIncorrect + predictedNotTakenIncorrect; 192 193 iewExecutedInsts 194 .name(name() + ".iewExecutedInsts") 195 .desc("Number of executed instructions"); 196 197 iewExecLoadInsts 198 .init(cpu->numThreads) 199 .name(name() + ".iewExecLoadInsts") 200 .desc("Number of load instructions executed") 201 .flags(total); 202 203 iewExecSquashedInsts 204 .name(name() + ".iewExecSquashedInsts") 205 .desc("Number of squashed instructions skipped in execute"); 206 207 iewExecutedSwp 208 .init(cpu->numThreads) 209 .name(name() + ".exec_swp") 210 .desc("number of swp insts executed") 211 .flags(total); 212 213 iewExecutedNop 214 .init(cpu->numThreads) 215 .name(name() + ".exec_nop") 216 .desc("number of nop insts executed") 217 .flags(total); 218 219 iewExecutedRefs 220 .init(cpu->numThreads) 221 .name(name() + ".exec_refs") 222 .desc("number of memory reference insts executed") 223 .flags(total); 224 225 iewExecutedBranches 226 .init(cpu->numThreads) 227 .name(name() + ".exec_branches") 228 .desc("Number of branches executed") 229 .flags(total); 230 231 iewExecStoreInsts 232 .name(name() + ".exec_stores") 233 .desc("Number of stores executed") 234 .flags(total); 235 iewExecStoreInsts = iewExecutedRefs - iewExecLoadInsts; 236 237 iewExecRate 238 .name(name() + ".exec_rate") 239 .desc("Inst execution rate") 240 .flags(total); 241 242 iewExecRate = iewExecutedInsts / cpu->numCycles; 243 244 iewInstsToCommit 245 .init(cpu->numThreads) 246 .name(name() + ".wb_sent") 247 .desc("cumulative count of insts sent to commit") 248 .flags(total); 249 250 writebackCount 251 .init(cpu->numThreads) 252 .name(name() + ".wb_count") 253 .desc("cumulative count of insts written-back") 254 .flags(total); 255 256 producerInst 257 .init(cpu->numThreads) 258 .name(name() + ".wb_producers") 259 .desc("num instructions producing a value") 260 .flags(total); 261 262 consumerInst 263 .init(cpu->numThreads) 264 .name(name() + ".wb_consumers") 265 .desc("num instructions consuming a value") 266 .flags(total); 267 268 wbPenalized 269 .init(cpu->numThreads) 270 .name(name() + ".wb_penalized") 271 .desc("number of instrctions required to write to 'other' IQ") 272 .flags(total); 273 274 wbPenalizedRate 275 .name(name() + ".wb_penalized_rate") 276 .desc ("fraction of instructions written-back that wrote to 'other' IQ") 277 .flags(total); 278 279 wbPenalizedRate = wbPenalized / writebackCount; 280 281 wbFanout 282 .name(name() + ".wb_fanout") 283 .desc("average fanout of values written-back") 284 .flags(total); 285 286 wbFanout = producerInst / consumerInst; 287 288 wbRate 289 .name(name() + ".wb_rate") 290 .desc("insts written-back per cycle") 291 .flags(total); 292 wbRate = writebackCount / cpu->numCycles; 293} 294 295template<class Impl> 296void 297DefaultIEW<Impl>::startupStage() 298{ 299 for (ThreadID tid = 0; tid < numThreads; tid++) { 300 toRename->iewInfo[tid].usedIQ = true; 301 toRename->iewInfo[tid].freeIQEntries = 302 instQueue.numFreeEntries(tid); 303 304 toRename->iewInfo[tid].usedLSQ = true; 305 toRename->iewInfo[tid].freeLSQEntries = 306 ldstQueue.numFreeEntries(tid); 307 } 308 309 // Initialize the checker's dcache port here 310 if (cpu->checker) { 311 cpu->checker->setDcachePort(&cpu->getDataPort()); 312 } 313 314 cpu->activateStage(O3CPU::IEWIdx); 315} 316 317template<class Impl> 318void 319DefaultIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 320{ 321 timeBuffer = tb_ptr; 322 323 // Setup wire to read information from time buffer, from commit. 324 fromCommit = timeBuffer->getWire(-commitToIEWDelay); 325 326 // Setup wire to write information back to previous stages. 327 toRename = timeBuffer->getWire(0); 328 329 toFetch = timeBuffer->getWire(0); 330 331 // Instruction queue also needs main time buffer. 332 instQueue.setTimeBuffer(tb_ptr); 333} 334 335template<class Impl> 336void 337DefaultIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 338{ 339 renameQueue = rq_ptr; 340 341 // Setup wire to read information from rename queue. 342 fromRename = renameQueue->getWire(-renameToIEWDelay); 343} 344 345template<class Impl> 346void 347DefaultIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr) 348{ 349 iewQueue = iq_ptr; 350 351 // Setup wire to write instructions to commit. 352 toCommit = iewQueue->getWire(0); 353} 354 355template<class Impl> 356void 357DefaultIEW<Impl>::setActiveThreads(list<ThreadID> *at_ptr) 358{ 359 activeThreads = at_ptr; 360 361 ldstQueue.setActiveThreads(at_ptr); 362 instQueue.setActiveThreads(at_ptr); 363} 364 365template<class Impl> 366void 367DefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr) 368{ 369 scoreboard = sb_ptr; 370} 371 372template <class Impl> 373bool 374DefaultIEW<Impl>::isDrained() const 375{ 376 bool drained(ldstQueue.isDrained()); 377 378 for (ThreadID tid = 0; tid < numThreads; tid++) { 379 if (!insts[tid].empty()) { 380 DPRINTF(Drain, "%i: Insts not empty.\n", tid); 381 drained = false; 382 } 383 if (!skidBuffer[tid].empty()) { 384 DPRINTF(Drain, "%i: Skid buffer not empty.\n", tid); 385 drained = false; 386 } 387 } 388 389 // Also check the FU pool as instructions are "stored" in FU 390 // completion events until they are done and not accounted for 391 // above 392 if (drained && !fuPool->isDrained()) { 393 DPRINTF(Drain, "FU pool still busy.\n"); 394 drained = false; 395 } 396 397 return drained; 398} 399 400template <class Impl> 401void 402DefaultIEW<Impl>::drainSanityCheck() const 403{ 404 assert(isDrained()); 405 406 instQueue.drainSanityCheck(); 407 ldstQueue.drainSanityCheck(); 408} 409 410template <class Impl> 411void 412DefaultIEW<Impl>::takeOverFrom() 413{ 414 // Reset all state. 415 _status = Active; 416 exeStatus = Running; 417 wbStatus = Idle; 418 419 instQueue.takeOverFrom(); 420 ldstQueue.takeOverFrom(); 421 fuPool->takeOverFrom(); 422 423 startupStage(); 424 cpu->activityThisCycle(); 425 426 for (ThreadID tid = 0; tid < numThreads; tid++) { 427 dispatchStatus[tid] = Running; 428 stalls[tid].commit = false; 429 fetchRedirect[tid] = false; 430 } 431 432 updateLSQNextCycle = false; 433 434 for (int i = 0; i < issueToExecQueue.getSize(); ++i) { 435 issueToExecQueue.advance(); 436 } 437} 438 439template<class Impl> 440void 441DefaultIEW<Impl>::squash(ThreadID tid) 442{ 443 DPRINTF(IEW, "[tid:%i]: Squashing all instructions.\n", tid); 444 445 // Tell the IQ to start squashing. 446 instQueue.squash(tid); 447 448 // Tell the LDSTQ to start squashing. 449 ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum, tid); 450 updatedQueues = true; 451 452 // Clear the skid buffer in case it has any data in it. 453 DPRINTF(IEW, "[tid:%i]: Removing skidbuffer instructions until [sn:%i].\n", 454 tid, fromCommit->commitInfo[tid].doneSeqNum); 455 456 while (!skidBuffer[tid].empty()) { 457 if (skidBuffer[tid].front()->isLoad() || 458 skidBuffer[tid].front()->isStore() ) { 459 toRename->iewInfo[tid].dispatchedToLSQ++; 460 } 461 462 toRename->iewInfo[tid].dispatched++; 463 464 skidBuffer[tid].pop(); 465 } 466 467 emptyRenameInsts(tid); 468} 469 470template<class Impl> 471void 472DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, ThreadID tid) 473{ 474 DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %s " 475 "[sn:%i].\n", tid, inst->pcState(), inst->seqNum); 476 477 if (toCommit->squash[tid] == false || 478 inst->seqNum < toCommit->squashedSeqNum[tid]) { 479 toCommit->squash[tid] = true; 480 toCommit->squashedSeqNum[tid] = inst->seqNum; 481 toCommit->branchTaken[tid] = inst->pcState().branching(); 482 483 TheISA::PCState pc = inst->pcState(); 484 TheISA::advancePC(pc, inst->staticInst); 485 486 toCommit->pc[tid] = pc; 487 toCommit->mispredictInst[tid] = inst; 488 toCommit->includeSquashInst[tid] = false; 489 490 wroteToTimeBuffer = true; 491 } 492 493} 494 495template<class Impl> 496void 497DefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, ThreadID tid) 498{ 499 DPRINTF(IEW, "[tid:%i]: Memory violation, squashing violator and younger " 500 "insts, PC: %s [sn:%i].\n", tid, inst->pcState(), inst->seqNum); 501 // Need to include inst->seqNum in the following comparison to cover the 502 // corner case when a branch misprediction and a memory violation for the 503 // same instruction (e.g. load PC) are detected in the same cycle. In this 504 // case the memory violator should take precedence over the branch 505 // misprediction because it requires the violator itself to be included in 506 // the squash. 507 if (toCommit->squash[tid] == false || 508 inst->seqNum <= toCommit->squashedSeqNum[tid]) { 509 toCommit->squash[tid] = true; 510 511 toCommit->squashedSeqNum[tid] = inst->seqNum; 512 toCommit->pc[tid] = inst->pcState(); 513 toCommit->mispredictInst[tid] = NULL; 514 515 // Must include the memory violator in the squash. 516 toCommit->includeSquashInst[tid] = true; 517 518 wroteToTimeBuffer = true; 519 } 520} 521 522template<class Impl> 523void 524DefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, ThreadID tid) 525{ 526 DPRINTF(IEW, "[tid:%i]: Memory blocked, squashing load and younger insts, " 527 "PC: %s [sn:%i].\n", tid, inst->pcState(), inst->seqNum); 528 if (toCommit->squash[tid] == false || 529 inst->seqNum < toCommit->squashedSeqNum[tid]) { 530 toCommit->squash[tid] = true; 531 532 toCommit->squashedSeqNum[tid] = inst->seqNum; 533 toCommit->pc[tid] = inst->pcState(); 534 toCommit->mispredictInst[tid] = NULL; 535 536 // Must include the broadcasted SN in the squash. 537 toCommit->includeSquashInst[tid] = true; 538 539 ldstQueue.setLoadBlockedHandled(tid); 540 541 wroteToTimeBuffer = true; 542 } 543} 544 545template<class Impl> 546void 547DefaultIEW<Impl>::block(ThreadID tid) 548{ 549 DPRINTF(IEW, "[tid:%u]: Blocking.\n", tid); 550 551 if (dispatchStatus[tid] != Blocked && 552 dispatchStatus[tid] != Unblocking) { 553 toRename->iewBlock[tid] = true; 554 wroteToTimeBuffer = true; 555 } 556 557 // Add the current inputs to the skid buffer so they can be 558 // reprocessed when this stage unblocks. 559 skidInsert(tid); 560 561 dispatchStatus[tid] = Blocked; 562} 563 564template<class Impl> 565void 566DefaultIEW<Impl>::unblock(ThreadID tid) 567{ 568 DPRINTF(IEW, "[tid:%i]: Reading instructions out of the skid " 569 "buffer %u.\n",tid, tid); 570 571 // If the skid bufffer is empty, signal back to previous stages to unblock. 572 // Also switch status to running. 573 if (skidBuffer[tid].empty()) { 574 toRename->iewUnblock[tid] = true; 575 wroteToTimeBuffer = true; 576 DPRINTF(IEW, "[tid:%i]: Done unblocking.\n",tid); 577 dispatchStatus[tid] = Running; 578 } 579} 580 581template<class Impl> 582void 583DefaultIEW<Impl>::wakeDependents(DynInstPtr &inst) 584{ 585 instQueue.wakeDependents(inst); 586} 587 588template<class Impl> 589void 590DefaultIEW<Impl>::rescheduleMemInst(DynInstPtr &inst) 591{ 592 instQueue.rescheduleMemInst(inst); 593} 594 595template<class Impl> 596void 597DefaultIEW<Impl>::replayMemInst(DynInstPtr &inst) 598{ 599 instQueue.replayMemInst(inst); 600} 601 602template<class Impl> 603void 604DefaultIEW<Impl>::instToCommit(DynInstPtr &inst) 605{ 606 // This function should not be called after writebackInsts in a 607 // single cycle. That will cause problems with an instruction 608 // being added to the queue to commit without being processed by 609 // writebackInsts prior to being sent to commit. 610 611 // First check the time slot that this instruction will write 612 // to. If there are free write ports at the time, then go ahead 613 // and write the instruction to that time. If there are not, 614 // keep looking back to see where's the first time there's a 615 // free slot. 616 while ((*iewQueue)[wbCycle].insts[wbNumInst]) { 617 ++wbNumInst; 618 if (wbNumInst == wbWidth) { 619 ++wbCycle; 620 wbNumInst = 0; 621 } 622 623 assert((wbCycle * wbWidth + wbNumInst) <= wbMax); 624 } 625 626 DPRINTF(IEW, "Current wb cycle: %i, width: %i, numInst: %i\nwbActual:%i\n", 627 wbCycle, wbWidth, wbNumInst, wbCycle * wbWidth + wbNumInst); 628 // Add finished instruction to queue to commit. 629 (*iewQueue)[wbCycle].insts[wbNumInst] = inst; 630 (*iewQueue)[wbCycle].size++; 631} 632 633template <class Impl> 634unsigned 635DefaultIEW<Impl>::validInstsFromRename() 636{ 637 unsigned inst_count = 0; 638 639 for (int i=0; i<fromRename->size; i++) { 640 if (!fromRename->insts[i]->isSquashed()) 641 inst_count++; 642 } 643 644 return inst_count; 645} 646 647template<class Impl> 648void 649DefaultIEW<Impl>::skidInsert(ThreadID tid) 650{ 651 DynInstPtr inst = NULL; 652 653 while (!insts[tid].empty()) { 654 inst = insts[tid].front(); 655 656 insts[tid].pop(); 657 658 DPRINTF(IEW,"[tid:%i]: Inserting [sn:%lli] PC:%s into " 659 "dispatch skidBuffer %i\n",tid, inst->seqNum, 660 inst->pcState(),tid); 661 662 skidBuffer[tid].push(inst); 663 } 664 665 assert(skidBuffer[tid].size() <= skidBufferMax && 666 "Skidbuffer Exceeded Max Size"); 667} 668 669template<class Impl> 670int 671DefaultIEW<Impl>::skidCount() 672{ 673 int max=0; 674 675 list<ThreadID>::iterator threads = activeThreads->begin(); 676 list<ThreadID>::iterator end = activeThreads->end(); 677 678 while (threads != end) { 679 ThreadID tid = *threads++; 680 unsigned thread_count = skidBuffer[tid].size(); 681 if (max < thread_count) 682 max = thread_count; 683 } 684 685 return max; 686} 687 688template<class Impl> 689bool 690DefaultIEW<Impl>::skidsEmpty() 691{ 692 list<ThreadID>::iterator threads = activeThreads->begin(); 693 list<ThreadID>::iterator end = activeThreads->end(); 694 695 while (threads != end) { 696 ThreadID tid = *threads++; 697 698 if (!skidBuffer[tid].empty()) 699 return false; 700 } 701 702 return true; 703} 704 705template <class Impl> 706void 707DefaultIEW<Impl>::updateStatus() 708{ 709 bool any_unblocking = false; 710 711 list<ThreadID>::iterator threads = activeThreads->begin(); 712 list<ThreadID>::iterator end = activeThreads->end(); 713 714 while (threads != end) { 715 ThreadID tid = *threads++; 716 717 if (dispatchStatus[tid] == Unblocking) { 718 any_unblocking = true; 719 break; 720 } 721 } 722 723 // If there are no ready instructions waiting to be scheduled by the IQ, 724 // and there's no stores waiting to write back, and dispatch is not 725 // unblocking, then there is no internal activity for the IEW stage. 726 instQueue.intInstQueueReads++; 727 if (_status == Active && !instQueue.hasReadyInsts() && 728 !ldstQueue.willWB() && !any_unblocking) { 729 DPRINTF(IEW, "IEW switching to idle\n"); 730 731 deactivateStage(); 732 733 _status = Inactive; 734 } else if (_status == Inactive && (instQueue.hasReadyInsts() || 735 ldstQueue.willWB() || 736 any_unblocking)) { 737 // Otherwise there is internal activity. Set to active. 738 DPRINTF(IEW, "IEW switching to active\n"); 739 740 activateStage(); 741 742 _status = Active; 743 } 744} 745 746template <class Impl> 747void 748DefaultIEW<Impl>::resetEntries() 749{ 750 instQueue.resetEntries(); 751 ldstQueue.resetEntries(); 752} 753 754template <class Impl> 755void 756DefaultIEW<Impl>::readStallSignals(ThreadID tid) 757{ 758 if (fromCommit->commitBlock[tid]) { 759 stalls[tid].commit = true; 760 } 761 762 if (fromCommit->commitUnblock[tid]) { 763 assert(stalls[tid].commit); 764 stalls[tid].commit = false; 765 } 766} 767 768template <class Impl> 769bool 770DefaultIEW<Impl>::checkStall(ThreadID tid) 771{ 772 bool ret_val(false); 773 774 if (stalls[tid].commit) { 775 DPRINTF(IEW,"[tid:%i]: Stall from Commit stage detected.\n",tid); 776 ret_val = true; 777 } else if (instQueue.isFull(tid)) { 778 DPRINTF(IEW,"[tid:%i]: Stall: IQ is full.\n",tid); 779 ret_val = true; 780 } else if (ldstQueue.isFull(tid)) { 781 DPRINTF(IEW,"[tid:%i]: Stall: LSQ is full\n",tid); 782 783 if (ldstQueue.numLoads(tid) > 0 ) { 784 785 DPRINTF(IEW,"[tid:%i]: LSQ oldest load: [sn:%i] \n", 786 tid,ldstQueue.getLoadHeadSeqNum(tid)); 787 } 788 789 if (ldstQueue.numStores(tid) > 0) { 790 791 DPRINTF(IEW,"[tid:%i]: LSQ oldest store: [sn:%i] \n", 792 tid,ldstQueue.getStoreHeadSeqNum(tid)); 793 } 794 795 ret_val = true; 796 } else if (ldstQueue.isStalled(tid)) { 797 DPRINTF(IEW,"[tid:%i]: Stall: LSQ stall detected.\n",tid); 798 ret_val = true; 799 } 800 801 return ret_val; 802} 803 804template <class Impl> 805void 806DefaultIEW<Impl>::checkSignalsAndUpdate(ThreadID tid) 807{ 808 // Check if there's a squash signal, squash if there is 809 // Check stall signals, block if there is. 810 // If status was Blocked 811 // if so then go to unblocking 812 // If status was Squashing 813 // check if squashing is not high. Switch to running this cycle. 814 815 readStallSignals(tid); 816 817 if (fromCommit->commitInfo[tid].squash) { 818 squash(tid); 819 820 if (dispatchStatus[tid] == Blocked || 821 dispatchStatus[tid] == Unblocking) { 822 toRename->iewUnblock[tid] = true; 823 wroteToTimeBuffer = true; 824 } 825 826 dispatchStatus[tid] = Squashing; 827 fetchRedirect[tid] = false; 828 return; 829 } 830 831 if (fromCommit->commitInfo[tid].robSquashing) { 832 DPRINTF(IEW, "[tid:%i]: ROB is still squashing.\n", tid); 833 834 dispatchStatus[tid] = Squashing; 835 emptyRenameInsts(tid); 836 wroteToTimeBuffer = true; 837 return; 838 } 839 840 if (checkStall(tid)) { 841 block(tid); 842 dispatchStatus[tid] = Blocked; 843 return; 844 } 845 846 if (dispatchStatus[tid] == Blocked) { 847 // Status from previous cycle was blocked, but there are no more stall 848 // conditions. Switch over to unblocking. 849 DPRINTF(IEW, "[tid:%i]: Done blocking, switching to unblocking.\n", 850 tid); 851 852 dispatchStatus[tid] = Unblocking; 853 854 unblock(tid); 855 856 return; 857 } 858 859 if (dispatchStatus[tid] == Squashing) { 860 // Switch status to running if rename isn't being told to block or 861 // squash this cycle. 862 DPRINTF(IEW, "[tid:%i]: Done squashing, switching to running.\n", 863 tid); 864 865 dispatchStatus[tid] = Running; 866 867 return; 868 } 869} 870 871template <class Impl> 872void 873DefaultIEW<Impl>::sortInsts() 874{ 875 int insts_from_rename = fromRename->size; 876#ifdef DEBUG 877 for (ThreadID tid = 0; tid < numThreads; tid++) 878 assert(insts[tid].empty()); 879#endif 880 for (int i = 0; i < insts_from_rename; ++i) { 881 insts[fromRename->insts[i]->threadNumber].push(fromRename->insts[i]); 882 } 883} 884 885template <class Impl> 886void 887DefaultIEW<Impl>::emptyRenameInsts(ThreadID tid) 888{ 889 DPRINTF(IEW, "[tid:%i]: Removing incoming rename instructions\n", tid); 890 891 while (!insts[tid].empty()) { 892 893 if (insts[tid].front()->isLoad() || 894 insts[tid].front()->isStore() ) { 895 toRename->iewInfo[tid].dispatchedToLSQ++; 896 } 897 898 toRename->iewInfo[tid].dispatched++; 899 900 insts[tid].pop(); 901 } 902} 903 904template <class Impl> 905void 906DefaultIEW<Impl>::wakeCPU() 907{ 908 cpu->wakeCPU(); 909} 910 911template <class Impl> 912void 913DefaultIEW<Impl>::activityThisCycle() 914{ 915 DPRINTF(Activity, "Activity this cycle.\n"); 916 cpu->activityThisCycle(); 917} 918 919template <class Impl> 920inline void 921DefaultIEW<Impl>::activateStage() 922{ 923 DPRINTF(Activity, "Activating stage.\n"); 924 cpu->activateStage(O3CPU::IEWIdx); 925} 926 927template <class Impl> 928inline void 929DefaultIEW<Impl>::deactivateStage() 930{ 931 DPRINTF(Activity, "Deactivating stage.\n"); 932 cpu->deactivateStage(O3CPU::IEWIdx); 933} 934 935template<class Impl> 936void 937DefaultIEW<Impl>::dispatch(ThreadID tid) 938{ 939 // If status is Running or idle, 940 // call dispatchInsts() 941 // If status is Unblocking, 942 // buffer any instructions coming from rename 943 // continue trying to empty skid buffer 944 // check if stall conditions have passed 945 946 if (dispatchStatus[tid] == Blocked) { 947 ++iewBlockCycles; 948 949 } else if (dispatchStatus[tid] == Squashing) { 950 ++iewSquashCycles; 951 } 952 953 // Dispatch should try to dispatch as many instructions as its bandwidth 954 // will allow, as long as it is not currently blocked. 955 if (dispatchStatus[tid] == Running || 956 dispatchStatus[tid] == Idle) { 957 DPRINTF(IEW, "[tid:%i] Not blocked, so attempting to run " 958 "dispatch.\n", tid); 959 960 dispatchInsts(tid); 961 } else if (dispatchStatus[tid] == Unblocking) { 962 // Make sure that the skid buffer has something in it if the 963 // status is unblocking. 964 assert(!skidsEmpty()); 965 966 // If the status was unblocking, then instructions from the skid 967 // buffer were used. Remove those instructions and handle 968 // the rest of unblocking. 969 dispatchInsts(tid); 970 971 ++iewUnblockCycles; 972 973 if (validInstsFromRename()) { 974 // Add the current inputs to the skid buffer so they can be 975 // reprocessed when this stage unblocks. 976 skidInsert(tid); 977 } 978 979 unblock(tid); 980 } 981} 982 983template <class Impl> 984void 985DefaultIEW<Impl>::dispatchInsts(ThreadID tid) 986{ 987 // Obtain instructions from skid buffer if unblocking, or queue from rename 988 // otherwise. 989 std::queue<DynInstPtr> &insts_to_dispatch = 990 dispatchStatus[tid] == Unblocking ? 991 skidBuffer[tid] : insts[tid]; 992 993 int insts_to_add = insts_to_dispatch.size(); 994 995 DynInstPtr inst; 996 bool add_to_iq = false; 997 int dis_num_inst = 0; 998 999 // Loop through the instructions, putting them in the instruction 1000 // queue. 1001 for ( ; dis_num_inst < insts_to_add && 1002 dis_num_inst < dispatchWidth; 1003 ++dis_num_inst) 1004 { 1005 inst = insts_to_dispatch.front(); 1006 1007 if (dispatchStatus[tid] == Unblocking) { 1008 DPRINTF(IEW, "[tid:%i]: Issue: Examining instruction from skid " 1009 "buffer\n", tid); 1010 } 1011 1012 // Make sure there's a valid instruction there. 1013 assert(inst); 1014 1015 DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %s [sn:%lli] [tid:%i] to " 1016 "IQ.\n", 1017 tid, inst->pcState(), inst->seqNum, inst->threadNumber); 1018 1019 // Be sure to mark these instructions as ready so that the 1020 // commit stage can go ahead and execute them, and mark 1021 // them as issued so the IQ doesn't reprocess them. 1022 1023 // Check for squashed instructions. 1024 if (inst->isSquashed()) { 1025 DPRINTF(IEW, "[tid:%i]: Issue: Squashed instruction encountered, " 1026 "not adding to IQ.\n", tid); 1027 1028 ++iewDispSquashedInsts; 1029 1030 insts_to_dispatch.pop(); 1031 1032 //Tell Rename That An Instruction has been processed 1033 if (inst->isLoad() || inst->isStore()) { 1034 toRename->iewInfo[tid].dispatchedToLSQ++; 1035 } 1036 toRename->iewInfo[tid].dispatched++; 1037 1038 continue; 1039 } 1040 1041 // Check for full conditions. 1042 if (instQueue.isFull(tid)) { 1043 DPRINTF(IEW, "[tid:%i]: Issue: IQ has become full.\n", tid); 1044 1045 // Call function to start blocking. 1046 block(tid); 1047 1048 // Set unblock to false. Special case where we are using 1049 // skidbuffer (unblocking) instructions but then we still 1050 // get full in the IQ. 1051 toRename->iewUnblock[tid] = false; 1052 1053 ++iewIQFullEvents; 1054 break; 1055 } else if (ldstQueue.isFull(tid)) { 1056 DPRINTF(IEW, "[tid:%i]: Issue: LSQ has become full.\n",tid); 1057 1058 // Call function to start blocking. 1059 block(tid); 1060 1061 // Set unblock to false. Special case where we are using 1062 // skidbuffer (unblocking) instructions but then we still 1063 // get full in the IQ. 1064 toRename->iewUnblock[tid] = false; 1065 1066 ++iewLSQFullEvents; 1067 break; 1068 } 1069 1070 // Otherwise issue the instruction just fine. 1071 if (inst->isLoad()) { 1072 DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction " 1073 "encountered, adding to LSQ.\n", tid); 1074 1075 // Reserve a spot in the load store queue for this 1076 // memory access. 1077 ldstQueue.insertLoad(inst); 1078 1079 ++iewDispLoadInsts; 1080 1081 add_to_iq = true; 1082 1083 toRename->iewInfo[tid].dispatchedToLSQ++; 1084 } else if (inst->isStore()) { 1085 DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction " 1086 "encountered, adding to LSQ.\n", tid); 1087 1088 ldstQueue.insertStore(inst); 1089 1090 ++iewDispStoreInsts; 1091 1092 if (inst->isStoreConditional()) { 1093 // Store conditionals need to be set as "canCommit()" 1094 // so that commit can process them when they reach the 1095 // head of commit. 1096 // @todo: This is somewhat specific to Alpha. 1097 inst->setCanCommit(); 1098 instQueue.insertNonSpec(inst); 1099 add_to_iq = false; 1100 1101 ++iewDispNonSpecInsts; 1102 } else { 1103 add_to_iq = true; 1104 } 1105 1106 toRename->iewInfo[tid].dispatchedToLSQ++; 1107 } else if (inst->isMemBarrier() || inst->isWriteBarrier()) { 1108 // Same as non-speculative stores. 1109 inst->setCanCommit(); 1110 instQueue.insertBarrier(inst); 1111 add_to_iq = false; 1112 } else if (inst->isNop()) { 1113 DPRINTF(IEW, "[tid:%i]: Issue: Nop instruction encountered, " 1114 "skipping.\n", tid); 1115 1116 inst->setIssued(); 1117 inst->setExecuted(); 1118 inst->setCanCommit(); 1119 1120 instQueue.recordProducer(inst); 1121 1122 iewExecutedNop[tid]++; 1123 1124 add_to_iq = false; 1125 } else if (inst->isExecuted()) { 1126 assert(0 && "Instruction shouldn't be executed.\n"); 1127 DPRINTF(IEW, "Issue: Executed branch encountered, " 1128 "skipping.\n"); 1129 1130 inst->setIssued(); 1131 inst->setCanCommit(); 1132 1133 instQueue.recordProducer(inst); 1134 1135 add_to_iq = false; 1136 } else { 1137 add_to_iq = true; 1138 } 1139 if (inst->isNonSpeculative()) { 1140 DPRINTF(IEW, "[tid:%i]: Issue: Nonspeculative instruction " 1141 "encountered, skipping.\n", tid); 1142 1143 // Same as non-speculative stores. 1144 inst->setCanCommit(); 1145 1146 // Specifically insert it as nonspeculative. 1147 instQueue.insertNonSpec(inst); 1148 1149 ++iewDispNonSpecInsts; 1150 1151 add_to_iq = false; 1152 } 1153 1154 // If the instruction queue is not full, then add the 1155 // instruction. 1156 if (add_to_iq) { 1157 instQueue.insert(inst); 1158 } 1159 1160 insts_to_dispatch.pop(); 1161 1162 toRename->iewInfo[tid].dispatched++; 1163 1164 ++iewDispatchedInsts; 1165 1166#if TRACING_ON 1167 inst->dispatchTick = curTick() - inst->fetchTick; 1168#endif 1169 ppDispatch->notify(inst); 1170 } 1171 1172 if (!insts_to_dispatch.empty()) { 1173 DPRINTF(IEW,"[tid:%i]: Issue: Bandwidth Full. Blocking.\n", tid); 1174 block(tid); 1175 toRename->iewUnblock[tid] = false; 1176 } 1177 1178 if (dispatchStatus[tid] == Idle && dis_num_inst) { 1179 dispatchStatus[tid] = Running; 1180 1181 updatedQueues = true; 1182 } 1183 1184 dis_num_inst = 0; 1185} 1186 1187template <class Impl> 1188void 1189DefaultIEW<Impl>::printAvailableInsts() 1190{ 1191 int inst = 0; 1192 1193 std::cout << "Available Instructions: "; 1194 1195 while (fromIssue->insts[inst]) { 1196 1197 if (inst%3==0) std::cout << "\n\t"; 1198 1199 std::cout << "PC: " << fromIssue->insts[inst]->pcState() 1200 << " TN: " << fromIssue->insts[inst]->threadNumber 1201 << " SN: " << fromIssue->insts[inst]->seqNum << " | "; 1202 1203 inst++; 1204 1205 } 1206 1207 std::cout << "\n"; 1208} 1209 1210template <class Impl> 1211void 1212DefaultIEW<Impl>::executeInsts() 1213{ 1214 wbNumInst = 0; 1215 wbCycle = 0; 1216 1217 list<ThreadID>::iterator threads = activeThreads->begin(); 1218 list<ThreadID>::iterator end = activeThreads->end(); 1219 1220 while (threads != end) { 1221 ThreadID tid = *threads++; 1222 fetchRedirect[tid] = false; 1223 } 1224 1225 // Uncomment this if you want to see all available instructions. 1226 // @todo This doesn't actually work anymore, we should fix it. 1227// printAvailableInsts(); 1228 1229 // Execute/writeback any instructions that are available. 1230 int insts_to_execute = fromIssue->size; 1231 int inst_num = 0; 1232 for (; inst_num < insts_to_execute; 1233 ++inst_num) { 1234 1235 DPRINTF(IEW, "Execute: Executing instructions from IQ.\n"); 1236 1237 DynInstPtr inst = instQueue.getInstToExecute(); 1238 1239 DPRINTF(IEW, "Execute: Processing PC %s, [tid:%i] [sn:%i].\n", 1240 inst->pcState(), inst->threadNumber,inst->seqNum); 1241 1242 // Check if the instruction is squashed; if so then skip it 1243 if (inst->isSquashed()) { 1244 DPRINTF(IEW, "Execute: Instruction was squashed. PC: %s, [tid:%i]" 1245 " [sn:%i]\n", inst->pcState(), inst->threadNumber, 1246 inst->seqNum); 1247 1248 // Consider this instruction executed so that commit can go 1249 // ahead and retire the instruction. 1250 inst->setExecuted(); 1251 1252 // Not sure if I should set this here or just let commit try to 1253 // commit any squashed instructions. I like the latter a bit more. 1254 inst->setCanCommit(); 1255 1256 ++iewExecSquashedInsts; 1257 1258 decrWb(inst->seqNum); 1259 continue; 1260 } 1261 1262 Fault fault = NoFault; 1263 1264 // Execute instruction. 1265 // Note that if the instruction faults, it will be handled 1266 // at the commit stage. 1267 if (inst->isMemRef()) { 1268 DPRINTF(IEW, "Execute: Calculating address for memory " 1269 "reference.\n"); 1270 1271 // Tell the LDSTQ to execute this instruction (if it is a load). 1272 if (inst->isLoad()) { 1273 // Loads will mark themselves as executed, and their writeback 1274 // event adds the instruction to the queue to commit 1275 fault = ldstQueue.executeLoad(inst); 1276 1277 if (inst->isTranslationDelayed() && 1278 fault == NoFault) { 1279 // A hw page table walk is currently going on; the 1280 // instruction must be deferred. 1281 DPRINTF(IEW, "Execute: Delayed translation, deferring " 1282 "load.\n"); 1283 instQueue.deferMemInst(inst); 1284 continue; 1285 } 1286 1287 if (inst->isDataPrefetch() || inst->isInstPrefetch()) { 1288 inst->fault = NoFault; 1289 } 1290 } else if (inst->isStore()) { 1291 fault = ldstQueue.executeStore(inst); 1292 1293 if (inst->isTranslationDelayed() && 1294 fault == NoFault) { 1295 // A hw page table walk is currently going on; the 1296 // instruction must be deferred. 1297 DPRINTF(IEW, "Execute: Delayed translation, deferring " 1298 "store.\n"); 1299 instQueue.deferMemInst(inst); 1300 continue; 1301 } 1302 1303 // If the store had a fault then it may not have a mem req 1304 if (fault != NoFault || inst->readPredicate() == false || 1305 !inst->isStoreConditional()) { 1306 // If the instruction faulted, then we need to send it along 1307 // to commit without the instruction completing. 1308 // Send this instruction to commit, also make sure iew stage 1309 // realizes there is activity. 1310 inst->setExecuted(); 1311 instToCommit(inst); 1312 activityThisCycle(); 1313 } 1314 1315 // Store conditionals will mark themselves as 1316 // executed, and their writeback event will add the 1317 // instruction to the queue to commit. 1318 } else { 1319 panic("Unexpected memory type!\n"); 1320 } 1321 1322 } else { 1323 // If the instruction has already faulted, then skip executing it. 1324 // Such case can happen when it faulted during ITLB translation. 1325 // If we execute the instruction (even if it's a nop) the fault 1326 // will be replaced and we will lose it. 1327 if (inst->getFault() == NoFault) { 1328 inst->execute(); 1329 if (inst->readPredicate() == false) 1330 inst->forwardOldRegs(); 1331 } 1332 1333 inst->setExecuted(); 1334 1335 instToCommit(inst); 1336 } 1337 1338 updateExeInstStats(inst); 1339 1340 // Check if branch prediction was correct, if not then we need 1341 // to tell commit to squash in flight instructions. Only 1342 // handle this if there hasn't already been something that 1343 // redirects fetch in this group of instructions. 1344 1345 // This probably needs to prioritize the redirects if a different 1346 // scheduler is used. Currently the scheduler schedules the oldest 1347 // instruction first, so the branch resolution order will be correct. 1348 ThreadID tid = inst->threadNumber; 1349 1350 if (!fetchRedirect[tid] || 1351 !toCommit->squash[tid] || 1352 toCommit->squashedSeqNum[tid] > inst->seqNum) { 1353 1354 // Prevent testing for misprediction on load instructions, 1355 // that have not been executed. 1356 bool loadNotExecuted = !inst->isExecuted() && inst->isLoad(); 1357 1358 if (inst->mispredicted() && !loadNotExecuted) { 1359 fetchRedirect[tid] = true; 1360 1361 DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); 1362 DPRINTF(IEW, "Predicted target was PC: %s.\n", 1363 inst->readPredTarg()); 1364 DPRINTF(IEW, "Execute: Redirecting fetch to PC: %s.\n", 1365 inst->pcState()); 1366 // If incorrect, then signal the ROB that it must be squashed. 1367 squashDueToBranch(inst, tid); 1368 1369 ppMispredict->notify(inst); 1370 1371 if (inst->readPredTaken()) { 1372 predictedTakenIncorrect++; 1373 } else { 1374 predictedNotTakenIncorrect++; 1375 } 1376 } else if (ldstQueue.violation(tid)) { 1377 assert(inst->isMemRef()); 1378 // If there was an ordering violation, then get the 1379 // DynInst that caused the violation. Note that this 1380 // clears the violation signal. 1381 DynInstPtr violator; 1382 violator = ldstQueue.getMemDepViolator(tid); 1383 1384 DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: %s " 1385 "[sn:%lli], inst PC: %s [sn:%lli]. Addr is: %#x.\n", 1386 violator->pcState(), violator->seqNum, 1387 inst->pcState(), inst->seqNum, inst->physEffAddr); 1388 1389 fetchRedirect[tid] = true; 1390 1391 // Tell the instruction queue that a violation has occured. 1392 instQueue.violation(inst, violator); 1393 1394 // Squash. 1395 squashDueToMemOrder(violator, tid); 1396 1397 ++memOrderViolationEvents; 1398 } else if (ldstQueue.loadBlocked(tid) && 1399 !ldstQueue.isLoadBlockedHandled(tid)) { 1400 fetchRedirect[tid] = true; 1401 1402 DPRINTF(IEW, "Load operation couldn't execute because the " 1403 "memory system is blocked. PC: %s [sn:%lli]\n", 1404 inst->pcState(), inst->seqNum); 1405 1406 squashDueToMemBlocked(inst, tid); 1407 } 1408 } else { 1409 // Reset any state associated with redirects that will not 1410 // be used. 1411 if (ldstQueue.violation(tid)) { 1412 assert(inst->isMemRef()); 1413 1414 DynInstPtr violator = ldstQueue.getMemDepViolator(tid); 1415 1416 DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: " 1417 "%s, inst PC: %s. Addr is: %#x.\n", 1418 violator->pcState(), inst->pcState(), 1419 inst->physEffAddr); 1420 DPRINTF(IEW, "Violation will not be handled because " 1421 "already squashing\n"); 1422 1423 ++memOrderViolationEvents; 1424 } 1425 if (ldstQueue.loadBlocked(tid) && 1426 !ldstQueue.isLoadBlockedHandled(tid)) { 1427 DPRINTF(IEW, "Load operation couldn't execute because the " 1428 "memory system is blocked. PC: %s [sn:%lli]\n", 1429 inst->pcState(), inst->seqNum); 1430 DPRINTF(IEW, "Blocked load will not be handled because " 1431 "already squashing\n"); 1432 1433 ldstQueue.setLoadBlockedHandled(tid); 1434 } 1435 1436 } 1437 } 1438 1439 // Update and record activity if we processed any instructions. 1440 if (inst_num) { 1441 if (exeStatus == Idle) { 1442 exeStatus = Running; 1443 } 1444 1445 updatedQueues = true; 1446 1447 cpu->activityThisCycle(); 1448 } 1449 1450 // Need to reset this in case a writeback event needs to write into the 1451 // iew queue. That way the writeback event will write into the correct 1452 // spot in the queue. 1453 wbNumInst = 0; 1454 1455} 1456 1457template <class Impl> 1458void 1459DefaultIEW<Impl>::writebackInsts() 1460{ 1461 // Loop through the head of the time buffer and wake any 1462 // dependents. These instructions are about to write back. Also 1463 // mark scoreboard that this instruction is finally complete. 1464 // Either have IEW have direct access to scoreboard, or have this 1465 // as part of backwards communication. 1466 for (int inst_num = 0; inst_num < wbWidth && 1467 toCommit->insts[inst_num]; inst_num++) { 1468 DynInstPtr inst = toCommit->insts[inst_num]; 1469 ThreadID tid = inst->threadNumber; 1470 1471 DPRINTF(IEW, "Sending instructions to commit, [sn:%lli] PC %s.\n", 1472 inst->seqNum, inst->pcState()); 1473 1474 iewInstsToCommit[tid]++; 1475 1476 // Some instructions will be sent to commit without having 1477 // executed because they need commit to handle them. 1478 // E.g. Uncached loads have not actually executed when they 1479 // are first sent to commit. Instead commit must tell the LSQ 1480 // when it's ready to execute the uncached load. 1481 if (!inst->isSquashed() && inst->isExecuted() && inst->getFault() == NoFault) { 1482 int dependents = instQueue.wakeDependents(inst); 1483 1484 for (int i = 0; i < inst->numDestRegs(); i++) { 1485 //mark as Ready 1486 DPRINTF(IEW,"Setting Destination Register %i\n", 1487 inst->renamedDestRegIdx(i)); 1488 scoreboard->setReg(inst->renamedDestRegIdx(i)); 1489 } 1490 1491 if (dependents) { 1492 producerInst[tid]++; 1493 consumerInst[tid]+= dependents; 1494 } 1495 writebackCount[tid]++; 1496 } 1497 1498 decrWb(inst->seqNum); 1499 } 1500} 1501 1502template<class Impl> 1503void 1504DefaultIEW<Impl>::tick() 1505{ 1506 wbNumInst = 0; 1507 wbCycle = 0; 1508 1509 wroteToTimeBuffer = false; 1510 updatedQueues = false; 1511 1512 sortInsts(); 1513 1514 // Free function units marked as being freed this cycle. 1515 fuPool->processFreeUnits(); 1516 1517 list<ThreadID>::iterator threads = activeThreads->begin(); 1518 list<ThreadID>::iterator end = activeThreads->end(); 1519 1520 // Check stall and squash signals, dispatch any instructions. 1521 while (threads != end) { 1522 ThreadID tid = *threads++; 1523 1524 DPRINTF(IEW,"Issue: Processing [tid:%i]\n",tid); 1525 1526 checkSignalsAndUpdate(tid); 1527 dispatch(tid); 1528 } 1529 1530 if (exeStatus != Squashing) { 1531 executeInsts(); 1532 1533 writebackInsts(); 1534 1535 // Have the instruction queue try to schedule any ready instructions. 1536 // (In actuality, this scheduling is for instructions that will 1537 // be executed next cycle.) 1538 instQueue.scheduleReadyInsts(); 1539 1540 // Also should advance its own time buffers if the stage ran. 1541 // Not the best place for it, but this works (hopefully). 1542 issueToExecQueue.advance(); 1543 } 1544 1545 bool broadcast_free_entries = false; 1546 1547 if (updatedQueues || exeStatus == Running || updateLSQNextCycle) { 1548 exeStatus = Idle; 1549 updateLSQNextCycle = false; 1550 1551 broadcast_free_entries = true; 1552 } 1553 1554 // Writeback any stores using any leftover bandwidth. 1555 ldstQueue.writebackStores(); 1556 1557 // Check the committed load/store signals to see if there's a load 1558 // or store to commit. Also check if it's being told to execute a 1559 // nonspeculative instruction. 1560 // This is pretty inefficient... 1561 1562 threads = activeThreads->begin(); 1563 while (threads != end) { 1564 ThreadID tid = (*threads++); 1565 1566 DPRINTF(IEW,"Processing [tid:%i]\n",tid); 1567 1568 // Update structures based on instructions committed. 1569 if (fromCommit->commitInfo[tid].doneSeqNum != 0 && 1570 !fromCommit->commitInfo[tid].squash && 1571 !fromCommit->commitInfo[tid].robSquashing) { 1572 1573 ldstQueue.commitStores(fromCommit->commitInfo[tid].doneSeqNum,tid); 1574 1575 ldstQueue.commitLoads(fromCommit->commitInfo[tid].doneSeqNum,tid); 1576 1577 updateLSQNextCycle = true; 1578 instQueue.commit(fromCommit->commitInfo[tid].doneSeqNum,tid); 1579 } 1580 1581 if (fromCommit->commitInfo[tid].nonSpecSeqNum != 0) { 1582 1583 //DPRINTF(IEW,"NonspecInst from thread %i",tid); 1584 if (fromCommit->commitInfo[tid].uncached) { 1585 instQueue.replayMemInst(fromCommit->commitInfo[tid].uncachedLoad); 1586 fromCommit->commitInfo[tid].uncachedLoad->setAtCommit(); 1587 } else { 1588 instQueue.scheduleNonSpec( 1589 fromCommit->commitInfo[tid].nonSpecSeqNum); 1590 } 1591 } 1592 1593 if (broadcast_free_entries) { 1594 toFetch->iewInfo[tid].iqCount = 1595 instQueue.getCount(tid); 1596 toFetch->iewInfo[tid].ldstqCount = 1597 ldstQueue.getCount(tid); 1598 1599 toRename->iewInfo[tid].usedIQ = true; 1600 toRename->iewInfo[tid].freeIQEntries = 1601 instQueue.numFreeEntries(tid); 1602 toRename->iewInfo[tid].usedLSQ = true; 1603 toRename->iewInfo[tid].freeLSQEntries = 1604 ldstQueue.numFreeEntries(tid); 1605 1606 wroteToTimeBuffer = true; 1607 } 1608 1609 DPRINTF(IEW, "[tid:%i], Dispatch dispatched %i instructions.\n", 1610 tid, toRename->iewInfo[tid].dispatched); 1611 } 1612 1613 DPRINTF(IEW, "IQ has %i free entries (Can schedule: %i). " 1614 "LSQ has %i free entries.\n", 1615 instQueue.numFreeEntries(), instQueue.hasReadyInsts(), 1616 ldstQueue.numFreeEntries()); 1617 1618 updateStatus(); 1619 1620 if (wroteToTimeBuffer) { 1621 DPRINTF(Activity, "Activity this cycle.\n"); 1622 cpu->activityThisCycle(); 1623 } 1624} 1625 1626template <class Impl> 1627void 1628DefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst) 1629{ 1630 ThreadID tid = inst->threadNumber; 1631 1632 iewExecutedInsts++; 1633 1634#if TRACING_ON 1635 if (DTRACE(O3PipeView)) { 1636 inst->completeTick = curTick() - inst->fetchTick; 1637 } 1638#endif 1639 1640 // 1641 // Control operations 1642 // 1643 if (inst->isControl()) 1644 iewExecutedBranches[tid]++; 1645 1646 // 1647 // Memory operations 1648 // 1649 if (inst->isMemRef()) { 1650 iewExecutedRefs[tid]++; 1651 1652 if (inst->isLoad()) { 1653 iewExecLoadInsts[tid]++; 1654 } 1655 } 1656} 1657 1658template <class Impl> 1659void 1660DefaultIEW<Impl>::checkMisprediction(DynInstPtr &inst) 1661{ 1662 ThreadID tid = inst->threadNumber; 1663 1664 if (!fetchRedirect[tid] || 1665 !toCommit->squash[tid] || 1666 toCommit->squashedSeqNum[tid] > inst->seqNum) { 1667 1668 if (inst->mispredicted()) { 1669 fetchRedirect[tid] = true; 1670 1671 DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); 1672 DPRINTF(IEW, "Predicted target was PC:%#x, NPC:%#x.\n", 1673 inst->predInstAddr(), inst->predNextInstAddr()); 1674 DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x," 1675 " NPC: %#x.\n", inst->nextInstAddr(), 1676 inst->nextInstAddr()); 1677 // If incorrect, then signal the ROB that it must be squashed. 1678 squashDueToBranch(inst, tid); 1679 1680 if (inst->readPredTaken()) { 1681 predictedTakenIncorrect++; 1682 } else { 1683 predictedNotTakenIncorrect++; 1684 } 1685 } 1686 } 1687} 1688 1689#endif//__CPU_O3_IEW_IMPL_IMPL_HH__ 1690