decode_impl.hh revision 13429:a1e199fd8122
113558Snikos.nikoleris@arm.com/* 28839Sandreas.hansson@arm.com * Copyright (c) 2012, 2014 ARM Limited 38839Sandreas.hansson@arm.com * All rights reserved 48839Sandreas.hansson@arm.com * 58839Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 68839Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 78839Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 88839Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 98839Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 108839Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 118839Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 128839Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 133101Sstever@eecs.umich.edu * 148579Ssteve.reinhardt@amd.com * Copyright (c) 2004-2006 The Regents of The University of Michigan 153101Sstever@eecs.umich.edu * All rights reserved. 163101Sstever@eecs.umich.edu * 173101Sstever@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 183101Sstever@eecs.umich.edu * modification, are permitted provided that the following conditions are 193101Sstever@eecs.umich.edu * met: redistributions of source code must retain the above copyright 203101Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 213101Sstever@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 223101Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 233101Sstever@eecs.umich.edu * documentation and/or other materials provided with the distribution; 243101Sstever@eecs.umich.edu * neither the name of the copyright holders nor the names of its 253101Sstever@eecs.umich.edu * contributors may be used to endorse or promote products derived from 263101Sstever@eecs.umich.edu * this software without specific prior written permission. 273101Sstever@eecs.umich.edu * 283101Sstever@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 293101Sstever@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 303101Sstever@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 313101Sstever@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 323101Sstever@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 333101Sstever@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 343101Sstever@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 353101Sstever@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 363101Sstever@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 373101Sstever@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 383101Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 393101Sstever@eecs.umich.edu * 403101Sstever@eecs.umich.edu * Authors: Kevin Lim 413101Sstever@eecs.umich.edu */ 427778Sgblack@eecs.umich.edu 438839Sandreas.hansson@arm.com#ifndef __CPU_O3_DECODE_IMPL_HH__ 443101Sstever@eecs.umich.edu#define __CPU_O3_DECODE_IMPL_HH__ 453101Sstever@eecs.umich.edu 463101Sstever@eecs.umich.edu#include "arch/types.hh" 473101Sstever@eecs.umich.edu#include "base/trace.hh" 483101Sstever@eecs.umich.edu#include "config/the_isa.hh" 493101Sstever@eecs.umich.edu#include "cpu/o3/decode.hh" 503101Sstever@eecs.umich.edu#include "cpu/inst_seq.hh" 513101Sstever@eecs.umich.edu#include "debug/Activity.hh" 523101Sstever@eecs.umich.edu#include "debug/Decode.hh" 533101Sstever@eecs.umich.edu#include "debug/O3PipeView.hh" 543101Sstever@eecs.umich.edu#include "params/DerivO3CPU.hh" 553101Sstever@eecs.umich.edu#include "sim/full_system.hh" 563101Sstever@eecs.umich.edu 573101Sstever@eecs.umich.edu// clang complains about std::set being overloaded with Packet::set if 583101Sstever@eecs.umich.edu// we open up the entire namespace std 593101Sstever@eecs.umich.eduusing std::list; 603101Sstever@eecs.umich.edu 613101Sstever@eecs.umich.edutemplate<class Impl> 6212563Sgabeblack@google.comDefaultDecode<Impl>::DefaultDecode(O3CPU *_cpu, DerivO3CPUParams *params) 6312563Sgabeblack@google.com : cpu(_cpu), 643885Sbinkertn@umich.edu renameToDecodeDelay(params->renameToDecodeDelay), 653885Sbinkertn@umich.edu iewToDecodeDelay(params->iewToDecodeDelay), 664762Snate@binkert.org commitToDecodeDelay(params->commitToDecodeDelay), 673885Sbinkertn@umich.edu fetchToDecodeDelay(params->fetchToDecodeDelay), 683885Sbinkertn@umich.edu decodeWidth(params->decodeWidth), 697528Ssteve.reinhardt@amd.com numThreads(params->numThreads) 703885Sbinkertn@umich.edu{ 714380Sbinkertn@umich.edu if (decodeWidth > Impl::MaxWidth) 724167Sbinkertn@umich.edu fatal("decodeWidth (%d) is larger than compiled limit (%d),\n" 733102Sstever@eecs.umich.edu "\tincrease MaxWidth in src/cpu/o3/impl.hh\n", 743101Sstever@eecs.umich.edu decodeWidth, static_cast<int>(Impl::MaxWidth)); 754762Snate@binkert.org 764762Snate@binkert.org // @todo: Make into a parameter 774762Snate@binkert.org skidBufferMax = (fetchToDecodeDelay + 1) * params->fetchWidth; 784762Snate@binkert.org} 794762Snate@binkert.org 804762Snate@binkert.orgtemplate<class Impl> 814762Snate@binkert.orgvoid 824762Snate@binkert.orgDefaultDecode<Impl>::startupStage() 834762Snate@binkert.org{ 845033Smilesck@eecs.umich.edu resetStage(); 855033Smilesck@eecs.umich.edu} 865033Smilesck@eecs.umich.edu 875033Smilesck@eecs.umich.edutemplate<class Impl> 885033Smilesck@eecs.umich.eduvoid 895033Smilesck@eecs.umich.eduDefaultDecode<Impl>::resetStage() 905033Smilesck@eecs.umich.edu{ 915033Smilesck@eecs.umich.edu _status = Inactive; 925033Smilesck@eecs.umich.edu 935033Smilesck@eecs.umich.edu // Setup status, make sure stall signals are clear. 943101Sstever@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; ++tid) { 953101Sstever@eecs.umich.edu decodeStatus[tid] = Idle; 963101Sstever@eecs.umich.edu 975033Smilesck@eecs.umich.edu stalls[tid].rename = false; 9810267SGeoffrey.Blake@arm.com } 998596Ssteve.reinhardt@amd.com} 1008596Ssteve.reinhardt@amd.com 1018596Ssteve.reinhardt@amd.comtemplate <class Impl> 1028596Ssteve.reinhardt@amd.comstd::string 1037673Snate@binkert.orgDefaultDecode<Impl>::name() const 1047673Snate@binkert.org{ 1057673Snate@binkert.org return cpu->name() + ".decode"; 1067673Snate@binkert.org} 10711988Sandreas.sandberg@arm.com 10811988Sandreas.sandberg@arm.comtemplate <class Impl> 10911988Sandreas.sandberg@arm.comvoid 11011988Sandreas.sandberg@arm.comDefaultDecode<Impl>::regStats() 1113101Sstever@eecs.umich.edu{ 1123101Sstever@eecs.umich.edu decodeIdleCycles 1133101Sstever@eecs.umich.edu .name(name() + ".IdleCycles") 1143101Sstever@eecs.umich.edu .desc("Number of cycles decode is idle") 1153101Sstever@eecs.umich.edu .prereq(decodeIdleCycles); 11610380SAndrew.Bardsley@arm.com decodeBlockedCycles 11710380SAndrew.Bardsley@arm.com .name(name() + ".BlockedCycles") 11810380SAndrew.Bardsley@arm.com .desc("Number of cycles decode is blocked") 11910380SAndrew.Bardsley@arm.com .prereq(decodeBlockedCycles); 12010380SAndrew.Bardsley@arm.com decodeRunCycles 12110380SAndrew.Bardsley@arm.com .name(name() + ".RunCycles") 12210458Sandreas.hansson@arm.com .desc("Number of cycles decode is running") 12310458Sandreas.hansson@arm.com .prereq(decodeRunCycles); 12410458Sandreas.hansson@arm.com decodeUnblockCycles 12510458Sandreas.hansson@arm.com .name(name() + ".UnblockCycles") 12610458Sandreas.hansson@arm.com .desc("Number of cycles decode is unblocking") 12710458Sandreas.hansson@arm.com .prereq(decodeUnblockCycles); 12810458Sandreas.hansson@arm.com decodeSquashCycles 12910458Sandreas.hansson@arm.com .name(name() + ".SquashCycles") 13010458Sandreas.hansson@arm.com .desc("Number of cycles decode is squashing") 13110458Sandreas.hansson@arm.com .prereq(decodeSquashCycles); 13210458Sandreas.hansson@arm.com decodeBranchResolved 13310458Sandreas.hansson@arm.com .name(name() + ".BranchResolved") 1343101Sstever@eecs.umich.edu .desc("Number of times decode resolved a branch") 1353101Sstever@eecs.umich.edu .prereq(decodeBranchResolved); 1363101Sstever@eecs.umich.edu decodeBranchMispred 1373101Sstever@eecs.umich.edu .name(name() + ".BranchMispred") 1383101Sstever@eecs.umich.edu .desc("Number of times decode detected a branch misprediction") 13910267SGeoffrey.Blake@arm.com .prereq(decodeBranchMispred); 14010267SGeoffrey.Blake@arm.com decodeControlMispred 14110267SGeoffrey.Blake@arm.com .name(name() + ".ControlMispred") 14210267SGeoffrey.Blake@arm.com .desc("Number of times decode detected an instruction incorrectly" 1433101Sstever@eecs.umich.edu " predicted as a control") 1443101Sstever@eecs.umich.edu .prereq(decodeControlMispred); 1453101Sstever@eecs.umich.edu decodeDecodedInsts 1463101Sstever@eecs.umich.edu .name(name() + ".DecodedInsts") 1473101Sstever@eecs.umich.edu .desc("Number of instructions handled by decode") 1483101Sstever@eecs.umich.edu .prereq(decodeDecodedInsts); 1493101Sstever@eecs.umich.edu decodeSquashedInsts 1503101Sstever@eecs.umich.edu .name(name() + ".SquashedInsts") 1513101Sstever@eecs.umich.edu .desc("Number of squashed instructions handled by decode") 1523101Sstever@eecs.umich.edu .prereq(decodeSquashedInsts); 1533101Sstever@eecs.umich.edu} 1543101Sstever@eecs.umich.edu 1553101Sstever@eecs.umich.edutemplate<class Impl> 1563101Sstever@eecs.umich.eduvoid 1573101Sstever@eecs.umich.eduDefaultDecode<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 1583101Sstever@eecs.umich.edu{ 1593101Sstever@eecs.umich.edu timeBuffer = tb_ptr; 1603101Sstever@eecs.umich.edu 1613101Sstever@eecs.umich.edu // Setup wire to write information back to fetch. 1623101Sstever@eecs.umich.edu toFetch = timeBuffer->getWire(0); 1633101Sstever@eecs.umich.edu 1643101Sstever@eecs.umich.edu // Create wires to get information from proper places in time buffer. 1653101Sstever@eecs.umich.edu fromRename = timeBuffer->getWire(-renameToDecodeDelay); 1663101Sstever@eecs.umich.edu fromIEW = timeBuffer->getWire(-iewToDecodeDelay); 1673101Sstever@eecs.umich.edu fromCommit = timeBuffer->getWire(-commitToDecodeDelay); 1683101Sstever@eecs.umich.edu} 1693101Sstever@eecs.umich.edu 1703101Sstever@eecs.umich.edutemplate<class Impl> 1713101Sstever@eecs.umich.eduvoid 1723101Sstever@eecs.umich.eduDefaultDecode<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr) 1733101Sstever@eecs.umich.edu{ 1743101Sstever@eecs.umich.edu decodeQueue = dq_ptr; 1753101Sstever@eecs.umich.edu 1763101Sstever@eecs.umich.edu // Setup wire to write information to proper place in decode queue. 1773101Sstever@eecs.umich.edu toRename = decodeQueue->getWire(0); 1785033Smilesck@eecs.umich.edu} 1796656Snate@binkert.org 1805033Smilesck@eecs.umich.edutemplate<class Impl> 1815033Smilesck@eecs.umich.eduvoid 1825033Smilesck@eecs.umich.eduDefaultDecode<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr) 1833101Sstever@eecs.umich.edu{ 1843101Sstever@eecs.umich.edu fetchQueue = fq_ptr; 1853101Sstever@eecs.umich.edu 18610267SGeoffrey.Blake@arm.com // Setup wire to read information from fetch queue. 18710267SGeoffrey.Blake@arm.com fromFetch = fetchQueue->getWire(-fetchToDecodeDelay); 18810267SGeoffrey.Blake@arm.com} 18910267SGeoffrey.Blake@arm.com 19010267SGeoffrey.Blake@arm.comtemplate<class Impl> 19110267SGeoffrey.Blake@arm.comvoid 19210267SGeoffrey.Blake@arm.comDefaultDecode<Impl>::setActiveThreads(std::list<ThreadID> *at_ptr) 19310267SGeoffrey.Blake@arm.com{ 19410267SGeoffrey.Blake@arm.com activeThreads = at_ptr; 19510267SGeoffrey.Blake@arm.com} 19610267SGeoffrey.Blake@arm.com 19710267SGeoffrey.Blake@arm.comtemplate <class Impl> 19810267SGeoffrey.Blake@arm.comvoid 1993101Sstever@eecs.umich.eduDefaultDecode<Impl>::drainSanityCheck() const 2003101Sstever@eecs.umich.edu{ 2013101Sstever@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; ++tid) { 2023101Sstever@eecs.umich.edu assert(insts[tid].empty()); 2033101Sstever@eecs.umich.edu assert(skidBuffer[tid].empty()); 2043101Sstever@eecs.umich.edu } 2053101Sstever@eecs.umich.edu} 2063101Sstever@eecs.umich.edu 2073101Sstever@eecs.umich.edutemplate <class Impl> 2083101Sstever@eecs.umich.edubool 2093102Sstever@eecs.umich.eduDefaultDecode<Impl>::isDrained() const 2103101Sstever@eecs.umich.edu{ 2113101Sstever@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; ++tid) { 2123101Sstever@eecs.umich.edu if (!insts[tid].empty() || !skidBuffer[tid].empty() || 21310267SGeoffrey.Blake@arm.com (decodeStatus[tid] != Running && decodeStatus[tid] != Idle)) 21410267SGeoffrey.Blake@arm.com return false; 21510267SGeoffrey.Blake@arm.com } 21610267SGeoffrey.Blake@arm.com return true; 21710267SGeoffrey.Blake@arm.com} 21810267SGeoffrey.Blake@arm.com 21910267SGeoffrey.Blake@arm.comtemplate<class Impl> 2207673Snate@binkert.orgbool 2218607Sgblack@eecs.umich.eduDefaultDecode<Impl>::checkStall(ThreadID tid) const 2227673Snate@binkert.org{ 2233101Sstever@eecs.umich.edu bool ret_val = false; 22411988Sandreas.sandberg@arm.com 22511988Sandreas.sandberg@arm.com if (stalls[tid].rename) { 22611988Sandreas.sandberg@arm.com DPRINTF(Decode,"[tid:%i]: Stall fom Rename stage detected.\n", tid); 2277673Snate@binkert.org ret_val = true; 2287673Snate@binkert.org } 2293101Sstever@eecs.umich.edu 2303101Sstever@eecs.umich.edu return ret_val; 2313101Sstever@eecs.umich.edu} 2323101Sstever@eecs.umich.edu 2333101Sstever@eecs.umich.edutemplate<class Impl> 2343101Sstever@eecs.umich.eduinline bool 2355033Smilesck@eecs.umich.eduDefaultDecode<Impl>::fetchInstsValid() 2365475Snate@binkert.org{ 2375475Snate@binkert.org return fromFetch->size > 0; 2385475Snate@binkert.org} 2395475Snate@binkert.org 24010380SAndrew.Bardsley@arm.comtemplate<class Impl> 24110380SAndrew.Bardsley@arm.combool 24210380SAndrew.Bardsley@arm.comDefaultDecode<Impl>::block(ThreadID tid) 2433101Sstever@eecs.umich.edu{ 2443101Sstever@eecs.umich.edu DPRINTF(Decode, "[tid:%u]: Blocking.\n", tid); 2453101Sstever@eecs.umich.edu 2464762Snate@binkert.org // Add the current inputs to the skid buffer so they can be 2474762Snate@binkert.org // reprocessed when this stage unblocks. 2484762Snate@binkert.org skidInsert(tid); 2493101Sstever@eecs.umich.edu 25012050Snikos.nikoleris@arm.com // If the decode status is blocked or unblocking then decode has not yet 25112050Snikos.nikoleris@arm.com // signalled fetch to unblock. In that case, there is no need to tell 25212050Snikos.nikoleris@arm.com // fetch to block. 2538459SAli.Saidi@ARM.com if (decodeStatus[tid] != Blocked) { 2548459SAli.Saidi@ARM.com // Set the status to Blocked. 25512050Snikos.nikoleris@arm.com decodeStatus[tid] = Blocked; 2563101Sstever@eecs.umich.edu 2577528Ssteve.reinhardt@amd.com if (toFetch->decodeUnblock[tid]) { 2587528Ssteve.reinhardt@amd.com toFetch->decodeUnblock[tid] = false; 2597528Ssteve.reinhardt@amd.com } else { 2607528Ssteve.reinhardt@amd.com toFetch->decodeBlock[tid] = true; 2617528Ssteve.reinhardt@amd.com wroteToTimeBuffer = true; 2627528Ssteve.reinhardt@amd.com } 2633101Sstever@eecs.umich.edu 2647528Ssteve.reinhardt@amd.com return true; 2657528Ssteve.reinhardt@amd.com } 2667528Ssteve.reinhardt@amd.com 2677528Ssteve.reinhardt@amd.com return false; 2687528Ssteve.reinhardt@amd.com} 2697528Ssteve.reinhardt@amd.com 2707528Ssteve.reinhardt@amd.comtemplate<class Impl> 2717528Ssteve.reinhardt@amd.combool 2727528Ssteve.reinhardt@amd.comDefaultDecode<Impl>::unblock(ThreadID tid) 2737528Ssteve.reinhardt@amd.com{ 2748321Ssteve.reinhardt@amd.com // Decode is done unblocking only if the skid buffer is empty. 27512194Sgabeblack@google.com if (skidBuffer[tid].empty()) { 2767528Ssteve.reinhardt@amd.com DPRINTF(Decode, "[tid:%u]: Done unblocking.\n", tid); 2777528Ssteve.reinhardt@amd.com toFetch->decodeUnblock[tid] = true; 2787528Ssteve.reinhardt@amd.com wroteToTimeBuffer = true; 2797528Ssteve.reinhardt@amd.com 2807528Ssteve.reinhardt@amd.com decodeStatus[tid] = Running; 2817528Ssteve.reinhardt@amd.com return true; 2827528Ssteve.reinhardt@amd.com } 2837528Ssteve.reinhardt@amd.com 2847528Ssteve.reinhardt@amd.com DPRINTF(Decode, "[tid:%u]: Currently unblocking.\n", tid); 2857528Ssteve.reinhardt@amd.com 2867528Ssteve.reinhardt@amd.com return false; 2877528Ssteve.reinhardt@amd.com} 2887528Ssteve.reinhardt@amd.com 2893101Sstever@eecs.umich.edutemplate<class Impl> 2908664SAli.Saidi@ARM.comvoid 2918664SAli.Saidi@ARM.comDefaultDecode<Impl>::squash(const DynInstPtr &inst, ThreadID tid) 2928664SAli.Saidi@ARM.com{ 2938664SAli.Saidi@ARM.com DPRINTF(Decode, "[tid:%i]: [sn:%i] Squashing due to incorrect branch " 2948664SAli.Saidi@ARM.com "prediction detected at decode.\n", tid, inst->seqNum); 2958664SAli.Saidi@ARM.com 2969953Sgeoffrey.blake@arm.com // Send back mispredict information. 2979953Sgeoffrey.blake@arm.com toFetch->decodeInfo[tid].branchMispredict = true; 2989953Sgeoffrey.blake@arm.com toFetch->decodeInfo[tid].predIncorrect = true; 2999953Sgeoffrey.blake@arm.com toFetch->decodeInfo[tid].mispredictInst = inst; 3009953Sgeoffrey.blake@arm.com toFetch->decodeInfo[tid].squash = true; 3019953Sgeoffrey.blake@arm.com toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum; 3029953Sgeoffrey.blake@arm.com toFetch->decodeInfo[tid].nextPC = inst->branchTarget(); 3039953Sgeoffrey.blake@arm.com toFetch->decodeInfo[tid].branchTaken = inst->pcState().branching(); 3049953Sgeoffrey.blake@arm.com toFetch->decodeInfo[tid].squashInst = inst; 3059953Sgeoffrey.blake@arm.com if (toFetch->decodeInfo[tid].mispredictInst->isUncondCtrl()) { 3069953Sgeoffrey.blake@arm.com toFetch->decodeInfo[tid].branchTaken = true; 3079953Sgeoffrey.blake@arm.com } 3089953Sgeoffrey.blake@arm.com 30910267SGeoffrey.Blake@arm.com InstSeqNum squash_seq_num = inst->seqNum; 31010267SGeoffrey.Blake@arm.com 31110267SGeoffrey.Blake@arm.com // Might have to tell fetch to unblock. 31210267SGeoffrey.Blake@arm.com if (decodeStatus[tid] == Blocked || 31310267SGeoffrey.Blake@arm.com decodeStatus[tid] == Unblocking) { 31410267SGeoffrey.Blake@arm.com toFetch->decodeUnblock[tid] = 1; 31510267SGeoffrey.Blake@arm.com } 31612563Sgabeblack@google.com 31710267SGeoffrey.Blake@arm.com // Set status to squashing. 31810267SGeoffrey.Blake@arm.com decodeStatus[tid] = Squashing; 31910267SGeoffrey.Blake@arm.com 32010267SGeoffrey.Blake@arm.com for (int i=0; i<fromFetch->size; i++) { 32110267SGeoffrey.Blake@arm.com if (fromFetch->insts[i]->threadNumber == tid && 32210267SGeoffrey.Blake@arm.com fromFetch->insts[i]->seqNum > squash_seq_num) { 32310267SGeoffrey.Blake@arm.com fromFetch->insts[i]->setSquashed(); 32410267SGeoffrey.Blake@arm.com } 32510267SGeoffrey.Blake@arm.com } 32610267SGeoffrey.Blake@arm.com 32710267SGeoffrey.Blake@arm.com // Clear the instruction list and skid buffer in case they have any 32810267SGeoffrey.Blake@arm.com // insts in them. 3293101Sstever@eecs.umich.edu while (!insts[tid].empty()) { 3303101Sstever@eecs.umich.edu insts[tid].pop(); 3313101Sstever@eecs.umich.edu } 3323101Sstever@eecs.umich.edu 3333101Sstever@eecs.umich.edu while (!skidBuffer[tid].empty()) { 3343101Sstever@eecs.umich.edu skidBuffer[tid].pop(); 3353101Sstever@eecs.umich.edu } 33610364SGeoffrey.Blake@arm.com 33710364SGeoffrey.Blake@arm.com // Squash instructions up until this one 33810364SGeoffrey.Blake@arm.com cpu->removeInstsUntil(squash_seq_num, tid); 33910364SGeoffrey.Blake@arm.com} 3403101Sstever@eecs.umich.edu 3414762Snate@binkert.orgtemplate<class Impl> 3424762Snate@binkert.orgunsigned 3434762Snate@binkert.orgDefaultDecode<Impl>::squash(ThreadID tid) 3444762Snate@binkert.org{ 3457528Ssteve.reinhardt@amd.com DPRINTF(Decode, "[tid:%i]: Squashing.\n",tid); 3464762Snate@binkert.org 3474762Snate@binkert.org if (decodeStatus[tid] == Blocked || 3484762Snate@binkert.org decodeStatus[tid] == Unblocking) { 34910267SGeoffrey.Blake@arm.com if (FullSystem) { 35010267SGeoffrey.Blake@arm.com toFetch->decodeUnblock[tid] = 1; 35110267SGeoffrey.Blake@arm.com } else { 35210267SGeoffrey.Blake@arm.com // In syscall emulation, we can have both a block and a squash due 35310267SGeoffrey.Blake@arm.com // to a syscall in the same cycle. This would cause both signals 35410267SGeoffrey.Blake@arm.com // to be high. This shouldn't happen in full system. 35510267SGeoffrey.Blake@arm.com // @todo: Determine if this still happens. 35610267SGeoffrey.Blake@arm.com if (toFetch->decodeBlock[tid]) 35710267SGeoffrey.Blake@arm.com toFetch->decodeBlock[tid] = 0; 35810267SGeoffrey.Blake@arm.com else 35910267SGeoffrey.Blake@arm.com toFetch->decodeUnblock[tid] = 1; 36010267SGeoffrey.Blake@arm.com } 36110267SGeoffrey.Blake@arm.com } 36210267SGeoffrey.Blake@arm.com 36310267SGeoffrey.Blake@arm.com // Set status to squashing. 36410267SGeoffrey.Blake@arm.com decodeStatus[tid] = Squashing; 36510267SGeoffrey.Blake@arm.com 36610267SGeoffrey.Blake@arm.com // Go through incoming instructions from fetch and squash them. 36710267SGeoffrey.Blake@arm.com unsigned squash_count = 0; 36810267SGeoffrey.Blake@arm.com 36910267SGeoffrey.Blake@arm.com for (int i=0; i<fromFetch->size; i++) { 37010267SGeoffrey.Blake@arm.com if (fromFetch->insts[i]->threadNumber == tid) { 37110267SGeoffrey.Blake@arm.com fromFetch->insts[i]->setSquashed(); 37210267SGeoffrey.Blake@arm.com squash_count++; 37310267SGeoffrey.Blake@arm.com } 37410267SGeoffrey.Blake@arm.com } 37510364SGeoffrey.Blake@arm.com 37610364SGeoffrey.Blake@arm.com // Clear the instruction list and skid buffer in case they have any 37710267SGeoffrey.Blake@arm.com // insts in them. 37810267SGeoffrey.Blake@arm.com while (!insts[tid].empty()) { 37910267SGeoffrey.Blake@arm.com insts[tid].pop(); 38010267SGeoffrey.Blake@arm.com } 38110267SGeoffrey.Blake@arm.com 38210267SGeoffrey.Blake@arm.com while (!skidBuffer[tid].empty()) { 3837673Snate@binkert.org skidBuffer[tid].pop(); 3847673Snate@binkert.org } 3857673Snate@binkert.org 3863101Sstever@eecs.umich.edu return squash_count; 38711988Sandreas.sandberg@arm.com} 38811988Sandreas.sandberg@arm.com 38911988Sandreas.sandberg@arm.comtemplate<class Impl> 39011988Sandreas.sandberg@arm.comvoid 3917673Snate@binkert.orgDefaultDecode<Impl>::skidInsert(ThreadID tid) 3927673Snate@binkert.org{ 3933101Sstever@eecs.umich.edu DynInstPtr inst = NULL; 3943101Sstever@eecs.umich.edu 3953101Sstever@eecs.umich.edu while (!insts[tid].empty()) { 3963101Sstever@eecs.umich.edu inst = insts[tid].front(); 3973101Sstever@eecs.umich.edu 3983101Sstever@eecs.umich.edu insts[tid].pop(); 3993101Sstever@eecs.umich.edu 4003101Sstever@eecs.umich.edu assert(tid == inst->threadNumber); 4013101Sstever@eecs.umich.edu 4023101Sstever@eecs.umich.edu skidBuffer[tid].push(inst); 4033101Sstever@eecs.umich.edu 4043101Sstever@eecs.umich.edu DPRINTF(Decode,"Inserting [tid:%d][sn:%lli] PC: %s into decode skidBuffer %i\n", 4053101Sstever@eecs.umich.edu inst->threadNumber, inst->seqNum, inst->pcState(), skidBuffer[tid].size()); 4063101Sstever@eecs.umich.edu } 4073101Sstever@eecs.umich.edu 4085033Smilesck@eecs.umich.edu // @todo: Eventually need to enforce this by not letting a thread 4095033Smilesck@eecs.umich.edu // fetch past its skidbuffer 4103101Sstever@eecs.umich.edu assert(skidBuffer[tid].size() <= skidBufferMax); 4113101Sstever@eecs.umich.edu} 4123101Sstever@eecs.umich.edu 4133101Sstever@eecs.umich.edutemplate<class Impl> 4143101Sstever@eecs.umich.edubool 4153101Sstever@eecs.umich.eduDefaultDecode<Impl>::skidsEmpty() 4163101Sstever@eecs.umich.edu{ 4173101Sstever@eecs.umich.edu list<ThreadID>::iterator threads = activeThreads->begin(); 4183101Sstever@eecs.umich.edu list<ThreadID>::iterator end = activeThreads->end(); 4193101Sstever@eecs.umich.edu 4203101Sstever@eecs.umich.edu while (threads != end) { 4213101Sstever@eecs.umich.edu ThreadID tid = *threads++; 4223101Sstever@eecs.umich.edu if (!skidBuffer[tid].empty()) 4233101Sstever@eecs.umich.edu return false; 4243101Sstever@eecs.umich.edu } 4253101Sstever@eecs.umich.edu 4263101Sstever@eecs.umich.edu return true; 4273101Sstever@eecs.umich.edu} 4283101Sstever@eecs.umich.edu 4293101Sstever@eecs.umich.edutemplate<class Impl> 4303101Sstever@eecs.umich.eduvoid 4313101Sstever@eecs.umich.eduDefaultDecode<Impl>::updateStatus() 4323101Sstever@eecs.umich.edu{ 4333101Sstever@eecs.umich.edu bool any_unblocking = false; 4343101Sstever@eecs.umich.edu 43510267SGeoffrey.Blake@arm.com list<ThreadID>::iterator threads = activeThreads->begin(); 4367673Snate@binkert.org list<ThreadID>::iterator end = activeThreads->end(); 4377673Snate@binkert.org 4387673Snate@binkert.org while (threads != end) { 4397673Snate@binkert.org ThreadID tid = *threads++; 4407673Snate@binkert.org 44110267SGeoffrey.Blake@arm.com if (decodeStatus[tid] == Unblocking) { 44210267SGeoffrey.Blake@arm.com any_unblocking = true; 44310267SGeoffrey.Blake@arm.com break; 44410267SGeoffrey.Blake@arm.com } 44510458Sandreas.hansson@arm.com } 44610458Sandreas.hansson@arm.com 44710458Sandreas.hansson@arm.com // Decode will have activity if it's unblocking. 44810458Sandreas.hansson@arm.com if (any_unblocking) { 44910458Sandreas.hansson@arm.com if (_status == Inactive) { 4504762Snate@binkert.org _status = Active; 4514762Snate@binkert.org 4523101Sstever@eecs.umich.edu DPRINTF(Activity, "Activating stage.\n"); 4533101Sstever@eecs.umich.edu 4543101Sstever@eecs.umich.edu cpu->activateStage(O3CPU::DecodeIdx); 4553101Sstever@eecs.umich.edu } 4563101Sstever@eecs.umich.edu } else { 4573101Sstever@eecs.umich.edu // If it's not unblocking, then decode will not have any internal 4583101Sstever@eecs.umich.edu // activity. Switch it to inactive. 4593101Sstever@eecs.umich.edu if (_status == Active) { 4603101Sstever@eecs.umich.edu _status = Inactive; 4613101Sstever@eecs.umich.edu DPRINTF(Activity, "Deactivating stage.\n"); 4623101Sstever@eecs.umich.edu 4633714Sstever@eecs.umich.edu cpu->deactivateStage(O3CPU::DecodeIdx); 4643714Sstever@eecs.umich.edu } 4653714Sstever@eecs.umich.edu } 4663714Sstever@eecs.umich.edu} 4673714Sstever@eecs.umich.edu 4683714Sstever@eecs.umich.edutemplate <class Impl> 4693101Sstever@eecs.umich.eduvoid 4703101Sstever@eecs.umich.eduDefaultDecode<Impl>::sortInsts() 4713101Sstever@eecs.umich.edu{ 4723101Sstever@eecs.umich.edu int insts_from_fetch = fromFetch->size; 4733101Sstever@eecs.umich.edu for (int i = 0; i < insts_from_fetch; ++i) { 4743101Sstever@eecs.umich.edu insts[fromFetch->insts[i]->threadNumber].push(fromFetch->insts[i]); 4753101Sstever@eecs.umich.edu } 4763101Sstever@eecs.umich.edu} 4773101Sstever@eecs.umich.edu 4783101Sstever@eecs.umich.edutemplate<class Impl> 4793101Sstever@eecs.umich.eduvoid 4803101Sstever@eecs.umich.eduDefaultDecode<Impl>::readStallSignals(ThreadID tid) 4813101Sstever@eecs.umich.edu{ 4823101Sstever@eecs.umich.edu if (fromRename->renameBlock[tid]) { 4833101Sstever@eecs.umich.edu stalls[tid].rename = true; 4843101Sstever@eecs.umich.edu } 4853101Sstever@eecs.umich.edu 4863101Sstever@eecs.umich.edu if (fromRename->renameUnblock[tid]) { 4873101Sstever@eecs.umich.edu assert(stalls[tid].rename); 4883101Sstever@eecs.umich.edu stalls[tid].rename = false; 4893101Sstever@eecs.umich.edu } 4903101Sstever@eecs.umich.edu} 4913101Sstever@eecs.umich.edu 4923101Sstever@eecs.umich.edutemplate <class Impl> 49310380SAndrew.Bardsley@arm.combool 49410380SAndrew.Bardsley@arm.comDefaultDecode<Impl>::checkSignalsAndUpdate(ThreadID tid) 49510380SAndrew.Bardsley@arm.com{ 49610458Sandreas.hansson@arm.com // Check if there's a squash signal, squash if there is. 49710458Sandreas.hansson@arm.com // Check stall signals, block if necessary. 49810458Sandreas.hansson@arm.com // If status was blocked 49910458Sandreas.hansson@arm.com // Check if stall conditions have passed 50010458Sandreas.hansson@arm.com // if so then go to unblocking 50110458Sandreas.hansson@arm.com // If status was Squashing 50210458Sandreas.hansson@arm.com // check if squashing is not high. Switch to running this cycle. 50310458Sandreas.hansson@arm.com 50410458Sandreas.hansson@arm.com // Update the per thread stall statuses. 50510458Sandreas.hansson@arm.com readStallSignals(tid); 50610458Sandreas.hansson@arm.com 50710458Sandreas.hansson@arm.com // Check squash signals from commit. 50810458Sandreas.hansson@arm.com if (fromCommit->commitInfo[tid].squash) { 5093101Sstever@eecs.umich.edu 5105033Smilesck@eecs.umich.edu DPRINTF(Decode, "[tid:%u]: Squashing instructions due to squash " 5113101Sstever@eecs.umich.edu "from commit.\n", tid); 5123101Sstever@eecs.umich.edu 5133101Sstever@eecs.umich.edu squash(tid); 5143101Sstever@eecs.umich.edu 5153101Sstever@eecs.umich.edu return true; 5163101Sstever@eecs.umich.edu } 5173101Sstever@eecs.umich.edu 5183101Sstever@eecs.umich.edu if (checkStall(tid)) { 5193101Sstever@eecs.umich.edu return block(tid); 5203101Sstever@eecs.umich.edu } 5213101Sstever@eecs.umich.edu 5223101Sstever@eecs.umich.edu if (decodeStatus[tid] == Blocked) { 5235822Ssaidi@eecs.umich.edu DPRINTF(Decode, "[tid:%u]: Done blocking, switching to unblocking.\n", 5245822Ssaidi@eecs.umich.edu tid); 5253101Sstever@eecs.umich.edu 5263101Sstever@eecs.umich.edu decodeStatus[tid] = Unblocking; 5273101Sstever@eecs.umich.edu 5283101Sstever@eecs.umich.edu unblock(tid); 5293101Sstever@eecs.umich.edu 5303101Sstever@eecs.umich.edu return true; 5313101Sstever@eecs.umich.edu } 5323101Sstever@eecs.umich.edu 5333101Sstever@eecs.umich.edu if (decodeStatus[tid] == Squashing) { 5343101Sstever@eecs.umich.edu // Switch status to running if decode isn't being told to block or 5353101Sstever@eecs.umich.edu // squash this cycle. 5363101Sstever@eecs.umich.edu DPRINTF(Decode, "[tid:%u]: Done squashing, switching to running.\n", 5373101Sstever@eecs.umich.edu tid); 53810267SGeoffrey.Blake@arm.com 5393101Sstever@eecs.umich.edu decodeStatus[tid] = Running; 5403101Sstever@eecs.umich.edu 5413101Sstever@eecs.umich.edu return false; 5423101Sstever@eecs.umich.edu } 5433101Sstever@eecs.umich.edu 5443101Sstever@eecs.umich.edu // If we've reached this point, we have not gotten any signals that 5453101Sstever@eecs.umich.edu // cause decode to change its status. Decode remains the same as before. 5463101Sstever@eecs.umich.edu return false; 5473102Sstever@eecs.umich.edu} 5483714Sstever@eecs.umich.edu 5493101Sstever@eecs.umich.edutemplate<class Impl> 5503714Sstever@eecs.umich.eduvoid 5513714Sstever@eecs.umich.eduDefaultDecode<Impl>::tick() 5523714Sstever@eecs.umich.edu{ 5533101Sstever@eecs.umich.edu wroteToTimeBuffer = false; 5543101Sstever@eecs.umich.edu 55510267SGeoffrey.Blake@arm.com bool status_change = false; 55610267SGeoffrey.Blake@arm.com 55710267SGeoffrey.Blake@arm.com toRenameIndex = 0; 55810267SGeoffrey.Blake@arm.com 5597673Snate@binkert.org list<ThreadID>::iterator threads = activeThreads->begin(); 5607673Snate@binkert.org list<ThreadID>::iterator end = activeThreads->end(); 5617673Snate@binkert.org 5627673Snate@binkert.org sortInsts(); 5637673Snate@binkert.org 5644762Snate@binkert.org //Check stall and squash signals. 5654762Snate@binkert.org while (threads != end) { 5664762Snate@binkert.org ThreadID tid = *threads++; 5673101Sstever@eecs.umich.edu 5683101Sstever@eecs.umich.edu DPRINTF(Decode,"Processing [tid:%i]\n",tid); 5693101Sstever@eecs.umich.edu status_change = checkSignalsAndUpdate(tid) || status_change; 5703101Sstever@eecs.umich.edu 5713101Sstever@eecs.umich.edu decode(status_change, tid); 5723101Sstever@eecs.umich.edu } 5733101Sstever@eecs.umich.edu 5743101Sstever@eecs.umich.edu if (status_change) { 5753101Sstever@eecs.umich.edu updateStatus(); 5763101Sstever@eecs.umich.edu } 5773101Sstever@eecs.umich.edu 5783101Sstever@eecs.umich.edu if (wroteToTimeBuffer) { 5793101Sstever@eecs.umich.edu DPRINTF(Activity, "Activity this cycle.\n"); 5803101Sstever@eecs.umich.edu 5813101Sstever@eecs.umich.edu cpu->activityThisCycle(); 5823101Sstever@eecs.umich.edu } 5833101Sstever@eecs.umich.edu} 5843101Sstever@eecs.umich.edu 5853101Sstever@eecs.umich.edutemplate<class Impl> 5869184Sandreas.hansson@arm.comvoid 5879184Sandreas.hansson@arm.comDefaultDecode<Impl>::decode(bool &status_change, ThreadID tid) 5889184Sandreas.hansson@arm.com{ 5899184Sandreas.hansson@arm.com // If status is Running or idle, 5909184Sandreas.hansson@arm.com // call decodeInsts() 5919184Sandreas.hansson@arm.com // If status is Unblocking, 59211802Sandreas.sandberg@arm.com // buffer any instructions coming from fetch 5939184Sandreas.hansson@arm.com // continue trying to empty skid buffer 5949184Sandreas.hansson@arm.com // check if stall conditions have passed 59510458Sandreas.hansson@arm.com 59610458Sandreas.hansson@arm.com if (decodeStatus[tid] == Blocked) { 59710458Sandreas.hansson@arm.com ++decodeBlockedCycles; 59810458Sandreas.hansson@arm.com } else if (decodeStatus[tid] == Squashing) { 59910458Sandreas.hansson@arm.com ++decodeSquashCycles; 60010458Sandreas.hansson@arm.com } 60110458Sandreas.hansson@arm.com 60210458Sandreas.hansson@arm.com // Decode should try to decode as many instructions as its bandwidth 60310458Sandreas.hansson@arm.com // will allow, as long as it is not currently blocked. 60410458Sandreas.hansson@arm.com if (decodeStatus[tid] == Running || 60510458Sandreas.hansson@arm.com decodeStatus[tid] == Idle) { 60610458Sandreas.hansson@arm.com DPRINTF(Decode, "[tid:%u]: Not blocked, so attempting to run " 60710458Sandreas.hansson@arm.com "stage.\n",tid); 60810458Sandreas.hansson@arm.com 6093101Sstever@eecs.umich.edu decodeInsts(tid); 6104446Sbinkertn@umich.edu } else if (decodeStatus[tid] == Unblocking) { 61110668SGeoffrey.Blake@arm.com // Make sure that the skid buffer has something in it if the 6123101Sstever@eecs.umich.edu // status is unblocking. 6135468Snate@binkert.org assert(!skidsEmpty()); 61410267SGeoffrey.Blake@arm.com 6155468Snate@binkert.org // If the status was unblocking, then instructions from the skid 6165468Snate@binkert.org // buffer were used. Remove those instructions and handle 6175468Snate@binkert.org // the rest of unblocking. 6185468Snate@binkert.org decodeInsts(tid); 6195468Snate@binkert.org 62010267SGeoffrey.Blake@arm.com if (fetchInstsValid()) { 62110267SGeoffrey.Blake@arm.com // Add the current inputs to the skid buffer so they can be 62210267SGeoffrey.Blake@arm.com // reprocessed when this stage unblocks. 62310267SGeoffrey.Blake@arm.com skidInsert(tid); 6244762Snate@binkert.org } 6254762Snate@binkert.org 6264762Snate@binkert.org status_change = unblock(tid) || status_change; 62710380SAndrew.Bardsley@arm.com } 62810380SAndrew.Bardsley@arm.com} 62910380SAndrew.Bardsley@arm.com 63010458Sandreas.hansson@arm.comtemplate <class Impl> 63110458Sandreas.hansson@arm.comvoid 63210458Sandreas.hansson@arm.comDefaultDecode<Impl>::decodeInsts(ThreadID tid) 63310458Sandreas.hansson@arm.com{ 63410458Sandreas.hansson@arm.com // Instructions can come either from the skid buffer or the list of 63510458Sandreas.hansson@arm.com // instructions coming from fetch, depending on decode's status. 63610458Sandreas.hansson@arm.com int insts_available = decodeStatus[tid] == Unblocking ? 63710458Sandreas.hansson@arm.com skidBuffer[tid].size() : insts[tid].size(); 6383101Sstever@eecs.umich.edu 6393101Sstever@eecs.umich.edu if (insts_available == 0) { 64010267SGeoffrey.Blake@arm.com DPRINTF(Decode, "[tid:%u] Nothing to do, breaking out" 6413101Sstever@eecs.umich.edu " early.\n",tid); 6423101Sstever@eecs.umich.edu // Should I change the status to idle? 6433101Sstever@eecs.umich.edu ++decodeIdleCycles; 6443101Sstever@eecs.umich.edu return; 6453101Sstever@eecs.umich.edu } else if (decodeStatus[tid] == Unblocking) { 6463101Sstever@eecs.umich.edu DPRINTF(Decode, "[tid:%u] Unblocking, removing insts from skid " 6473102Sstever@eecs.umich.edu "buffer.\n",tid); 6483101Sstever@eecs.umich.edu ++decodeUnblockCycles; 6493101Sstever@eecs.umich.edu } else if (decodeStatus[tid] == Running) { 6503101Sstever@eecs.umich.edu ++decodeRunCycles; 6514168Sbinkertn@umich.edu } 65210267SGeoffrey.Blake@arm.com 6533101Sstever@eecs.umich.edu std::queue<DynInstPtr> 6543101Sstever@eecs.umich.edu &insts_to_decode = decodeStatus[tid] == Unblocking ? 6553101Sstever@eecs.umich.edu skidBuffer[tid] : insts[tid]; 6563101Sstever@eecs.umich.edu 6573101Sstever@eecs.umich.edu DPRINTF(Decode, "[tid:%u]: Sending instruction to rename.\n",tid); 6583101Sstever@eecs.umich.edu 6593102Sstever@eecs.umich.edu while (insts_available > 0 && toRenameIndex < decodeWidth) { 6603101Sstever@eecs.umich.edu assert(!insts_to_decode.empty()); 6613101Sstever@eecs.umich.edu 6623101Sstever@eecs.umich.edu DynInstPtr inst = std::move(insts_to_decode.front()); 6633101Sstever@eecs.umich.edu 6643101Sstever@eecs.umich.edu insts_to_decode.pop(); 6653101Sstever@eecs.umich.edu 6663101Sstever@eecs.umich.edu DPRINTF(Decode, "[tid:%u]: Processing instruction [sn:%lli] with " 6673101Sstever@eecs.umich.edu "PC %s\n", tid, inst->seqNum, inst->pcState()); 6683101Sstever@eecs.umich.edu 6693101Sstever@eecs.umich.edu if (inst->isSquashed()) { 6703101Sstever@eecs.umich.edu DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %s is " 67110317Smitch.hayenga@arm.com "squashed, skipping.\n", 67210317Smitch.hayenga@arm.com tid, inst->seqNum, inst->pcState()); 67310317Smitch.hayenga@arm.com 67410317Smitch.hayenga@arm.com ++decodeSquashedInsts; 67510317Smitch.hayenga@arm.com 6763102Sstever@eecs.umich.edu --insts_available; 67710317Smitch.hayenga@arm.com 67810317Smitch.hayenga@arm.com continue; 67910317Smitch.hayenga@arm.com } 68010317Smitch.hayenga@arm.com 68110317Smitch.hayenga@arm.com // Also check if instructions have no source registers. Mark 6823101Sstever@eecs.umich.edu // them as ready to issue at any time. Not sure if this check 6833584Ssaidi@eecs.umich.edu // should exist here or at a later stage; however it doesn't matter 6843584Ssaidi@eecs.umich.edu // too much for function correctness. 6853584Ssaidi@eecs.umich.edu if (inst->numSrcRegs() == 0) { 6863584Ssaidi@eecs.umich.edu inst->setCanIssue(); 6873584Ssaidi@eecs.umich.edu } 68810267SGeoffrey.Blake@arm.com 68910267SGeoffrey.Blake@arm.com // This current instruction is valid, so add it into the decode 69010267SGeoffrey.Blake@arm.com // queue. The next instruction may not be valid, so check to 69110267SGeoffrey.Blake@arm.com // see if branches were predicted correctly. 69210267SGeoffrey.Blake@arm.com toRename->insts[toRenameIndex] = inst; 69310267SGeoffrey.Blake@arm.com 6943101Sstever@eecs.umich.edu ++(toRename->size); 6959232Sandreas.hansson@arm.com ++toRenameIndex; 6969235Sandreas.hansson@arm.com ++decodeDecodedInsts; 6973101Sstever@eecs.umich.edu --insts_available; 6983101Sstever@eecs.umich.edu 69910676Sandreas.hansson@arm.com#if TRACING_ON 7009411Sandreas.hansson@arm.com if (DTRACE(O3PipeView)) { 70110676Sandreas.hansson@arm.com inst->decodeTick = curTick() - inst->fetchTick; 7029411Sandreas.hansson@arm.com } 7039411Sandreas.hansson@arm.com#endif 7049411Sandreas.hansson@arm.com 7053101Sstever@eecs.umich.edu // Ensure that if it was predicted as a branch, it really is a 7069411Sandreas.hansson@arm.com // branch. 7079411Sandreas.hansson@arm.com if (inst->readPredTaken() && !inst->isControl()) { 7089411Sandreas.hansson@arm.com panic("Instruction predicted as a branch!"); 7093101Sstever@eecs.umich.edu 7109232Sandreas.hansson@arm.com ++decodeControlMispred; 7113101Sstever@eecs.umich.edu 7129232Sandreas.hansson@arm.com // Might want to set some sort of boolean and just do 7133101Sstever@eecs.umich.edu // a check at the end 7143101Sstever@eecs.umich.edu squash(inst, inst->threadNumber); 7153101Sstever@eecs.umich.edu 7169411Sandreas.hansson@arm.com break; 7179411Sandreas.hansson@arm.com } 7189411Sandreas.hansson@arm.com 71910676Sandreas.hansson@arm.com // Go ahead and compute any PC-relative branches. 72010676Sandreas.hansson@arm.com // This includes direct unconditional control and 7219411Sandreas.hansson@arm.com // direct conditional control that is predicted taken. 7229411Sandreas.hansson@arm.com if (inst->isDirectCtrl() && 7239411Sandreas.hansson@arm.com (inst->isUncondCtrl() || inst->readPredTaken())) 7249411Sandreas.hansson@arm.com { 7259411Sandreas.hansson@arm.com ++decodeBranchResolved; 7263101Sstever@eecs.umich.edu 7279232Sandreas.hansson@arm.com if (!(inst->branchTarget() == inst->readPredTarg())) { 7283101Sstever@eecs.umich.edu ++decodeBranchMispred; 7293101Sstever@eecs.umich.edu 7303101Sstever@eecs.umich.edu // Might want to set some sort of boolean and just do 7313101Sstever@eecs.umich.edu // a check at the end 7329232Sandreas.hansson@arm.com squash(inst, inst->threadNumber); 7333101Sstever@eecs.umich.edu TheISA::PCState target = inst->branchTarget(); 7345219Ssaidi@eecs.umich.edu 7359232Sandreas.hansson@arm.com DPRINTF(Decode, "[sn:%i]: Updating predictions: PredPC: %s\n", 7369232Sandreas.hansson@arm.com inst->seqNum, target); 7373101Sstever@eecs.umich.edu //The micro pc after an instruction level branch should be 0 7389232Sandreas.hansson@arm.com inst->setPredTarg(target); 7399232Sandreas.hansson@arm.com break; 7403101Sstever@eecs.umich.edu } 7413101Sstever@eecs.umich.edu } 7429232Sandreas.hansson@arm.com } 7439232Sandreas.hansson@arm.com 7443101Sstever@eecs.umich.edu // If we didn't process all instructions, then we will need to block 7453101Sstever@eecs.umich.edu // and put all those instructions into the skid buffer. 7463101Sstever@eecs.umich.edu if (!insts_to_decode.empty()) { 7473101Sstever@eecs.umich.edu block(tid); 7489232Sandreas.hansson@arm.com } 7493101Sstever@eecs.umich.edu 7503101Sstever@eecs.umich.edu // Record that decode has written to the time buffer for activity 75111620SMatthew.Poremba@amd.com // tracking. 75211620SMatthew.Poremba@amd.com if (toRenameIndex) { 75311620SMatthew.Poremba@amd.com wroteToTimeBuffer = true; 7549232Sandreas.hansson@arm.com } 7559232Sandreas.hansson@arm.com} 7569411Sandreas.hansson@arm.com 7579411Sandreas.hansson@arm.com#endif//__CPU_O3_DECODE_IMPL_HH__ 7583101Sstever@eecs.umich.edu