iew_impl.hh revision 7851:bb38f0c47ade
12391SN/A/* 28931Sandreas.hansson@arm.com * Copyright (c) 2010 ARM Limited 37733SAli.Saidi@ARM.com * All rights reserved. 47733SAli.Saidi@ARM.com * 57733SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall 67733SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual 77733SAli.Saidi@ARM.com * property including but not limited to intellectual property relating 87733SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software 97733SAli.Saidi@ARM.com * licensed hereunder. You may use the software subject to the license 107733SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated 117733SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software, 127733SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form. 137733SAli.Saidi@ARM.com * 142391SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan 152391SN/A * All rights reserved. 162391SN/A * 172391SN/A * Redistribution and use in source and binary forms, with or without 182391SN/A * modification, are permitted provided that the following conditions are 192391SN/A * met: redistributions of source code must retain the above copyright 202391SN/A * notice, this list of conditions and the following disclaimer; 212391SN/A * redistributions in binary form must reproduce the above copyright 222391SN/A * notice, this list of conditions and the following disclaimer in the 232391SN/A * documentation and/or other materials provided with the distribution; 242391SN/A * neither the name of the copyright holders nor the names of its 252391SN/A * contributors may be used to endorse or promote products derived from 262391SN/A * this software without specific prior written permission. 272391SN/A * 282391SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292391SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302391SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 312391SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 322391SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332391SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 342391SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 352391SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362665Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 378931Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 382391SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392391SN/A * 409293Sandreas.hansson@arm.com * Authors: Kevin Lim 419293Sandreas.hansson@arm.com */ 429293Sandreas.hansson@arm.com 439293Sandreas.hansson@arm.com// @todo: Fix the instantaneous communication among all the stages within 449293Sandreas.hansson@arm.com// iew. There's a clear delay between issue and execute, yet backwards 459293Sandreas.hansson@arm.com// communication happens simultaneously. 469293Sandreas.hansson@arm.com 479293Sandreas.hansson@arm.com#include <queue> 489293Sandreas.hansson@arm.com 499293Sandreas.hansson@arm.com#include "cpu/timebuf.hh" 509293Sandreas.hansson@arm.com#include "config/the_isa.hh" 519293Sandreas.hansson@arm.com#include "cpu/o3/fu_pool.hh" 529293Sandreas.hansson@arm.com#include "cpu/o3/iew.hh" 539356Snilay@cs.wisc.edu#include "params/DerivO3CPU.hh" 548931Sandreas.hansson@arm.com 559293Sandreas.hansson@arm.comusing namespace std; 569293Sandreas.hansson@arm.com 572394SN/Atemplate<class Impl> 582394SN/ADefaultIEW<Impl>::DefaultIEW(O3CPU *_cpu, DerivO3CPUParams *params) 592391SN/A : issueToExecQueue(params->backComSize, params->forwardComSize), 602391SN/A cpu(_cpu), 619293Sandreas.hansson@arm.com instQueue(_cpu, this, params), 629293Sandreas.hansson@arm.com ldstQueue(_cpu, this, params), 639293Sandreas.hansson@arm.com fuPool(params->fuPool), 642391SN/A commitToIEWDelay(params->commitToIEWDelay), 659293Sandreas.hansson@arm.com renameToIEWDelay(params->renameToIEWDelay), 669293Sandreas.hansson@arm.com issueToExecuteDelay(params->issueToExecuteDelay), 678931Sandreas.hansson@arm.com dispatchWidth(params->dispatchWidth), 688931Sandreas.hansson@arm.com issueWidth(params->issueWidth), 698931Sandreas.hansson@arm.com wbOutstanding(0), 708931Sandreas.hansson@arm.com wbWidth(params->wbWidth), 718931Sandreas.hansson@arm.com numThreads(params->numThreads), 722391SN/A switchedOut(false) 738931Sandreas.hansson@arm.com{ 748931Sandreas.hansson@arm.com _status = Active; 758931Sandreas.hansson@arm.com exeStatus = Running; 768931Sandreas.hansson@arm.com wbStatus = Idle; 778931Sandreas.hansson@arm.com 788931Sandreas.hansson@arm.com // Setup wire to read instructions coming from issue. 798931Sandreas.hansson@arm.com fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay); 808931Sandreas.hansson@arm.com 819293Sandreas.hansson@arm.com // Instruction queue needs the queue between issue and execute. 829293Sandreas.hansson@arm.com instQueue.setIssueToExecuteQueue(&issueToExecQueue); 839293Sandreas.hansson@arm.com 849293Sandreas.hansson@arm.com for (ThreadID tid = 0; tid < numThreads; tid++) { 859293Sandreas.hansson@arm.com dispatchStatus[tid] = Running; 869293Sandreas.hansson@arm.com stalls[tid].commit = false; 879293Sandreas.hansson@arm.com fetchRedirect[tid] = false; 889293Sandreas.hansson@arm.com } 899293Sandreas.hansson@arm.com 909293Sandreas.hansson@arm.com wbMax = wbWidth * params->wbDepth; 919293Sandreas.hansson@arm.com 929293Sandreas.hansson@arm.com updateLSQNextCycle = false; 939293Sandreas.hansson@arm.com 949293Sandreas.hansson@arm.com ableToIssue = true; 958931Sandreas.hansson@arm.com 969293Sandreas.hansson@arm.com skidBufferMax = (3 * (renameToIEWDelay * params->renameWidth)) + issueWidth; 979293Sandreas.hansson@arm.com} 9810070Sandreas.hansson@arm.com 9910070Sandreas.hansson@arm.comtemplate <class Impl> 10010070Sandreas.hansson@arm.comstd::string 1019565Sandreas.hansson@arm.comDefaultIEW<Impl>::name() const 1029293Sandreas.hansson@arm.com{ 1039293Sandreas.hansson@arm.com return cpu->name() + ".iew"; 1049293Sandreas.hansson@arm.com} 1059293Sandreas.hansson@arm.com 1069293Sandreas.hansson@arm.comtemplate <class Impl> 1079293Sandreas.hansson@arm.comvoid 1089565Sandreas.hansson@arm.comDefaultIEW<Impl>::regStats() 1099565Sandreas.hansson@arm.com{ 1109565Sandreas.hansson@arm.com using namespace Stats; 1119565Sandreas.hansson@arm.com 1129565Sandreas.hansson@arm.com instQueue.regStats(); 1139565Sandreas.hansson@arm.com ldstQueue.regStats(); 1149565Sandreas.hansson@arm.com 1159565Sandreas.hansson@arm.com iewIdleCycles 1169565Sandreas.hansson@arm.com .name(name() + ".iewIdleCycles") 1179565Sandreas.hansson@arm.com .desc("Number of cycles IEW is idle"); 1189565Sandreas.hansson@arm.com 1199565Sandreas.hansson@arm.com iewSquashCycles 1209565Sandreas.hansson@arm.com .name(name() + ".iewSquashCycles") 1219565Sandreas.hansson@arm.com .desc("Number of cycles IEW is squashing"); 1229565Sandreas.hansson@arm.com 1239565Sandreas.hansson@arm.com iewBlockCycles 1249565Sandreas.hansson@arm.com .name(name() + ".iewBlockCycles") 1259565Sandreas.hansson@arm.com .desc("Number of cycles IEW is blocking"); 1269565Sandreas.hansson@arm.com 1279293Sandreas.hansson@arm.com iewUnblockCycles 1289293Sandreas.hansson@arm.com .name(name() + ".iewUnblockCycles") 1299565Sandreas.hansson@arm.com .desc("Number of cycles IEW is unblocking"); 1309565Sandreas.hansson@arm.com 1319565Sandreas.hansson@arm.com iewDispatchedInsts 1329565Sandreas.hansson@arm.com .name(name() + ".iewDispatchedInsts") 1339565Sandreas.hansson@arm.com .desc("Number of instructions dispatched to IQ"); 1349565Sandreas.hansson@arm.com 1359565Sandreas.hansson@arm.com iewDispSquashedInsts 1369293Sandreas.hansson@arm.com .name(name() + ".iewDispSquashedInsts") 1379293Sandreas.hansson@arm.com .desc("Number of squashed instructions skipped by dispatch"); 1389293Sandreas.hansson@arm.com 1399293Sandreas.hansson@arm.com iewDispLoadInsts 1409293Sandreas.hansson@arm.com .name(name() + ".iewDispLoadInsts") 1419293Sandreas.hansson@arm.com .desc("Number of dispatched load instructions"); 1429411Sandreas.hansson@arm.com 1439411Sandreas.hansson@arm.com iewDispStoreInsts 1449411Sandreas.hansson@arm.com .name(name() + ".iewDispStoreInsts") 1459411Sandreas.hansson@arm.com .desc("Number of dispatched store instructions"); 1469293Sandreas.hansson@arm.com 1479411Sandreas.hansson@arm.com iewDispNonSpecInsts 1489411Sandreas.hansson@arm.com .name(name() + ".iewDispNonSpecInsts") 1499293Sandreas.hansson@arm.com .desc("Number of dispatched non-speculative instructions"); 1509293Sandreas.hansson@arm.com 1519293Sandreas.hansson@arm.com iewIQFullEvents 1529293Sandreas.hansson@arm.com .name(name() + ".iewIQFullEvents") 1539293Sandreas.hansson@arm.com .desc("Number of times the IQ has become full, causing a stall"); 1549293Sandreas.hansson@arm.com 1559293Sandreas.hansson@arm.com iewLSQFullEvents 1569405Sandreas.hansson@arm.com .name(name() + ".iewLSQFullEvents") 1579405Sandreas.hansson@arm.com .desc("Number of times the LSQ has become full, causing a stall"); 1589293Sandreas.hansson@arm.com 1599293Sandreas.hansson@arm.com memOrderViolationEvents 1609293Sandreas.hansson@arm.com .name(name() + ".memOrderViolationEvents") 1619293Sandreas.hansson@arm.com .desc("Number of memory order violations"); 1629293Sandreas.hansson@arm.com 1639293Sandreas.hansson@arm.com predictedTakenIncorrect 16410070Sandreas.hansson@arm.com .name(name() + ".predictedTakenIncorrect") 1659293Sandreas.hansson@arm.com .desc("Number of branches that were predicted taken incorrectly"); 1669293Sandreas.hansson@arm.com 1679293Sandreas.hansson@arm.com predictedNotTakenIncorrect 1688931Sandreas.hansson@arm.com .name(name() + ".predictedNotTakenIncorrect") 1699293Sandreas.hansson@arm.com .desc("Number of branches that were predicted not taken incorrectly"); 1708931Sandreas.hansson@arm.com 1718931Sandreas.hansson@arm.com branchMispredicts 1728931Sandreas.hansson@arm.com .name(name() + ".branchMispredicts") 1739293Sandreas.hansson@arm.com .desc("Number of branch mispredicts detected at execute"); 1749293Sandreas.hansson@arm.com 1759293Sandreas.hansson@arm.com branchMispredicts = predictedTakenIncorrect + predictedNotTakenIncorrect; 1769293Sandreas.hansson@arm.com 1779293Sandreas.hansson@arm.com iewExecutedInsts 1789293Sandreas.hansson@arm.com .name(name() + ".iewExecutedInsts") 1799293Sandreas.hansson@arm.com .desc("Number of executed instructions"); 1809293Sandreas.hansson@arm.com 1818931Sandreas.hansson@arm.com iewExecLoadInsts 1828931Sandreas.hansson@arm.com .init(cpu->numThreads) 1838931Sandreas.hansson@arm.com .name(name() + ".iewExecLoadInsts") 1848931Sandreas.hansson@arm.com .desc("Number of load instructions executed") 1859405Sandreas.hansson@arm.com .flags(total); 1868931Sandreas.hansson@arm.com 1879235Sandreas.hansson@arm.com iewExecSquashedInsts 1888931Sandreas.hansson@arm.com .name(name() + ".iewExecSquashedInsts") 1898931Sandreas.hansson@arm.com .desc("Number of squashed instructions skipped in execute"); 1908931Sandreas.hansson@arm.com 1918931Sandreas.hansson@arm.com iewExecutedSwp 1928931Sandreas.hansson@arm.com .init(cpu->numThreads) 1938931Sandreas.hansson@arm.com .name(name() + ".EXEC:swp") 1948851Sandreas.hansson@arm.com .desc("number of swp insts executed") 1958851Sandreas.hansson@arm.com .flags(total); 1968931Sandreas.hansson@arm.com 1975477Snate@binkert.org iewExecutedNop 1988931Sandreas.hansson@arm.com .init(cpu->numThreads) 1998931Sandreas.hansson@arm.com .name(name() + ".EXEC:nop") 2008931Sandreas.hansson@arm.com .desc("number of nop insts executed") 2017730SAli.Saidi@ARM.com .flags(total); 2028931Sandreas.hansson@arm.com 2038931Sandreas.hansson@arm.com iewExecutedRefs 2048931Sandreas.hansson@arm.com .init(cpu->numThreads) 2058931Sandreas.hansson@arm.com .name(name() + ".EXEC:refs") 2068931Sandreas.hansson@arm.com .desc("number of memory reference insts executed") 2078931Sandreas.hansson@arm.com .flags(total); 2089413Sandreas.hansson@arm.com 2099413Sandreas.hansson@arm.com iewExecutedBranches 2109413Sandreas.hansson@arm.com .init(cpu->numThreads) 2119413Sandreas.hansson@arm.com .name(name() + ".EXEC:branches") 2129413Sandreas.hansson@arm.com .desc("Number of branches executed") 2139413Sandreas.hansson@arm.com .flags(total); 2149413Sandreas.hansson@arm.com 2159413Sandreas.hansson@arm.com iewExecStoreInsts 2169413Sandreas.hansson@arm.com .name(name() + ".EXEC:stores") 2179413Sandreas.hansson@arm.com .desc("Number of stores executed") 2189413Sandreas.hansson@arm.com .flags(total); 2199413Sandreas.hansson@arm.com iewExecStoreInsts = iewExecutedRefs - iewExecLoadInsts; 2209413Sandreas.hansson@arm.com 2219413Sandreas.hansson@arm.com iewExecRate 2229413Sandreas.hansson@arm.com .name(name() + ".EXEC:rate") 2239413Sandreas.hansson@arm.com .desc("Inst execution rate") 2249413Sandreas.hansson@arm.com .flags(total); 2259413Sandreas.hansson@arm.com 2269413Sandreas.hansson@arm.com iewExecRate = iewExecutedInsts / cpu->numCycles; 2278931Sandreas.hansson@arm.com 2287730SAli.Saidi@ARM.com iewInstsToCommit 2292391SN/A .init(cpu->numThreads) 2309413Sandreas.hansson@arm.com .name(name() + ".WB:sent") 2319413Sandreas.hansson@arm.com .desc("cumulative count of insts sent to commit") 2329413Sandreas.hansson@arm.com .flags(total); 2339413Sandreas.hansson@arm.com 2349413Sandreas.hansson@arm.com writebackCount 2359413Sandreas.hansson@arm.com .init(cpu->numThreads) 2368931Sandreas.hansson@arm.com .name(name() + ".WB:count") 2372391SN/A .desc("cumulative count of insts written-back") 2382391SN/A .flags(total); 2392541SN/A 2408931Sandreas.hansson@arm.com producerInst 2412541SN/A .init(cpu->numThreads) 2428931Sandreas.hansson@arm.com .name(name() + ".WB:producers") 2438931Sandreas.hansson@arm.com .desc("num instructions producing a value") 2449235Sandreas.hansson@arm.com .flags(total); 2458931Sandreas.hansson@arm.com 2468931Sandreas.hansson@arm.com consumerInst 2472391SN/A .init(cpu->numThreads) 2482391SN/A .name(name() + ".WB:consumers") 2498719SAli.Saidi@ARM.com .desc("num instructions consuming a value") 2508931Sandreas.hansson@arm.com .flags(total); 2518719SAli.Saidi@ARM.com 2528931Sandreas.hansson@arm.com wbPenalized 2538931Sandreas.hansson@arm.com .init(cpu->numThreads) 2549235Sandreas.hansson@arm.com .name(name() + ".WB:penalized") 2558931Sandreas.hansson@arm.com .desc("number of instrctions required to write to 'other' IQ") 2568931Sandreas.hansson@arm.com .flags(total); 2578719SAli.Saidi@ARM.com 2589293Sandreas.hansson@arm.com wbPenalizedRate 2599293Sandreas.hansson@arm.com .name(name() + ".WB:penalized_rate") 2609293Sandreas.hansson@arm.com .desc ("fraction of instructions written-back that wrote to 'other' IQ") 2619293Sandreas.hansson@arm.com .flags(total); 2629293Sandreas.hansson@arm.com 2639293Sandreas.hansson@arm.com wbPenalizedRate = wbPenalized / writebackCount; 2649293Sandreas.hansson@arm.com 2659293Sandreas.hansson@arm.com wbFanout 2669293Sandreas.hansson@arm.com .name(name() + ".WB:fanout") 2679293Sandreas.hansson@arm.com .desc("average fanout of values written-back") 2689293Sandreas.hansson@arm.com .flags(total); 2699293Sandreas.hansson@arm.com 2709293Sandreas.hansson@arm.com wbFanout = producerInst / consumerInst; 2719293Sandreas.hansson@arm.com 2729293Sandreas.hansson@arm.com wbRate 2739293Sandreas.hansson@arm.com .name(name() + ".WB:rate") 2749293Sandreas.hansson@arm.com .desc("insts written-back per cycle") 2759293Sandreas.hansson@arm.com .flags(total); 2769293Sandreas.hansson@arm.com wbRate = writebackCount / cpu->numCycles; 2779293Sandreas.hansson@arm.com} 2789293Sandreas.hansson@arm.com 2799293Sandreas.hansson@arm.comtemplate<class Impl> 2809293Sandreas.hansson@arm.comvoid 2819293Sandreas.hansson@arm.comDefaultIEW<Impl>::initStage() 2829293Sandreas.hansson@arm.com{ 2839293Sandreas.hansson@arm.com for (ThreadID tid = 0; tid < numThreads; tid++) { 2849293Sandreas.hansson@arm.com toRename->iewInfo[tid].usedIQ = true; 2859293Sandreas.hansson@arm.com toRename->iewInfo[tid].freeIQEntries = 2869293Sandreas.hansson@arm.com instQueue.numFreeEntries(tid); 2879293Sandreas.hansson@arm.com 2889293Sandreas.hansson@arm.com toRename->iewInfo[tid].usedLSQ = true; 2899293Sandreas.hansson@arm.com toRename->iewInfo[tid].freeLSQEntries = 2909293Sandreas.hansson@arm.com ldstQueue.numFreeEntries(tid); 2919293Sandreas.hansson@arm.com } 2929293Sandreas.hansson@arm.com 2939293Sandreas.hansson@arm.com cpu->activateStage(O3CPU::IEWIdx); 2949293Sandreas.hansson@arm.com} 2959293Sandreas.hansson@arm.com 2969293Sandreas.hansson@arm.comtemplate<class Impl> 2979293Sandreas.hansson@arm.comvoid 2989386Sandreas.hansson@arm.comDefaultIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 2999293Sandreas.hansson@arm.com{ 3009293Sandreas.hansson@arm.com timeBuffer = tb_ptr; 3019293Sandreas.hansson@arm.com 3029293Sandreas.hansson@arm.com // Setup wire to read information from time buffer, from commit. 3039293Sandreas.hansson@arm.com fromCommit = timeBuffer->getWire(-commitToIEWDelay); 3049293Sandreas.hansson@arm.com 3059293Sandreas.hansson@arm.com // Setup wire to write information back to previous stages. 3069293Sandreas.hansson@arm.com toRename = timeBuffer->getWire(0); 3079293Sandreas.hansson@arm.com 3089293Sandreas.hansson@arm.com toFetch = timeBuffer->getWire(0); 3099293Sandreas.hansson@arm.com 3109293Sandreas.hansson@arm.com // Instruction queue also needs main time buffer. 3119293Sandreas.hansson@arm.com instQueue.setTimeBuffer(tb_ptr); 3129293Sandreas.hansson@arm.com} 3139293Sandreas.hansson@arm.com 3149293Sandreas.hansson@arm.comtemplate<class Impl> 3159293Sandreas.hansson@arm.comvoid 3169293Sandreas.hansson@arm.comDefaultIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 3179293Sandreas.hansson@arm.com{ 3189293Sandreas.hansson@arm.com renameQueue = rq_ptr; 3199293Sandreas.hansson@arm.com 3209293Sandreas.hansson@arm.com // Setup wire to read information from rename queue. 3219293Sandreas.hansson@arm.com fromRename = renameQueue->getWire(-renameToIEWDelay); 3229293Sandreas.hansson@arm.com} 3239293Sandreas.hansson@arm.com 3249293Sandreas.hansson@arm.comtemplate<class Impl> 3259293Sandreas.hansson@arm.comvoid 3269293Sandreas.hansson@arm.comDefaultIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr) 3279293Sandreas.hansson@arm.com{ 3289293Sandreas.hansson@arm.com iewQueue = iq_ptr; 3299293Sandreas.hansson@arm.com 3309293Sandreas.hansson@arm.com // Setup wire to write instructions to commit. 3319293Sandreas.hansson@arm.com toCommit = iewQueue->getWire(0); 3329293Sandreas.hansson@arm.com} 3339293Sandreas.hansson@arm.com 3349293Sandreas.hansson@arm.comtemplate<class Impl> 3359293Sandreas.hansson@arm.comvoid 3369293Sandreas.hansson@arm.comDefaultIEW<Impl>::setActiveThreads(list<ThreadID> *at_ptr) 3379293Sandreas.hansson@arm.com{ 3389293Sandreas.hansson@arm.com activeThreads = at_ptr; 3399293Sandreas.hansson@arm.com 3409293Sandreas.hansson@arm.com ldstQueue.setActiveThreads(at_ptr); 3419293Sandreas.hansson@arm.com instQueue.setActiveThreads(at_ptr); 3429293Sandreas.hansson@arm.com} 3439293Sandreas.hansson@arm.com 3449293Sandreas.hansson@arm.comtemplate<class Impl> 3459293Sandreas.hansson@arm.comvoid 3469293Sandreas.hansson@arm.comDefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr) 3479293Sandreas.hansson@arm.com{ 3489293Sandreas.hansson@arm.com scoreboard = sb_ptr; 3499293Sandreas.hansson@arm.com} 3509293Sandreas.hansson@arm.com 3519293Sandreas.hansson@arm.comtemplate <class Impl> 3529293Sandreas.hansson@arm.combool 3539293Sandreas.hansson@arm.comDefaultIEW<Impl>::drain() 3549293Sandreas.hansson@arm.com{ 3559409Sandreas.hansson@arm.com // IEW is ready to drain at any time. 3569409Sandreas.hansson@arm.com cpu->signalDrained(); 3579293Sandreas.hansson@arm.com return true; 3589293Sandreas.hansson@arm.com} 3599293Sandreas.hansson@arm.com 3609293Sandreas.hansson@arm.comtemplate <class Impl> 3619293Sandreas.hansson@arm.comvoid 3629293Sandreas.hansson@arm.comDefaultIEW<Impl>::resume() 3639293Sandreas.hansson@arm.com{ 3649293Sandreas.hansson@arm.com} 3659293Sandreas.hansson@arm.com 3669293Sandreas.hansson@arm.comtemplate <class Impl> 3679293Sandreas.hansson@arm.comvoid 3689293Sandreas.hansson@arm.comDefaultIEW<Impl>::switchOut() 3699293Sandreas.hansson@arm.com{ 3709293Sandreas.hansson@arm.com // Clear any state. 3719293Sandreas.hansson@arm.com switchedOut = true; 3729293Sandreas.hansson@arm.com assert(insts[0].empty()); 3739293Sandreas.hansson@arm.com assert(skidBuffer[0].empty()); 3749293Sandreas.hansson@arm.com 3759293Sandreas.hansson@arm.com instQueue.switchOut(); 3769293Sandreas.hansson@arm.com ldstQueue.switchOut(); 3779293Sandreas.hansson@arm.com fuPool->switchOut(); 3789293Sandreas.hansson@arm.com 3799293Sandreas.hansson@arm.com for (ThreadID tid = 0; tid < numThreads; tid++) { 3809293Sandreas.hansson@arm.com while (!insts[tid].empty()) 3819293Sandreas.hansson@arm.com insts[tid].pop(); 3829293Sandreas.hansson@arm.com while (!skidBuffer[tid].empty()) 3839293Sandreas.hansson@arm.com skidBuffer[tid].pop(); 3849293Sandreas.hansson@arm.com } 3859293Sandreas.hansson@arm.com} 3869293Sandreas.hansson@arm.com 3879293Sandreas.hansson@arm.comtemplate <class Impl> 3889293Sandreas.hansson@arm.comvoid 3899293Sandreas.hansson@arm.comDefaultIEW<Impl>::takeOverFrom() 3909293Sandreas.hansson@arm.com{ 3919293Sandreas.hansson@arm.com // Reset all state. 3929293Sandreas.hansson@arm.com _status = Active; 3939293Sandreas.hansson@arm.com exeStatus = Running; 39410070Sandreas.hansson@arm.com wbStatus = Idle; 3959293Sandreas.hansson@arm.com switchedOut = false; 3969293Sandreas.hansson@arm.com 3979293Sandreas.hansson@arm.com instQueue.takeOverFrom(); 3989293Sandreas.hansson@arm.com ldstQueue.takeOverFrom(); 3999293Sandreas.hansson@arm.com fuPool->takeOverFrom(); 4009293Sandreas.hansson@arm.com 4019293Sandreas.hansson@arm.com initStage(); 4029293Sandreas.hansson@arm.com cpu->activityThisCycle(); 4039293Sandreas.hansson@arm.com 4049293Sandreas.hansson@arm.com for (ThreadID tid = 0; tid < numThreads; tid++) { 4059293Sandreas.hansson@arm.com dispatchStatus[tid] = Running; 4069293Sandreas.hansson@arm.com stalls[tid].commit = false; 4079293Sandreas.hansson@arm.com fetchRedirect[tid] = false; 4089293Sandreas.hansson@arm.com } 4099293Sandreas.hansson@arm.com 4109293Sandreas.hansson@arm.com updateLSQNextCycle = false; 4119293Sandreas.hansson@arm.com 4129293Sandreas.hansson@arm.com for (int i = 0; i < issueToExecQueue.getSize(); ++i) { 4139293Sandreas.hansson@arm.com issueToExecQueue.advance(); 4149293Sandreas.hansson@arm.com } 4159293Sandreas.hansson@arm.com} 4169293Sandreas.hansson@arm.com 4179293Sandreas.hansson@arm.comtemplate<class Impl> 4189293Sandreas.hansson@arm.comvoid 4199293Sandreas.hansson@arm.comDefaultIEW<Impl>::squash(ThreadID tid) 4209293Sandreas.hansson@arm.com{ 4219293Sandreas.hansson@arm.com DPRINTF(IEW, "[tid:%i]: Squashing all instructions.\n", tid); 4229293Sandreas.hansson@arm.com 4239293Sandreas.hansson@arm.com // Tell the IQ to start squashing. 4249293Sandreas.hansson@arm.com instQueue.squash(tid); 4259293Sandreas.hansson@arm.com 4269293Sandreas.hansson@arm.com // Tell the LDSTQ to start squashing. 4279293Sandreas.hansson@arm.com ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum, tid); 4289293Sandreas.hansson@arm.com updatedQueues = true; 4299293Sandreas.hansson@arm.com 4309293Sandreas.hansson@arm.com // Clear the skid buffer in case it has any data in it. 4319293Sandreas.hansson@arm.com DPRINTF(IEW, "[tid:%i]: Removing skidbuffer instructions until [sn:%i].\n", 4329293Sandreas.hansson@arm.com tid, fromCommit->commitInfo[tid].doneSeqNum); 4339293Sandreas.hansson@arm.com 4349293Sandreas.hansson@arm.com while (!skidBuffer[tid].empty()) { 4359293Sandreas.hansson@arm.com if (skidBuffer[tid].front()->isLoad() || 436 skidBuffer[tid].front()->isStore() ) { 437 toRename->iewInfo[tid].dispatchedToLSQ++; 438 } 439 440 toRename->iewInfo[tid].dispatched++; 441 442 skidBuffer[tid].pop(); 443 } 444 445 emptyRenameInsts(tid); 446} 447 448template<class Impl> 449void 450DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, ThreadID tid) 451{ 452 DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %s " 453 "[sn:%i].\n", tid, inst->pcState(), inst->seqNum); 454 455 toCommit->squash[tid] = true; 456 toCommit->squashedSeqNum[tid] = inst->seqNum; 457 toCommit->mispredPC[tid] = inst->instAddr(); 458 toCommit->branchMispredict[tid] = true; 459 toCommit->mispredictInst[tid] = inst; 460 461 toCommit->branchTaken[tid] = inst->pcState().branching(); 462 TheISA::PCState pc = inst->pcState(); 463 TheISA::advancePC(pc, inst->staticInst); 464 toCommit->pc[tid] = pc; 465 466 toCommit->includeSquashInst[tid] = false; 467 468 wroteToTimeBuffer = true; 469} 470 471template<class Impl> 472void 473DefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, ThreadID tid) 474{ 475 DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, " 476 "PC: %s [sn:%i].\n", tid, inst->pcState(), inst->seqNum); 477 478 toCommit->squash[tid] = true; 479 toCommit->squashedSeqNum[tid] = inst->seqNum; 480 TheISA::PCState pc = inst->pcState(); 481 TheISA::advancePC(pc, inst->staticInst); 482 toCommit->pc[tid] = pc; 483 toCommit->branchMispredict[tid] = false; 484 485 toCommit->includeSquashInst[tid] = false; 486 487 wroteToTimeBuffer = true; 488} 489 490template<class Impl> 491void 492DefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, ThreadID tid) 493{ 494 DPRINTF(IEW, "[tid:%i]: Memory blocked, squashing load and younger insts, " 495 "PC: %s [sn:%i].\n", tid, inst->pcState(), inst->seqNum); 496 497 toCommit->squash[tid] = true; 498 toCommit->squashedSeqNum[tid] = inst->seqNum; 499 toCommit->pc[tid] = inst->pcState(); 500 toCommit->branchMispredict[tid] = false; 501 502 // Must include the broadcasted SN in the squash. 503 toCommit->includeSquashInst[tid] = true; 504 505 ldstQueue.setLoadBlockedHandled(tid); 506 507 wroteToTimeBuffer = true; 508} 509 510template<class Impl> 511void 512DefaultIEW<Impl>::block(ThreadID tid) 513{ 514 DPRINTF(IEW, "[tid:%u]: Blocking.\n", tid); 515 516 if (dispatchStatus[tid] != Blocked && 517 dispatchStatus[tid] != Unblocking) { 518 toRename->iewBlock[tid] = true; 519 wroteToTimeBuffer = true; 520 } 521 522 // Add the current inputs to the skid buffer so they can be 523 // reprocessed when this stage unblocks. 524 skidInsert(tid); 525 526 dispatchStatus[tid] = Blocked; 527} 528 529template<class Impl> 530void 531DefaultIEW<Impl>::unblock(ThreadID tid) 532{ 533 DPRINTF(IEW, "[tid:%i]: Reading instructions out of the skid " 534 "buffer %u.\n",tid, tid); 535 536 // If the skid bufffer is empty, signal back to previous stages to unblock. 537 // Also switch status to running. 538 if (skidBuffer[tid].empty()) { 539 toRename->iewUnblock[tid] = true; 540 wroteToTimeBuffer = true; 541 DPRINTF(IEW, "[tid:%i]: Done unblocking.\n",tid); 542 dispatchStatus[tid] = Running; 543 } 544} 545 546template<class Impl> 547void 548DefaultIEW<Impl>::wakeDependents(DynInstPtr &inst) 549{ 550 instQueue.wakeDependents(inst); 551} 552 553template<class Impl> 554void 555DefaultIEW<Impl>::rescheduleMemInst(DynInstPtr &inst) 556{ 557 instQueue.rescheduleMemInst(inst); 558} 559 560template<class Impl> 561void 562DefaultIEW<Impl>::replayMemInst(DynInstPtr &inst) 563{ 564 instQueue.replayMemInst(inst); 565} 566 567template<class Impl> 568void 569DefaultIEW<Impl>::instToCommit(DynInstPtr &inst) 570{ 571 // This function should not be called after writebackInsts in a 572 // single cycle. That will cause problems with an instruction 573 // being added to the queue to commit without being processed by 574 // writebackInsts prior to being sent to commit. 575 576 // First check the time slot that this instruction will write 577 // to. If there are free write ports at the time, then go ahead 578 // and write the instruction to that time. If there are not, 579 // keep looking back to see where's the first time there's a 580 // free slot. 581 while ((*iewQueue)[wbCycle].insts[wbNumInst]) { 582 ++wbNumInst; 583 if (wbNumInst == wbWidth) { 584 ++wbCycle; 585 wbNumInst = 0; 586 } 587 588 assert((wbCycle * wbWidth + wbNumInst) <= wbMax); 589 } 590 591 DPRINTF(IEW, "Current wb cycle: %i, width: %i, numInst: %i\nwbActual:%i\n", 592 wbCycle, wbWidth, wbNumInst, wbCycle * wbWidth + wbNumInst); 593 // Add finished instruction to queue to commit. 594 (*iewQueue)[wbCycle].insts[wbNumInst] = inst; 595 (*iewQueue)[wbCycle].size++; 596} 597 598template <class Impl> 599unsigned 600DefaultIEW<Impl>::validInstsFromRename() 601{ 602 unsigned inst_count = 0; 603 604 for (int i=0; i<fromRename->size; i++) { 605 if (!fromRename->insts[i]->isSquashed()) 606 inst_count++; 607 } 608 609 return inst_count; 610} 611 612template<class Impl> 613void 614DefaultIEW<Impl>::skidInsert(ThreadID tid) 615{ 616 DynInstPtr inst = NULL; 617 618 while (!insts[tid].empty()) { 619 inst = insts[tid].front(); 620 621 insts[tid].pop(); 622 623 DPRINTF(Decode,"[tid:%i]: Inserting [sn:%lli] PC:%s into " 624 "dispatch skidBuffer %i\n",tid, inst->seqNum, 625 inst->pcState(),tid); 626 627 skidBuffer[tid].push(inst); 628 } 629 630 assert(skidBuffer[tid].size() <= skidBufferMax && 631 "Skidbuffer Exceeded Max Size"); 632} 633 634template<class Impl> 635int 636DefaultIEW<Impl>::skidCount() 637{ 638 int max=0; 639 640 list<ThreadID>::iterator threads = activeThreads->begin(); 641 list<ThreadID>::iterator end = activeThreads->end(); 642 643 while (threads != end) { 644 ThreadID tid = *threads++; 645 unsigned thread_count = skidBuffer[tid].size(); 646 if (max < thread_count) 647 max = thread_count; 648 } 649 650 return max; 651} 652 653template<class Impl> 654bool 655DefaultIEW<Impl>::skidsEmpty() 656{ 657 list<ThreadID>::iterator threads = activeThreads->begin(); 658 list<ThreadID>::iterator end = activeThreads->end(); 659 660 while (threads != end) { 661 ThreadID tid = *threads++; 662 663 if (!skidBuffer[tid].empty()) 664 return false; 665 } 666 667 return true; 668} 669 670template <class Impl> 671void 672DefaultIEW<Impl>::updateStatus() 673{ 674 bool any_unblocking = false; 675 676 list<ThreadID>::iterator threads = activeThreads->begin(); 677 list<ThreadID>::iterator end = activeThreads->end(); 678 679 while (threads != end) { 680 ThreadID tid = *threads++; 681 682 if (dispatchStatus[tid] == Unblocking) { 683 any_unblocking = true; 684 break; 685 } 686 } 687 688 // If there are no ready instructions waiting to be scheduled by the IQ, 689 // and there's no stores waiting to write back, and dispatch is not 690 // unblocking, then there is no internal activity for the IEW stage. 691 if (_status == Active && !instQueue.hasReadyInsts() && 692 !ldstQueue.willWB() && !any_unblocking) { 693 DPRINTF(IEW, "IEW switching to idle\n"); 694 695 deactivateStage(); 696 697 _status = Inactive; 698 } else if (_status == Inactive && (instQueue.hasReadyInsts() || 699 ldstQueue.willWB() || 700 any_unblocking)) { 701 // Otherwise there is internal activity. Set to active. 702 DPRINTF(IEW, "IEW switching to active\n"); 703 704 activateStage(); 705 706 _status = Active; 707 } 708} 709 710template <class Impl> 711void 712DefaultIEW<Impl>::resetEntries() 713{ 714 instQueue.resetEntries(); 715 ldstQueue.resetEntries(); 716} 717 718template <class Impl> 719void 720DefaultIEW<Impl>::readStallSignals(ThreadID tid) 721{ 722 if (fromCommit->commitBlock[tid]) { 723 stalls[tid].commit = true; 724 } 725 726 if (fromCommit->commitUnblock[tid]) { 727 assert(stalls[tid].commit); 728 stalls[tid].commit = false; 729 } 730} 731 732template <class Impl> 733bool 734DefaultIEW<Impl>::checkStall(ThreadID tid) 735{ 736 bool ret_val(false); 737 738 if (stalls[tid].commit) { 739 DPRINTF(IEW,"[tid:%i]: Stall from Commit stage detected.\n",tid); 740 ret_val = true; 741 } else if (instQueue.isFull(tid)) { 742 DPRINTF(IEW,"[tid:%i]: Stall: IQ is full.\n",tid); 743 ret_val = true; 744 } else if (ldstQueue.isFull(tid)) { 745 DPRINTF(IEW,"[tid:%i]: Stall: LSQ is full\n",tid); 746 747 if (ldstQueue.numLoads(tid) > 0 ) { 748 749 DPRINTF(IEW,"[tid:%i]: LSQ oldest load: [sn:%i] \n", 750 tid,ldstQueue.getLoadHeadSeqNum(tid)); 751 } 752 753 if (ldstQueue.numStores(tid) > 0) { 754 755 DPRINTF(IEW,"[tid:%i]: LSQ oldest store: [sn:%i] \n", 756 tid,ldstQueue.getStoreHeadSeqNum(tid)); 757 } 758 759 ret_val = true; 760 } else if (ldstQueue.isStalled(tid)) { 761 DPRINTF(IEW,"[tid:%i]: Stall: LSQ stall detected.\n",tid); 762 ret_val = true; 763 } 764 765 return ret_val; 766} 767 768template <class Impl> 769void 770DefaultIEW<Impl>::checkSignalsAndUpdate(ThreadID tid) 771{ 772 // Check if there's a squash signal, squash if there is 773 // Check stall signals, block if there is. 774 // If status was Blocked 775 // if so then go to unblocking 776 // If status was Squashing 777 // check if squashing is not high. Switch to running this cycle. 778 779 readStallSignals(tid); 780 781 if (fromCommit->commitInfo[tid].squash) { 782 squash(tid); 783 784 if (dispatchStatus[tid] == Blocked || 785 dispatchStatus[tid] == Unblocking) { 786 toRename->iewUnblock[tid] = true; 787 wroteToTimeBuffer = true; 788 } 789 790 dispatchStatus[tid] = Squashing; 791 792 fetchRedirect[tid] = false; 793 return; 794 } 795 796 if (fromCommit->commitInfo[tid].robSquashing) { 797 DPRINTF(IEW, "[tid:%i]: ROB is still squashing.\n", tid); 798 799 dispatchStatus[tid] = Squashing; 800 801 emptyRenameInsts(tid); 802 wroteToTimeBuffer = true; 803 return; 804 } 805 806 if (checkStall(tid)) { 807 block(tid); 808 dispatchStatus[tid] = Blocked; 809 return; 810 } 811 812 if (dispatchStatus[tid] == Blocked) { 813 // Status from previous cycle was blocked, but there are no more stall 814 // conditions. Switch over to unblocking. 815 DPRINTF(IEW, "[tid:%i]: Done blocking, switching to unblocking.\n", 816 tid); 817 818 dispatchStatus[tid] = Unblocking; 819 820 unblock(tid); 821 822 return; 823 } 824 825 if (dispatchStatus[tid] == Squashing) { 826 // Switch status to running if rename isn't being told to block or 827 // squash this cycle. 828 DPRINTF(IEW, "[tid:%i]: Done squashing, switching to running.\n", 829 tid); 830 831 dispatchStatus[tid] = Running; 832 833 return; 834 } 835} 836 837template <class Impl> 838void 839DefaultIEW<Impl>::sortInsts() 840{ 841 int insts_from_rename = fromRename->size; 842#ifdef DEBUG 843 for (ThreadID tid = 0; tid < numThreads; tid++) 844 assert(insts[tid].empty()); 845#endif 846 for (int i = 0; i < insts_from_rename; ++i) { 847 insts[fromRename->insts[i]->threadNumber].push(fromRename->insts[i]); 848 } 849} 850 851template <class Impl> 852void 853DefaultIEW<Impl>::emptyRenameInsts(ThreadID tid) 854{ 855 DPRINTF(IEW, "[tid:%i]: Removing incoming rename instructions\n", tid); 856 857 while (!insts[tid].empty()) { 858 859 if (insts[tid].front()->isLoad() || 860 insts[tid].front()->isStore() ) { 861 toRename->iewInfo[tid].dispatchedToLSQ++; 862 } 863 864 toRename->iewInfo[tid].dispatched++; 865 866 insts[tid].pop(); 867 } 868} 869 870template <class Impl> 871void 872DefaultIEW<Impl>::wakeCPU() 873{ 874 cpu->wakeCPU(); 875} 876 877template <class Impl> 878void 879DefaultIEW<Impl>::activityThisCycle() 880{ 881 DPRINTF(Activity, "Activity this cycle.\n"); 882 cpu->activityThisCycle(); 883} 884 885template <class Impl> 886inline void 887DefaultIEW<Impl>::activateStage() 888{ 889 DPRINTF(Activity, "Activating stage.\n"); 890 cpu->activateStage(O3CPU::IEWIdx); 891} 892 893template <class Impl> 894inline void 895DefaultIEW<Impl>::deactivateStage() 896{ 897 DPRINTF(Activity, "Deactivating stage.\n"); 898 cpu->deactivateStage(O3CPU::IEWIdx); 899} 900 901template<class Impl> 902void 903DefaultIEW<Impl>::dispatch(ThreadID tid) 904{ 905 // If status is Running or idle, 906 // call dispatchInsts() 907 // If status is Unblocking, 908 // buffer any instructions coming from rename 909 // continue trying to empty skid buffer 910 // check if stall conditions have passed 911 912 if (dispatchStatus[tid] == Blocked) { 913 ++iewBlockCycles; 914 915 } else if (dispatchStatus[tid] == Squashing) { 916 ++iewSquashCycles; 917 } 918 919 // Dispatch should try to dispatch as many instructions as its bandwidth 920 // will allow, as long as it is not currently blocked. 921 if (dispatchStatus[tid] == Running || 922 dispatchStatus[tid] == Idle) { 923 DPRINTF(IEW, "[tid:%i] Not blocked, so attempting to run " 924 "dispatch.\n", tid); 925 926 dispatchInsts(tid); 927 } else if (dispatchStatus[tid] == Unblocking) { 928 // Make sure that the skid buffer has something in it if the 929 // status is unblocking. 930 assert(!skidsEmpty()); 931 932 // If the status was unblocking, then instructions from the skid 933 // buffer were used. Remove those instructions and handle 934 // the rest of unblocking. 935 dispatchInsts(tid); 936 937 ++iewUnblockCycles; 938 939 if (validInstsFromRename()) { 940 // Add the current inputs to the skid buffer so they can be 941 // reprocessed when this stage unblocks. 942 skidInsert(tid); 943 } 944 945 unblock(tid); 946 } 947} 948 949template <class Impl> 950void 951DefaultIEW<Impl>::dispatchInsts(ThreadID tid) 952{ 953 // Obtain instructions from skid buffer if unblocking, or queue from rename 954 // otherwise. 955 std::queue<DynInstPtr> &insts_to_dispatch = 956 dispatchStatus[tid] == Unblocking ? 957 skidBuffer[tid] : insts[tid]; 958 959 int insts_to_add = insts_to_dispatch.size(); 960 961 DynInstPtr inst; 962 bool add_to_iq = false; 963 int dis_num_inst = 0; 964 965 // Loop through the instructions, putting them in the instruction 966 // queue. 967 for ( ; dis_num_inst < insts_to_add && 968 dis_num_inst < dispatchWidth; 969 ++dis_num_inst) 970 { 971 inst = insts_to_dispatch.front(); 972 973 if (dispatchStatus[tid] == Unblocking) { 974 DPRINTF(IEW, "[tid:%i]: Issue: Examining instruction from skid " 975 "buffer\n", tid); 976 } 977 978 // Make sure there's a valid instruction there. 979 assert(inst); 980 981 DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %s [sn:%lli] [tid:%i] to " 982 "IQ.\n", 983 tid, inst->pcState(), inst->seqNum, inst->threadNumber); 984 985 // Be sure to mark these instructions as ready so that the 986 // commit stage can go ahead and execute them, and mark 987 // them as issued so the IQ doesn't reprocess them. 988 989 // Check for squashed instructions. 990 if (inst->isSquashed()) { 991 DPRINTF(IEW, "[tid:%i]: Issue: Squashed instruction encountered, " 992 "not adding to IQ.\n", tid); 993 994 ++iewDispSquashedInsts; 995 996 insts_to_dispatch.pop(); 997 998 //Tell Rename That An Instruction has been processed 999 if (inst->isLoad() || inst->isStore()) { 1000 toRename->iewInfo[tid].dispatchedToLSQ++; 1001 } 1002 toRename->iewInfo[tid].dispatched++; 1003 1004 continue; 1005 } 1006 1007 // Check for full conditions. 1008 if (instQueue.isFull(tid)) { 1009 DPRINTF(IEW, "[tid:%i]: Issue: IQ has become full.\n", tid); 1010 1011 // Call function to start blocking. 1012 block(tid); 1013 1014 // Set unblock to false. Special case where we are using 1015 // skidbuffer (unblocking) instructions but then we still 1016 // get full in the IQ. 1017 toRename->iewUnblock[tid] = false; 1018 1019 ++iewIQFullEvents; 1020 break; 1021 } else if (ldstQueue.isFull(tid)) { 1022 DPRINTF(IEW, "[tid:%i]: Issue: LSQ has become full.\n",tid); 1023 1024 // Call function to start blocking. 1025 block(tid); 1026 1027 // Set unblock to false. Special case where we are using 1028 // skidbuffer (unblocking) instructions but then we still 1029 // get full in the IQ. 1030 toRename->iewUnblock[tid] = false; 1031 1032 ++iewLSQFullEvents; 1033 break; 1034 } 1035 1036 // Otherwise issue the instruction just fine. 1037 if (inst->isLoad()) { 1038 DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction " 1039 "encountered, adding to LSQ.\n", tid); 1040 1041 // Reserve a spot in the load store queue for this 1042 // memory access. 1043 ldstQueue.insertLoad(inst); 1044 1045 ++iewDispLoadInsts; 1046 1047 add_to_iq = true; 1048 1049 toRename->iewInfo[tid].dispatchedToLSQ++; 1050 } else if (inst->isStore()) { 1051 DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction " 1052 "encountered, adding to LSQ.\n", tid); 1053 1054 ldstQueue.insertStore(inst); 1055 1056 ++iewDispStoreInsts; 1057 1058 if (inst->isStoreConditional()) { 1059 // Store conditionals need to be set as "canCommit()" 1060 // so that commit can process them when they reach the 1061 // head of commit. 1062 // @todo: This is somewhat specific to Alpha. 1063 inst->setCanCommit(); 1064 instQueue.insertNonSpec(inst); 1065 add_to_iq = false; 1066 1067 ++iewDispNonSpecInsts; 1068 } else { 1069 add_to_iq = true; 1070 } 1071 1072 toRename->iewInfo[tid].dispatchedToLSQ++; 1073 } else if (inst->isMemBarrier() || inst->isWriteBarrier()) { 1074 // Same as non-speculative stores. 1075 inst->setCanCommit(); 1076 instQueue.insertBarrier(inst); 1077 add_to_iq = false; 1078 } else if (inst->isNop()) { 1079 DPRINTF(IEW, "[tid:%i]: Issue: Nop instruction encountered, " 1080 "skipping.\n", tid); 1081 1082 inst->setIssued(); 1083 inst->setExecuted(); 1084 inst->setCanCommit(); 1085 1086 instQueue.recordProducer(inst); 1087 1088 iewExecutedNop[tid]++; 1089 1090 add_to_iq = false; 1091 } else if (inst->isExecuted()) { 1092 assert(0 && "Instruction shouldn't be executed.\n"); 1093 DPRINTF(IEW, "Issue: Executed branch encountered, " 1094 "skipping.\n"); 1095 1096 inst->setIssued(); 1097 inst->setCanCommit(); 1098 1099 instQueue.recordProducer(inst); 1100 1101 add_to_iq = false; 1102 } else { 1103 add_to_iq = true; 1104 } 1105 if (inst->isNonSpeculative()) { 1106 DPRINTF(IEW, "[tid:%i]: Issue: Nonspeculative instruction " 1107 "encountered, skipping.\n", tid); 1108 1109 // Same as non-speculative stores. 1110 inst->setCanCommit(); 1111 1112 // Specifically insert it as nonspeculative. 1113 instQueue.insertNonSpec(inst); 1114 1115 ++iewDispNonSpecInsts; 1116 1117 add_to_iq = false; 1118 } 1119 1120 // If the instruction queue is not full, then add the 1121 // instruction. 1122 if (add_to_iq) { 1123 instQueue.insert(inst); 1124 } 1125 1126 insts_to_dispatch.pop(); 1127 1128 toRename->iewInfo[tid].dispatched++; 1129 1130 ++iewDispatchedInsts; 1131 } 1132 1133 if (!insts_to_dispatch.empty()) { 1134 DPRINTF(IEW,"[tid:%i]: Issue: Bandwidth Full. Blocking.\n", tid); 1135 block(tid); 1136 toRename->iewUnblock[tid] = false; 1137 } 1138 1139 if (dispatchStatus[tid] == Idle && dis_num_inst) { 1140 dispatchStatus[tid] = Running; 1141 1142 updatedQueues = true; 1143 } 1144 1145 dis_num_inst = 0; 1146} 1147 1148template <class Impl> 1149void 1150DefaultIEW<Impl>::printAvailableInsts() 1151{ 1152 int inst = 0; 1153 1154 std::cout << "Available Instructions: "; 1155 1156 while (fromIssue->insts[inst]) { 1157 1158 if (inst%3==0) std::cout << "\n\t"; 1159 1160 std::cout << "PC: " << fromIssue->insts[inst]->pcState() 1161 << " TN: " << fromIssue->insts[inst]->threadNumber 1162 << " SN: " << fromIssue->insts[inst]->seqNum << " | "; 1163 1164 inst++; 1165 1166 } 1167 1168 std::cout << "\n"; 1169} 1170 1171template <class Impl> 1172void 1173DefaultIEW<Impl>::executeInsts() 1174{ 1175 wbNumInst = 0; 1176 wbCycle = 0; 1177 1178 list<ThreadID>::iterator threads = activeThreads->begin(); 1179 list<ThreadID>::iterator end = activeThreads->end(); 1180 1181 while (threads != end) { 1182 ThreadID tid = *threads++; 1183 fetchRedirect[tid] = false; 1184 } 1185 1186 // Uncomment this if you want to see all available instructions. 1187 // @todo This doesn't actually work anymore, we should fix it. 1188// printAvailableInsts(); 1189 1190 // Execute/writeback any instructions that are available. 1191 int insts_to_execute = fromIssue->size; 1192 int inst_num = 0; 1193 for (; inst_num < insts_to_execute; 1194 ++inst_num) { 1195 1196 DPRINTF(IEW, "Execute: Executing instructions from IQ.\n"); 1197 1198 DynInstPtr inst = instQueue.getInstToExecute(); 1199 1200 DPRINTF(IEW, "Execute: Processing PC %s, [tid:%i] [sn:%i].\n", 1201 inst->pcState(), inst->threadNumber,inst->seqNum); 1202 1203 // Check if the instruction is squashed; if so then skip it 1204 if (inst->isSquashed()) { 1205 DPRINTF(IEW, "Execute: Instruction was squashed.\n"); 1206 1207 // Consider this instruction executed so that commit can go 1208 // ahead and retire the instruction. 1209 inst->setExecuted(); 1210 1211 // Not sure if I should set this here or just let commit try to 1212 // commit any squashed instructions. I like the latter a bit more. 1213 inst->setCanCommit(); 1214 1215 ++iewExecSquashedInsts; 1216 1217 decrWb(inst->seqNum); 1218 continue; 1219 } 1220 1221 Fault fault = NoFault; 1222 1223 // Execute instruction. 1224 // Note that if the instruction faults, it will be handled 1225 // at the commit stage. 1226 if (inst->isMemRef()) { 1227 DPRINTF(IEW, "Execute: Calculating address for memory " 1228 "reference.\n"); 1229 1230 // Tell the LDSTQ to execute this instruction (if it is a load). 1231 if (inst->isLoad()) { 1232 // Loads will mark themselves as executed, and their writeback 1233 // event adds the instruction to the queue to commit 1234 fault = ldstQueue.executeLoad(inst); 1235 if (inst->isDataPrefetch() || inst->isInstPrefetch()) { 1236 fault = NoFault; 1237 } 1238 } else if (inst->isStore()) { 1239 fault = ldstQueue.executeStore(inst); 1240 1241 // If the store had a fault then it may not have a mem req 1242 if (fault != NoFault || inst->readPredicate() == false || 1243 !inst->isStoreConditional()) { 1244 // If the instruction faulted, then we need to send it along 1245 // to commit without the instruction completing. 1246 // Send this instruction to commit, also make sure iew stage 1247 // realizes there is activity. 1248 inst->setExecuted(); 1249 instToCommit(inst); 1250 activityThisCycle(); 1251 } 1252 1253 // Store conditionals will mark themselves as 1254 // executed, and their writeback event will add the 1255 // instruction to the queue to commit. 1256 } else { 1257 panic("Unexpected memory type!\n"); 1258 } 1259 1260 } else { 1261 // If the instruction has already faulted, then skip executing it. 1262 // Such case can happen when it faulted during ITLB translation. 1263 // If we execute the instruction (even if it's a nop) the fault 1264 // will be replaced and we will lose it. 1265 if (inst->getFault() == NoFault) { 1266 inst->execute(); 1267 if (inst->readPredicate() == false) 1268 inst->forwardOldRegs(); 1269 } 1270 1271 inst->setExecuted(); 1272 1273 instToCommit(inst); 1274 } 1275 1276 updateExeInstStats(inst); 1277 1278 // Check if branch prediction was correct, if not then we need 1279 // to tell commit to squash in flight instructions. Only 1280 // handle this if there hasn't already been something that 1281 // redirects fetch in this group of instructions. 1282 1283 // This probably needs to prioritize the redirects if a different 1284 // scheduler is used. Currently the scheduler schedules the oldest 1285 // instruction first, so the branch resolution order will be correct. 1286 ThreadID tid = inst->threadNumber; 1287 1288 if (!fetchRedirect[tid] || 1289 toCommit->squashedSeqNum[tid] > inst->seqNum) { 1290 1291 if (inst->mispredicted()) { 1292 fetchRedirect[tid] = true; 1293 1294 DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); 1295 DPRINTF(IEW, "Predicted target was PC:%#x, NPC:%#x.\n", 1296 inst->predInstAddr(), inst->predNextInstAddr()); 1297 DPRINTF(IEW, "Execute: Redirecting fetch to PC: %s.\n", 1298 inst->pcState(), inst->nextInstAddr()); 1299 // If incorrect, then signal the ROB that it must be squashed. 1300 squashDueToBranch(inst, tid); 1301 1302 if (inst->readPredTaken()) { 1303 predictedTakenIncorrect++; 1304 } else { 1305 predictedNotTakenIncorrect++; 1306 } 1307 } else if (ldstQueue.violation(tid)) { 1308 assert(inst->isMemRef()); 1309 // If there was an ordering violation, then get the 1310 // DynInst that caused the violation. Note that this 1311 // clears the violation signal. 1312 DynInstPtr violator; 1313 violator = ldstQueue.getMemDepViolator(tid); 1314 1315 DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: %s " 1316 "[sn:%lli], inst PC: %s [sn:%lli]. Addr is: %#x.\n", 1317 violator->pcState(), violator->seqNum, 1318 inst->pcState(), inst->seqNum, inst->physEffAddr); 1319 1320 fetchRedirect[tid] = true; 1321 1322 // Tell the instruction queue that a violation has occured. 1323 instQueue.violation(inst, violator); 1324 1325 // Squash. 1326 squashDueToMemOrder(inst,tid); 1327 1328 ++memOrderViolationEvents; 1329 } else if (ldstQueue.loadBlocked(tid) && 1330 !ldstQueue.isLoadBlockedHandled(tid)) { 1331 fetchRedirect[tid] = true; 1332 1333 DPRINTF(IEW, "Load operation couldn't execute because the " 1334 "memory system is blocked. PC: %s [sn:%lli]\n", 1335 inst->pcState(), inst->seqNum); 1336 1337 squashDueToMemBlocked(inst, tid); 1338 } 1339 } else { 1340 // Reset any state associated with redirects that will not 1341 // be used. 1342 if (ldstQueue.violation(tid)) { 1343 assert(inst->isMemRef()); 1344 1345 DynInstPtr violator = ldstQueue.getMemDepViolator(tid); 1346 1347 DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: " 1348 "%s, inst PC: %s. Addr is: %#x.\n", 1349 violator->pcState(), inst->pcState(), 1350 inst->physEffAddr); 1351 DPRINTF(IEW, "Violation will not be handled because " 1352 "already squashing\n"); 1353 1354 ++memOrderViolationEvents; 1355 } 1356 if (ldstQueue.loadBlocked(tid) && 1357 !ldstQueue.isLoadBlockedHandled(tid)) { 1358 DPRINTF(IEW, "Load operation couldn't execute because the " 1359 "memory system is blocked. PC: %s [sn:%lli]\n", 1360 inst->pcState(), inst->seqNum); 1361 DPRINTF(IEW, "Blocked load will not be handled because " 1362 "already squashing\n"); 1363 1364 ldstQueue.setLoadBlockedHandled(tid); 1365 } 1366 1367 } 1368 } 1369 1370 // Update and record activity if we processed any instructions. 1371 if (inst_num) { 1372 if (exeStatus == Idle) { 1373 exeStatus = Running; 1374 } 1375 1376 updatedQueues = true; 1377 1378 cpu->activityThisCycle(); 1379 } 1380 1381 // Need to reset this in case a writeback event needs to write into the 1382 // iew queue. That way the writeback event will write into the correct 1383 // spot in the queue. 1384 wbNumInst = 0; 1385} 1386 1387template <class Impl> 1388void 1389DefaultIEW<Impl>::writebackInsts() 1390{ 1391 // Loop through the head of the time buffer and wake any 1392 // dependents. These instructions are about to write back. Also 1393 // mark scoreboard that this instruction is finally complete. 1394 // Either have IEW have direct access to scoreboard, or have this 1395 // as part of backwards communication. 1396 for (int inst_num = 0; inst_num < wbWidth && 1397 toCommit->insts[inst_num]; inst_num++) { 1398 DynInstPtr inst = toCommit->insts[inst_num]; 1399 ThreadID tid = inst->threadNumber; 1400 1401 DPRINTF(IEW, "Sending instructions to commit, [sn:%lli] PC %s.\n", 1402 inst->seqNum, inst->pcState()); 1403 1404 iewInstsToCommit[tid]++; 1405 1406 // Some instructions will be sent to commit without having 1407 // executed because they need commit to handle them. 1408 // E.g. Uncached loads have not actually executed when they 1409 // are first sent to commit. Instead commit must tell the LSQ 1410 // when it's ready to execute the uncached load. 1411 if (!inst->isSquashed() && inst->isExecuted() && inst->getFault() == NoFault) { 1412 int dependents = instQueue.wakeDependents(inst); 1413 1414 for (int i = 0; i < inst->numDestRegs(); i++) { 1415 //mark as Ready 1416 DPRINTF(IEW,"Setting Destination Register %i\n", 1417 inst->renamedDestRegIdx(i)); 1418 scoreboard->setReg(inst->renamedDestRegIdx(i)); 1419 } 1420 1421 if (dependents) { 1422 producerInst[tid]++; 1423 consumerInst[tid]+= dependents; 1424 } 1425 writebackCount[tid]++; 1426 } 1427 1428 decrWb(inst->seqNum); 1429 } 1430} 1431 1432template<class Impl> 1433void 1434DefaultIEW<Impl>::tick() 1435{ 1436 wbNumInst = 0; 1437 wbCycle = 0; 1438 1439 wroteToTimeBuffer = false; 1440 updatedQueues = false; 1441 1442 sortInsts(); 1443 1444 // Free function units marked as being freed this cycle. 1445 fuPool->processFreeUnits(); 1446 1447 list<ThreadID>::iterator threads = activeThreads->begin(); 1448 list<ThreadID>::iterator end = activeThreads->end(); 1449 1450 // Check stall and squash signals, dispatch any instructions. 1451 while (threads != end) { 1452 ThreadID tid = *threads++; 1453 1454 DPRINTF(IEW,"Issue: Processing [tid:%i]\n",tid); 1455 1456 checkSignalsAndUpdate(tid); 1457 dispatch(tid); 1458 } 1459 1460 if (exeStatus != Squashing) { 1461 executeInsts(); 1462 1463 writebackInsts(); 1464 1465 // Have the instruction queue try to schedule any ready instructions. 1466 // (In actuality, this scheduling is for instructions that will 1467 // be executed next cycle.) 1468 instQueue.scheduleReadyInsts(); 1469 1470 // Also should advance its own time buffers if the stage ran. 1471 // Not the best place for it, but this works (hopefully). 1472 issueToExecQueue.advance(); 1473 } 1474 1475 bool broadcast_free_entries = false; 1476 1477 if (updatedQueues || exeStatus == Running || updateLSQNextCycle) { 1478 exeStatus = Idle; 1479 updateLSQNextCycle = false; 1480 1481 broadcast_free_entries = true; 1482 } 1483 1484 // Writeback any stores using any leftover bandwidth. 1485 ldstQueue.writebackStores(); 1486 1487 // Check the committed load/store signals to see if there's a load 1488 // or store to commit. Also check if it's being told to execute a 1489 // nonspeculative instruction. 1490 // This is pretty inefficient... 1491 1492 threads = activeThreads->begin(); 1493 while (threads != end) { 1494 ThreadID tid = (*threads++); 1495 1496 DPRINTF(IEW,"Processing [tid:%i]\n",tid); 1497 1498 // Update structures based on instructions committed. 1499 if (fromCommit->commitInfo[tid].doneSeqNum != 0 && 1500 !fromCommit->commitInfo[tid].squash && 1501 !fromCommit->commitInfo[tid].robSquashing) { 1502 1503 ldstQueue.commitStores(fromCommit->commitInfo[tid].doneSeqNum,tid); 1504 1505 ldstQueue.commitLoads(fromCommit->commitInfo[tid].doneSeqNum,tid); 1506 1507 updateLSQNextCycle = true; 1508 instQueue.commit(fromCommit->commitInfo[tid].doneSeqNum,tid); 1509 } 1510 1511 if (fromCommit->commitInfo[tid].nonSpecSeqNum != 0) { 1512 1513 //DPRINTF(IEW,"NonspecInst from thread %i",tid); 1514 if (fromCommit->commitInfo[tid].uncached) { 1515 instQueue.replayMemInst(fromCommit->commitInfo[tid].uncachedLoad); 1516 fromCommit->commitInfo[tid].uncachedLoad->setAtCommit(); 1517 } else { 1518 instQueue.scheduleNonSpec( 1519 fromCommit->commitInfo[tid].nonSpecSeqNum); 1520 } 1521 } 1522 1523 if (broadcast_free_entries) { 1524 toFetch->iewInfo[tid].iqCount = 1525 instQueue.getCount(tid); 1526 toFetch->iewInfo[tid].ldstqCount = 1527 ldstQueue.getCount(tid); 1528 1529 toRename->iewInfo[tid].usedIQ = true; 1530 toRename->iewInfo[tid].freeIQEntries = 1531 instQueue.numFreeEntries(); 1532 toRename->iewInfo[tid].usedLSQ = true; 1533 toRename->iewInfo[tid].freeLSQEntries = 1534 ldstQueue.numFreeEntries(tid); 1535 1536 wroteToTimeBuffer = true; 1537 } 1538 1539 DPRINTF(IEW, "[tid:%i], Dispatch dispatched %i instructions.\n", 1540 tid, toRename->iewInfo[tid].dispatched); 1541 } 1542 1543 DPRINTF(IEW, "IQ has %i free entries (Can schedule: %i). " 1544 "LSQ has %i free entries.\n", 1545 instQueue.numFreeEntries(), instQueue.hasReadyInsts(), 1546 ldstQueue.numFreeEntries()); 1547 1548 updateStatus(); 1549 1550 if (wroteToTimeBuffer) { 1551 DPRINTF(Activity, "Activity this cycle.\n"); 1552 cpu->activityThisCycle(); 1553 } 1554} 1555 1556template <class Impl> 1557void 1558DefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst) 1559{ 1560 ThreadID tid = inst->threadNumber; 1561 1562 // 1563 // Pick off the software prefetches 1564 // 1565#ifdef TARGET_ALPHA 1566 if (inst->isDataPrefetch()) 1567 iewExecutedSwp[tid]++; 1568 else 1569 iewIewExecutedcutedInsts++; 1570#else 1571 iewExecutedInsts++; 1572#endif 1573 1574 // 1575 // Control operations 1576 // 1577 if (inst->isControl()) 1578 iewExecutedBranches[tid]++; 1579 1580 // 1581 // Memory operations 1582 // 1583 if (inst->isMemRef()) { 1584 iewExecutedRefs[tid]++; 1585 1586 if (inst->isLoad()) { 1587 iewExecLoadInsts[tid]++; 1588 } 1589 } 1590} 1591 1592template <class Impl> 1593void 1594DefaultIEW<Impl>::checkMisprediction(DynInstPtr &inst) 1595{ 1596 ThreadID tid = inst->threadNumber; 1597 1598 if (!fetchRedirect[tid] || 1599 toCommit->squashedSeqNum[tid] > inst->seqNum) { 1600 1601 if (inst->mispredicted()) { 1602 fetchRedirect[tid] = true; 1603 1604 DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); 1605 DPRINTF(IEW, "Predicted target was PC:%#x, NPC:%#x.\n", 1606 inst->predInstAddr(), inst->predNextInstAddr()); 1607 DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x," 1608 " NPC: %#x.\n", inst->nextInstAddr(), 1609 inst->nextInstAddr()); 1610 // If incorrect, then signal the ROB that it must be squashed. 1611 squashDueToBranch(inst, tid); 1612 1613 if (inst->readPredTaken()) { 1614 predictedTakenIncorrect++; 1615 } else { 1616 predictedNotTakenIncorrect++; 1617 } 1618 } 1619 } 1620} 1621