decode_impl.hh revision 8230
12968SN/A/* 22968SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan 32968SN/A * All rights reserved. 49988Snilay@cs.wisc.edu * 58835SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 69988Snilay@cs.wisc.edu * modification, are permitted provided that the following conditions are 77935SN/A * met: redistributions of source code must retain the above copyright 87935SN/A * notice, this list of conditions and the following disclaimer; 97935SN/A * redistributions in binary form must reproduce the above copyright 102968SN/A * notice, this list of conditions and the following disclaimer in the 112968SN/A * documentation and/or other materials provided with the distribution; 122968SN/A * neither the name of the copyright holders nor the names of its 1310315Snilay@cs.wisc.edu * contributors may be used to endorse or promote products derived from 144463SN/A * this software without specific prior written permission. 152968SN/A * 169885Sstever@gmail.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 179885Sstever@gmail.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1811570SCurtis.Dunham@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1911570SCurtis.Dunham@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 209988Snilay@cs.wisc.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2111312Santhony.gutierrez@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222968SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2311570SCurtis.Dunham@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2410315Snilay@cs.wisc.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257670SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2610315Snilay@cs.wisc.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272968SN/A * 289481Snilay@cs.wisc.edu * Authors: Kevin Lim 298721SN/A */ 3010736Snilay@cs.wisc.edu 3111219Snilay@cs.wisc.edu#include "arch/types.hh" 328721SN/A#include "base/trace.hh" 3311570SCurtis.Dunham@arm.com#include "config/full_system.hh" 3411570SCurtis.Dunham@arm.com#include "config/the_isa.hh" 3511570SCurtis.Dunham@arm.com#include "cpu/o3/decode.hh" 3611570SCurtis.Dunham@arm.com#include "cpu/inst_seq.hh" 3711570SCurtis.Dunham@arm.com#include "params/DerivO3CPU.hh" 3811570SCurtis.Dunham@arm.com 393140SN/Ausing namespace std; 402968SN/A 412968SN/Atemplate<class Impl> 4211440SCurtis.Dunham@arm.comDefaultDecode<Impl>::DefaultDecode(O3CPU *_cpu, DerivO3CPUParams *params) 4311440SCurtis.Dunham@arm.com : cpu(_cpu), 447935SN/A renameToDecodeDelay(params->renameToDecodeDelay), 457935SN/A iewToDecodeDelay(params->iewToDecodeDelay), 467935SN/A commitToDecodeDelay(params->commitToDecodeDelay), 477935SN/A fetchToDecodeDelay(params->fetchToDecodeDelay), 487935SN/A decodeWidth(params->decodeWidth), 497935SN/A numThreads(params->numThreads) 507935SN/A{ 518983Snate@binkert.org _status = Inactive; 522968SN/A 532968SN/A // Setup status, make sure stall signals are clear. 542968SN/A for (ThreadID tid = 0; tid < numThreads; ++tid) { 559885Sstever@gmail.com decodeStatus[tid] = Idle; 5611570SCurtis.Dunham@arm.com 574463SN/A stalls[tid].rename = false; 589988Snilay@cs.wisc.edu stalls[tid].iew = false; 5911570SCurtis.Dunham@arm.com stalls[tid].commit = false; 6011570SCurtis.Dunham@arm.com } 6111570SCurtis.Dunham@arm.com 6211570SCurtis.Dunham@arm.com // @todo: Make into a parameter 638721SN/A skidBufferMax = (fetchToDecodeDelay * params->fetchWidth) + decodeWidth; 648721SN/A} 658721SN/A 668983Snate@binkert.orgtemplate <class Impl> 678983Snate@binkert.orgstd::string 682968SN/ADefaultDecode<Impl>::name() const 699885Sstever@gmail.com{ 709885Sstever@gmail.com return cpu->name() + ".decode"; 719885Sstever@gmail.com} 7210315Snilay@cs.wisc.edu 739988Snilay@cs.wisc.edutemplate <class Impl> 7410315Snilay@cs.wisc.eduvoid 759885Sstever@gmail.comDefaultDecode<Impl>::regStats() 769885Sstever@gmail.com{ 772968SN/A decodeIdleCycles 782968SN/A .name(name() + ".DECODE:IdleCycles") 799481Snilay@cs.wisc.edu .desc("Number of cycles decode is idle") 8010315Snilay@cs.wisc.edu .prereq(decodeIdleCycles); 815876SN/A decodeBlockedCycles 829885Sstever@gmail.com .name(name() + ".DECODE:BlockedCycles") 833171SN/A .desc("Number of cycles decode is blocked") 8411570SCurtis.Dunham@arm.com .prereq(decodeBlockedCycles); 853638SN/A decodeRunCycles 863638SN/A .name(name() + ".DECODE:RunCycles") 873638SN/A .desc("Number of cycles decode is running") 882968SN/A .prereq(decodeRunCycles); 899988Snilay@cs.wisc.edu decodeUnblockCycles 908983Snate@binkert.org .name(name() + ".DECODE:UnblockCycles") 912968SN/A .desc("Number of cycles decode is unblocking") 922968SN/A .prereq(decodeUnblockCycles); 935723SN/A decodeSquashCycles 949481Snilay@cs.wisc.edu .name(name() + ".DECODE:SquashCycles") 952968SN/A .desc("Number of cycles decode is squashing") 962968SN/A .prereq(decodeSquashCycles); 972968SN/A decodeBranchResolved 982968SN/A .name(name() + ".DECODE:BranchResolved") 992968SN/A .desc("Number of times decode resolved a branch") 1005575SN/A .prereq(decodeBranchResolved); 10111570SCurtis.Dunham@arm.com decodeBranchMispred 10211570SCurtis.Dunham@arm.com .name(name() + ".DECODE:BranchMispred") 10311570SCurtis.Dunham@arm.com .desc("Number of times decode detected a branch misprediction") 10411570SCurtis.Dunham@arm.com .prereq(decodeBranchMispred); 1052968SN/A decodeControlMispred 1063140SN/A .name(name() + ".DECODE:ControlMispred") 1079885Sstever@gmail.com .desc("Number of times decode detected an instruction incorrectly" 1085509SN/A " predicted as a control") 1095509SN/A .prereq(decodeControlMispred); 11010315Snilay@cs.wisc.edu decodeDecodedInsts 1119481Snilay@cs.wisc.edu .name(name() + ".DECODE:DecodedInsts") 1122968SN/A .desc("Number of instructions handled by decode") 1134938SN/A .prereq(decodeDecodedInsts); 1142968SN/A decodeSquashedInsts 1158835SAli.Saidi@ARM.com .name(name() + ".DECODE:SquashedInsts") 1164463SN/A .desc("Number of squashed instructions handled by decode") 1174463SN/A .prereq(decodeSquashedInsts); 1184463SN/A} 1194463SN/A 12011103Snilay@cs.wisc.edutemplate<class Impl> 1219885Sstever@gmail.comvoid 1228983Snate@binkert.orgDefaultDecode<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 1234463SN/A{ 1249885Sstever@gmail.com timeBuffer = tb_ptr; 12511219Snilay@cs.wisc.edu 12611570SCurtis.Dunham@arm.com // Setup wire to write information back to fetch. 12710636Snilay@cs.wisc.edu toFetch = timeBuffer->getWire(0); 1289988Snilay@cs.wisc.edu 1299481Snilay@cs.wisc.edu // Create wires to get information from proper places in time buffer. 13011103Snilay@cs.wisc.edu fromRename = timeBuffer->getWire(-renameToDecodeDelay); 1314463SN/A fromIEW = timeBuffer->getWire(-iewToDecodeDelay); 1324463SN/A fromCommit = timeBuffer->getWire(-commitToDecodeDelay); 13311570SCurtis.Dunham@arm.com} 13411570SCurtis.Dunham@arm.com 13511570SCurtis.Dunham@arm.comtemplate<class Impl> 13611570SCurtis.Dunham@arm.comvoid 1375876SN/ADefaultDecode<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr) 1388835SAli.Saidi@ARM.com{ 1399481Snilay@cs.wisc.edu decodeQueue = dq_ptr; 14010036SAli.Saidi@ARM.com 1414463SN/A // Setup wire to write information to proper place in decode queue. 1428835SAli.Saidi@ARM.com toRename = decodeQueue->getWire(0); 1439885Sstever@gmail.com} 1449481Snilay@cs.wisc.edu 1454463SN/Atemplate<class Impl> 14611219Snilay@cs.wisc.eduvoid 1474463SN/ADefaultDecode<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr) 1489481Snilay@cs.wisc.edu{ 1494463SN/A fetchQueue = fq_ptr; 1509885Sstever@gmail.com 1519885Sstever@gmail.com // Setup wire to read information from fetch queue. 1529885Sstever@gmail.com fromFetch = fetchQueue->getWire(-fetchToDecodeDelay); 1539885Sstever@gmail.com} 1549885Sstever@gmail.com 15511570SCurtis.Dunham@arm.comtemplate<class Impl> 1569988Snilay@cs.wisc.eduvoid 1579885Sstever@gmail.comDefaultDecode<Impl>::setActiveThreads(std::list<ThreadID> *at_ptr) 15811570SCurtis.Dunham@arm.com{ 15911570SCurtis.Dunham@arm.com activeThreads = at_ptr; 16011570SCurtis.Dunham@arm.com} 16111570SCurtis.Dunham@arm.com 16210036SAli.Saidi@ARM.comtemplate <class Impl> 1639885Sstever@gmail.combool 1649885Sstever@gmail.comDefaultDecode<Impl>::drain() 1652968SN/A{ 1666024SN/A // Decode is done draining at any time. 1679988Snilay@cs.wisc.edu cpu->signalDrained(); 1682968SN/A return true; 1692968SN/A} 1704463SN/A 17111103Snilay@cs.wisc.edutemplate <class Impl> 1729885Sstever@gmail.comvoid 1738983Snate@binkert.orgDefaultDecode<Impl>::takeOverFrom() 1744463SN/A{ 1759885Sstever@gmail.com _status = Inactive; 17611219Snilay@cs.wisc.edu 17711570SCurtis.Dunham@arm.com // Be sure to reset state and clear out any old instructions. 17810636Snilay@cs.wisc.edu for (ThreadID tid = 0; tid < numThreads; ++tid) { 1799988Snilay@cs.wisc.edu decodeStatus[tid] = Idle; 1809481Snilay@cs.wisc.edu 18111103Snilay@cs.wisc.edu stalls[tid].rename = false; 1824463SN/A stalls[tid].iew = false; 1834463SN/A stalls[tid].commit = false; 18411570SCurtis.Dunham@arm.com while (!insts[tid].empty()) 18511570SCurtis.Dunham@arm.com insts[tid].pop(); 18611570SCurtis.Dunham@arm.com while (!skidBuffer[tid].empty()) 18711570SCurtis.Dunham@arm.com skidBuffer[tid].pop(); 1885876SN/A branchCount[tid] = 0; 1898835SAli.Saidi@ARM.com } 1909481Snilay@cs.wisc.edu wroteToTimeBuffer = false; 19110036SAli.Saidi@ARM.com} 1924463SN/A 1938835SAli.Saidi@ARM.comtemplate<class Impl> 1949885Sstever@gmail.combool 1959481Snilay@cs.wisc.eduDefaultDecode<Impl>::checkStall(ThreadID tid) const 1964463SN/A{ 19711219Snilay@cs.wisc.edu bool ret_val = false; 1984463SN/A 1999481Snilay@cs.wisc.edu if (stalls[tid].rename) { 2004463SN/A DPRINTF(Decode,"[tid:%i]: Stall fom Rename stage detected.\n", tid); 2019885Sstever@gmail.com ret_val = true; 2029885Sstever@gmail.com } else if (stalls[tid].iew) { 2039885Sstever@gmail.com DPRINTF(Decode,"[tid:%i]: Stall fom IEW stage detected.\n", tid); 2049885Sstever@gmail.com ret_val = true; 2059885Sstever@gmail.com } else if (stalls[tid].commit) { 20611570SCurtis.Dunham@arm.com DPRINTF(Decode,"[tid:%i]: Stall fom Commit stage detected.\n", tid); 2079988Snilay@cs.wisc.edu ret_val = true; 2089885Sstever@gmail.com } 20911570SCurtis.Dunham@arm.com 21011570SCurtis.Dunham@arm.com return ret_val; 21111570SCurtis.Dunham@arm.com} 21211570SCurtis.Dunham@arm.com 21310036SAli.Saidi@ARM.comtemplate<class Impl> 2149885Sstever@gmail.cominline bool 2159885Sstever@gmail.comDefaultDecode<Impl>::fetchInstsValid() 2165723SN/A{ 2175723SN/A return fromFetch->size > 0; 2189988Snilay@cs.wisc.edu} 2195723SN/A 2209481Snilay@cs.wisc.edutemplate<class Impl> 2219481Snilay@cs.wisc.edubool 2229988Snilay@cs.wisc.eduDefaultDecode<Impl>::block(ThreadID tid) 22310036SAli.Saidi@ARM.com{ 2249481Snilay@cs.wisc.edu DPRINTF(Decode, "[tid:%u]: Blocking.\n", tid); 2252968SN/A 2266024SN/A // Add the current inputs to the skid buffer so they can be 2279988Snilay@cs.wisc.edu // reprocessed when this stage unblocks. 2282968SN/A skidInsert(tid); 2292968SN/A 2309481Snilay@cs.wisc.edu // If the decode status is blocked or unblocking then decode has not yet 23111103Snilay@cs.wisc.edu // signalled fetch to unblock. In that case, there is no need to tell 2329885Sstever@gmail.com // fetch to block. 2339481Snilay@cs.wisc.edu if (decodeStatus[tid] != Blocked) { 2349481Snilay@cs.wisc.edu // Set the status to Blocked. 2359885Sstever@gmail.com decodeStatus[tid] = Blocked; 23611219Snilay@cs.wisc.edu 23711570SCurtis.Dunham@arm.com if (decodeStatus[tid] != Unblocking) { 23810636Snilay@cs.wisc.edu toFetch->decodeBlock[tid] = true; 2399988Snilay@cs.wisc.edu wroteToTimeBuffer = true; 2409481Snilay@cs.wisc.edu } 24111103Snilay@cs.wisc.edu 2429481Snilay@cs.wisc.edu return true; 2439481Snilay@cs.wisc.edu } 24411570SCurtis.Dunham@arm.com 24511570SCurtis.Dunham@arm.com return false; 24611570SCurtis.Dunham@arm.com} 24711570SCurtis.Dunham@arm.com 2489481Snilay@cs.wisc.edutemplate<class Impl> 2499481Snilay@cs.wisc.edubool 2509481Snilay@cs.wisc.eduDefaultDecode<Impl>::unblock(ThreadID tid) 25110036SAli.Saidi@ARM.com{ 2529481Snilay@cs.wisc.edu // Decode is done unblocking only if the skid buffer is empty. 2539481Snilay@cs.wisc.edu if (skidBuffer[tid].empty()) { 2549885Sstever@gmail.com DPRINTF(Decode, "[tid:%u]: Done unblocking.\n", tid); 2559481Snilay@cs.wisc.edu toFetch->decodeUnblock[tid] = true; 2569481Snilay@cs.wisc.edu wroteToTimeBuffer = true; 25711219Snilay@cs.wisc.edu 2589481Snilay@cs.wisc.edu decodeStatus[tid] = Running; 2599481Snilay@cs.wisc.edu return true; 2609481Snilay@cs.wisc.edu } 2619885Sstever@gmail.com 2629885Sstever@gmail.com DPRINTF(Decode, "[tid:%u]: Currently unblocking.\n", tid); 2639885Sstever@gmail.com 2649885Sstever@gmail.com return false; 2659885Sstever@gmail.com} 26611570SCurtis.Dunham@arm.com 2679988Snilay@cs.wisc.edutemplate<class Impl> 2689885Sstever@gmail.comvoid 26911570SCurtis.Dunham@arm.comDefaultDecode<Impl>::squash(DynInstPtr &inst, ThreadID tid) 27011570SCurtis.Dunham@arm.com{ 27111570SCurtis.Dunham@arm.com DPRINTF(Decode, "[tid:%i]: [sn:%i] Squashing due to incorrect branch " 27211570SCurtis.Dunham@arm.com "prediction detected at decode.\n", tid, inst->seqNum); 27310036SAli.Saidi@ARM.com 2749885Sstever@gmail.com // Send back mispredict information. 2759885Sstever@gmail.com toFetch->decodeInfo[tid].branchMispredict = true; 2769481Snilay@cs.wisc.edu toFetch->decodeInfo[tid].predIncorrect = true; 27710451Snilay@cs.wisc.edu toFetch->decodeInfo[tid].squash = true; 27811219Snilay@cs.wisc.edu toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum; 2799885Sstever@gmail.com toFetch->decodeInfo[tid].nextPC = inst->branchTarget(); 28011570SCurtis.Dunham@arm.com toFetch->decodeInfo[tid].branchTaken = inst->pcState().branching(); 2819988Snilay@cs.wisc.edu 28210736Snilay@cs.wisc.edu InstSeqNum squash_seq_num = inst->seqNum; 28310736Snilay@cs.wisc.edu 28411570SCurtis.Dunham@arm.com // Might have to tell fetch to unblock. 28511570SCurtis.Dunham@arm.com if (decodeStatus[tid] == Blocked || 28611570SCurtis.Dunham@arm.com decodeStatus[tid] == Unblocking) { 28711440SCurtis.Dunham@arm.com toFetch->decodeUnblock[tid] = 1; 28811570SCurtis.Dunham@arm.com } 28910736Snilay@cs.wisc.edu 29011219Snilay@cs.wisc.edu // Set status to squashing. 29110736Snilay@cs.wisc.edu decodeStatus[tid] = Squashing; 2929885Sstever@gmail.com 2939481Snilay@cs.wisc.edu for (int i=0; i<fromFetch->size; i++) { 2949481Snilay@cs.wisc.edu if (fromFetch->insts[i]->threadNumber == tid && 2959481Snilay@cs.wisc.edu fromFetch->insts[i]->seqNum > squash_seq_num) { 2969481Snilay@cs.wisc.edu fromFetch->insts[i]->setSquashed(); 2979481Snilay@cs.wisc.edu } 29811219Snilay@cs.wisc.edu } 29911219Snilay@cs.wisc.edu 30011219Snilay@cs.wisc.edu // Clear the instruction list and skid buffer in case they have any 30111219Snilay@cs.wisc.edu // insts in them. 30211219Snilay@cs.wisc.edu while (!insts[tid].empty()) { 30311219Snilay@cs.wisc.edu insts[tid].pop(); 30411219Snilay@cs.wisc.edu } 3054938SN/A 3064938SN/A while (!skidBuffer[tid].empty()) { 3079988Snilay@cs.wisc.edu skidBuffer[tid].pop(); 3084938SN/A } 3099885Sstever@gmail.com 3109885Sstever@gmail.com // Squash instructions up until this one 3119885Sstever@gmail.com cpu->removeInstsUntil(squash_seq_num, tid); 31210315Snilay@cs.wisc.edu} 3139988Snilay@cs.wisc.edu 31410315Snilay@cs.wisc.edutemplate<class Impl> 3159885Sstever@gmail.comunsigned 3169885Sstever@gmail.comDefaultDecode<Impl>::squash(ThreadID tid) 3172968SN/A{ 3182968SN/A DPRINTF(Decode, "[tid:%i]: Squashing.\n",tid); 3192968SN/A 3204463SN/A if (decodeStatus[tid] == Blocked || 3212968SN/A decodeStatus[tid] == Unblocking) { 3229988Snilay@cs.wisc.edu#if !FULL_SYSTEM 3232968SN/A // In syscall emulation, we can have both a block and a squash due 3242968SN/A // to a syscall in the same cycle. This would cause both signals to 3252968SN/A // be high. This shouldn't happen in full system. 3262968SN/A // @todo: Determine if this still happens. 3272968SN/A if (toFetch->decodeBlock[tid]) { 3282968SN/A toFetch->decodeBlock[tid] = 0; 3299988Snilay@cs.wisc.edu } else { 3305876SN/A toFetch->decodeUnblock[tid] = 1; 3312968SN/A } 3322968SN/A#else 3332968SN/A toFetch->decodeUnblock[tid] = 1; 3342968SN/A#endif 3352968SN/A } 3369988Snilay@cs.wisc.edu 33711570SCurtis.Dunham@arm.com // Set status to squashing. 3382968SN/A decodeStatus[tid] = Squashing; 3392968SN/A 3402968SN/A // Go through incoming instructions from fetch and squash them. 3412968SN/A unsigned squash_count = 0; 3422968SN/A 3434463SN/A for (int i=0; i<fromFetch->size; i++) { 3442968SN/A if (fromFetch->insts[i]->threadNumber == tid) { 3459988Snilay@cs.wisc.edu fromFetch->insts[i]->setSquashed(); 3462968SN/A squash_count++; 3472968SN/A } 3482968SN/A } 3492968SN/A 3502968SN/A // Clear the instruction list and skid buffer in case they have any 3512968SN/A // insts in them. 3529988Snilay@cs.wisc.edu while (!insts[tid].empty()) { 3535876SN/A insts[tid].pop(); 3542968SN/A } 3552968SN/A 3562968SN/A while (!skidBuffer[tid].empty()) { 3572968SN/A skidBuffer[tid].pop(); 3582968SN/A } 3599988Snilay@cs.wisc.edu 36011570SCurtis.Dunham@arm.com return squash_count; 3612968SN/A} 3622968SN/A 36310315Snilay@cs.wisc.edutemplate<class Impl> 36410315Snilay@cs.wisc.eduvoid 36510315Snilay@cs.wisc.eduDefaultDecode<Impl>::skidInsert(ThreadID tid) 36610315Snilay@cs.wisc.edu{ 36710315Snilay@cs.wisc.edu DynInstPtr inst = NULL; 36810315Snilay@cs.wisc.edu 36910315Snilay@cs.wisc.edu while (!insts[tid].empty()) { 37010315Snilay@cs.wisc.edu inst = insts[tid].front(); 3712968SN/A 3722968SN/A insts[tid].pop(); 3739988Snilay@cs.wisc.edu 3744103SN/A assert(tid == inst->threadNumber); 3752968SN/A 3762968SN/A DPRINTF(Decode,"Inserting [sn:%lli] PC: %s into decode skidBuffer %i\n", 37710451Snilay@cs.wisc.edu inst->seqNum, inst->pcState(), inst->threadNumber); 3789885Sstever@gmail.com 37911570SCurtis.Dunham@arm.com skidBuffer[tid].push(inst); 3809988Snilay@cs.wisc.edu } 38110736Snilay@cs.wisc.edu 38210736Snilay@cs.wisc.edu // @todo: Eventually need to enforce this by not letting a thread 38311570SCurtis.Dunham@arm.com // fetch past its skidbuffer 38411570SCurtis.Dunham@arm.com assert(skidBuffer[tid].size() <= skidBufferMax); 38511570SCurtis.Dunham@arm.com} 38611570SCurtis.Dunham@arm.com 38710736Snilay@cs.wisc.edutemplate<class Impl> 38811245Sandreas.sandberg@arm.combool 38910736Snilay@cs.wisc.eduDefaultDecode<Impl>::skidsEmpty() 39011245Sandreas.sandberg@arm.com{ 3918983Snate@binkert.org list<ThreadID>::iterator threads = activeThreads->begin(); 3924966SN/A list<ThreadID>::iterator end = activeThreads->end(); 3934966SN/A 39411103Snilay@cs.wisc.edu while (threads != end) { 3959885Sstever@gmail.com ThreadID tid = *threads++; 3969481Snilay@cs.wisc.edu if (!skidBuffer[tid].empty()) 3974966SN/A return false; 3989885Sstever@gmail.com } 39911219Snilay@cs.wisc.edu 40011570SCurtis.Dunham@arm.com return true; 40110636Snilay@cs.wisc.edu} 4029988Snilay@cs.wisc.edu 4039481Snilay@cs.wisc.edutemplate<class Impl> 40411103Snilay@cs.wisc.eduvoid 4054966SN/ADefaultDecode<Impl>::updateStatus() 4064966SN/A{ 40711570SCurtis.Dunham@arm.com bool any_unblocking = false; 40811570SCurtis.Dunham@arm.com 40911570SCurtis.Dunham@arm.com list<ThreadID>::iterator threads = activeThreads->begin(); 41011570SCurtis.Dunham@arm.com list<ThreadID>::iterator end = activeThreads->end(); 4115876SN/A 4128835SAli.Saidi@ARM.com while (threads != end) { 4139481Snilay@cs.wisc.edu ThreadID tid = *threads++; 41410036SAli.Saidi@ARM.com 4154966SN/A if (decodeStatus[tid] == Unblocking) { 4168835SAli.Saidi@ARM.com any_unblocking = true; 4179885Sstever@gmail.com break; 4184966SN/A } 4194966SN/A } 42011219Snilay@cs.wisc.edu 42111245Sandreas.sandberg@arm.com // Decode will have activity if it's unblocking. 4228983Snate@binkert.org if (any_unblocking) { 4234463SN/A if (_status == Inactive) { 4249885Sstever@gmail.com _status = Active; 4259885Sstever@gmail.com 4269885Sstever@gmail.com DPRINTF(Activity, "Activating stage.\n"); 4279885Sstever@gmail.com 4289885Sstever@gmail.com cpu->activateStage(O3CPU::DecodeIdx); 42911570SCurtis.Dunham@arm.com } 4309988Snilay@cs.wisc.edu } else { 4319885Sstever@gmail.com // If it's not unblocking, then decode will not have any internal 43211570SCurtis.Dunham@arm.com // activity. Switch it to inactive. 43311570SCurtis.Dunham@arm.com if (_status == Active) { 43411570SCurtis.Dunham@arm.com _status = Inactive; 43511570SCurtis.Dunham@arm.com DPRINTF(Activity, "Deactivating stage.\n"); 43610036SAli.Saidi@ARM.com 4379885Sstever@gmail.com cpu->deactivateStage(O3CPU::DecodeIdx); 4389885Sstever@gmail.com } 4392968SN/A } 44010451Snilay@cs.wisc.edu} 4416123SN/A 4429885Sstever@gmail.comtemplate <class Impl> 44311570SCurtis.Dunham@arm.comvoid 4449988Snilay@cs.wisc.eduDefaultDecode<Impl>::sortInsts() 44510736Snilay@cs.wisc.edu{ 44610736Snilay@cs.wisc.edu int insts_from_fetch = fromFetch->size; 44711570SCurtis.Dunham@arm.com#ifdef DEBUG 44811570SCurtis.Dunham@arm.com for (ThreadID tid = 0; tid < numThreads; tid++) 44911570SCurtis.Dunham@arm.com assert(insts[tid].empty()); 45011440SCurtis.Dunham@arm.com#endif 45111570SCurtis.Dunham@arm.com for (int i = 0; i < insts_from_fetch; ++i) { 45210736Snilay@cs.wisc.edu insts[fromFetch->insts[i]->threadNumber].push(fromFetch->insts[i]); 45310451Snilay@cs.wisc.edu } 45410736Snilay@cs.wisc.edu} 4559885Sstever@gmail.com 4567524SN/Atemplate<class Impl> 45710736Snilay@cs.wisc.eduvoid 4586123SN/ADefaultDecode<Impl>::readStallSignals(ThreadID tid) 4599134Ssaidi@eecs.umich.edu{ 4609481Snilay@cs.wisc.edu if (fromRename->renameBlock[tid]) { 4612968SN/A stalls[tid].rename = true; 4626123SN/A } 4633505SN/A 4649885Sstever@gmail.com if (fromRename->renameUnblock[tid]) { 46511570SCurtis.Dunham@arm.com assert(stalls[tid].rename); 4669988Snilay@cs.wisc.edu stalls[tid].rename = false; 4678721SN/A } 46811570SCurtis.Dunham@arm.com 46911570SCurtis.Dunham@arm.com if (fromIEW->iewBlock[tid]) { 47011570SCurtis.Dunham@arm.com stalls[tid].iew = true; 4713493SN/A } 4729481Snilay@cs.wisc.edu 4733505SN/A if (fromIEW->iewUnblock[tid]) { 47411570SCurtis.Dunham@arm.com assert(stalls[tid].iew); 4753505SN/A stalls[tid].iew = false; 4763934SN/A } 4773934SN/A 4783934SN/A if (fromCommit->commitBlock[tid]) { 4793934SN/A stalls[tid].commit = true; 4803493SN/A } 4813934SN/A 4823934SN/A if (fromCommit->commitUnblock[tid]) { 4833493SN/A assert(stalls[tid].commit); 4843493SN/A stalls[tid].commit = false; 4852968SN/A } 4869988Snilay@cs.wisc.edu} 4879988Snilay@cs.wisc.edu 4889885Sstever@gmail.comtemplate <class Impl> 4899885Sstever@gmail.combool 49011570SCurtis.Dunham@arm.comDefaultDecode<Impl>::checkSignalsAndUpdate(ThreadID tid) 4919988Snilay@cs.wisc.edu{ 4928983Snate@binkert.org // Check if there's a squash signal, squash if there is. 4939988Snilay@cs.wisc.edu // Check stall signals, block if necessary. 4949988Snilay@cs.wisc.edu // If status was blocked 4955509SN/A // Check if stall conditions have passed 49611570SCurtis.Dunham@arm.com // if so then go to unblocking 49711570SCurtis.Dunham@arm.com // If status was Squashing 49811570SCurtis.Dunham@arm.com // check if squashing is not high. Switch to running this cycle. 49911570SCurtis.Dunham@arm.com 5002968SN/A // Update the per thread stall statuses. 5018983Snate@binkert.org readStallSignals(tid); 5022968SN/A 5032968SN/A // Check squash signals from commit. 5042968SN/A if (fromCommit->commitInfo[tid].squash) { 5052968SN/A 5062968SN/A DPRINTF(Decode, "[tid:%u]: Squashing instructions due to squash " 5079988Snilay@cs.wisc.edu "from commit.\n", tid); 5082968SN/A 5092968SN/A squash(tid); 5102968SN/A 5112968SN/A return true; 5129988Snilay@cs.wisc.edu } 51311570SCurtis.Dunham@arm.com 5142968SN/A // Check ROB squash signals from commit. 5152968SN/A if (fromCommit->commitInfo[tid].robSquashing) { 5165509SN/A DPRINTF(Decode, "[tid:%u]: ROB is still squashing.\n", tid); 5175509SN/A 5189988Snilay@cs.wisc.edu // Continue to squash. 5195509SN/A decodeStatus[tid] = Squashing; 5205509SN/A 5215509SN/A return true; 5225509SN/A } 5235509SN/A 5242968SN/A if (checkStall(tid)) { 5252968SN/A return block(tid); 52611245Sandreas.sandberg@arm.com } 5279988Snilay@cs.wisc.edu 5282968SN/A if (decodeStatus[tid] == Blocked) { 5292968SN/A DPRINTF(Decode, "[tid:%u]: Done blocking, switching to unblocking.\n", 5302968SN/A tid); 5315509SN/A 5325509SN/A decodeStatus[tid] = Unblocking; 5339885Sstever@gmail.com 5345509SN/A unblock(tid); 53511570SCurtis.Dunham@arm.com 5365509SN/A return true; 5379988Snilay@cs.wisc.edu } 53811570SCurtis.Dunham@arm.com 53911570SCurtis.Dunham@arm.com if (decodeStatus[tid] == Squashing) { 54011570SCurtis.Dunham@arm.com // Switch status to running if decode isn't being told to block or 5415509SN/A // squash this cycle. 5429481Snilay@cs.wisc.edu DPRINTF(Decode, "[tid:%u]: Done squashing, switching to running.\n", 5435509SN/A tid); 54411570SCurtis.Dunham@arm.com 5455509SN/A decodeStatus[tid] = Running; 5465509SN/A 5478983Snate@binkert.org return false; 5485509SN/A } 5492968SN/A 5502968SN/A // If we've reached this point, we have not gotten any signals that 5519885Sstever@gmail.com // cause decode to change its status. Decode remains the same as before. 55211570SCurtis.Dunham@arm.com return false; 5539988Snilay@cs.wisc.edu} 55411570SCurtis.Dunham@arm.com 55511570SCurtis.Dunham@arm.comtemplate<class Impl> 55611570SCurtis.Dunham@arm.comvoid 5572968SN/ADefaultDecode<Impl>::tick() 5589481Snilay@cs.wisc.edu{ 55911570SCurtis.Dunham@arm.com wroteToTimeBuffer = false; 5602968SN/A 5612968SN/A bool status_change = false; 5628983Snate@binkert.org 5632968SN/A toRenameIndex = 0; 5642968SN/A 5652968SN/A list<ThreadID>::iterator threads = activeThreads->begin(); 5662968SN/A list<ThreadID>::iterator end = activeThreads->end(); 5675876SN/A 5682968SN/A sortInsts(); 5692968SN/A 5705876SN/A //Check stall and squash signals. 5712968SN/A while (threads != end) { 5722968SN/A ThreadID tid = *threads++; 5735876SN/A 5742968SN/A DPRINTF(Decode,"Processing [tid:%i]\n",tid); 5752968SN/A status_change = checkSignalsAndUpdate(tid) || status_change; 5765876SN/A 5772968SN/A decode(status_change, tid); 5782968SN/A } 5795876SN/A 5802968SN/A if (status_change) { 5812968SN/A updateStatus(); 5825876SN/A } 5832968SN/A 5842968SN/A if (wroteToTimeBuffer) { 5852968SN/A DPRINTF(Activity, "Activity this cycle.\n"); 5869988Snilay@cs.wisc.edu 5872968SN/A cpu->activityThisCycle(); 5882968SN/A } 5892968SN/A} 5902968SN/A 5912968SN/Atemplate<class Impl> 5922968SN/Avoid 5932968SN/ADefaultDecode<Impl>::decode(bool &status_change, ThreadID tid) 5942968SN/A{ 5952968SN/A // If status is Running or idle, 59610451Snilay@cs.wisc.edu // call decodeInsts() 5979988Snilay@cs.wisc.edu // If status is Unblocking, 5989988Snilay@cs.wisc.edu // buffer any instructions coming from fetch 5999988Snilay@cs.wisc.edu // continue trying to empty skid buffer 6009988Snilay@cs.wisc.edu // check if stall conditions have passed 6019988Snilay@cs.wisc.edu 6029988Snilay@cs.wisc.edu if (decodeStatus[tid] == Blocked) { 6039988Snilay@cs.wisc.edu ++decodeBlockedCycles; 6049988Snilay@cs.wisc.edu } else if (decodeStatus[tid] == Squashing) { 6059988Snilay@cs.wisc.edu ++decodeSquashCycles; 6069988Snilay@cs.wisc.edu } 6079988Snilay@cs.wisc.edu 6089988Snilay@cs.wisc.edu // Decode should try to decode as many instructions as its bandwidth 6099988Snilay@cs.wisc.edu // will allow, as long as it is not currently blocked. 6109988Snilay@cs.wisc.edu if (decodeStatus[tid] == Running || 6119988Snilay@cs.wisc.edu decodeStatus[tid] == Idle) { 6122968SN/A DPRINTF(Decode, "[tid:%u]: Not blocked, so attempting to run " 6132968SN/A "stage.\n",tid); 6149988Snilay@cs.wisc.edu 6159988Snilay@cs.wisc.edu decodeInsts(tid); 6169988Snilay@cs.wisc.edu } else if (decodeStatus[tid] == Unblocking) { 6179988Snilay@cs.wisc.edu // Make sure that the skid buffer has something in it if the 6189988Snilay@cs.wisc.edu // status is unblocking. 6199988Snilay@cs.wisc.edu assert(!skidsEmpty()); 6209988Snilay@cs.wisc.edu 6219988Snilay@cs.wisc.edu // If the status was unblocking, then instructions from the skid 6229988Snilay@cs.wisc.edu // buffer were used. Remove those instructions and handle 6239988Snilay@cs.wisc.edu // the rest of unblocking. 6249988Snilay@cs.wisc.edu decodeInsts(tid); 6259988Snilay@cs.wisc.edu 6269988Snilay@cs.wisc.edu if (fetchInstsValid()) { 6279988Snilay@cs.wisc.edu // Add the current inputs to the skid buffer so they can be 6289988Snilay@cs.wisc.edu // reprocessed when this stage unblocks. 6299988Snilay@cs.wisc.edu skidInsert(tid); 6309988Snilay@cs.wisc.edu } 6312968SN/A 6322968SN/A status_change = unblock(tid) || status_change; 6332968SN/A } 6342968SN/A} 6352968SN/A 6362968SN/Atemplate <class Impl> 6372968SN/Avoid 6389885Sstever@gmail.comDefaultDecode<Impl>::decodeInsts(ThreadID tid) 6395102SN/A{ 64011570SCurtis.Dunham@arm.com // Instructions can come either from the skid buffer or the list of 6415102SN/A // instructions coming from fetch, depending on decode's status. 6425102SN/A int insts_available = decodeStatus[tid] == Unblocking ? 6435102SN/A skidBuffer[tid].size() : insts[tid].size(); 6445102SN/A 6455102SN/A if (insts_available == 0) { 6465102SN/A DPRINTF(Decode, "[tid:%u] Nothing to do, breaking out" 6475102SN/A " early.\n",tid); 6489988Snilay@cs.wisc.edu // Should I change the status to idle? 6495102SN/A ++decodeIdleCycles; 65011245Sandreas.sandberg@arm.com return; 6515102SN/A } else if (decodeStatus[tid] == Unblocking) { 65211570SCurtis.Dunham@arm.com DPRINTF(Decode, "[tid:%u] Unblocking, removing insts from skid " 65311570SCurtis.Dunham@arm.com "buffer.\n",tid); 65411570SCurtis.Dunham@arm.com ++decodeUnblockCycles; 6555102SN/A } else if (decodeStatus[tid] == Running) { 6565102SN/A ++decodeRunCycles; 6575102SN/A } 6589481Snilay@cs.wisc.edu 65911570SCurtis.Dunham@arm.com DynInstPtr inst; 6605102SN/A 6615102SN/A std::queue<DynInstPtr> 6625102SN/A &insts_to_decode = decodeStatus[tid] == Unblocking ? 6635102SN/A skidBuffer[tid] : insts[tid]; 6645102SN/A 6655102SN/A DPRINTF(Decode, "[tid:%u]: Sending instruction to rename.\n",tid); 6665102SN/A 6675102SN/A while (insts_available > 0 && toRenameIndex < decodeWidth) { 6685102SN/A assert(!insts_to_decode.empty()); 6698983Snate@binkert.org 67011245Sandreas.sandberg@arm.com inst = insts_to_decode.front(); 6712968SN/A 6722968SN/A insts_to_decode.pop(); 6732968SN/A 6749885Sstever@gmail.com DPRINTF(Decode, "[tid:%u]: Processing instruction [sn:%lli] with " 67511570SCurtis.Dunham@arm.com "PC %s\n", tid, inst->seqNum, inst->pcState()); 6769988Snilay@cs.wisc.edu 6778721SN/A if (inst->isSquashed()) { 67811570SCurtis.Dunham@arm.com DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %s is " 67911570SCurtis.Dunham@arm.com "squashed, skipping.\n", 68011570SCurtis.Dunham@arm.com tid, inst->seqNum, inst->pcState()); 6812968SN/A 6829481Snilay@cs.wisc.edu ++decodeSquashedInsts; 6832968SN/A 68411570SCurtis.Dunham@arm.com --insts_available; 6853505SN/A 6863934SN/A continue; 6873934SN/A } 6883934SN/A 6893934SN/A // Also check if instructions have no source registers. Mark 6902968SN/A // them as ready to issue at any time. Not sure if this check 6913934SN/A // should exist here or at a later stage; however it doesn't matter 6923934SN/A // too much for function correctness. 6938983Snate@binkert.org if (inst->numSrcRegs() == 0) { 6942968SN/A inst->setCanIssue(); 6952968SN/A } 6962968SN/A 6979885Sstever@gmail.com // This current instruction is valid, so add it into the decode 69811570SCurtis.Dunham@arm.com // queue. The next instruction may not be valid, so check to 6999988Snilay@cs.wisc.edu // see if branches were predicted correctly. 7008721SN/A toRename->insts[toRenameIndex] = inst; 70111570SCurtis.Dunham@arm.com 70211570SCurtis.Dunham@arm.com ++(toRename->size); 70311570SCurtis.Dunham@arm.com ++toRenameIndex; 7042968SN/A ++decodeDecodedInsts; 7059481Snilay@cs.wisc.edu --insts_available; 7062968SN/A 70711570SCurtis.Dunham@arm.com // Ensure that if it was predicted as a branch, it really is a 7083505SN/A // branch. 7093934SN/A if (inst->readPredTaken() && !inst->isControl()) { 7103934SN/A panic("Instruction predicted as a branch!"); 7113934SN/A 7123934SN/A ++decodeControlMispred; 7132968SN/A 7143934SN/A // Might want to set some sort of boolean and just do 7153934SN/A // a check at the end 7168983Snate@binkert.org squash(inst, inst->threadNumber); 7172968SN/A 7182968SN/A break; 7192968SN/A } 7209885Sstever@gmail.com 72111570SCurtis.Dunham@arm.com // Go ahead and compute any PC-relative branches. 7229988Snilay@cs.wisc.edu if (inst->isDirectCtrl() && inst->isUncondCtrl()) { 7238721SN/A ++decodeBranchResolved; 72411570SCurtis.Dunham@arm.com 72511570SCurtis.Dunham@arm.com if (!(inst->branchTarget() == inst->readPredTarg())) { 72611570SCurtis.Dunham@arm.com ++decodeBranchMispred; 7272968SN/A 7289481Snilay@cs.wisc.edu // Might want to set some sort of boolean and just do 7292968SN/A // a check at the end 73011570SCurtis.Dunham@arm.com squash(inst, inst->threadNumber); 7313505SN/A TheISA::PCState target = inst->branchTarget(); 7323934SN/A 7333934SN/A DPRINTF(Decode, "[sn:%i]: Updating predictions: PredPC: %s\n", 7343934SN/A inst->seqNum, target); 7353934SN/A //The micro pc after an instruction level branch should be 0 7362968SN/A inst->setPredTarg(target); 7373934SN/A break; 7383934SN/A } 7398983Snate@binkert.org } 7402968SN/A } 7412968SN/A 7422968SN/A // If we didn't process all instructions, then we will need to block 7439885Sstever@gmail.com // and put all those instructions into the skid buffer. 74411570SCurtis.Dunham@arm.com if (!insts_to_decode.empty()) { 7459988Snilay@cs.wisc.edu block(tid); 7468721SN/A } 74711570SCurtis.Dunham@arm.com 74811570SCurtis.Dunham@arm.com // Record that decode has written to the time buffer for activity 74911570SCurtis.Dunham@arm.com // tracking. 7502968SN/A if (toRenameIndex) { 7519481Snilay@cs.wisc.edu wroteToTimeBuffer = true; 7522968SN/A } 75311570SCurtis.Dunham@arm.com} 7543505SN/A