iew_impl.hh revision 12106
12623SN/A/* 22623SN/A * Copyright (c) 2010-2013 ARM Limited 32623SN/A * Copyright (c) 2013 Advanced Micro Devices, Inc. 42623SN/A * All rights reserved. 52623SN/A * 62623SN/A * The license below extends only to copyright in the software and shall 72623SN/A * not be construed as granting a license to any other intellectual 82623SN/A * property including but not limited to intellectual property relating 92623SN/A * to a hardware implementation of the functionality of the software 102623SN/A * licensed hereunder. You may use the software subject to the license 112623SN/A * terms below provided that you ensure that this notice is replicated 122623SN/A * unmodified and in its entirety in all distributions of the software, 132623SN/A * modified or unmodified, in source code or in binary form. 142623SN/A * 152623SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan 162623SN/A * All rights reserved. 172623SN/A * 182623SN/A * Redistribution and use in source and binary forms, with or without 192623SN/A * modification, are permitted provided that the following conditions are 202623SN/A * met: redistributions of source code must retain the above copyright 212623SN/A * notice, this list of conditions and the following disclaimer; 222623SN/A * redistributions in binary form must reproduce the above copyright 232623SN/A * notice, this list of conditions and the following disclaimer in the 242623SN/A * documentation and/or other materials provided with the distribution; 252623SN/A * neither the name of the copyright holders nor the names of its 262623SN/A * contributors may be used to endorse or promote products derived from 272665Ssaidi@eecs.umich.edu * this software without specific prior written permission. 282665Ssaidi@eecs.umich.edu * 292623SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 302623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 313170Sstever@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 325103Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 332623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 344040Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 352623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 362623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 373348Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 383348Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 394762Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 402901Ssaidi@eecs.umich.edu * 412623SN/A * Authors: Kevin Lim 422623SN/A */ 432623SN/A 442623SN/A#ifndef __CPU_O3_IEW_IMPL_IMPL_HH__ 452856Srdreslin@umich.edu#define __CPU_O3_IEW_IMPL_IMPL_HH__ 462856Srdreslin@umich.edu 472856Srdreslin@umich.edu// @todo: Fix the instantaneous communication among all the stages within 482856Srdreslin@umich.edu// iew. There's a clear delay between issue and execute, yet backwards 492856Srdreslin@umich.edu// communication happens simultaneously. 502856Srdreslin@umich.edu 512856Srdreslin@umich.edu#include <queue> 522856Srdreslin@umich.edu 532856Srdreslin@umich.edu#include "arch/utility.hh" 542856Srdreslin@umich.edu#include "config/the_isa.hh" 552623SN/A#include "cpu/checker/cpu.hh" 562623SN/A#include "cpu/o3/fu_pool.hh" 572623SN/A#include "cpu/o3/iew.hh" 582623SN/A#include "cpu/timebuf.hh" 592623SN/A#include "debug/Activity.hh" 605310Ssaidi@eecs.umich.edu#include "debug/Drain.hh" 612623SN/A#include "debug/IEW.hh" 622680Sktlim@umich.edu#include "debug/O3PipeView.hh" 632680Sktlim@umich.edu#include "params/DerivO3CPU.hh" 642623SN/A 652623SN/Ausing namespace std; 665310Ssaidi@eecs.umich.edu 672623SN/Atemplate<class Impl> 682623SN/ADefaultIEW<Impl>::DefaultIEW(O3CPU *_cpu, DerivO3CPUParams *params) 692623SN/A : issueToExecQueue(params->backComSize, params->forwardComSize), 702623SN/A cpu(_cpu), 712623SN/A instQueue(_cpu, this, params), 723349Sbinkertn@umich.edu ldstQueue(_cpu, this, params), 732623SN/A fuPool(params->fuPool), 742623SN/A commitToIEWDelay(params->commitToIEWDelay), 752623SN/A renameToIEWDelay(params->renameToIEWDelay), 762623SN/A issueToExecuteDelay(params->issueToExecuteDelay), 772623SN/A dispatchWidth(params->dispatchWidth), 782623SN/A issueWidth(params->issueWidth), 793349Sbinkertn@umich.edu wbWidth(params->wbWidth), 802623SN/A numThreads(params->numThreads) 813184Srdreslin@umich.edu{ 823184Srdreslin@umich.edu if (dispatchWidth > Impl::MaxWidth) 832623SN/A fatal("dispatchWidth (%d) is larger than compiled limit (%d),\n" 842623SN/A "\tincrease MaxWidth in src/cpu/o3/impl.hh\n", 852623SN/A dispatchWidth, static_cast<int>(Impl::MaxWidth)); 862623SN/A if (issueWidth > Impl::MaxWidth) 872623SN/A fatal("issueWidth (%d) is larger than compiled limit (%d),\n" 883647Srdreslin@umich.edu "\tincrease MaxWidth in src/cpu/o3/impl.hh\n", 893647Srdreslin@umich.edu issueWidth, static_cast<int>(Impl::MaxWidth)); 903647Srdreslin@umich.edu if (wbWidth > Impl::MaxWidth) 913647Srdreslin@umich.edu fatal("wbWidth (%d) is larger than compiled limit (%d),\n" 923647Srdreslin@umich.edu "\tincrease MaxWidth in src/cpu/o3/impl.hh\n", 932631SN/A wbWidth, static_cast<int>(Impl::MaxWidth)); 943647Srdreslin@umich.edu 952631SN/A _status = Active; 962623SN/A exeStatus = Running; 972623SN/A wbStatus = Idle; 982623SN/A 992948Ssaidi@eecs.umich.edu // Setup wire to read instructions coming from issue. 1002948Ssaidi@eecs.umich.edu fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay); 1013349Sbinkertn@umich.edu 1022948Ssaidi@eecs.umich.edu // Instruction queue needs the queue between issue and execute. 1032948Ssaidi@eecs.umich.edu instQueue.setIssueToExecuteQueue(&issueToExecQueue); 1045606Snate@binkert.org 1052948Ssaidi@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 1062948Ssaidi@eecs.umich.edu dispatchStatus[tid] = Running; 1075529Snate@binkert.org fetchRedirect[tid] = false; 1085169Ssaidi@eecs.umich.edu } 1092623SN/A 1102623SN/A updateLSQNextCycle = false; 1113647Srdreslin@umich.edu 1123647Srdreslin@umich.edu skidBufferMax = (renameToIEWDelay + 1) * params->renameWidth; 1133647Srdreslin@umich.edu} 1143647Srdreslin@umich.edu 1152623SN/Atemplate <class Impl> 1162839Sktlim@umich.edustd::string 1172867Sktlim@umich.eduDefaultIEW<Impl>::name() const 1183222Sktlim@umich.edu{ 1192901Ssaidi@eecs.umich.edu return cpu->name() + ".iew"; 1202623SN/A} 1212623SN/A 1222623SN/Atemplate <class Impl> 1232623SN/Avoid 1242623SN/ADefaultIEW<Impl>::regProbePoints() 1252623SN/A{ 1262623SN/A ppDispatch = new ProbePointArg<DynInstPtr>(cpu->getProbeManager(), "Dispatch"); 1272623SN/A ppMispredict = new ProbePointArg<DynInstPtr>(cpu->getProbeManager(), "Mispredict"); 1282623SN/A /** 1292623SN/A * Probe point with dynamic instruction as the argument used to probe when 1302915Sktlim@umich.edu * an instruction starts to execute. 1312915Sktlim@umich.edu */ 1322623SN/A ppExecute = new ProbePointArg<DynInstPtr>(cpu->getProbeManager(), 1332623SN/A "Execute"); 1342623SN/A /** 1352623SN/A * Probe point with dynamic instruction as the argument used to probe when 1362623SN/A * an instruction execution completes and it is marked ready to commit. 1372623SN/A */ 1382915Sktlim@umich.edu ppToCommit = new ProbePointArg<DynInstPtr>(cpu->getProbeManager(), 1392915Sktlim@umich.edu "ToCommit"); 1402623SN/A} 1412798Sktlim@umich.edu 1422798Sktlim@umich.edutemplate <class Impl> 1432901Ssaidi@eecs.umich.eduvoid 1442839Sktlim@umich.eduDefaultIEW<Impl>::regStats() 1452798Sktlim@umich.edu{ 1462839Sktlim@umich.edu using namespace Stats; 1472798Sktlim@umich.edu 1485496Ssaidi@eecs.umich.edu instQueue.regStats(); 1492901Ssaidi@eecs.umich.edu ldstQueue.regStats(); 1502901Ssaidi@eecs.umich.edu 1512798Sktlim@umich.edu iewIdleCycles 1522839Sktlim@umich.edu .name(name() + ".iewIdleCycles") 1532839Sktlim@umich.edu .desc("Number of cycles IEW is idle"); 1542901Ssaidi@eecs.umich.edu 1552798Sktlim@umich.edu iewSquashCycles 1562623SN/A .name(name() + ".iewSquashCycles") 1572623SN/A .desc("Number of cycles IEW is squashing"); 1582623SN/A 1592798Sktlim@umich.edu iewBlockCycles 1602623SN/A .name(name() + ".iewBlockCycles") 1615221Ssaidi@eecs.umich.edu .desc("Number of cycles IEW is blocking"); 1622798Sktlim@umich.edu 1634762Snate@binkert.org iewUnblockCycles 1643201Shsul@eecs.umich.edu .name(name() + ".iewUnblockCycles") 1652867Sktlim@umich.edu .desc("Number of cycles IEW is unblocking"); 1662867Sktlim@umich.edu 1672915Sktlim@umich.edu iewDispatchedInsts 1685606Snate@binkert.org .name(name() + ".iewDispatchedInsts") 1692915Sktlim@umich.edu .desc("Number of instructions dispatched to IQ"); 1702867Sktlim@umich.edu 1712867Sktlim@umich.edu iewDispSquashedInsts 1722867Sktlim@umich.edu .name(name() + ".iewDispSquashedInsts") 1734471Sstever@eecs.umich.edu .desc("Number of squashed instructions skipped by dispatch"); 1742623SN/A 1752798Sktlim@umich.edu iewDispLoadInsts 1762901Ssaidi@eecs.umich.edu .name(name() + ".iewDispLoadInsts") 1772798Sktlim@umich.edu .desc("Number of dispatched load instructions"); 1782798Sktlim@umich.edu 1792798Sktlim@umich.edu iewDispStoreInsts 1802798Sktlim@umich.edu .name(name() + ".iewDispStoreInsts") 1812798Sktlim@umich.edu .desc("Number of dispatched store instructions"); 1825496Ssaidi@eecs.umich.edu 1832798Sktlim@umich.edu iewDispNonSpecInsts 1845099Ssaidi@eecs.umich.edu .name(name() + ".iewDispNonSpecInsts") 1852867Sktlim@umich.edu .desc("Number of dispatched non-speculative instructions"); 1862867Sktlim@umich.edu 1872867Sktlim@umich.edu iewIQFullEvents 1882867Sktlim@umich.edu .name(name() + ".iewIQFullEvents") 1895606Snate@binkert.org .desc("Number of times the IQ has become full, causing a stall"); 1902623SN/A 1912623SN/A iewLSQFullEvents 1922623SN/A .name(name() + ".iewLSQFullEvents") 1932623SN/A .desc("Number of times the LSQ has become full, causing a stall"); 1942623SN/A 1952623SN/A memOrderViolationEvents 1964192Sktlim@umich.edu .name(name() + ".memOrderViolationEvents") 1972623SN/A .desc("Number of memory order violations"); 1982680Sktlim@umich.edu 1992623SN/A predictedTakenIncorrect 2002680Sktlim@umich.edu .name(name() + ".predictedTakenIncorrect") 2012680Sktlim@umich.edu .desc("Number of branches that were predicted taken incorrectly"); 2022680Sktlim@umich.edu 2032623SN/A predictedNotTakenIncorrect 2042623SN/A .name(name() + ".predictedNotTakenIncorrect") 2052623SN/A .desc("Number of branches that were predicted not taken incorrectly"); 2062623SN/A 2073201Shsul@eecs.umich.edu branchMispredicts 2083201Shsul@eecs.umich.edu .name(name() + ".branchMispredicts") 2093201Shsul@eecs.umich.edu .desc("Number of branch mispredicts detected at execute"); 2103201Shsul@eecs.umich.edu 2115169Ssaidi@eecs.umich.edu branchMispredicts = predictedTakenIncorrect + predictedNotTakenIncorrect; 2125169Ssaidi@eecs.umich.edu 2135101Ssaidi@eecs.umich.edu iewExecutedInsts 2142623SN/A .name(name() + ".iewExecutedInsts") 2152623SN/A .desc("Number of executed instructions"); 2162623SN/A 2172623SN/A iewExecLoadInsts 2182623SN/A .init(cpu->numThreads) 2192623SN/A .name(name() + ".iewExecLoadInsts") 2205221Ssaidi@eecs.umich.edu .desc("Number of load instructions executed") 2215221Ssaidi@eecs.umich.edu .flags(total); 2222623SN/A 2232683Sktlim@umich.edu iewExecSquashedInsts 2242623SN/A .name(name() + ".iewExecSquashedInsts") 2252623SN/A .desc("Number of squashed instructions skipped in execute"); 2262623SN/A 2272623SN/A iewExecutedSwp 2282623SN/A .init(cpu->numThreads) 2293686Sktlim@umich.edu .name(name() + ".exec_swp") 2302623SN/A .desc("number of swp insts executed") 2315606Snate@binkert.org .flags(total); 2325606Snate@binkert.org 2332623SN/A iewExecutedNop 2342623SN/A .init(cpu->numThreads) 2352623SN/A .name(name() + ".exec_nop") 2362623SN/A .desc("number of nop insts executed") 2372623SN/A .flags(total); 2382623SN/A 2395221Ssaidi@eecs.umich.edu iewExecutedRefs 2405221Ssaidi@eecs.umich.edu .init(cpu->numThreads) 2412623SN/A .name(name() + ".exec_refs") 2422683Sktlim@umich.edu .desc("number of memory reference insts executed") 2432623SN/A .flags(total); 2442644Sstever@eecs.umich.edu 2452623SN/A iewExecutedBranches 2462644Sstever@eecs.umich.edu .init(cpu->numThreads) 2472644Sstever@eecs.umich.edu .name(name() + ".exec_branches") 2482623SN/A .desc("Number of branches executed") 2492623SN/A .flags(total); 2502623SN/A 2512623SN/A iewExecStoreInsts 2522623SN/A .name(name() + ".exec_stores") 2532623SN/A .desc("Number of stores executed") 2542623SN/A .flags(total); 2552623SN/A iewExecStoreInsts = iewExecutedRefs - iewExecLoadInsts; 2562623SN/A 2572623SN/A iewExecRate 2583169Sstever@eecs.umich.edu .name(name() + ".exec_rate") 2593169Sstever@eecs.umich.edu .desc("Inst execution rate") 2605169Ssaidi@eecs.umich.edu .flags(total); 2612623SN/A 2622623SN/A iewExecRate = iewExecutedInsts / cpu->numCycles; 2633169Sstever@eecs.umich.edu 2642623SN/A iewInstsToCommit 2652623SN/A .init(cpu->numThreads) 2662623SN/A .name(name() + ".wb_sent") 2673169Sstever@eecs.umich.edu .desc("cumulative count of insts sent to commit") 2682623SN/A .flags(total); 2692623SN/A 2702623SN/A writebackCount 2713349Sbinkertn@umich.edu .init(cpu->numThreads) 2724878Sstever@eecs.umich.edu .name(name() + ".wb_count") 2734878Sstever@eecs.umich.edu .desc("cumulative count of insts written-back") 2744878Sstever@eecs.umich.edu .flags(total); 2754878Sstever@eecs.umich.edu 2763169Sstever@eecs.umich.edu producerInst 2772623SN/A .init(cpu->numThreads) 2785103Ssaidi@eecs.umich.edu .name(name() + ".wb_producers") 2795103Ssaidi@eecs.umich.edu .desc("num instructions producing a value") 2805103Ssaidi@eecs.umich.edu .flags(total); 2815103Ssaidi@eecs.umich.edu 2825103Ssaidi@eecs.umich.edu consumerInst 2835103Ssaidi@eecs.umich.edu .init(cpu->numThreads) 2845103Ssaidi@eecs.umich.edu .name(name() + ".wb_consumers") 2852623SN/A .desc("num instructions consuming a value") 2863169Sstever@eecs.umich.edu .flags(total); 2872623SN/A 2882623SN/A wbFanout 2893169Sstever@eecs.umich.edu .name(name() + ".wb_fanout") 2902623SN/A .desc("average fanout of values written-back") 2912623SN/A .flags(total); 2924200Ssaidi@eecs.umich.edu 2934200Ssaidi@eecs.umich.edu wbFanout = producerInst / consumerInst; 2944200Ssaidi@eecs.umich.edu 2954200Ssaidi@eecs.umich.edu wbRate 2963658Sktlim@umich.edu .name(name() + ".wb_rate") 2973658Sktlim@umich.edu .desc("insts written-back per cycle") 2982623SN/A .flags(total); 2992623SN/A wbRate = writebackCount / cpu->numCycles; 3005408Sgblack@eecs.umich.edu} 3015408Sgblack@eecs.umich.edu 3025408Sgblack@eecs.umich.edutemplate<class Impl> 3032623SN/Avoid 3042623SN/ADefaultIEW<Impl>::startupStage() 3052623SN/A{ 3065177Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 3075177Sgblack@eecs.umich.edu toRename->iewInfo[tid].usedIQ = true; 3085177Sgblack@eecs.umich.edu toRename->iewInfo[tid].freeIQEntries = 3095177Sgblack@eecs.umich.edu instQueue.numFreeEntries(tid); 3105177Sgblack@eecs.umich.edu 3115177Sgblack@eecs.umich.edu toRename->iewInfo[tid].usedLSQ = true; 3125177Sgblack@eecs.umich.edu toRename->iewInfo[tid].freeLQEntries = ldstQueue.numFreeLoadEntries(tid); 3135177Sgblack@eecs.umich.edu toRename->iewInfo[tid].freeSQEntries = ldstQueue.numFreeStoreEntries(tid); 3145177Sgblack@eecs.umich.edu } 3155177Sgblack@eecs.umich.edu 3165177Sgblack@eecs.umich.edu // Initialize the checker's dcache port here 3175177Sgblack@eecs.umich.edu if (cpu->checker) { 3185177Sgblack@eecs.umich.edu cpu->checker->setDcachePort(&cpu->getDataPort()); 3195177Sgblack@eecs.umich.edu } 3205177Sgblack@eecs.umich.edu 3215177Sgblack@eecs.umich.edu cpu->activateStage(O3CPU::IEWIdx); 3225177Sgblack@eecs.umich.edu} 3235177Sgblack@eecs.umich.edu 3245177Sgblack@eecs.umich.edutemplate<class Impl> 3255177Sgblack@eecs.umich.eduvoid 3262623SN/ADefaultIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 3272623SN/A{ 3282623SN/A timeBuffer = tb_ptr; 3292623SN/A 3304040Ssaidi@eecs.umich.edu // Setup wire to read information from time buffer, from commit. 3314040Ssaidi@eecs.umich.edu fromCommit = timeBuffer->getWire(-commitToIEWDelay); 3324040Ssaidi@eecs.umich.edu 3334040Ssaidi@eecs.umich.edu // Setup wire to write information back to previous stages. 3344115Ssaidi@eecs.umich.edu toRename = timeBuffer->getWire(0); 3354115Ssaidi@eecs.umich.edu 3364115Ssaidi@eecs.umich.edu toFetch = timeBuffer->getWire(0); 3374115Ssaidi@eecs.umich.edu 3382623SN/A // Instruction queue also needs main time buffer. 3392623SN/A instQueue.setTimeBuffer(tb_ptr); 3402623SN/A} 3412623SN/A 3422623SN/Atemplate<class Impl> 3432623SN/Avoid 3442623SN/ADefaultIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 3452623SN/A{ 3462623SN/A renameQueue = rq_ptr; 3472623SN/A 3482623SN/A // Setup wire to read information from rename queue. 3492623SN/A fromRename = renameQueue->getWire(-renameToIEWDelay); 3502623SN/A} 3512623SN/A 3522623SN/Atemplate<class Impl> 3532623SN/Avoid 3542623SN/ADefaultIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr) 3552623SN/A{ 3562623SN/A iewQueue = iq_ptr; 3572623SN/A 3582623SN/A // Setup wire to write instructions to commit. 3592623SN/A toCommit = iewQueue->getWire(0); 3602623SN/A} 3612623SN/A 3622623SN/Atemplate<class Impl> 3632623SN/Avoid 3642623SN/ADefaultIEW<Impl>::setActiveThreads(list<ThreadID> *at_ptr) 3652623SN/A{ 3662623SN/A activeThreads = at_ptr; 3672623SN/A 3682623SN/A ldstQueue.setActiveThreads(at_ptr); 3692623SN/A instQueue.setActiveThreads(at_ptr); 3702623SN/A} 3712623SN/A 3722623SN/Atemplate<class Impl> 3732623SN/Avoid 3742623SN/ADefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr) 3752623SN/A{ 3762623SN/A scoreboard = sb_ptr; 3772623SN/A} 3782623SN/A 3792623SN/Atemplate <class Impl> 3802623SN/Abool 3813169Sstever@eecs.umich.eduDefaultIEW<Impl>::isDrained() const 3823169Sstever@eecs.umich.edu{ 3835169Ssaidi@eecs.umich.edu bool drained = ldstQueue.isDrained() && instQueue.isDrained(); 3842623SN/A 3854040Ssaidi@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 3864040Ssaidi@eecs.umich.edu if (!insts[tid].empty()) { 3874040Ssaidi@eecs.umich.edu DPRINTF(Drain, "%i: Insts not empty.\n", tid); 3884040Ssaidi@eecs.umich.edu drained = false; 3892623SN/A } 3903169Sstever@eecs.umich.edu if (!skidBuffer[tid].empty()) { 3913169Sstever@eecs.umich.edu DPRINTF(Drain, "%i: Skid buffer not empty.\n", tid); 3922623SN/A drained = false; 3932623SN/A } 3944878Sstever@eecs.umich.edu drained = drained && dispatchStatus[tid] == Running; 3953170Sstever@eecs.umich.edu } 3963170Sstever@eecs.umich.edu 3973170Sstever@eecs.umich.edu // Also check the FU pool as instructions are "stored" in FU 3984878Sstever@eecs.umich.edu // completion events until they are done and not accounted for 3993170Sstever@eecs.umich.edu // above 4004878Sstever@eecs.umich.edu if (drained && !fuPool->isDrained()) { 4014878Sstever@eecs.umich.edu DPRINTF(Drain, "FU pool still busy.\n"); 4024878Sstever@eecs.umich.edu drained = false; 4034878Sstever@eecs.umich.edu } 4044878Sstever@eecs.umich.edu 4054878Sstever@eecs.umich.edu return drained; 4063170Sstever@eecs.umich.edu} 4074584Ssaidi@eecs.umich.edu 4084881Sstever@eecs.umich.edutemplate <class Impl> 4094881Sstever@eecs.umich.eduvoid 4104881Sstever@eecs.umich.eduDefaultIEW<Impl>::drainSanityCheck() const 4114881Sstever@eecs.umich.edu{ 4124881Sstever@eecs.umich.edu assert(isDrained()); 4134881Sstever@eecs.umich.edu 4143170Sstever@eecs.umich.edu instQueue.drainSanityCheck(); 4153170Sstever@eecs.umich.edu ldstQueue.drainSanityCheck(); 4165103Ssaidi@eecs.umich.edu} 4175103Ssaidi@eecs.umich.edu 4185103Ssaidi@eecs.umich.edutemplate <class Impl> 4195103Ssaidi@eecs.umich.eduvoid 4205103Ssaidi@eecs.umich.eduDefaultIEW<Impl>::takeOverFrom() 4215103Ssaidi@eecs.umich.edu{ 4225103Ssaidi@eecs.umich.edu // Reset all state. 4235103Ssaidi@eecs.umich.edu _status = Active; 4243170Sstever@eecs.umich.edu exeStatus = Running; 4253170Sstever@eecs.umich.edu wbStatus = Idle; 4263170Sstever@eecs.umich.edu 4273170Sstever@eecs.umich.edu instQueue.takeOverFrom(); 4283170Sstever@eecs.umich.edu ldstQueue.takeOverFrom(); 4293170Sstever@eecs.umich.edu fuPool->takeOverFrom(); 4302623SN/A 4314200Ssaidi@eecs.umich.edu startupStage(); 4324200Ssaidi@eecs.umich.edu cpu->activityThisCycle(); 4334200Ssaidi@eecs.umich.edu 4343658Sktlim@umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 4353658Sktlim@umich.edu dispatchStatus[tid] = Running; 4362623SN/A fetchRedirect[tid] = false; 4372623SN/A } 4385408Sgblack@eecs.umich.edu 4395408Sgblack@eecs.umich.edu updateLSQNextCycle = false; 4405408Sgblack@eecs.umich.edu 4412623SN/A for (int i = 0; i < issueToExecQueue.getSize(); ++i) { 4422623SN/A issueToExecQueue.advance(); 4432623SN/A } 4442623SN/A} 4452623SN/A 4462623SN/Atemplate<class Impl> 4475177Sgblack@eecs.umich.eduvoid 4485177Sgblack@eecs.umich.eduDefaultIEW<Impl>::squash(ThreadID tid) 4495177Sgblack@eecs.umich.edu{ 4505177Sgblack@eecs.umich.edu DPRINTF(IEW, "[tid:%i]: Squashing all instructions.\n", tid); 4515177Sgblack@eecs.umich.edu 4525177Sgblack@eecs.umich.edu // Tell the IQ to start squashing. 4535177Sgblack@eecs.umich.edu instQueue.squash(tid); 4545177Sgblack@eecs.umich.edu 4555177Sgblack@eecs.umich.edu // Tell the LDSTQ to start squashing. 4565177Sgblack@eecs.umich.edu ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum, tid); 4575177Sgblack@eecs.umich.edu updatedQueues = true; 4585177Sgblack@eecs.umich.edu 4595177Sgblack@eecs.umich.edu // Clear the skid buffer in case it has any data in it. 4605177Sgblack@eecs.umich.edu DPRINTF(IEW, "[tid:%i]: Removing skidbuffer instructions until [sn:%i].\n", 4615177Sgblack@eecs.umich.edu tid, fromCommit->commitInfo[tid].doneSeqNum); 4625177Sgblack@eecs.umich.edu 4635177Sgblack@eecs.umich.edu while (!skidBuffer[tid].empty()) { 4645177Sgblack@eecs.umich.edu if (skidBuffer[tid].front()->isLoad()) { 4655177Sgblack@eecs.umich.edu toRename->iewInfo[tid].dispatchedToLQ++; 4665177Sgblack@eecs.umich.edu } 4672623SN/A if (skidBuffer[tid].front()->isStore()) { 4682623SN/A toRename->iewInfo[tid].dispatchedToSQ++; 4692623SN/A } 4702623SN/A 4714224Sgblack@eecs.umich.edu toRename->iewInfo[tid].dispatched++; 4724224Sgblack@eecs.umich.edu 4734224Sgblack@eecs.umich.edu skidBuffer[tid].pop(); 4744224Sgblack@eecs.umich.edu } 4754224Sgblack@eecs.umich.edu 4764224Sgblack@eecs.umich.edu emptyRenameInsts(tid); 4774224Sgblack@eecs.umich.edu} 4784224Sgblack@eecs.umich.edu 4794224Sgblack@eecs.umich.edutemplate<class Impl> 4804224Sgblack@eecs.umich.eduvoid 4812623SN/ADefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, ThreadID tid) 4822623SN/A{ 4832623SN/A DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %s " 4842623SN/A "[sn:%i].\n", tid, inst->pcState(), inst->seqNum); 4852623SN/A 4862623SN/A if (!toCommit->squash[tid] || 4872623SN/A inst->seqNum < toCommit->squashedSeqNum[tid]) { 4882623SN/A toCommit->squash[tid] = true; 4892623SN/A toCommit->squashedSeqNum[tid] = inst->seqNum; 4902623SN/A toCommit->branchTaken[tid] = inst->pcState().branching(); 4912623SN/A 4922623SN/A TheISA::PCState pc = inst->pcState(); 4932623SN/A TheISA::advancePC(pc, inst->staticInst); 4942623SN/A 4952623SN/A toCommit->pc[tid] = pc; 4962623SN/A toCommit->mispredictInst[tid] = inst; 4972623SN/A toCommit->includeSquashInst[tid] = false; 4982623SN/A 4992623SN/A wroteToTimeBuffer = true; 5002623SN/A } 5012623SN/A 5022623SN/A} 5032623SN/A 5042623SN/Atemplate<class Impl> 5052623SN/Avoid 5062623SN/ADefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, ThreadID tid) 5072623SN/A{ 5082623SN/A DPRINTF(IEW, "[tid:%i]: Memory violation, squashing violator and younger " 5092623SN/A "insts, PC: %s [sn:%i].\n", tid, inst->pcState(), inst->seqNum); 5102623SN/A // Need to include inst->seqNum in the following comparison to cover the 5112623SN/A // corner case when a branch misprediction and a memory violation for the 5122623SN/A // same instruction (e.g. load PC) are detected in the same cycle. In this 5132623SN/A // case the memory violator should take precedence over the branch 5142623SN/A // misprediction because it requires the violator itself to be included in 5152623SN/A // the squash. 5162623SN/A if (!toCommit->squash[tid] || 5172623SN/A inst->seqNum <= toCommit->squashedSeqNum[tid]) { 5182623SN/A toCommit->squash[tid] = true; 5192623SN/A 5202623SN/A toCommit->squashedSeqNum[tid] = inst->seqNum; 5212623SN/A toCommit->pc[tid] = inst->pcState(); 5222623SN/A toCommit->mispredictInst[tid] = NULL; 5232623SN/A 5242623SN/A // Must include the memory violator in the squash. 5252623SN/A toCommit->includeSquashInst[tid] = true; 5262623SN/A 5275221Ssaidi@eecs.umich.edu wroteToTimeBuffer = true; 5285221Ssaidi@eecs.umich.edu } 5293387Sgblack@eecs.umich.edu} 5303387Sgblack@eecs.umich.edu 5312631SN/Atemplate<class Impl> 5325348Ssaidi@eecs.umich.eduvoid 5335348Ssaidi@eecs.umich.eduDefaultIEW<Impl>::block(ThreadID tid) 5345669Sgblack@eecs.umich.edu{ 5352623SN/A DPRINTF(IEW, "[tid:%u]: Blocking.\n", tid); 5365669Sgblack@eecs.umich.edu 5375669Sgblack@eecs.umich.edu if (dispatchStatus[tid] != Blocked && 5385669Sgblack@eecs.umich.edu dispatchStatus[tid] != Unblocking) { 5395669Sgblack@eecs.umich.edu toRename->iewBlock[tid] = true; 5402623SN/A wroteToTimeBuffer = true; 5415669Sgblack@eecs.umich.edu } 5425669Sgblack@eecs.umich.edu 5435669Sgblack@eecs.umich.edu // Add the current inputs to the skid buffer so they can be 5445669Sgblack@eecs.umich.edu // reprocessed when this stage unblocks. 5455669Sgblack@eecs.umich.edu skidInsert(tid); 5465669Sgblack@eecs.umich.edu 5475669Sgblack@eecs.umich.edu dispatchStatus[tid] = Blocked; 5485669Sgblack@eecs.umich.edu} 5495669Sgblack@eecs.umich.edu 5505669Sgblack@eecs.umich.edutemplate<class Impl> 5515669Sgblack@eecs.umich.eduvoid 5525669Sgblack@eecs.umich.eduDefaultIEW<Impl>::unblock(ThreadID tid) 5535669Sgblack@eecs.umich.edu{ 5542623SN/A DPRINTF(IEW, "[tid:%i]: Reading instructions out of the skid " 5555669Sgblack@eecs.umich.edu "buffer %u.\n",tid, tid); 5565669Sgblack@eecs.umich.edu 5575669Sgblack@eecs.umich.edu // If the skid bufffer is empty, signal back to previous stages to unblock. 5585669Sgblack@eecs.umich.edu // Also switch status to running. 5592623SN/A if (skidBuffer[tid].empty()) { 5602623SN/A toRename->iewUnblock[tid] = true; 5615669Sgblack@eecs.umich.edu wroteToTimeBuffer = true; 5625669Sgblack@eecs.umich.edu DPRINTF(IEW, "[tid:%i]: Done unblocking.\n",tid); 5632623SN/A dispatchStatus[tid] = Running; 5643222Sktlim@umich.edu } 5655099Ssaidi@eecs.umich.edu} 5663222Sktlim@umich.edu 5672623SN/Atemplate<class Impl> 5682623SN/Avoid 5692623SN/ADefaultIEW<Impl>::wakeDependents(DynInstPtr &inst) 5702623SN/A{ 5712644Sstever@eecs.umich.edu instQueue.wakeDependents(inst); 5722623SN/A} 5732623SN/A 5742623SN/Atemplate<class Impl> 5752631SN/Avoid 5762631SN/ADefaultIEW<Impl>::rescheduleMemInst(DynInstPtr &inst) 5772631SN/A{ 5782631SN/A instQueue.rescheduleMemInst(inst); 5792631SN/A} 5802631SN/A 5812623SN/Atemplate<class Impl> 5822623SN/Avoid 5832623SN/ADefaultIEW<Impl>::replayMemInst(DynInstPtr &inst) 5842623SN/A{ 5853349Sbinkertn@umich.edu instQueue.replayMemInst(inst); 5862623SN/A} 5875221Ssaidi@eecs.umich.edu 5885221Ssaidi@eecs.umich.edutemplate<class Impl> 5892623SN/Avoid 5902623SN/ADefaultIEW<Impl>::blockMemInst(DynInstPtr& inst) 5915669Sgblack@eecs.umich.edu{ 5925669Sgblack@eecs.umich.edu instQueue.blockMemInst(inst); 5932623SN/A} 5942798Sktlim@umich.edu 5952623SN/Atemplate<class Impl> 5962644Sstever@eecs.umich.eduvoid 5975099Ssaidi@eecs.umich.eduDefaultIEW<Impl>::cacheUnblocked() 5983222Sktlim@umich.edu{ 5993222Sktlim@umich.edu instQueue.cacheUnblocked(); 6002839Sktlim@umich.edu} 6015669Sgblack@eecs.umich.edu 6025669Sgblack@eecs.umich.edutemplate<class Impl> 6035669Sgblack@eecs.umich.eduvoid 6045669Sgblack@eecs.umich.eduDefaultIEW<Impl>::instToCommit(DynInstPtr &inst) 6053658Sktlim@umich.edu{ 6062839Sktlim@umich.edu // This function should not be called after writebackInsts in a 6072798Sktlim@umich.edu // single cycle. That will cause problems with an instruction 6082798Sktlim@umich.edu // being added to the queue to commit without being processed by 6092798Sktlim@umich.edu // writebackInsts prior to being sent to commit. 6102623SN/A 6112644Sstever@eecs.umich.edu // First check the time slot that this instruction will write 6122623SN/A // to. If there are free write ports at the time, then go ahead 6132623SN/A // and write the instruction to that time. If there are not, 6143170Sstever@eecs.umich.edu // keep looking back to see where's the first time there's a 6153170Sstever@eecs.umich.edu // free slot. 6163170Sstever@eecs.umich.edu while ((*iewQueue)[wbCycle].insts[wbNumInst]) { 6173170Sstever@eecs.umich.edu ++wbNumInst; 6182644Sstever@eecs.umich.edu if (wbNumInst == wbWidth) { 6193170Sstever@eecs.umich.edu ++wbCycle; 6205335Shines@cs.fsu.edu wbNumInst = 0; 6215335Shines@cs.fsu.edu } 6223170Sstever@eecs.umich.edu } 6235335Shines@cs.fsu.edu 6245335Shines@cs.fsu.edu DPRINTF(IEW, "Current wb cycle: %i, width: %i, numInst: %i\nwbActual:%i\n", 6253170Sstever@eecs.umich.edu wbCycle, wbWidth, wbNumInst, wbCycle * wbWidth + wbNumInst); 6263170Sstever@eecs.umich.edu // Add finished instruction to queue to commit. 6275335Shines@cs.fsu.edu (*iewQueue)[wbCycle].insts[wbNumInst] = inst; 6285335Shines@cs.fsu.edu (*iewQueue)[wbCycle].size++; 6295335Shines@cs.fsu.edu} 6305335Shines@cs.fsu.edu 6315335Shines@cs.fsu.edutemplate <class Impl> 6325335Shines@cs.fsu.eduunsigned 6334998Sgblack@eecs.umich.eduDefaultIEW<Impl>::validInstsFromRename() 6344998Sgblack@eecs.umich.edu{ 6354998Sgblack@eecs.umich.edu unsigned inst_count = 0; 6364998Sgblack@eecs.umich.edu 6375001Sgblack@eecs.umich.edu for (int i=0; i<fromRename->size; i++) { 6385001Sgblack@eecs.umich.edu if (!fromRename->insts[i]->isSquashed()) 6395001Sgblack@eecs.umich.edu inst_count++; 6405001Sgblack@eecs.umich.edu } 6413170Sstever@eecs.umich.edu 6424998Sgblack@eecs.umich.edu return inst_count; 6432644Sstever@eecs.umich.edu} 6445103Ssaidi@eecs.umich.edu 6455103Ssaidi@eecs.umich.edutemplate<class Impl> 6465103Ssaidi@eecs.umich.eduvoid 6475103Ssaidi@eecs.umich.eduDefaultIEW<Impl>::skidInsert(ThreadID tid) 6482644Sstever@eecs.umich.edu{ 6492644Sstever@eecs.umich.edu DynInstPtr inst = NULL; 6502623SN/A 6512623SN/A while (!insts[tid].empty()) { 6522623SN/A inst = insts[tid].front(); 6534998Sgblack@eecs.umich.edu 6544998Sgblack@eecs.umich.edu insts[tid].pop(); 6554998Sgblack@eecs.umich.edu 6564998Sgblack@eecs.umich.edu DPRINTF(IEW,"[tid:%i]: Inserting [sn:%lli] PC:%s into " 6575001Sgblack@eecs.umich.edu "dispatch skidBuffer %i\n",tid, inst->seqNum, 6585001Sgblack@eecs.umich.edu inst->pcState(),tid); 6595001Sgblack@eecs.umich.edu 6605001Sgblack@eecs.umich.edu skidBuffer[tid].push(inst); 6615001Sgblack@eecs.umich.edu } 6624998Sgblack@eecs.umich.edu 6632644Sstever@eecs.umich.edu assert(skidBuffer[tid].size() <= skidBufferMax && 6645103Ssaidi@eecs.umich.edu "Skidbuffer Exceeded Max Size"); 6655103Ssaidi@eecs.umich.edu} 6665103Ssaidi@eecs.umich.edu 6675103Ssaidi@eecs.umich.edutemplate<class Impl> 6682644Sstever@eecs.umich.eduint 6692623SN/ADefaultIEW<Impl>::skidCount() 6703658Sktlim@umich.edu{ 6715669Sgblack@eecs.umich.edu int max=0; 6725669Sgblack@eecs.umich.edu 6735669Sgblack@eecs.umich.edu list<ThreadID>::iterator threads = activeThreads->begin(); 6745669Sgblack@eecs.umich.edu list<ThreadID>::iterator end = activeThreads->end(); 6752623SN/A 6762623SN/A while (threads != end) { 6772948Ssaidi@eecs.umich.edu ThreadID tid = *threads++; 6782948Ssaidi@eecs.umich.edu unsigned thread_count = skidBuffer[tid].size(); 6792948Ssaidi@eecs.umich.edu if (max < thread_count) 6802948Ssaidi@eecs.umich.edu max = thread_count; 6812948Ssaidi@eecs.umich.edu } 6822623SN/A 6832623SN/A return max; 6843349Sbinkertn@umich.edu} 6852623SN/A 6864986Ssaidi@eecs.umich.edutemplate<class Impl> 6873310Srdreslin@umich.edubool 6884584Ssaidi@eecs.umich.eduDefaultIEW<Impl>::skidsEmpty() 6892948Ssaidi@eecs.umich.edu{ 6903495Sktlim@umich.edu list<ThreadID>::iterator threads = activeThreads->begin(); 6913310Srdreslin@umich.edu list<ThreadID>::iterator end = activeThreads->end(); 6923310Srdreslin@umich.edu 6933495Sktlim@umich.edu while (threads != end) { 6942948Ssaidi@eecs.umich.edu ThreadID tid = *threads++; 6953310Srdreslin@umich.edu 6963310Srdreslin@umich.edu if (!skidBuffer[tid].empty()) 6974870Sstever@eecs.umich.edu return false; 6984433Ssaidi@eecs.umich.edu } 6994433Ssaidi@eecs.umich.edu 7004433Ssaidi@eecs.umich.edu return true; 7014433Ssaidi@eecs.umich.edu} 7024433Ssaidi@eecs.umich.edu 7034433Ssaidi@eecs.umich.edutemplate <class Impl> 7043310Srdreslin@umich.eduvoid 7054433Ssaidi@eecs.umich.eduDefaultIEW<Impl>::updateStatus() 7064433Ssaidi@eecs.umich.edu{ 7072623SN/A bool any_unblocking = false; 7082623SN/A 7092657Ssaidi@eecs.umich.edu list<ThreadID>::iterator threads = activeThreads->begin(); 7102623SN/A list<ThreadID>::iterator end = activeThreads->end(); 7112623SN/A 7122623SN/A while (threads != end) { 7132623SN/A ThreadID tid = *threads++; 7142623SN/A 7152623SN/A if (dispatchStatus[tid] == Unblocking) { 7163349Sbinkertn@umich.edu any_unblocking = true; 7172657Ssaidi@eecs.umich.edu break; 7182657Ssaidi@eecs.umich.edu } 7192657Ssaidi@eecs.umich.edu } 7202657Ssaidi@eecs.umich.edu 7212623SN/A // If there are no ready instructions waiting to be scheduled by the IQ, 7222623SN/A // and there's no stores waiting to write back, and dispatch is not 7232623SN/A // unblocking, then there is no internal activity for the IEW stage. 7243349Sbinkertn@umich.edu instQueue.intInstQueueReads++; 7252623SN/A if (_status == Active && !instQueue.hasReadyInsts() && 7262623SN/A !ldstQueue.willWB() && !any_unblocking) { 7272623SN/A DPRINTF(IEW, "IEW switching to idle\n"); 7284870Sstever@eecs.umich.edu 7292623SN/A deactivateStage(); 7302623SN/A 7312623SN/A _status = Inactive; 7325099Ssaidi@eecs.umich.edu } else if (_status == Inactive && (instQueue.hasReadyInsts() || 7333222Sktlim@umich.edu ldstQueue.willWB() || 7343184Srdreslin@umich.edu any_unblocking)) { 7352623SN/A // Otherwise there is internal activity. Set to active. 7362623SN/A DPRINTF(IEW, "IEW switching to active\n"); 7374998Sgblack@eecs.umich.edu 7384998Sgblack@eecs.umich.edu activateStage(); 7394998Sgblack@eecs.umich.edu 7405001Sgblack@eecs.umich.edu _status = Active; 7415001Sgblack@eecs.umich.edu } 7425001Sgblack@eecs.umich.edu} 7435001Sgblack@eecs.umich.edu 7445001Sgblack@eecs.umich.edutemplate <class Impl> 7454998Sgblack@eecs.umich.eduvoid 7465507Sstever@gmail.comDefaultIEW<Impl>::resetEntries() 7475507Sstever@gmail.com{ 7485507Sstever@gmail.com instQueue.resetEntries(); 7493170Sstever@eecs.umich.edu ldstQueue.resetEntries(); 7503170Sstever@eecs.umich.edu} 7513170Sstever@eecs.umich.edu 7522644Sstever@eecs.umich.edutemplate <class Impl> 7532644Sstever@eecs.umich.edubool 7542644Sstever@eecs.umich.eduDefaultIEW<Impl>::checkStall(ThreadID tid) 7553184Srdreslin@umich.edu{ 7563227Sktlim@umich.edu bool ret_val(false); 7573201Shsul@eecs.umich.edu 7583201Shsul@eecs.umich.edu if (fromCommit->commitInfo[tid].robSquashing) { 7593201Shsul@eecs.umich.edu DPRINTF(IEW,"[tid:%i]: Stall from Commit stage detected.\n",tid); 7603201Shsul@eecs.umich.edu ret_val = true; 7613201Shsul@eecs.umich.edu } else if (instQueue.isFull(tid)) { 7623201Shsul@eecs.umich.edu DPRINTF(IEW,"[tid:%i]: Stall: IQ is full.\n",tid); 7633201Shsul@eecs.umich.edu ret_val = true; 7642644Sstever@eecs.umich.edu } 7652623SN/A 7662623SN/A return ret_val; 7672623SN/A} 7682798Sktlim@umich.edu 7692839Sktlim@umich.edutemplate <class Impl> 7702798Sktlim@umich.eduvoid 7712839Sktlim@umich.eduDefaultIEW<Impl>::checkSignalsAndUpdate(ThreadID tid) 7722901Ssaidi@eecs.umich.edu{ 7732839Sktlim@umich.edu // Check if there's a squash signal, squash if there is 7742798Sktlim@umich.edu // Check stall signals, block if there is. 7752623SN/A // If status was Blocked 7764192Sktlim@umich.edu // if so then go to unblocking 7774192Sktlim@umich.edu // If status was Squashing 7784192Sktlim@umich.edu // check if squashing is not high. Switch to running this cycle. 7794192Sktlim@umich.edu 7804192Sktlim@umich.edu if (fromCommit->commitInfo[tid].squash) { 7814192Sktlim@umich.edu squash(tid); 7824192Sktlim@umich.edu 7834192Sktlim@umich.edu if (dispatchStatus[tid] == Blocked || 7845497Ssaidi@eecs.umich.edu dispatchStatus[tid] == Unblocking) { 7854192Sktlim@umich.edu toRename->iewUnblock[tid] = true; 7864192Sktlim@umich.edu wroteToTimeBuffer = true; 7874192Sktlim@umich.edu } 7882623SN/A 7893349Sbinkertn@umich.edu dispatchStatus[tid] = Squashing; 7902623SN/A fetchRedirect[tid] = false; 7914986Ssaidi@eecs.umich.edu return; 7923310Srdreslin@umich.edu } 7934584Ssaidi@eecs.umich.edu 7942948Ssaidi@eecs.umich.edu if (fromCommit->commitInfo[tid].robSquashing) { 7953495Sktlim@umich.edu DPRINTF(IEW, "[tid:%i]: ROB is still squashing.\n", tid); 7963310Srdreslin@umich.edu 7973310Srdreslin@umich.edu dispatchStatus[tid] = Squashing; 7983495Sktlim@umich.edu emptyRenameInsts(tid); 7992948Ssaidi@eecs.umich.edu wroteToTimeBuffer = true; 8003310Srdreslin@umich.edu } 8013310Srdreslin@umich.edu 8024870Sstever@eecs.umich.edu if (checkStall(tid)) { 8034433Ssaidi@eecs.umich.edu block(tid); 8044433Ssaidi@eecs.umich.edu dispatchStatus[tid] = Blocked; 8054433Ssaidi@eecs.umich.edu return; 8064433Ssaidi@eecs.umich.edu } 8074433Ssaidi@eecs.umich.edu 8084433Ssaidi@eecs.umich.edu if (dispatchStatus[tid] == Blocked) { 8093310Srdreslin@umich.edu // Status from previous cycle was blocked, but there are no more stall 8104433Ssaidi@eecs.umich.edu // conditions. Switch over to unblocking. 8114433Ssaidi@eecs.umich.edu DPRINTF(IEW, "[tid:%i]: Done blocking, switching to unblocking.\n", 8122948Ssaidi@eecs.umich.edu tid); 8132948Ssaidi@eecs.umich.edu 8142948Ssaidi@eecs.umich.edu dispatchStatus[tid] = Unblocking; 8152948Ssaidi@eecs.umich.edu 8162948Ssaidi@eecs.umich.edu unblock(tid); 8172630SN/A 8182623SN/A return; 8192623SN/A } 8202657Ssaidi@eecs.umich.edu 8212623SN/A if (dispatchStatus[tid] == Squashing) { 8222623SN/A // Switch status to running if rename isn't being told to block or 8232623SN/A // squash this cycle. 8242623SN/A DPRINTF(IEW, "[tid:%i]: Done squashing, switching to running.\n", 8252623SN/A tid); 8262623SN/A 8273349Sbinkertn@umich.edu dispatchStatus[tid] = Running; 8282657Ssaidi@eecs.umich.edu 8292657Ssaidi@eecs.umich.edu return; 8303170Sstever@eecs.umich.edu } 8312657Ssaidi@eecs.umich.edu} 8322657Ssaidi@eecs.umich.edu 8332623SN/Atemplate <class Impl> 8342623SN/Avoid 8355606Snate@binkert.orgDefaultIEW<Impl>::sortInsts() 8365606Snate@binkert.org{ 8375606Snate@binkert.org int insts_from_rename = fromRename->size; 8385103Ssaidi@eecs.umich.edu#ifdef DEBUG 8395606Snate@binkert.org for (ThreadID tid = 0; tid < numThreads; tid++) 8405103Ssaidi@eecs.umich.edu assert(insts[tid].empty()); 8415103Ssaidi@eecs.umich.edu#endif 8425103Ssaidi@eecs.umich.edu for (int i = 0; i < insts_from_rename; ++i) { 8435103Ssaidi@eecs.umich.edu insts[fromRename->insts[i]->threadNumber].push(fromRename->insts[i]); 8445103Ssaidi@eecs.umich.edu } 8455103Ssaidi@eecs.umich.edu} 8465103Ssaidi@eecs.umich.edu 8475103Ssaidi@eecs.umich.edutemplate <class Impl> 8485103Ssaidi@eecs.umich.eduvoid 8495336Shines@cs.fsu.eduDefaultIEW<Impl>::emptyRenameInsts(ThreadID tid) 8505103Ssaidi@eecs.umich.edu{ 8515103Ssaidi@eecs.umich.edu DPRINTF(IEW, "[tid:%i]: Removing incoming rename instructions\n", tid); 8525103Ssaidi@eecs.umich.edu 8535103Ssaidi@eecs.umich.edu while (!insts[tid].empty()) { 8542623SN/A 8555315Sstever@gmail.com if (insts[tid].front()->isLoad()) { 8565315Sstever@gmail.com toRename->iewInfo[tid].dispatchedToLQ++; 8575315Sstever@gmail.com } 8585315Sstever@gmail.com if (insts[tid].front()->isStore()) { 8595315Sstever@gmail.com toRename->iewInfo[tid].dispatchedToSQ++; 8605315Sstever@gmail.com } 8615315Sstever@gmail.com 8622623SN/A toRename->iewInfo[tid].dispatched++; 8632623SN/A 8642623SN/A insts[tid].pop(); 8652623SN/A } 8664762Snate@binkert.org} 8674762Snate@binkert.org 8682623SN/Atemplate <class Impl> 8695529Snate@binkert.orgvoid 8705529Snate@binkert.orgDefaultIEW<Impl>::wakeCPU() 8714762Snate@binkert.org{ 8724762Snate@binkert.org cpu->wakeCPU(); 8732623SN/A} 8745529Snate@binkert.org 8752623SN/Atemplate <class Impl> 876void 877DefaultIEW<Impl>::activityThisCycle() 878{ 879 DPRINTF(Activity, "Activity this cycle.\n"); 880 cpu->activityThisCycle(); 881} 882 883template <class Impl> 884inline void 885DefaultIEW<Impl>::activateStage() 886{ 887 DPRINTF(Activity, "Activating stage.\n"); 888 cpu->activateStage(O3CPU::IEWIdx); 889} 890 891template <class Impl> 892inline void 893DefaultIEW<Impl>::deactivateStage() 894{ 895 DPRINTF(Activity, "Deactivating stage.\n"); 896 cpu->deactivateStage(O3CPU::IEWIdx); 897} 898 899template<class Impl> 900void 901DefaultIEW<Impl>::dispatch(ThreadID tid) 902{ 903 // If status is Running or idle, 904 // call dispatchInsts() 905 // If status is Unblocking, 906 // buffer any instructions coming from rename 907 // continue trying to empty skid buffer 908 // check if stall conditions have passed 909 910 if (dispatchStatus[tid] == Blocked) { 911 ++iewBlockCycles; 912 913 } else if (dispatchStatus[tid] == Squashing) { 914 ++iewSquashCycles; 915 } 916 917 // Dispatch should try to dispatch as many instructions as its bandwidth 918 // will allow, as long as it is not currently blocked. 919 if (dispatchStatus[tid] == Running || 920 dispatchStatus[tid] == Idle) { 921 DPRINTF(IEW, "[tid:%i] Not blocked, so attempting to run " 922 "dispatch.\n", tid); 923 924 dispatchInsts(tid); 925 } else if (dispatchStatus[tid] == Unblocking) { 926 // Make sure that the skid buffer has something in it if the 927 // status is unblocking. 928 assert(!skidsEmpty()); 929 930 // If the status was unblocking, then instructions from the skid 931 // buffer were used. Remove those instructions and handle 932 // the rest of unblocking. 933 dispatchInsts(tid); 934 935 ++iewUnblockCycles; 936 937 if (validInstsFromRename()) { 938 // Add the current inputs to the skid buffer so they can be 939 // reprocessed when this stage unblocks. 940 skidInsert(tid); 941 } 942 943 unblock(tid); 944 } 945} 946 947template <class Impl> 948void 949DefaultIEW<Impl>::dispatchInsts(ThreadID tid) 950{ 951 // Obtain instructions from skid buffer if unblocking, or queue from rename 952 // otherwise. 953 std::queue<DynInstPtr> &insts_to_dispatch = 954 dispatchStatus[tid] == Unblocking ? 955 skidBuffer[tid] : insts[tid]; 956 957 int insts_to_add = insts_to_dispatch.size(); 958 959 DynInstPtr inst; 960 bool add_to_iq = false; 961 int dis_num_inst = 0; 962 963 // Loop through the instructions, putting them in the instruction 964 // queue. 965 for ( ; dis_num_inst < insts_to_add && 966 dis_num_inst < dispatchWidth; 967 ++dis_num_inst) 968 { 969 inst = insts_to_dispatch.front(); 970 971 if (dispatchStatus[tid] == Unblocking) { 972 DPRINTF(IEW, "[tid:%i]: Issue: Examining instruction from skid " 973 "buffer\n", tid); 974 } 975 976 // Make sure there's a valid instruction there. 977 assert(inst); 978 979 DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %s [sn:%lli] [tid:%i] to " 980 "IQ.\n", 981 tid, inst->pcState(), inst->seqNum, inst->threadNumber); 982 983 // Be sure to mark these instructions as ready so that the 984 // commit stage can go ahead and execute them, and mark 985 // them as issued so the IQ doesn't reprocess them. 986 987 // Check for squashed instructions. 988 if (inst->isSquashed()) { 989 DPRINTF(IEW, "[tid:%i]: Issue: Squashed instruction encountered, " 990 "not adding to IQ.\n", tid); 991 992 ++iewDispSquashedInsts; 993 994 insts_to_dispatch.pop(); 995 996 //Tell Rename That An Instruction has been processed 997 if (inst->isLoad()) { 998 toRename->iewInfo[tid].dispatchedToLQ++; 999 } 1000 if (inst->isStore()) { 1001 toRename->iewInfo[tid].dispatchedToSQ++; 1002 } 1003 1004 toRename->iewInfo[tid].dispatched++; 1005 1006 continue; 1007 } 1008 1009 // Check for full conditions. 1010 if (instQueue.isFull(tid)) { 1011 DPRINTF(IEW, "[tid:%i]: Issue: IQ has become full.\n", tid); 1012 1013 // Call function to start blocking. 1014 block(tid); 1015 1016 // Set unblock to false. Special case where we are using 1017 // skidbuffer (unblocking) instructions but then we still 1018 // get full in the IQ. 1019 toRename->iewUnblock[tid] = false; 1020 1021 ++iewIQFullEvents; 1022 break; 1023 } 1024 1025 // Check LSQ if inst is LD/ST 1026 if ((inst->isLoad() && ldstQueue.lqFull(tid)) || 1027 (inst->isStore() && ldstQueue.sqFull(tid))) { 1028 DPRINTF(IEW, "[tid:%i]: Issue: %s has become full.\n",tid, 1029 inst->isLoad() ? "LQ" : "SQ"); 1030 1031 // Call function to start blocking. 1032 block(tid); 1033 1034 // Set unblock to false. Special case where we are using 1035 // skidbuffer (unblocking) instructions but then we still 1036 // get full in the IQ. 1037 toRename->iewUnblock[tid] = false; 1038 1039 ++iewLSQFullEvents; 1040 break; 1041 } 1042 1043 // Otherwise issue the instruction just fine. 1044 if (inst->isLoad()) { 1045 DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction " 1046 "encountered, adding to LSQ.\n", tid); 1047 1048 // Reserve a spot in the load store queue for this 1049 // memory access. 1050 ldstQueue.insertLoad(inst); 1051 1052 ++iewDispLoadInsts; 1053 1054 add_to_iq = true; 1055 1056 toRename->iewInfo[tid].dispatchedToLQ++; 1057 } else if (inst->isStore()) { 1058 DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction " 1059 "encountered, adding to LSQ.\n", tid); 1060 1061 ldstQueue.insertStore(inst); 1062 1063 ++iewDispStoreInsts; 1064 1065 if (inst->isStoreConditional()) { 1066 // Store conditionals need to be set as "canCommit()" 1067 // so that commit can process them when they reach the 1068 // head of commit. 1069 // @todo: This is somewhat specific to Alpha. 1070 inst->setCanCommit(); 1071 instQueue.insertNonSpec(inst); 1072 add_to_iq = false; 1073 1074 ++iewDispNonSpecInsts; 1075 } else { 1076 add_to_iq = true; 1077 } 1078 1079 toRename->iewInfo[tid].dispatchedToSQ++; 1080 } else if (inst->isMemBarrier() || inst->isWriteBarrier()) { 1081 // Same as non-speculative stores. 1082 inst->setCanCommit(); 1083 instQueue.insertBarrier(inst); 1084 add_to_iq = false; 1085 } else if (inst->isNop()) { 1086 DPRINTF(IEW, "[tid:%i]: Issue: Nop instruction encountered, " 1087 "skipping.\n", tid); 1088 1089 inst->setIssued(); 1090 inst->setExecuted(); 1091 inst->setCanCommit(); 1092 1093 instQueue.recordProducer(inst); 1094 1095 iewExecutedNop[tid]++; 1096 1097 add_to_iq = false; 1098 } else { 1099 assert(!inst->isExecuted()); 1100 add_to_iq = true; 1101 } 1102 1103 if (inst->isNonSpeculative()) { 1104 DPRINTF(IEW, "[tid:%i]: Issue: Nonspeculative instruction " 1105 "encountered, skipping.\n", tid); 1106 1107 // Same as non-speculative stores. 1108 inst->setCanCommit(); 1109 1110 // Specifically insert it as nonspeculative. 1111 instQueue.insertNonSpec(inst); 1112 1113 ++iewDispNonSpecInsts; 1114 1115 add_to_iq = false; 1116 } 1117 1118 // If the instruction queue is not full, then add the 1119 // instruction. 1120 if (add_to_iq) { 1121 instQueue.insert(inst); 1122 } 1123 1124 insts_to_dispatch.pop(); 1125 1126 toRename->iewInfo[tid].dispatched++; 1127 1128 ++iewDispatchedInsts; 1129 1130#if TRACING_ON 1131 inst->dispatchTick = curTick() - inst->fetchTick; 1132#endif 1133 ppDispatch->notify(inst); 1134 } 1135 1136 if (!insts_to_dispatch.empty()) { 1137 DPRINTF(IEW,"[tid:%i]: Issue: Bandwidth Full. Blocking.\n", tid); 1138 block(tid); 1139 toRename->iewUnblock[tid] = false; 1140 } 1141 1142 if (dispatchStatus[tid] == Idle && dis_num_inst) { 1143 dispatchStatus[tid] = Running; 1144 1145 updatedQueues = true; 1146 } 1147 1148 dis_num_inst = 0; 1149} 1150 1151template <class Impl> 1152void 1153DefaultIEW<Impl>::printAvailableInsts() 1154{ 1155 int inst = 0; 1156 1157 std::cout << "Available Instructions: "; 1158 1159 while (fromIssue->insts[inst]) { 1160 1161 if (inst%3==0) std::cout << "\n\t"; 1162 1163 std::cout << "PC: " << fromIssue->insts[inst]->pcState() 1164 << " TN: " << fromIssue->insts[inst]->threadNumber 1165 << " SN: " << fromIssue->insts[inst]->seqNum << " | "; 1166 1167 inst++; 1168 1169 } 1170 1171 std::cout << "\n"; 1172} 1173 1174template <class Impl> 1175void 1176DefaultIEW<Impl>::executeInsts() 1177{ 1178 wbNumInst = 0; 1179 wbCycle = 0; 1180 1181 list<ThreadID>::iterator threads = activeThreads->begin(); 1182 list<ThreadID>::iterator end = activeThreads->end(); 1183 1184 while (threads != end) { 1185 ThreadID tid = *threads++; 1186 fetchRedirect[tid] = false; 1187 } 1188 1189 // Uncomment this if you want to see all available instructions. 1190 // @todo This doesn't actually work anymore, we should fix it. 1191// printAvailableInsts(); 1192 1193 // Execute/writeback any instructions that are available. 1194 int insts_to_execute = fromIssue->size; 1195 int inst_num = 0; 1196 for (; inst_num < insts_to_execute; 1197 ++inst_num) { 1198 1199 DPRINTF(IEW, "Execute: Executing instructions from IQ.\n"); 1200 1201 DynInstPtr inst = instQueue.getInstToExecute(); 1202 1203 DPRINTF(IEW, "Execute: Processing PC %s, [tid:%i] [sn:%i].\n", 1204 inst->pcState(), inst->threadNumber,inst->seqNum); 1205 1206 // Notify potential listeners that this instruction has started 1207 // executing 1208 ppExecute->notify(inst); 1209 1210 // Check if the instruction is squashed; if so then skip it 1211 if (inst->isSquashed()) { 1212 DPRINTF(IEW, "Execute: Instruction was squashed. PC: %s, [tid:%i]" 1213 " [sn:%i]\n", inst->pcState(), inst->threadNumber, 1214 inst->seqNum); 1215 1216 // Consider this instruction executed so that commit can go 1217 // ahead and retire the instruction. 1218 inst->setExecuted(); 1219 1220 // Not sure if I should set this here or just let commit try to 1221 // commit any squashed instructions. I like the latter a bit more. 1222 inst->setCanCommit(); 1223 1224 ++iewExecSquashedInsts; 1225 1226 continue; 1227 } 1228 1229 Fault fault = NoFault; 1230 1231 // Execute instruction. 1232 // Note that if the instruction faults, it will be handled 1233 // at the commit stage. 1234 if (inst->isMemRef()) { 1235 DPRINTF(IEW, "Execute: Calculating address for memory " 1236 "reference.\n"); 1237 1238 // Tell the LDSTQ to execute this instruction (if it is a load). 1239 if (inst->isLoad()) { 1240 // Loads will mark themselves as executed, and their writeback 1241 // event adds the instruction to the queue to commit 1242 fault = ldstQueue.executeLoad(inst); 1243 1244 if (inst->isTranslationDelayed() && 1245 fault == NoFault) { 1246 // A hw page table walk is currently going on; the 1247 // instruction must be deferred. 1248 DPRINTF(IEW, "Execute: Delayed translation, deferring " 1249 "load.\n"); 1250 instQueue.deferMemInst(inst); 1251 continue; 1252 } 1253 1254 if (inst->isDataPrefetch() || inst->isInstPrefetch()) { 1255 inst->fault = NoFault; 1256 } 1257 } else if (inst->isStore()) { 1258 fault = ldstQueue.executeStore(inst); 1259 1260 if (inst->isTranslationDelayed() && 1261 fault == NoFault) { 1262 // A hw page table walk is currently going on; the 1263 // instruction must be deferred. 1264 DPRINTF(IEW, "Execute: Delayed translation, deferring " 1265 "store.\n"); 1266 instQueue.deferMemInst(inst); 1267 continue; 1268 } 1269 1270 // If the store had a fault then it may not have a mem req 1271 if (fault != NoFault || !inst->readPredicate() || 1272 !inst->isStoreConditional()) { 1273 // If the instruction faulted, then we need to send it along 1274 // to commit without the instruction completing. 1275 // Send this instruction to commit, also make sure iew stage 1276 // realizes there is activity. 1277 inst->setExecuted(); 1278 instToCommit(inst); 1279 activityThisCycle(); 1280 } 1281 1282 // Store conditionals will mark themselves as 1283 // executed, and their writeback event will add the 1284 // instruction to the queue to commit. 1285 } else { 1286 panic("Unexpected memory type!\n"); 1287 } 1288 1289 } else { 1290 // If the instruction has already faulted, then skip executing it. 1291 // Such case can happen when it faulted during ITLB translation. 1292 // If we execute the instruction (even if it's a nop) the fault 1293 // will be replaced and we will lose it. 1294 if (inst->getFault() == NoFault) { 1295 inst->execute(); 1296 if (!inst->readPredicate()) 1297 inst->forwardOldRegs(); 1298 } 1299 1300 inst->setExecuted(); 1301 1302 instToCommit(inst); 1303 } 1304 1305 updateExeInstStats(inst); 1306 1307 // Check if branch prediction was correct, if not then we need 1308 // to tell commit to squash in flight instructions. Only 1309 // handle this if there hasn't already been something that 1310 // redirects fetch in this group of instructions. 1311 1312 // This probably needs to prioritize the redirects if a different 1313 // scheduler is used. Currently the scheduler schedules the oldest 1314 // instruction first, so the branch resolution order will be correct. 1315 ThreadID tid = inst->threadNumber; 1316 1317 if (!fetchRedirect[tid] || 1318 !toCommit->squash[tid] || 1319 toCommit->squashedSeqNum[tid] > inst->seqNum) { 1320 1321 // Prevent testing for misprediction on load instructions, 1322 // that have not been executed. 1323 bool loadNotExecuted = !inst->isExecuted() && inst->isLoad(); 1324 1325 if (inst->mispredicted() && !loadNotExecuted) { 1326 fetchRedirect[tid] = true; 1327 1328 DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); 1329 DPRINTF(IEW, "Predicted target was PC: %s.\n", 1330 inst->readPredTarg()); 1331 DPRINTF(IEW, "Execute: Redirecting fetch to PC: %s.\n", 1332 inst->pcState()); 1333 // If incorrect, then signal the ROB that it must be squashed. 1334 squashDueToBranch(inst, tid); 1335 1336 ppMispredict->notify(inst); 1337 1338 if (inst->readPredTaken()) { 1339 predictedTakenIncorrect++; 1340 } else { 1341 predictedNotTakenIncorrect++; 1342 } 1343 } else if (ldstQueue.violation(tid)) { 1344 assert(inst->isMemRef()); 1345 // If there was an ordering violation, then get the 1346 // DynInst that caused the violation. Note that this 1347 // clears the violation signal. 1348 DynInstPtr violator; 1349 violator = ldstQueue.getMemDepViolator(tid); 1350 1351 DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: %s " 1352 "[sn:%lli], inst PC: %s [sn:%lli]. Addr is: %#x.\n", 1353 violator->pcState(), violator->seqNum, 1354 inst->pcState(), inst->seqNum, inst->physEffAddrLow); 1355 1356 fetchRedirect[tid] = true; 1357 1358 // Tell the instruction queue that a violation has occured. 1359 instQueue.violation(inst, violator); 1360 1361 // Squash. 1362 squashDueToMemOrder(violator, tid); 1363 1364 ++memOrderViolationEvents; 1365 } 1366 } else { 1367 // Reset any state associated with redirects that will not 1368 // be used. 1369 if (ldstQueue.violation(tid)) { 1370 assert(inst->isMemRef()); 1371 1372 DynInstPtr violator = ldstQueue.getMemDepViolator(tid); 1373 1374 DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: " 1375 "%s, inst PC: %s. Addr is: %#x.\n", 1376 violator->pcState(), inst->pcState(), 1377 inst->physEffAddrLow); 1378 DPRINTF(IEW, "Violation will not be handled because " 1379 "already squashing\n"); 1380 1381 ++memOrderViolationEvents; 1382 } 1383 } 1384 } 1385 1386 // Update and record activity if we processed any instructions. 1387 if (inst_num) { 1388 if (exeStatus == Idle) { 1389 exeStatus = Running; 1390 } 1391 1392 updatedQueues = true; 1393 1394 cpu->activityThisCycle(); 1395 } 1396 1397 // Need to reset this in case a writeback event needs to write into the 1398 // iew queue. That way the writeback event will write into the correct 1399 // spot in the queue. 1400 wbNumInst = 0; 1401 1402} 1403 1404template <class Impl> 1405void 1406DefaultIEW<Impl>::writebackInsts() 1407{ 1408 // Loop through the head of the time buffer and wake any 1409 // dependents. These instructions are about to write back. Also 1410 // mark scoreboard that this instruction is finally complete. 1411 // Either have IEW have direct access to scoreboard, or have this 1412 // as part of backwards communication. 1413 for (int inst_num = 0; inst_num < wbWidth && 1414 toCommit->insts[inst_num]; inst_num++) { 1415 DynInstPtr inst = toCommit->insts[inst_num]; 1416 ThreadID tid = inst->threadNumber; 1417 1418 DPRINTF(IEW, "Sending instructions to commit, [sn:%lli] PC %s.\n", 1419 inst->seqNum, inst->pcState()); 1420 1421 iewInstsToCommit[tid]++; 1422 // Notify potential listeners that execution is complete for this 1423 // instruction. 1424 ppToCommit->notify(inst); 1425 1426 // Some instructions will be sent to commit without having 1427 // executed because they need commit to handle them. 1428 // E.g. Strictly ordered loads have not actually executed when they 1429 // are first sent to commit. Instead commit must tell the LSQ 1430 // when it's ready to execute the strictly ordered load. 1431 if (!inst->isSquashed() && inst->isExecuted() && inst->getFault() == NoFault) { 1432 int dependents = instQueue.wakeDependents(inst); 1433 1434 for (int i = 0; i < inst->numDestRegs(); i++) { 1435 //mark as Ready 1436 DPRINTF(IEW,"Setting Destination Register %i (%s)\n", 1437 inst->renamedDestRegIdx(i)->index(), 1438 inst->renamedDestRegIdx(i)->className()); 1439 scoreboard->setReg(inst->renamedDestRegIdx(i)); 1440 } 1441 1442 if (dependents) { 1443 producerInst[tid]++; 1444 consumerInst[tid]+= dependents; 1445 } 1446 writebackCount[tid]++; 1447 } 1448 } 1449} 1450 1451template<class Impl> 1452void 1453DefaultIEW<Impl>::tick() 1454{ 1455 wbNumInst = 0; 1456 wbCycle = 0; 1457 1458 wroteToTimeBuffer = false; 1459 updatedQueues = false; 1460 1461 sortInsts(); 1462 1463 // Free function units marked as being freed this cycle. 1464 fuPool->processFreeUnits(); 1465 1466 list<ThreadID>::iterator threads = activeThreads->begin(); 1467 list<ThreadID>::iterator end = activeThreads->end(); 1468 1469 // Check stall and squash signals, dispatch any instructions. 1470 while (threads != end) { 1471 ThreadID tid = *threads++; 1472 1473 DPRINTF(IEW,"Issue: Processing [tid:%i]\n",tid); 1474 1475 checkSignalsAndUpdate(tid); 1476 dispatch(tid); 1477 } 1478 1479 if (exeStatus != Squashing) { 1480 executeInsts(); 1481 1482 writebackInsts(); 1483 1484 // Have the instruction queue try to schedule any ready instructions. 1485 // (In actuality, this scheduling is for instructions that will 1486 // be executed next cycle.) 1487 instQueue.scheduleReadyInsts(); 1488 1489 // Also should advance its own time buffers if the stage ran. 1490 // Not the best place for it, but this works (hopefully). 1491 issueToExecQueue.advance(); 1492 } 1493 1494 bool broadcast_free_entries = false; 1495 1496 if (updatedQueues || exeStatus == Running || updateLSQNextCycle) { 1497 exeStatus = Idle; 1498 updateLSQNextCycle = false; 1499 1500 broadcast_free_entries = true; 1501 } 1502 1503 // Writeback any stores using any leftover bandwidth. 1504 ldstQueue.writebackStores(); 1505 1506 // Check the committed load/store signals to see if there's a load 1507 // or store to commit. Also check if it's being told to execute a 1508 // nonspeculative instruction. 1509 // This is pretty inefficient... 1510 1511 threads = activeThreads->begin(); 1512 while (threads != end) { 1513 ThreadID tid = (*threads++); 1514 1515 DPRINTF(IEW,"Processing [tid:%i]\n",tid); 1516 1517 // Update structures based on instructions committed. 1518 if (fromCommit->commitInfo[tid].doneSeqNum != 0 && 1519 !fromCommit->commitInfo[tid].squash && 1520 !fromCommit->commitInfo[tid].robSquashing) { 1521 1522 ldstQueue.commitStores(fromCommit->commitInfo[tid].doneSeqNum,tid); 1523 1524 ldstQueue.commitLoads(fromCommit->commitInfo[tid].doneSeqNum,tid); 1525 1526 updateLSQNextCycle = true; 1527 instQueue.commit(fromCommit->commitInfo[tid].doneSeqNum,tid); 1528 } 1529 1530 if (fromCommit->commitInfo[tid].nonSpecSeqNum != 0) { 1531 1532 //DPRINTF(IEW,"NonspecInst from thread %i",tid); 1533 if (fromCommit->commitInfo[tid].strictlyOrdered) { 1534 instQueue.replayMemInst( 1535 fromCommit->commitInfo[tid].strictlyOrderedLoad); 1536 fromCommit->commitInfo[tid].strictlyOrderedLoad->setAtCommit(); 1537 } else { 1538 instQueue.scheduleNonSpec( 1539 fromCommit->commitInfo[tid].nonSpecSeqNum); 1540 } 1541 } 1542 1543 if (broadcast_free_entries) { 1544 toFetch->iewInfo[tid].iqCount = 1545 instQueue.getCount(tid); 1546 toFetch->iewInfo[tid].ldstqCount = 1547 ldstQueue.getCount(tid); 1548 1549 toRename->iewInfo[tid].usedIQ = true; 1550 toRename->iewInfo[tid].freeIQEntries = 1551 instQueue.numFreeEntries(tid); 1552 toRename->iewInfo[tid].usedLSQ = true; 1553 1554 toRename->iewInfo[tid].freeLQEntries = 1555 ldstQueue.numFreeLoadEntries(tid); 1556 toRename->iewInfo[tid].freeSQEntries = 1557 ldstQueue.numFreeStoreEntries(tid); 1558 1559 wroteToTimeBuffer = true; 1560 } 1561 1562 DPRINTF(IEW, "[tid:%i], Dispatch dispatched %i instructions.\n", 1563 tid, toRename->iewInfo[tid].dispatched); 1564 } 1565 1566 DPRINTF(IEW, "IQ has %i free entries (Can schedule: %i). " 1567 "LQ has %i free entries. SQ has %i free entries.\n", 1568 instQueue.numFreeEntries(), instQueue.hasReadyInsts(), 1569 ldstQueue.numFreeLoadEntries(), ldstQueue.numFreeStoreEntries()); 1570 1571 updateStatus(); 1572 1573 if (wroteToTimeBuffer) { 1574 DPRINTF(Activity, "Activity this cycle.\n"); 1575 cpu->activityThisCycle(); 1576 } 1577} 1578 1579template <class Impl> 1580void 1581DefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst) 1582{ 1583 ThreadID tid = inst->threadNumber; 1584 1585 iewExecutedInsts++; 1586 1587#if TRACING_ON 1588 if (DTRACE(O3PipeView)) { 1589 inst->completeTick = curTick() - inst->fetchTick; 1590 } 1591#endif 1592 1593 // 1594 // Control operations 1595 // 1596 if (inst->isControl()) 1597 iewExecutedBranches[tid]++; 1598 1599 // 1600 // Memory operations 1601 // 1602 if (inst->isMemRef()) { 1603 iewExecutedRefs[tid]++; 1604 1605 if (inst->isLoad()) { 1606 iewExecLoadInsts[tid]++; 1607 } 1608 } 1609} 1610 1611template <class Impl> 1612void 1613DefaultIEW<Impl>::checkMisprediction(DynInstPtr &inst) 1614{ 1615 ThreadID tid = inst->threadNumber; 1616 1617 if (!fetchRedirect[tid] || 1618 !toCommit->squash[tid] || 1619 toCommit->squashedSeqNum[tid] > inst->seqNum) { 1620 1621 if (inst->mispredicted()) { 1622 fetchRedirect[tid] = true; 1623 1624 DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); 1625 DPRINTF(IEW, "Predicted target was PC:%#x, NPC:%#x.\n", 1626 inst->predInstAddr(), inst->predNextInstAddr()); 1627 DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x," 1628 " NPC: %#x.\n", inst->nextInstAddr(), 1629 inst->nextInstAddr()); 1630 // If incorrect, then signal the ROB that it must be squashed. 1631 squashDueToBranch(inst, tid); 1632 1633 if (inst->readPredTaken()) { 1634 predictedTakenIncorrect++; 1635 } else { 1636 predictedNotTakenIncorrect++; 1637 } 1638 } 1639 } 1640} 1641 1642#endif//__CPU_O3_IEW_IMPL_IMPL_HH__ 1643