decode_impl.hh revision 11320:42ecb523c64a
11689SN/A/* 28948Sandreas.hansson@arm.com * Copyright (c) 2012, 2014 ARM Limited 38707Sandreas.hansson@arm.com * All rights reserved 48707Sandreas.hansson@arm.com * 58707Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 68707Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 78707Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 88707Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 98707Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 108707Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 118707Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 128707Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 138707Sandreas.hansson@arm.com * 142325SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan 157897Shestness@cs.utexas.edu * All rights reserved. 161689SN/A * 171689SN/A * Redistribution and use in source and binary forms, with or without 181689SN/A * modification, are permitted provided that the following conditions are 191689SN/A * met: redistributions of source code must retain the above copyright 201689SN/A * notice, this list of conditions and the following disclaimer; 211689SN/A * redistributions in binary form must reproduce the above copyright 221689SN/A * notice, this list of conditions and the following disclaimer in the 231689SN/A * documentation and/or other materials provided with the distribution; 241689SN/A * neither the name of the copyright holders nor the names of its 251689SN/A * contributors may be used to endorse or promote products derived from 261689SN/A * this software without specific prior written permission. 271689SN/A * 281689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 291689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 301689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 311689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 321689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 331689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 341689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 351689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 361689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 371689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 381689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 391689SN/A * 402665Ssaidi@eecs.umich.edu * Authors: Kevin Lim 412665Ssaidi@eecs.umich.edu */ 422756Sksewell@umich.edu 437897Shestness@cs.utexas.edu#ifndef __CPU_O3_DECODE_IMPL_HH__ 441689SN/A#define __CPU_O3_DECODE_IMPL_HH__ 451689SN/A 468779Sgblack@eecs.umich.edu#include "arch/types.hh" 476658Snate@binkert.org#include "base/trace.hh" 488887Sgeoffrey.blake@arm.com#include "config/the_isa.hh" 498887Sgeoffrey.blake@arm.com#include "cpu/o3/decode.hh" 508229Snate@binkert.org#include "cpu/inst_seq.hh" 518229Snate@binkert.org#include "debug/Activity.hh" 528229Snate@binkert.org#include "debug/Decode.hh" 534762Snate@binkert.org#include "debug/O3PipeView.hh" 548779Sgblack@eecs.umich.edu#include "params/DerivO3CPU.hh" 554762Snate@binkert.org#include "sim/full_system.hh" 564762Snate@binkert.org 578232Snate@binkert.org// clang complains about std::set being overloaded with Packet::set if 589152Satgutier@umich.edu// we open up the entire namespace std 598232Snate@binkert.orgusing std::list; 608232Snate@binkert.org 614762Snate@binkert.orgtemplate<class Impl> 624762Snate@binkert.orgDefaultDecode<Impl>::DefaultDecode(O3CPU *_cpu, DerivO3CPUParams *params) 638793Sgblack@eecs.umich.edu : cpu(_cpu), 648779Sgblack@eecs.umich.edu renameToDecodeDelay(params->renameToDecodeDelay), 654762Snate@binkert.org iewToDecodeDelay(params->iewToDecodeDelay), 668460SAli.Saidi@ARM.com commitToDecodeDelay(params->commitToDecodeDelay), 674762Snate@binkert.org fetchToDecodeDelay(params->fetchToDecodeDelay), 685702Ssaidi@eecs.umich.edu decodeWidth(params->decodeWidth), 695702Ssaidi@eecs.umich.edu numThreads(params->numThreads) 708232Snate@binkert.org{ 715702Ssaidi@eecs.umich.edu if (decodeWidth > Impl::MaxWidth) 725702Ssaidi@eecs.umich.edu fatal("decodeWidth (%d) is larger than compiled limit (%d),\n" 738737Skoansin.tan@gmail.com "\tincrease MaxWidth in src/cpu/o3/impl.hh\n", 745529Snate@binkert.org decodeWidth, static_cast<int>(Impl::MaxWidth)); 752669Sktlim@umich.edu 766221Snate@binkert.org // @todo: Make into a parameter 771060SN/A skidBufferMax = (fetchToDecodeDelay + 1) * params->fetchWidth; 785529Snate@binkert.org} 795712Shsul@eecs.umich.edu 801060SN/Atemplate<class Impl> 811060SN/Avoid 821060SN/ADefaultDecode<Impl>::startupStage() 832292SN/A{ 842733Sktlim@umich.edu resetStage(); 852292SN/A} 862292SN/A 872292SN/Atemplate<class Impl> 882292SN/Avoid 898707Sandreas.hansson@arm.comDefaultDecode<Impl>::resetStage() 908707Sandreas.hansson@arm.com{ 918975Sandreas.hansson@arm.com _status = Inactive; 928707Sandreas.hansson@arm.com 938707Sandreas.hansson@arm.com // Setup status, make sure stall signals are clear. 948948Sandreas.hansson@arm.com for (ThreadID tid = 0; tid < numThreads; ++tid) { 958948Sandreas.hansson@arm.com decodeStatus[tid] = Idle; 968948Sandreas.hansson@arm.com 978707Sandreas.hansson@arm.com stalls[tid].rename = false; 988707Sandreas.hansson@arm.com } 998707Sandreas.hansson@arm.com} 1008707Sandreas.hansson@arm.com 1018707Sandreas.hansson@arm.comtemplate <class Impl> 1028707Sandreas.hansson@arm.comstd::string 1038707Sandreas.hansson@arm.comDefaultDecode<Impl>::name() const 1048707Sandreas.hansson@arm.com{ 1058707Sandreas.hansson@arm.com return cpu->name() + ".decode"; 1068707Sandreas.hansson@arm.com} 1078707Sandreas.hansson@arm.com 1088707Sandreas.hansson@arm.comtemplate <class Impl> 1098707Sandreas.hansson@arm.comvoid 1108975Sandreas.hansson@arm.comDefaultDecode<Impl>::regStats() 1118707Sandreas.hansson@arm.com{ 1128975Sandreas.hansson@arm.com decodeIdleCycles 1138707Sandreas.hansson@arm.com .name(name() + ".IdleCycles") 1148707Sandreas.hansson@arm.com .desc("Number of cycles decode is idle") 1158707Sandreas.hansson@arm.com .prereq(decodeIdleCycles); 1168975Sandreas.hansson@arm.com decodeBlockedCycles 1178975Sandreas.hansson@arm.com .name(name() + ".BlockedCycles") 1188948Sandreas.hansson@arm.com .desc("Number of cycles decode is blocked") 1198975Sandreas.hansson@arm.com .prereq(decodeBlockedCycles); 1208948Sandreas.hansson@arm.com decodeRunCycles 1218948Sandreas.hansson@arm.com .name(name() + ".RunCycles") 1228948Sandreas.hansson@arm.com .desc("Number of cycles decode is running") 1238707Sandreas.hansson@arm.com .prereq(decodeRunCycles); 1248707Sandreas.hansson@arm.com decodeUnblockCycles 1258707Sandreas.hansson@arm.com .name(name() + ".UnblockCycles") 1268707Sandreas.hansson@arm.com .desc("Number of cycles decode is unblocking") 1278707Sandreas.hansson@arm.com .prereq(decodeUnblockCycles); 1288707Sandreas.hansson@arm.com decodeSquashCycles 1291060SN/A .name(name() + ".SquashCycles") 1301755SN/A .desc("Number of cycles decode is squashing") 1315606Snate@binkert.org .prereq(decodeSquashCycles); 1321060SN/A decodeBranchResolved 1331060SN/A .name(name() + ".BranchResolved") 1341060SN/A .desc("Number of times decode resolved a branch") 1351060SN/A .prereq(decodeBranchResolved); 1361060SN/A decodeBranchMispred 1371755SN/A .name(name() + ".BranchMispred") 1381060SN/A .desc("Number of times decode detected a branch misprediction") 1391060SN/A .prereq(decodeBranchMispred); 1401060SN/A decodeControlMispred 1411060SN/A .name(name() + ".ControlMispred") 1421060SN/A .desc("Number of times decode detected an instruction incorrectly" 1431060SN/A " predicted as a control") 1445336Shines@cs.fsu.edu .prereq(decodeControlMispred); 1451060SN/A decodeDecodedInsts 1464873Sstever@eecs.umich.edu .name(name() + ".DecodedInsts") 1471060SN/A .desc("Number of instructions handled by decode") 1481060SN/A .prereq(decodeDecodedInsts); 1491060SN/A decodeSquashedInsts 1502829Sksewell@umich.edu .name(name() + ".SquashedInsts") 1515606Snate@binkert.org .desc("Number of squashed instructions handled by decode") 1522829Sksewell@umich.edu .prereq(decodeSquashedInsts); 1532829Sksewell@umich.edu} 1542829Sksewell@umich.edu 1552829Sksewell@umich.edutemplate<class Impl> 1562829Sksewell@umich.eduvoid 1572829Sksewell@umich.eduDefaultDecode<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 1582829Sksewell@umich.edu{ 1592829Sksewell@umich.edu timeBuffer = tb_ptr; 1602829Sksewell@umich.edu 1612829Sksewell@umich.edu // Setup wire to write information back to fetch. 1622829Sksewell@umich.edu toFetch = timeBuffer->getWire(0); 1632829Sksewell@umich.edu 1642829Sksewell@umich.edu // Create wires to get information from proper places in time buffer. 1652829Sksewell@umich.edu fromRename = timeBuffer->getWire(-renameToDecodeDelay); 1662829Sksewell@umich.edu fromIEW = timeBuffer->getWire(-iewToDecodeDelay); 1672829Sksewell@umich.edu fromCommit = timeBuffer->getWire(-commitToDecodeDelay); 1682829Sksewell@umich.edu} 1692829Sksewell@umich.edu 1702829Sksewell@umich.edutemplate<class Impl> 1712829Sksewell@umich.eduvoid 1722829Sksewell@umich.eduDefaultDecode<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr) 1735336Shines@cs.fsu.edu{ 1742829Sksewell@umich.edu decodeQueue = dq_ptr; 1754873Sstever@eecs.umich.edu 1762829Sksewell@umich.edu // Setup wire to write information to proper place in decode queue. 1772829Sksewell@umich.edu toRename = decodeQueue->getWire(0); 1782829Sksewell@umich.edu} 1792875Sksewell@umich.edu 1805606Snate@binkert.orgtemplate<class Impl> 1812875Sksewell@umich.eduvoid 1822875Sksewell@umich.eduDefaultDecode<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr) 1832875Sksewell@umich.edu{ 1842875Sksewell@umich.edu fetchQueue = fq_ptr; 1852875Sksewell@umich.edu 1862875Sksewell@umich.edu // Setup wire to read information from fetch queue. 1873859Sbinkertn@umich.edu fromFetch = fetchQueue->getWire(-fetchToDecodeDelay); 1882875Sksewell@umich.edu} 1892875Sksewell@umich.edu 1902875Sksewell@umich.edutemplate<class Impl> 1913859Sbinkertn@umich.eduvoid 1922875Sksewell@umich.eduDefaultDecode<Impl>::setActiveThreads(std::list<ThreadID> *at_ptr) 1932875Sksewell@umich.edu{ 1942875Sksewell@umich.edu activeThreads = at_ptr; 1952875Sksewell@umich.edu} 1962875Sksewell@umich.edu 1972875Sksewell@umich.edutemplate <class Impl> 1982875Sksewell@umich.eduvoid 1993221Sktlim@umich.eduDefaultDecode<Impl>::drainSanityCheck() const 2003221Sktlim@umich.edu{ 2012875Sksewell@umich.edu for (ThreadID tid = 0; tid < numThreads; ++tid) { 2022875Sksewell@umich.edu assert(insts[tid].empty()); 2032875Sksewell@umich.edu assert(skidBuffer[tid].empty()); 2042875Sksewell@umich.edu } 2055336Shines@cs.fsu.edu} 2062875Sksewell@umich.edu 2074873Sstever@eecs.umich.edutemplate <class Impl> 2082875Sksewell@umich.edubool 2092875Sksewell@umich.eduDefaultDecode<Impl>::isDrained() const 2102875Sksewell@umich.edu{ 2115595Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; ++tid) { 2122733Sktlim@umich.edu if (!insts[tid].empty() || !skidBuffer[tid].empty()) 2133781Sgblack@eecs.umich.edu return false; 2143781Sgblack@eecs.umich.edu } 2151060SN/A return true; 2165737Scws3k@cs.virginia.edu} 2175737Scws3k@cs.virginia.edu 2185737Scws3k@cs.virginia.edutemplate<class Impl> 2192292SN/Abool 2205595Sgblack@eecs.umich.eduDefaultDecode<Impl>::checkStall(ThreadID tid) const 2215595Sgblack@eecs.umich.edu{ 2225595Sgblack@eecs.umich.edu bool ret_val = false; 2235595Sgblack@eecs.umich.edu 2245595Sgblack@eecs.umich.edu if (stalls[tid].rename) { 2251060SN/A DPRINTF(Decode,"[tid:%i]: Stall fom Rename stage detected.\n", tid); 2265595Sgblack@eecs.umich.edu ret_val = true; 2274329Sktlim@umich.edu } 2281060SN/A 2295529Snate@binkert.org return ret_val; 2302292SN/A} 2312292SN/A 2321060SN/Atemplate<class Impl> 2335595Sgblack@eecs.umich.eduinline bool 2344329Sktlim@umich.eduDefaultDecode<Impl>::fetchInstsValid() 2352292SN/A{ 2365529Snate@binkert.org return fromFetch->size > 0; 2371060SN/A} 2385529Snate@binkert.org 2392292SN/Atemplate<class Impl> 2402292SN/Abool 2416221Snate@binkert.orgDefaultDecode<Impl>::block(ThreadID tid) 2422292SN/A{ 2431060SN/A DPRINTF(Decode, "[tid:%u]: Blocking.\n", tid); 2449384SAndreas.Sandberg@arm.com 2459384SAndreas.Sandberg@arm.com // Add the current inputs to the skid buffer so they can be 2468707Sandreas.hansson@arm.com // reprocessed when this stage unblocks. 2478707Sandreas.hansson@arm.com skidInsert(tid); 2488707Sandreas.hansson@arm.com 2492873Sktlim@umich.edu // If the decode status is blocked or unblocking then decode has not yet 2502873Sktlim@umich.edu // signalled fetch to unblock. In that case, there is no need to tell 2512873Sktlim@umich.edu // fetch to block. 2522873Sktlim@umich.edu if (decodeStatus[tid] != Blocked) { 2532873Sktlim@umich.edu // Set the status to Blocked. 2545804Snate@binkert.org decodeStatus[tid] = Blocked; 2552873Sktlim@umich.edu 2562873Sktlim@umich.edu if (toFetch->decodeUnblock[tid]) { 2571060SN/A toFetch->decodeUnblock[tid] = false; 2581060SN/A } else { 2592292SN/A toFetch->decodeBlock[tid] = true; 2609444SAndreas.Sandberg@ARM.com wroteToTimeBuffer = true; 2619180Sandreas.hansson@arm.com } 2621060SN/A 2639433SAndreas.Sandberg@ARM.com return true; 2643221Sktlim@umich.edu } 2653221Sktlim@umich.edu 2669152Satgutier@umich.edu return false; 2673221Sktlim@umich.edu} 2681681SN/A 2692794Sktlim@umich.edutemplate<class Impl> 2702316SN/Abool 2718733Sgeoffrey.blake@arm.comDefaultDecode<Impl>::unblock(ThreadID tid) 2728707Sandreas.hansson@arm.com{ 2732316SN/A // Decode is done unblocking only if the skid buffer is empty. 2744598Sbinkertn@umich.edu if (skidBuffer[tid].empty()) { 2754598Sbinkertn@umich.edu DPRINTF(Decode, "[tid:%u]: Done unblocking.\n", tid); 2764598Sbinkertn@umich.edu toFetch->decodeUnblock[tid] = true; 2772316SN/A wroteToTimeBuffer = true; 2788793Sgblack@eecs.umich.edu 2798793Sgblack@eecs.umich.edu decodeStatus[tid] = Running; 2808793Sgblack@eecs.umich.edu return true; 2818793Sgblack@eecs.umich.edu } 2821681SN/A 2832325SN/A DPRINTF(Decode, "[tid:%u]: Currently unblocking.\n", tid); 2842325SN/A 2852325SN/A return false; 2861060SN/A} 2872292SN/A 2882292SN/Atemplate<class Impl> 2892292SN/Avoid 2902292SN/ADefaultDecode<Impl>::squash(DynInstPtr &inst, ThreadID tid) 2912292SN/A{ 2922292SN/A DPRINTF(Decode, "[tid:%i]: [sn:%i] Squashing due to incorrect branch " 2931060SN/A "prediction detected at decode.\n", tid, inst->seqNum); 2941060SN/A 2951060SN/A // Send back mispredict information. 2961060SN/A toFetch->decodeInfo[tid].branchMispredict = true; 2971060SN/A toFetch->decodeInfo[tid].predIncorrect = true; 2981060SN/A toFetch->decodeInfo[tid].mispredictInst = inst; 2991060SN/A toFetch->decodeInfo[tid].squash = true; 3001060SN/A toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum; 3011060SN/A toFetch->decodeInfo[tid].nextPC = inst->branchTarget(); 3021060SN/A toFetch->decodeInfo[tid].branchTaken = inst->pcState().branching(); 3031060SN/A toFetch->decodeInfo[tid].squashInst = inst; 3042292SN/A if (toFetch->decodeInfo[tid].mispredictInst->isUncondCtrl()) { 3051060SN/A toFetch->decodeInfo[tid].branchTaken = true; 3061060SN/A } 3071060SN/A 3081060SN/A InstSeqNum squash_seq_num = inst->seqNum; 3091060SN/A 3101060SN/A // Might have to tell fetch to unblock. 3111060SN/A if (decodeStatus[tid] == Blocked || 3121060SN/A decodeStatus[tid] == Unblocking) { 3132292SN/A toFetch->decodeUnblock[tid] = 1; 3142292SN/A } 3152292SN/A 3162292SN/A // Set status to squashing. 3178793Sgblack@eecs.umich.edu decodeStatus[tid] = Squashing; 3188793Sgblack@eecs.umich.edu 3198793Sgblack@eecs.umich.edu for (int i=0; i<fromFetch->size; i++) { 3208793Sgblack@eecs.umich.edu if (fromFetch->insts[i]->threadNumber == tid && 3218793Sgblack@eecs.umich.edu fromFetch->insts[i]->seqNum > squash_seq_num) { 3222831Sksewell@umich.edu fromFetch->insts[i]->setSquashed(); 3238793Sgblack@eecs.umich.edu } 3248793Sgblack@eecs.umich.edu } 3258793Sgblack@eecs.umich.edu 3268793Sgblack@eecs.umich.edu // Clear the instruction list and skid buffer in case they have any 3278793Sgblack@eecs.umich.edu // insts in them. 3282831Sksewell@umich.edu while (!insts[tid].empty()) { 3292292SN/A insts[tid].pop(); 3302316SN/A } 3312292SN/A 3322292SN/A while (!skidBuffer[tid].empty()) { 3332292SN/A skidBuffer[tid].pop(); 3342292SN/A } 3352292SN/A 3362292SN/A // Squash instructions up until this one 3371060SN/A cpu->removeInstsUntil(squash_seq_num, tid); 3382292SN/A} 3392292SN/A 3401060SN/Atemplate<class Impl> 3416221Snate@binkert.orgunsigned 3422307SN/ADefaultDecode<Impl>::squash(ThreadID tid) 3432292SN/A{ 3449384SAndreas.Sandberg@arm.com DPRINTF(Decode, "[tid:%i]: Squashing.\n",tid); 3459384SAndreas.Sandberg@arm.com 3462292SN/A if (decodeStatus[tid] == Blocked || 3472292SN/A decodeStatus[tid] == Unblocking) { 3482325SN/A if (FullSystem) { 3492292SN/A toFetch->decodeUnblock[tid] = 1; 3502292SN/A } else { 3512292SN/A // In syscall emulation, we can have both a block and a squash due 3522325SN/A // to a syscall in the same cycle. This would cause both signals 3532292SN/A // to be high. This shouldn't happen in full system. 3542292SN/A // @todo: Determine if this still happens. 3552292SN/A if (toFetch->decodeBlock[tid]) 3562292SN/A toFetch->decodeBlock[tid] = 0; 3572292SN/A else 3582292SN/A toFetch->decodeUnblock[tid] = 1; 3592292SN/A } 3602292SN/A } 3612292SN/A 3622292SN/A // Set status to squashing. 3632292SN/A decodeStatus[tid] = Squashing; 3642325SN/A 3652292SN/A // Go through incoming instructions from fetch and squash them. 3662292SN/A unsigned squash_count = 0; 3672292SN/A 3682325SN/A for (int i=0; i<fromFetch->size; i++) { 3692292SN/A if (fromFetch->insts[i]->threadNumber == tid) { 3702292SN/A fromFetch->insts[i]->setSquashed(); 3712292SN/A squash_count++; 3722292SN/A } 3732292SN/A } 3742292SN/A 3752292SN/A // Clear the instruction list and skid buffer in case they have any 3762292SN/A // insts in them. 3773221Sktlim@umich.edu while (!insts[tid].empty()) { 3783221Sktlim@umich.edu insts[tid].pop(); 3793221Sktlim@umich.edu } 3802292SN/A 3812292SN/A while (!skidBuffer[tid].empty()) { 3822292SN/A skidBuffer[tid].pop(); 3832292SN/A } 3842292SN/A 3852292SN/A return squash_count; 3866221Snate@binkert.org} 3876221Snate@binkert.org 3881060SN/Atemplate<class Impl> 3892292SN/Avoid 3901060SN/ADefaultDecode<Impl>::skidInsert(ThreadID tid) 3911060SN/A{ 3922292SN/A DynInstPtr inst = NULL; 3939158Sandreas.hansson@arm.com 3946221Snate@binkert.org while (!insts[tid].empty()) { 3953093Sksewell@umich.edu inst = insts[tid].front(); 3966221Snate@binkert.org 3976221Snate@binkert.org insts[tid].pop(); 3986221Snate@binkert.org 3993093Sksewell@umich.edu assert(tid == inst->threadNumber); 4002292SN/A 4015595Sgblack@eecs.umich.edu skidBuffer[tid].push(inst); 4025595Sgblack@eecs.umich.edu 4035595Sgblack@eecs.umich.edu DPRINTF(Decode,"Inserting [tid:%d][sn:%lli] PC: %s into decode skidBuffer %i\n", 4045595Sgblack@eecs.umich.edu inst->threadNumber, inst->seqNum, inst->pcState(), skidBuffer[tid].size()); 4055595Sgblack@eecs.umich.edu } 4066221Snate@binkert.org 4078793Sgblack@eecs.umich.edu // @todo: Eventually need to enforce this by not letting a thread 4088793Sgblack@eecs.umich.edu // fetch past its skidbuffer 4098793Sgblack@eecs.umich.edu assert(skidBuffer[tid].size() <= skidBufferMax); 4108793Sgblack@eecs.umich.edu} 4118793Sgblack@eecs.umich.edu 4128793Sgblack@eecs.umich.edutemplate<class Impl> 4138793Sgblack@eecs.umich.edubool 4148793Sgblack@eecs.umich.eduDefaultDecode<Impl>::skidsEmpty() 4158793Sgblack@eecs.umich.edu{ 4168793Sgblack@eecs.umich.edu list<ThreadID>::iterator threads = activeThreads->begin(); 4178793Sgblack@eecs.umich.edu list<ThreadID>::iterator end = activeThreads->end(); 4185595Sgblack@eecs.umich.edu 4198793Sgblack@eecs.umich.edu while (threads != end) { 4208793Sgblack@eecs.umich.edu ThreadID tid = *threads++; 4218793Sgblack@eecs.umich.edu if (!skidBuffer[tid].empty()) 4228793Sgblack@eecs.umich.edu return false; 4238793Sgblack@eecs.umich.edu } 4248793Sgblack@eecs.umich.edu 4255595Sgblack@eecs.umich.edu return true; 4268793Sgblack@eecs.umich.edu} 4278793Sgblack@eecs.umich.edu 4288793Sgblack@eecs.umich.edutemplate<class Impl> 4298793Sgblack@eecs.umich.eduvoid 4308793Sgblack@eecs.umich.eduDefaultDecode<Impl>::updateStatus() 4315595Sgblack@eecs.umich.edu{ 4325595Sgblack@eecs.umich.edu bool any_unblocking = false; 4335595Sgblack@eecs.umich.edu 4345595Sgblack@eecs.umich.edu list<ThreadID>::iterator threads = activeThreads->begin(); 4355595Sgblack@eecs.umich.edu list<ThreadID>::iterator end = activeThreads->end(); 4365595Sgblack@eecs.umich.edu 4375595Sgblack@eecs.umich.edu while (threads != end) { 4385595Sgblack@eecs.umich.edu ThreadID tid = *threads++; 4395595Sgblack@eecs.umich.edu 4405595Sgblack@eecs.umich.edu if (decodeStatus[tid] == Unblocking) { 4415595Sgblack@eecs.umich.edu any_unblocking = true; 4425595Sgblack@eecs.umich.edu break; 4435595Sgblack@eecs.umich.edu } 4445595Sgblack@eecs.umich.edu } 4455595Sgblack@eecs.umich.edu 4465595Sgblack@eecs.umich.edu // Decode will have activity if it's unblocking. 4475595Sgblack@eecs.umich.edu if (any_unblocking) { 4485595Sgblack@eecs.umich.edu if (_status == Inactive) { 4496221Snate@binkert.org _status = Active; 4505595Sgblack@eecs.umich.edu 4518793Sgblack@eecs.umich.edu DPRINTF(Activity, "Activating stage.\n"); 4528793Sgblack@eecs.umich.edu 4538793Sgblack@eecs.umich.edu cpu->activateStage(O3CPU::DecodeIdx); 4548793Sgblack@eecs.umich.edu } 4555595Sgblack@eecs.umich.edu } else { 4566221Snate@binkert.org // If it's not unblocking, then decode will not have any internal 4575595Sgblack@eecs.umich.edu // activity. Switch it to inactive. 4585595Sgblack@eecs.umich.edu if (_status == Active) { 4595595Sgblack@eecs.umich.edu _status = Inactive; 4605595Sgblack@eecs.umich.edu DPRINTF(Activity, "Deactivating stage.\n"); 4615595Sgblack@eecs.umich.edu 4628876Sandreas.hansson@arm.com cpu->deactivateStage(O3CPU::DecodeIdx); 4639433SAndreas.Sandberg@ARM.com } 4648876Sandreas.hansson@arm.com } 4658876Sandreas.hansson@arm.com} 4668876Sandreas.hansson@arm.com 4678876Sandreas.hansson@arm.comtemplate <class Impl> 4686221Snate@binkert.orgvoid 4696221Snate@binkert.orgDefaultDecode<Impl>::sortInsts() 4701060SN/A{ 4711060SN/A int insts_from_fetch = fromFetch->size; 4721060SN/A for (int i = 0; i < insts_from_fetch; ++i) { 4731755SN/A insts[fromFetch->insts[i]->threadNumber].push(fromFetch->insts[i]); 4741060SN/A } 4751060SN/A} 4761060SN/A 4771060SN/Atemplate<class Impl> 4781060SN/Avoid 4795595Sgblack@eecs.umich.eduDefaultDecode<Impl>::readStallSignals(ThreadID tid) 4801062SN/A{ 4812733Sktlim@umich.edu if (fromRename->renameBlock[tid]) { 4822292SN/A stalls[tid].rename = true; 4832733Sktlim@umich.edu } 4842292SN/A 4852292SN/A if (fromRename->renameUnblock[tid]) { 4862292SN/A assert(stalls[tid].rename); 4872292SN/A stalls[tid].rename = false; 4882292SN/A } 4892292SN/A} 4902292SN/A 4912292SN/Atemplate <class Impl> 4922292SN/Abool 4932292SN/ADefaultDecode<Impl>::checkSignalsAndUpdate(ThreadID tid) 4942292SN/A{ 4952292SN/A // Check if there's a squash signal, squash if there is. 4968627SAli.Saidi@ARM.com // Check stall signals, block if necessary. 4978627SAli.Saidi@ARM.com // If status was blocked 4988627SAli.Saidi@ARM.com // Check if stall conditions have passed 4998627SAli.Saidi@ARM.com // if so then go to unblocking 5008627SAli.Saidi@ARM.com // If status was Squashing 5018627SAli.Saidi@ARM.com // check if squashing is not high. Switch to running this cycle. 5022292SN/A 5032292SN/A // Update the per thread stall statuses. 5042292SN/A readStallSignals(tid); 5052292SN/A 5062292SN/A // Check squash signals from commit. 5072292SN/A if (fromCommit->commitInfo[tid].squash) { 5082292SN/A 5092292SN/A DPRINTF(Decode, "[tid:%u]: Squashing instructions due to squash " 5102292SN/A "from commit.\n", tid); 5118834Satgutier@umich.edu 5128834Satgutier@umich.edu squash(tid); 5138834Satgutier@umich.edu 5148834Satgutier@umich.edu return true; 5158834Satgutier@umich.edu } 5162292SN/A 5172292SN/A if (checkStall(tid)) { 5182292SN/A return block(tid); 5192292SN/A } 5202292SN/A 5212292SN/A if (decodeStatus[tid] == Blocked) { 5222292SN/A DPRINTF(Decode, "[tid:%u]: Done blocking, switching to unblocking.\n", 5232292SN/A tid); 5244392Sktlim@umich.edu 5252292SN/A decodeStatus[tid] = Unblocking; 5262292SN/A 5272292SN/A unblock(tid); 5282292SN/A 5292292SN/A return true; 5304392Sktlim@umich.edu } 5312292SN/A 5322292SN/A if (decodeStatus[tid] == Squashing) { 5332292SN/A // Switch status to running if decode isn't being told to block or 5342292SN/A // squash this cycle. 5352292SN/A DPRINTF(Decode, "[tid:%u]: Done squashing, switching to running.\n", 5364392Sktlim@umich.edu tid); 5372292SN/A 5382292SN/A decodeStatus[tid] = Running; 5392292SN/A 5402292SN/A return false; 5412292SN/A } 5424392Sktlim@umich.edu 5432292SN/A // If we've reached this point, we have not gotten any signals that 5445595Sgblack@eecs.umich.edu // cause decode to change its status. Decode remains the same as before. 5455595Sgblack@eecs.umich.edu return false; 5465595Sgblack@eecs.umich.edu} 5475595Sgblack@eecs.umich.edu 5485595Sgblack@eecs.umich.edutemplate<class Impl> 5497897Shestness@cs.utexas.eduvoid 5507897Shestness@cs.utexas.eduDefaultDecode<Impl>::tick() 5517897Shestness@cs.utexas.edu{ 5527897Shestness@cs.utexas.edu wroteToTimeBuffer = false; 5537897Shestness@cs.utexas.edu 5547897Shestness@cs.utexas.edu bool status_change = false; 5557897Shestness@cs.utexas.edu 5567897Shestness@cs.utexas.edu toRenameIndex = 0; 5577897Shestness@cs.utexas.edu 5587897Shestness@cs.utexas.edu list<ThreadID>::iterator threads = activeThreads->begin(); 5597897Shestness@cs.utexas.edu list<ThreadID>::iterator end = activeThreads->end(); 5607897Shestness@cs.utexas.edu 5617897Shestness@cs.utexas.edu sortInsts(); 5627897Shestness@cs.utexas.edu 5637897Shestness@cs.utexas.edu //Check stall and squash signals. 5647897Shestness@cs.utexas.edu while (threads != end) { 5657897Shestness@cs.utexas.edu ThreadID tid = *threads++; 5667897Shestness@cs.utexas.edu 5677897Shestness@cs.utexas.edu DPRINTF(Decode,"Processing [tid:%i]\n",tid); 5687897Shestness@cs.utexas.edu status_change = checkSignalsAndUpdate(tid) || status_change; 5697897Shestness@cs.utexas.edu 5707897Shestness@cs.utexas.edu decode(status_change, tid); 5717897Shestness@cs.utexas.edu } 5727897Shestness@cs.utexas.edu 5737897Shestness@cs.utexas.edu if (status_change) { 5747897Shestness@cs.utexas.edu updateStatus(); 5757897Shestness@cs.utexas.edu } 5767897Shestness@cs.utexas.edu 5777897Shestness@cs.utexas.edu if (wroteToTimeBuffer) { 5787897Shestness@cs.utexas.edu DPRINTF(Activity, "Activity this cycle.\n"); 5797897Shestness@cs.utexas.edu 5801062SN/A cpu->activityThisCycle(); 5811062SN/A } 5821062SN/A} 5831062SN/A 5841755SN/Atemplate<class Impl> 5851060SN/Avoid 5862733Sktlim@umich.eduDefaultDecode<Impl>::decode(bool &status_change, ThreadID tid) 5879444SAndreas.Sandberg@ARM.com{ 5889444SAndreas.Sandberg@ARM.com // If status is Running or idle, 5891060SN/A // call decodeInsts() 5902292SN/A // If status is Unblocking, 5912292SN/A // buffer any instructions coming from fetch 5922325SN/A // continue trying to empty skid buffer 5932292SN/A // check if stall conditions have passed 5942292SN/A 5951060SN/A if (decodeStatus[tid] == Blocked) { 5961060SN/A ++decodeBlockedCycles; 5971060SN/A } else if (decodeStatus[tid] == Squashing) { 5981060SN/A ++decodeSquashCycles; 5991060SN/A } 6001060SN/A 6011060SN/A // Decode should try to decode as many instructions as its bandwidth 6021060SN/A // will allow, as long as it is not currently blocked. 6031060SN/A if (decodeStatus[tid] == Running || 6041060SN/A decodeStatus[tid] == Idle) { 6058793Sgblack@eecs.umich.edu DPRINTF(Decode, "[tid:%u]: Not blocked, so attempting to run " 6068793Sgblack@eecs.umich.edu "stage.\n",tid); 6072292SN/A 6082292SN/A decodeInsts(tid); 6091060SN/A } else if (decodeStatus[tid] == Unblocking) { 6101060SN/A // Make sure that the skid buffer has something in it if the 6111060SN/A // status is unblocking. 6121060SN/A assert(!skidsEmpty()); 6131060SN/A 6141060SN/A // If the status was unblocking, then instructions from the skid 6151060SN/A // buffer were used. Remove those instructions and handle 6162325SN/A // the rest of unblocking. 6172292SN/A decodeInsts(tid); 6182292SN/A 6192292SN/A if (fetchInstsValid()) { 6202292SN/A // Add the current inputs to the skid buffer so they can be 6212292SN/A // reprocessed when this stage unblocks. 6222325SN/A skidInsert(tid); 6239444SAndreas.Sandberg@ARM.com } 6243226Sktlim@umich.edu 6252325SN/A status_change = unblock(tid) || status_change; 6269179Sandreas.hansson@arm.com } 6273221Sktlim@umich.edu} 6283226Sktlim@umich.edu 6299179Sandreas.hansson@arm.comtemplate <class Impl> 6302325SN/Avoid 6312325SN/ADefaultDecode<Impl>::decodeInsts(ThreadID tid) 6329180Sandreas.hansson@arm.com{ 6333226Sktlim@umich.edu // Instructions can come either from the skid buffer or the list of 6342325SN/A // instructions coming from fetch, depending on decode's status. 6352292SN/A int insts_available = decodeStatus[tid] == Unblocking ? 6362292SN/A skidBuffer[tid].size() : insts[tid].size(); 6378793Sgblack@eecs.umich.edu 6388793Sgblack@eecs.umich.edu if (insts_available == 0) { 6399444SAndreas.Sandberg@ARM.com DPRINTF(Decode, "[tid:%u] Nothing to do, breaking out" 6409444SAndreas.Sandberg@ARM.com " early.\n",tid); 6411060SN/A // Should I change the status to idle? 6421060SN/A ++decodeIdleCycles; 6431060SN/A return; 6441060SN/A } else if (decodeStatus[tid] == Unblocking) { 6451755SN/A DPRINTF(Decode, "[tid:%u] Unblocking, removing insts from skid " 6461060SN/A "buffer.\n",tid); 6475714Shsul@eecs.umich.edu ++decodeUnblockCycles; 6481060SN/A } else if (decodeStatus[tid] == Running) { 6498921Sandreas.hansson@arm.com ++decodeRunCycles; 6509382SAli.Saidi@ARM.com } 6518921Sandreas.hansson@arm.com 6529382SAli.Saidi@ARM.com DynInstPtr inst; 6538921Sandreas.hansson@arm.com 6548921Sandreas.hansson@arm.com std::queue<DynInstPtr> 6558921Sandreas.hansson@arm.com &insts_to_decode = decodeStatus[tid] == Unblocking ? 6562292SN/A skidBuffer[tid] : insts[tid]; 6579433SAndreas.Sandberg@ARM.com 6588793Sgblack@eecs.umich.edu DPRINTF(Decode, "[tid:%u]: Sending instruction to rename.\n",tid); 6598793Sgblack@eecs.umich.edu 6608793Sgblack@eecs.umich.edu while (insts_available > 0 && toRenameIndex < decodeWidth) { 6618793Sgblack@eecs.umich.edu assert(!insts_to_decode.empty()); 6626034Ssteve.reinhardt@amd.com 6632292SN/A inst = insts_to_decode.front(); 6649382SAli.Saidi@ARM.com 6656221Snate@binkert.org insts_to_decode.pop(); 6669382SAli.Saidi@ARM.com 6672292SN/A DPRINTF(Decode, "[tid:%u]: Processing instruction [sn:%lli] with " 6689427SAndreas.Sandberg@ARM.com "PC %s\n", tid, inst->seqNum, inst->pcState()); 6699427SAndreas.Sandberg@ARM.com 6702292SN/A if (inst->isSquashed()) { 6719427SAndreas.Sandberg@ARM.com DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %s is " 6729427SAndreas.Sandberg@ARM.com "squashed, skipping.\n", 6739427SAndreas.Sandberg@ARM.com tid, inst->seqNum, inst->pcState()); 6749427SAndreas.Sandberg@ARM.com 6759461Snilay@cs.wisc.edu ++decodeSquashedInsts; 6769461Snilay@cs.wisc.edu 6779461Snilay@cs.wisc.edu --insts_available; 6789427SAndreas.Sandberg@ARM.com 6799444SAndreas.Sandberg@ARM.com continue; 6809427SAndreas.Sandberg@ARM.com } 6819427SAndreas.Sandberg@ARM.com 6829427SAndreas.Sandberg@ARM.com // Also check if instructions have no source registers. Mark 6832292SN/A // them as ready to issue at any time. Not sure if this check 6842292SN/A // should exist here or at a later stage; however it doesn't matter 6852292SN/A // too much for function correctness. 6862292SN/A if (inst->numSrcRegs() == 0) { 6876221Snate@binkert.org inst->setCanIssue(); 6882875Sksewell@umich.edu } 6896221Snate@binkert.org 6905314Sstever@gmail.com // This current instruction is valid, so add it into the decode 6912875Sksewell@umich.edu // queue. The next instruction may not be valid, so check to 6923226Sktlim@umich.edu // see if branches were predicted correctly. 6939444SAndreas.Sandberg@ARM.com toRename->insts[toRenameIndex] = inst; 6943226Sktlim@umich.edu 6952875Sksewell@umich.edu ++(toRename->size); 6962875Sksewell@umich.edu ++toRenameIndex; 6972875Sksewell@umich.edu ++decodeDecodedInsts; 6982875Sksewell@umich.edu --insts_available; 6992875Sksewell@umich.edu 7002875Sksewell@umich.edu#if TRACING_ON 7012875Sksewell@umich.edu if (DTRACE(O3PipeView)) { 7022875Sksewell@umich.edu inst->decodeTick = curTick() - inst->fetchTick; 7032875Sksewell@umich.edu } 7042875Sksewell@umich.edu#endif 7056221Snate@binkert.org 7062875Sksewell@umich.edu // Ensure that if it was predicted as a branch, it really is a 7072875Sksewell@umich.edu // branch. 7086221Snate@binkert.org if (inst->readPredTaken() && !inst->isControl()) { 7095314Sstever@gmail.com panic("Instruction predicted as a branch!"); 7102875Sksewell@umich.edu 7113226Sktlim@umich.edu ++decodeControlMispred; 7129444SAndreas.Sandberg@ARM.com 7133226Sktlim@umich.edu // Might want to set some sort of boolean and just do 7142875Sksewell@umich.edu // a check at the end 7152875Sksewell@umich.edu squash(inst, inst->threadNumber); 7162875Sksewell@umich.edu 7172875Sksewell@umich.edu break; 7182875Sksewell@umich.edu } 7192875Sksewell@umich.edu 7202875Sksewell@umich.edu // Go ahead and compute any PC-relative branches. 7212875Sksewell@umich.edu if (inst->isDirectCtrl() && inst->isUncondCtrl()) { 7226221Snate@binkert.org ++decodeBranchResolved; 7238834Satgutier@umich.edu 7246221Snate@binkert.org if (!(inst->branchTarget() == inst->readPredTarg())) { 7256221Snate@binkert.org ++decodeBranchMispred; 7266221Snate@binkert.org 7276221Snate@binkert.org // Might want to set some sort of boolean and just do 7286221Snate@binkert.org // a check at the end 7296221Snate@binkert.org squash(inst, inst->threadNumber); 7306221Snate@binkert.org TheISA::PCState target = inst->branchTarget(); 7316221Snate@binkert.org 7326221Snate@binkert.org DPRINTF(Decode, "[sn:%i]: Updating predictions: PredPC: %s\n", 7336221Snate@binkert.org inst->seqNum, target); 7346221Snate@binkert.org //The micro pc after an instruction level branch should be 0 7358834Satgutier@umich.edu inst->setPredTarg(target); 7368834Satgutier@umich.edu break; 7378834Satgutier@umich.edu } 7388834Satgutier@umich.edu } 7398834Satgutier@umich.edu } 7408834Satgutier@umich.edu 7418834Satgutier@umich.edu // If we didn't process all instructions, then we will need to block 7428834Satgutier@umich.edu // and put all those instructions into the skid buffer. 7438834Satgutier@umich.edu if (!insts_to_decode.empty()) { 7448834Satgutier@umich.edu block(tid); 7458834Satgutier@umich.edu } 7468834Satgutier@umich.edu 7478834Satgutier@umich.edu // Record that decode has written to the time buffer for activity 7482875Sksewell@umich.edu // tracking. 7499180Sandreas.hansson@arm.com if (toRenameIndex) { 7502875Sksewell@umich.edu wroteToTimeBuffer = true; 7519444SAndreas.Sandberg@ARM.com } 7529444SAndreas.Sandberg@ARM.com} 7532875Sksewell@umich.edu 7542875Sksewell@umich.edu#endif//__CPU_O3_DECODE_IMPL_HH__ 7552875Sksewell@umich.edu