11689SN/A/* 210328Smitch.hayenga@arm.com * Copyright (c) 2010-2014 ARM Limited 310960Sdavid.hashe@amd.com * Copyright (c) 2012-2013 AMD 47847Sminkyu.jeong@arm.com * All rights reserved. 57847Sminkyu.jeong@arm.com * 67847Sminkyu.jeong@arm.com * The license below extends only to copyright in the software and shall 77847Sminkyu.jeong@arm.com * not be construed as granting a license to any other intellectual 87847Sminkyu.jeong@arm.com * property including but not limited to intellectual property relating 97847Sminkyu.jeong@arm.com * to a hardware implementation of the functionality of the software 107847Sminkyu.jeong@arm.com * licensed hereunder. You may use the software subject to the license 117847Sminkyu.jeong@arm.com * terms below provided that you ensure that this notice is replicated 127847Sminkyu.jeong@arm.com * unmodified and in its entirety in all distributions of the software, 137847Sminkyu.jeong@arm.com * modified or unmodified, in source code or in binary form. 147847Sminkyu.jeong@arm.com * 152323SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan 161689SN/A * All rights reserved. 171689SN/A * 181689SN/A * Redistribution and use in source and binary forms, with or without 191689SN/A * modification, are permitted provided that the following conditions are 201689SN/A * met: redistributions of source code must retain the above copyright 211689SN/A * notice, this list of conditions and the following disclaimer; 221689SN/A * redistributions in binary form must reproduce the above copyright 231689SN/A * notice, this list of conditions and the following disclaimer in the 241689SN/A * documentation and/or other materials provided with the distribution; 251689SN/A * neither the name of the copyright holders nor the names of its 261689SN/A * contributors may be used to endorse or promote products derived from 271689SN/A * this software without specific prior written permission. 281689SN/A * 291689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 301689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 311689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 321689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 331689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 341689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 351689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 361689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 371689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 381689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 391689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 402665Ssaidi@eecs.umich.edu * 412665Ssaidi@eecs.umich.edu * Authors: Kevin Lim 422756Sksewell@umich.edu * Korey Sewell 431689SN/A */ 441689SN/A 459944Smatt.horsnell@ARM.com#ifndef __CPU_O3_FETCH_IMPL_HH__ 469944Smatt.horsnell@ARM.com#define __CPU_O3_FETCH_IMPL_HH__ 479944Smatt.horsnell@ARM.com 484551Sbinkertn@umich.edu#include <algorithm> 494551Sbinkertn@umich.edu#include <cstring> 508733Sgeoffrey.blake@arm.com#include <list> 518733Sgeoffrey.blake@arm.com#include <map> 528733Sgeoffrey.blake@arm.com#include <queue> 534551Sbinkertn@umich.edu 5412406Sgabeblack@google.com#include "arch/generic/tlb.hh" 552037SN/A#include "arch/isa_traits.hh" 562669Sktlim@umich.edu#include "arch/utility.hh" 578793Sgblack@eecs.umich.edu#include "arch/vtophys.hh" 5810331Smitch.hayenga@arm.com#include "base/random.hh" 596216Snate@binkert.org#include "base/types.hh" 606658Snate@binkert.org#include "config/the_isa.hh" 618462Sgeoffrey.blake@arm.com#include "cpu/base.hh" 628887Sgeoffrey.blake@arm.com//#include "cpu/checker/cpu.hh" 6314195Sgabeblack@google.com#include "cpu/o3/cpu.hh" 648229Snate@binkert.org#include "cpu/o3/fetch.hh" 652632Sstever@eecs.umich.edu#include "cpu/exetrace.hh" 668232Snate@binkert.org#include "debug/Activity.hh" 679444SAndreas.Sandberg@ARM.com#include "debug/Drain.hh" 688232Snate@binkert.org#include "debug/Fetch.hh" 6914195Sgabeblack@google.com#include "debug/O3CPU.hh" 709527SMatt.Horsnell@arm.com#include "debug/O3PipeView.hh" 712669Sktlim@umich.edu#include "mem/packet.hh" 726216Snate@binkert.org#include "params/DerivO3CPU.hh" 732036SN/A#include "sim/byteswap.hh" 744167Sbinkertn@umich.edu#include "sim/core.hh" 758462Sgeoffrey.blake@arm.com#include "sim/eventq.hh" 768793Sgblack@eecs.umich.edu#include "sim/full_system.hh" 772292SN/A#include "sim/system.hh" 7811165SRekai.GonzalezAlberquilla@arm.com#include "cpu/o3/isa_specific.hh" 792292SN/A 806221Snate@binkert.orgusing namespace std; 816221Snate@binkert.org 821060SN/Atemplate<class Impl> 835529Snate@binkert.orgDefaultFetch<Impl>::DefaultFetch(O3CPU *_cpu, DerivO3CPUParams *params) 8413559Snikos.nikoleris@arm.com : fetchPolicy(params->smtFetchPolicy), 8513559Snikos.nikoleris@arm.com cpu(_cpu), 8613453Srekai.gonzalezalberquilla@arm.com branchPred(nullptr), 872292SN/A decodeToFetchDelay(params->decodeToFetchDelay), 882292SN/A renameToFetchDelay(params->renameToFetchDelay), 892292SN/A iewToFetchDelay(params->iewToFetchDelay), 902292SN/A commitToFetchDelay(params->commitToFetchDelay), 912292SN/A fetchWidth(params->fetchWidth), 9210329Smitch.hayenga@arm.com decodeWidth(params->decodeWidth), 932696Sktlim@umich.edu retryPkt(NULL), 946221Snate@binkert.org retryTid(InvalidThreadID), 959814Sandreas.hansson@arm.com cacheBlkSize(cpu->cacheLineSize()), 969982Satgutier@umich.edu fetchBufferSize(params->fetchBufferSize), 979982Satgutier@umich.edu fetchBufferMask(fetchBufferSize - 1), 9810329Smitch.hayenga@arm.com fetchQueueSize(params->fetchQueueSize), 995529Snate@binkert.org numThreads(params->numThreads), 1002292SN/A numFetchingThreads(params->smtNumFetchingThreads), 10114195Sgabeblack@google.com icachePort(this, _cpu), 1028462Sgeoffrey.blake@arm.com finishTranslationEvent(this) 1032632Sstever@eecs.umich.edu{ 1042292SN/A if (numThreads > Impl::MaxThreads) 1055982Sstever@gmail.com fatal("numThreads (%d) is larger than compiled limit (%d),\n" 1065982Sstever@gmail.com "\tincrease MaxThreads in src/cpu/o3/impl.hh\n", 1075982Sstever@gmail.com numThreads, static_cast<int>(Impl::MaxThreads)); 1088895Sb.grayson@samsung.com if (fetchWidth > Impl::MaxWidth) 1098895Sb.grayson@samsung.com fatal("fetchWidth (%d) is larger than compiled limit (%d),\n" 1108895Sb.grayson@samsung.com "\tincrease MaxWidth in src/cpu/o3/impl.hh\n", 1118895Sb.grayson@samsung.com fetchWidth, static_cast<int>(Impl::MaxWidth)); 1129982Satgutier@umich.edu if (fetchBufferSize > cacheBlkSize) 1139982Satgutier@umich.edu fatal("fetch buffer size (%u bytes) is greater than the cache " 1149982Satgutier@umich.edu "block size (%u bytes)\n", fetchBufferSize, cacheBlkSize); 1159982Satgutier@umich.edu if (cacheBlkSize % fetchBufferSize) 1169982Satgutier@umich.edu fatal("cache block (%u bytes) is not a multiple of the " 1179982Satgutier@umich.edu "fetch buffer (%u bytes)\n", cacheBlkSize, fetchBufferSize); 1182632Sstever@eecs.umich.edu 1192292SN/A // Figure out fetch policy 12013559Snikos.nikoleris@arm.com panic_if(fetchPolicy == FetchPolicy::SingleThread && numThreads > 1, 12113559Snikos.nikoleris@arm.com "Invalid Fetch Policy for a SMT workload."); 1221060SN/A 1231060SN/A // Get the size of an instruction. 1242980Sgblack@eecs.umich.edu instSize = sizeof(TheISA::MachInst); 1259023Sgblack@eecs.umich.edu 1269152Satgutier@umich.edu for (int i = 0; i < Impl::MaxThreads; i++) { 12713453Srekai.gonzalezalberquilla@arm.com fetchStatus[i] = Idle; 12813453Srekai.gonzalezalberquilla@arm.com decoder[i] = nullptr; 12913453Srekai.gonzalezalberquilla@arm.com pc[i] = 0; 13013453Srekai.gonzalezalberquilla@arm.com fetchOffset[i] = 0; 13113453Srekai.gonzalezalberquilla@arm.com macroop[i] = nullptr; 13213453Srekai.gonzalezalberquilla@arm.com delayedCommit[i] = false; 13313453Srekai.gonzalezalberquilla@arm.com memReq[i] = nullptr; 13413453Srekai.gonzalezalberquilla@arm.com stalls[i] = {false, false}; 1359982Satgutier@umich.edu fetchBuffer[i] = NULL; 1369982Satgutier@umich.edu fetchBufferPC[i] = 0; 1379982Satgutier@umich.edu fetchBufferValid[i] = false; 13813453Srekai.gonzalezalberquilla@arm.com lastIcacheStall[i] = 0; 13913453Srekai.gonzalezalberquilla@arm.com issuePipelinedIfetch[i] = false; 1409152Satgutier@umich.edu } 1419480Snilay@cs.wisc.edu 1429480Snilay@cs.wisc.edu branchPred = params->branchPred; 1439814Sandreas.hansson@arm.com 1449814Sandreas.hansson@arm.com for (ThreadID tid = 0; tid < numThreads; tid++) { 14511165SRekai.GonzalezAlberquilla@arm.com decoder[tid] = new TheISA::Decoder(params->isa[tid]); 1469982Satgutier@umich.edu // Create space to buffer the cache line data, 1479982Satgutier@umich.edu // which may not hold the entire cache line. 1489982Satgutier@umich.edu fetchBuffer[tid] = new uint8_t[fetchBufferSize]; 1499814Sandreas.hansson@arm.com } 1502292SN/A} 1511062SN/A 1522292SN/Atemplate <class Impl> 1532292SN/Astd::string 1542292SN/ADefaultFetch<Impl>::name() const 1552292SN/A{ 1562292SN/A return cpu->name() + ".fetch"; 1571062SN/A} 1581062SN/A 1591062SN/Atemplate <class Impl> 1601062SN/Avoid 16110023Smatt.horsnell@ARM.comDefaultFetch<Impl>::regProbePoints() 16210023Smatt.horsnell@ARM.com{ 16310023Smatt.horsnell@ARM.com ppFetch = new ProbePointArg<DynInstPtr>(cpu->getProbeManager(), "Fetch"); 16411246Sradhika.jagtap@ARM.com ppFetchRequestSent = new ProbePointArg<RequestPtr>(cpu->getProbeManager(), 16511246Sradhika.jagtap@ARM.com "FetchRequest"); 16611246Sradhika.jagtap@ARM.com 16710023Smatt.horsnell@ARM.com} 16810023Smatt.horsnell@ARM.com 16910023Smatt.horsnell@ARM.comtemplate <class Impl> 17010023Smatt.horsnell@ARM.comvoid 1712292SN/ADefaultFetch<Impl>::regStats() 1721062SN/A{ 1731062SN/A icacheStallCycles 1742348SN/A .name(name() + ".icacheStallCycles") 1751062SN/A .desc("Number of cycles fetch is stalled on an Icache miss") 1761062SN/A .prereq(icacheStallCycles); 1771062SN/A 1781062SN/A fetchedInsts 1792348SN/A .name(name() + ".Insts") 1801062SN/A .desc("Number of instructions fetch has processed") 1811062SN/A .prereq(fetchedInsts); 1822292SN/A 1832301SN/A fetchedBranches 1842348SN/A .name(name() + ".Branches") 1852301SN/A .desc("Number of branches that fetch encountered") 1862301SN/A .prereq(fetchedBranches); 1872301SN/A 1881062SN/A predictedBranches 1892348SN/A .name(name() + ".predictedBranches") 1901062SN/A .desc("Number of branches that fetch has predicted taken") 1911062SN/A .prereq(predictedBranches); 1922292SN/A 1931062SN/A fetchCycles 1942348SN/A .name(name() + ".Cycles") 1951062SN/A .desc("Number of cycles fetch has run and was not squashing or" 1961062SN/A " blocked") 1971062SN/A .prereq(fetchCycles); 1982292SN/A 1991062SN/A fetchSquashCycles 2002348SN/A .name(name() + ".SquashCycles") 2011062SN/A .desc("Number of cycles fetch has spent squashing") 2021062SN/A .prereq(fetchSquashCycles); 2032292SN/A 2047849SAli.Saidi@ARM.com fetchTlbCycles 2057849SAli.Saidi@ARM.com .name(name() + ".TlbCycles") 2067849SAli.Saidi@ARM.com .desc("Number of cycles fetch has spent waiting for tlb") 2077849SAli.Saidi@ARM.com .prereq(fetchTlbCycles); 2087849SAli.Saidi@ARM.com 2092292SN/A fetchIdleCycles 2102348SN/A .name(name() + ".IdleCycles") 2112292SN/A .desc("Number of cycles fetch was idle") 2122292SN/A .prereq(fetchIdleCycles); 2132292SN/A 2141062SN/A fetchBlockedCycles 2152348SN/A .name(name() + ".BlockedCycles") 2161062SN/A .desc("Number of cycles fetch has spent blocked") 2171062SN/A .prereq(fetchBlockedCycles); 2182292SN/A 2191062SN/A fetchedCacheLines 2202348SN/A .name(name() + ".CacheLines") 2211062SN/A .desc("Number of cache lines fetched") 2221062SN/A .prereq(fetchedCacheLines); 2231062SN/A 2242307SN/A fetchMiscStallCycles 2252348SN/A .name(name() + ".MiscStallCycles") 2262307SN/A .desc("Number of cycles fetch has spent waiting on interrupts, or " 2272307SN/A "bad addresses, or out of MSHRs") 2282307SN/A .prereq(fetchMiscStallCycles); 2292307SN/A 2308462Sgeoffrey.blake@arm.com fetchPendingDrainCycles 2318462Sgeoffrey.blake@arm.com .name(name() + ".PendingDrainCycles") 2328462Sgeoffrey.blake@arm.com .desc("Number of cycles fetch has spent waiting on pipes to drain") 2338462Sgeoffrey.blake@arm.com .prereq(fetchPendingDrainCycles); 2348462Sgeoffrey.blake@arm.com 2358462Sgeoffrey.blake@arm.com fetchNoActiveThreadStallCycles 2368462Sgeoffrey.blake@arm.com .name(name() + ".NoActiveThreadStallCycles") 2378462Sgeoffrey.blake@arm.com .desc("Number of stall cycles due to no active thread to fetch from") 2388462Sgeoffrey.blake@arm.com .prereq(fetchNoActiveThreadStallCycles); 2398462Sgeoffrey.blake@arm.com 2408462Sgeoffrey.blake@arm.com fetchPendingTrapStallCycles 2418462Sgeoffrey.blake@arm.com .name(name() + ".PendingTrapStallCycles") 2428462Sgeoffrey.blake@arm.com .desc("Number of stall cycles due to pending traps") 2438462Sgeoffrey.blake@arm.com .prereq(fetchPendingTrapStallCycles); 2448462Sgeoffrey.blake@arm.com 2458462Sgeoffrey.blake@arm.com fetchPendingQuiesceStallCycles 2468462Sgeoffrey.blake@arm.com .name(name() + ".PendingQuiesceStallCycles") 2478462Sgeoffrey.blake@arm.com .desc("Number of stall cycles due to pending quiesce instructions") 2488462Sgeoffrey.blake@arm.com .prereq(fetchPendingQuiesceStallCycles); 2498462Sgeoffrey.blake@arm.com 2508462Sgeoffrey.blake@arm.com fetchIcacheWaitRetryStallCycles 2518462Sgeoffrey.blake@arm.com .name(name() + ".IcacheWaitRetryStallCycles") 2528462Sgeoffrey.blake@arm.com .desc("Number of stall cycles due to full MSHR") 2538462Sgeoffrey.blake@arm.com .prereq(fetchIcacheWaitRetryStallCycles); 2548462Sgeoffrey.blake@arm.com 2552301SN/A fetchIcacheSquashes 2562348SN/A .name(name() + ".IcacheSquashes") 2572301SN/A .desc("Number of outstanding Icache misses that were squashed") 2582301SN/A .prereq(fetchIcacheSquashes); 2592301SN/A 2608064SAli.Saidi@ARM.com fetchTlbSquashes 2618064SAli.Saidi@ARM.com .name(name() + ".ItlbSquashes") 2628064SAli.Saidi@ARM.com .desc("Number of outstanding ITLB misses that were squashed") 2638064SAli.Saidi@ARM.com .prereq(fetchTlbSquashes); 2648064SAli.Saidi@ARM.com 2652292SN/A fetchNisnDist 2661062SN/A .init(/* base value */ 0, 2671062SN/A /* last value */ fetchWidth, 2681062SN/A /* bucket size */ 1) 2692348SN/A .name(name() + ".rateDist") 2701062SN/A .desc("Number of instructions fetched each cycle (Total)") 2712292SN/A .flags(Stats::pdf); 2722292SN/A 2732292SN/A idleRate 2742348SN/A .name(name() + ".idleRate") 2752292SN/A .desc("Percent of cycles fetch was idle") 2762292SN/A .prereq(idleRate); 2772292SN/A idleRate = fetchIdleCycles * 100 / cpu->numCycles; 2782292SN/A 2792292SN/A branchRate 2802348SN/A .name(name() + ".branchRate") 2812292SN/A .desc("Number of branch fetches per cycle") 2822292SN/A .flags(Stats::total); 2832348SN/A branchRate = fetchedBranches / cpu->numCycles; 2842292SN/A 2852292SN/A fetchRate 2862348SN/A .name(name() + ".rate") 2872292SN/A .desc("Number of inst fetches per cycle") 2882292SN/A .flags(Stats::total); 2892292SN/A fetchRate = fetchedInsts / cpu->numCycles; 2901060SN/A} 2911060SN/A 2921060SN/Atemplate<class Impl> 2931060SN/Avoid 2942292SN/ADefaultFetch<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *time_buffer) 2951060SN/A{ 2961060SN/A timeBuffer = time_buffer; 2971060SN/A 2981060SN/A // Create wires to get information from proper places in time buffer. 2991060SN/A fromDecode = timeBuffer->getWire(-decodeToFetchDelay); 3001060SN/A fromRename = timeBuffer->getWire(-renameToFetchDelay); 3011060SN/A fromIEW = timeBuffer->getWire(-iewToFetchDelay); 3021060SN/A fromCommit = timeBuffer->getWire(-commitToFetchDelay); 3031060SN/A} 3041060SN/A 3051060SN/Atemplate<class Impl> 3061060SN/Avoid 3076221Snate@binkert.orgDefaultFetch<Impl>::setActiveThreads(std::list<ThreadID> *at_ptr) 3081060SN/A{ 3092292SN/A activeThreads = at_ptr; 3102292SN/A} 3112292SN/A 3122292SN/Atemplate<class Impl> 3132292SN/Avoid 31410329Smitch.hayenga@arm.comDefaultFetch<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *ftb_ptr) 3152292SN/A{ 31610329Smitch.hayenga@arm.com // Create wire to write information to proper place in fetch time buf. 31710329Smitch.hayenga@arm.com toDecode = ftb_ptr->getWire(0); 3181060SN/A} 3191060SN/A 3202292SN/Atemplate<class Impl> 3212292SN/Avoid 3229427SAndreas.Sandberg@ARM.comDefaultFetch<Impl>::startupStage() 3232292SN/A{ 3249444SAndreas.Sandberg@ARM.com assert(priorityList.empty()); 3259444SAndreas.Sandberg@ARM.com resetStage(); 3269444SAndreas.Sandberg@ARM.com 3279444SAndreas.Sandberg@ARM.com // Fetch needs to start fetching instructions at the very beginning, 3289444SAndreas.Sandberg@ARM.com // so it must start up in active state. 3299444SAndreas.Sandberg@ARM.com switchToActive(); 3309444SAndreas.Sandberg@ARM.com} 3319444SAndreas.Sandberg@ARM.com 3329444SAndreas.Sandberg@ARM.comtemplate<class Impl> 3339444SAndreas.Sandberg@ARM.comvoid 33413641Sqtt2@cornell.eduDefaultFetch<Impl>::clearStates(ThreadID tid) 33513641Sqtt2@cornell.edu{ 33613641Sqtt2@cornell.edu fetchStatus[tid] = Running; 33713641Sqtt2@cornell.edu pc[tid] = cpu->pcState(tid); 33813641Sqtt2@cornell.edu fetchOffset[tid] = 0; 33913641Sqtt2@cornell.edu macroop[tid] = NULL; 34013641Sqtt2@cornell.edu delayedCommit[tid] = false; 34113641Sqtt2@cornell.edu memReq[tid] = NULL; 34213641Sqtt2@cornell.edu stalls[tid].decode = false; 34313641Sqtt2@cornell.edu stalls[tid].drain = false; 34413641Sqtt2@cornell.edu fetchBufferPC[tid] = 0; 34513641Sqtt2@cornell.edu fetchBufferValid[tid] = false; 34613641Sqtt2@cornell.edu fetchQueue[tid].clear(); 34713641Sqtt2@cornell.edu 34813641Sqtt2@cornell.edu // TODO not sure what to do with priorityList for now 34913641Sqtt2@cornell.edu // priorityList.push_back(tid); 35013641Sqtt2@cornell.edu} 35113641Sqtt2@cornell.edu 35213641Sqtt2@cornell.edutemplate<class Impl> 35313641Sqtt2@cornell.eduvoid 3549444SAndreas.Sandberg@ARM.comDefaultFetch<Impl>::resetStage() 3559444SAndreas.Sandberg@ARM.com{ 3569444SAndreas.Sandberg@ARM.com numInst = 0; 3579444SAndreas.Sandberg@ARM.com interruptPending = false; 3589444SAndreas.Sandberg@ARM.com cacheBlocked = false; 3599444SAndreas.Sandberg@ARM.com 3609444SAndreas.Sandberg@ARM.com priorityList.clear(); 3619444SAndreas.Sandberg@ARM.com 3622348SN/A // Setup PC and nextPC with initial state. 3639982Satgutier@umich.edu for (ThreadID tid = 0; tid < numThreads; ++tid) { 3649444SAndreas.Sandberg@ARM.com fetchStatus[tid] = Running; 3657720Sgblack@eecs.umich.edu pc[tid] = cpu->pcState(tid); 3667764Sgblack@eecs.umich.edu fetchOffset[tid] = 0; 3677764Sgblack@eecs.umich.edu macroop[tid] = NULL; 3689444SAndreas.Sandberg@ARM.com 3698314Sgeoffrey.blake@arm.com delayedCommit[tid] = false; 3703730Sktlim@umich.edu memReq[tid] = NULL; 3713730Sktlim@umich.edu 3724302Sktlim@umich.edu stalls[tid].decode = false; 3739444SAndreas.Sandberg@ARM.com stalls[tid].drain = false; 3749444SAndreas.Sandberg@ARM.com 3759982Satgutier@umich.edu fetchBufferPC[tid] = 0; 3769982Satgutier@umich.edu fetchBufferValid[tid] = false; 3779982Satgutier@umich.edu 37810331Smitch.hayenga@arm.com fetchQueue[tid].clear(); 37910331Smitch.hayenga@arm.com 3809444SAndreas.Sandberg@ARM.com priorityList.push_back(tid); 3814302Sktlim@umich.edu } 3824329Sktlim@umich.edu 3839444SAndreas.Sandberg@ARM.com wroteToTimeBuffer = false; 3849444SAndreas.Sandberg@ARM.com _status = Inactive; 3852292SN/A} 3862292SN/A 3872292SN/Atemplate<class Impl> 3882292SN/Avoid 3892669Sktlim@umich.eduDefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt) 3902292SN/A{ 39111435Smitch.hayenga@arm.com ThreadID tid = cpu->contextToThread(pkt->req->contextId()); 3922292SN/A 39313831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Waking up from cache miss.\n", tid); 3949444SAndreas.Sandberg@ARM.com assert(!cpu->switchedOut()); 3951060SN/A 3961060SN/A // Only change the status if it's still waiting on the icache access 3971060SN/A // to return. 3982669Sktlim@umich.edu if (fetchStatus[tid] != IcacheWaitResponse || 3999444SAndreas.Sandberg@ARM.com pkt->req != memReq[tid]) { 4002301SN/A ++fetchIcacheSquashes; 4012669Sktlim@umich.edu delete pkt; 4022292SN/A return; 4032301SN/A } 4042292SN/A 40510563Sandreas.hansson@arm.com memcpy(fetchBuffer[tid], pkt->getConstPtr<uint8_t>(), fetchBufferSize); 4069982Satgutier@umich.edu fetchBufferValid[tid] = true; 4072894Srdreslin@umich.edu 4089444SAndreas.Sandberg@ARM.com // Wake up the CPU (if it went to sleep and was waiting on 4099444SAndreas.Sandberg@ARM.com // this completion event). 4109444SAndreas.Sandberg@ARM.com cpu->wakeCPU(); 4112292SN/A 41213831SAndrea.Mondelli@ucf.edu DPRINTF(Activity, "[tid:%i] Activating fetch due to cache completion\n", 4139444SAndreas.Sandberg@ARM.com tid); 4142292SN/A 4159444SAndreas.Sandberg@ARM.com switchToActive(); 4162292SN/A 4172669Sktlim@umich.edu // Only switch to IcacheAccessComplete if we're not stalled as well. 4182292SN/A if (checkStall(tid)) { 4192292SN/A fetchStatus[tid] = Blocked; 4202292SN/A } else { 4212669Sktlim@umich.edu fetchStatus[tid] = IcacheAccessComplete; 4222292SN/A } 4232292SN/A 42410020Smatt.horsnell@ARM.com pkt->req->setAccessLatency(); 42510023Smatt.horsnell@ARM.com cpu->ppInstAccessComplete->notify(pkt); 4262323SN/A // Reset the mem req to NULL. 4272669Sktlim@umich.edu delete pkt; 4282678Sktlim@umich.edu memReq[tid] = NULL; 4292292SN/A} 4302292SN/A 4312292SN/Atemplate <class Impl> 4329444SAndreas.Sandberg@ARM.comvoid 4339444SAndreas.Sandberg@ARM.comDefaultFetch<Impl>::drainResume() 4342307SN/A{ 43511650Srekai.gonzalezalberquilla@arm.com for (ThreadID i = 0; i < numThreads; ++i) { 43611650Srekai.gonzalezalberquilla@arm.com stalls[i].decode = false; 4379444SAndreas.Sandberg@ARM.com stalls[i].drain = false; 43811650Srekai.gonzalezalberquilla@arm.com } 4392316SN/A} 4402316SN/A 4412316SN/Atemplate <class Impl> 4422316SN/Avoid 4439444SAndreas.Sandberg@ARM.comDefaultFetch<Impl>::drainSanityCheck() const 4442316SN/A{ 4459444SAndreas.Sandberg@ARM.com assert(isDrained()); 4469444SAndreas.Sandberg@ARM.com assert(retryPkt == NULL); 4479444SAndreas.Sandberg@ARM.com assert(retryTid == InvalidThreadID); 44810231Ssteve.reinhardt@amd.com assert(!cacheBlocked); 44910231Ssteve.reinhardt@amd.com assert(!interruptPending); 4509444SAndreas.Sandberg@ARM.com 4519444SAndreas.Sandberg@ARM.com for (ThreadID i = 0; i < numThreads; ++i) { 4529444SAndreas.Sandberg@ARM.com assert(!memReq[i]); 4539444SAndreas.Sandberg@ARM.com assert(fetchStatus[i] == Idle || stalls[i].drain); 4549444SAndreas.Sandberg@ARM.com } 4559444SAndreas.Sandberg@ARM.com 4569480Snilay@cs.wisc.edu branchPred->drainSanityCheck(); 4572843Sktlim@umich.edu} 4582843Sktlim@umich.edu 4592843Sktlim@umich.edutemplate <class Impl> 4609444SAndreas.Sandberg@ARM.combool 4619444SAndreas.Sandberg@ARM.comDefaultFetch<Impl>::isDrained() const 4622843Sktlim@umich.edu{ 4639444SAndreas.Sandberg@ARM.com /* Make sure that threads are either idle of that the commit stage 4649444SAndreas.Sandberg@ARM.com * has signaled that draining has completed by setting the drain 4659444SAndreas.Sandberg@ARM.com * stall flag. This effectively forces the pipeline to be disabled 4669444SAndreas.Sandberg@ARM.com * until the whole system is drained (simulation may continue to 4679444SAndreas.Sandberg@ARM.com * drain other components). 4689444SAndreas.Sandberg@ARM.com */ 4699444SAndreas.Sandberg@ARM.com for (ThreadID i = 0; i < numThreads; ++i) { 47010331Smitch.hayenga@arm.com // Verify fetch queues are drained 47110331Smitch.hayenga@arm.com if (!fetchQueue[i].empty()) 4729444SAndreas.Sandberg@ARM.com return false; 47310331Smitch.hayenga@arm.com 47410331Smitch.hayenga@arm.com // Return false if not idle or drain stalled 47510331Smitch.hayenga@arm.com if (fetchStatus[i] != Idle) { 47610331Smitch.hayenga@arm.com if (fetchStatus[i] == Blocked && stalls[i].drain) 47710331Smitch.hayenga@arm.com continue; 47810331Smitch.hayenga@arm.com else 47910331Smitch.hayenga@arm.com return false; 48010331Smitch.hayenga@arm.com } 4819444SAndreas.Sandberg@ARM.com } 4829444SAndreas.Sandberg@ARM.com 4839444SAndreas.Sandberg@ARM.com /* The pipeline might start up again in the middle of the drain 4849444SAndreas.Sandberg@ARM.com * cycle if the finish translation event is scheduled, so make 4859444SAndreas.Sandberg@ARM.com * sure that's not the case. 4869444SAndreas.Sandberg@ARM.com */ 4879444SAndreas.Sandberg@ARM.com return !finishTranslationEvent.scheduled(); 4882307SN/A} 4892307SN/A 4902307SN/Atemplate <class Impl> 4912307SN/Avoid 4922307SN/ADefaultFetch<Impl>::takeOverFrom() 4932307SN/A{ 4949444SAndreas.Sandberg@ARM.com assert(cpu->getInstPort().isConnected()); 4959444SAndreas.Sandberg@ARM.com resetStage(); 4968707Sandreas.hansson@arm.com 4972307SN/A} 4982307SN/A 4992307SN/Atemplate <class Impl> 5002307SN/Avoid 5019444SAndreas.Sandberg@ARM.comDefaultFetch<Impl>::drainStall(ThreadID tid) 5029444SAndreas.Sandberg@ARM.com{ 5039444SAndreas.Sandberg@ARM.com assert(cpu->isDraining()); 5049444SAndreas.Sandberg@ARM.com assert(!stalls[tid].drain); 5059444SAndreas.Sandberg@ARM.com DPRINTF(Drain, "%i: Thread drained.\n", tid); 5069444SAndreas.Sandberg@ARM.com stalls[tid].drain = true; 5079444SAndreas.Sandberg@ARM.com} 5089444SAndreas.Sandberg@ARM.com 5099444SAndreas.Sandberg@ARM.comtemplate <class Impl> 5109444SAndreas.Sandberg@ARM.comvoid 5112292SN/ADefaultFetch<Impl>::wakeFromQuiesce() 5122292SN/A{ 5132292SN/A DPRINTF(Fetch, "Waking up from quiesce\n"); 5142292SN/A // Hopefully this is safe 5152348SN/A // @todo: Allow other threads to wake from quiesce. 5162292SN/A fetchStatus[0] = Running; 5172292SN/A} 5182292SN/A 5192292SN/Atemplate <class Impl> 5202292SN/Ainline void 5212292SN/ADefaultFetch<Impl>::switchToActive() 5222292SN/A{ 5232292SN/A if (_status == Inactive) { 5242292SN/A DPRINTF(Activity, "Activating stage.\n"); 5252292SN/A 5262733Sktlim@umich.edu cpu->activateStage(O3CPU::FetchIdx); 5272292SN/A 5282292SN/A _status = Active; 5292292SN/A } 5302292SN/A} 5312292SN/A 5322292SN/Atemplate <class Impl> 5332292SN/Ainline void 5342292SN/ADefaultFetch<Impl>::switchToInactive() 5352292SN/A{ 5362292SN/A if (_status == Active) { 5372292SN/A DPRINTF(Activity, "Deactivating stage.\n"); 5382292SN/A 5392733Sktlim@umich.edu cpu->deactivateStage(O3CPU::FetchIdx); 5402292SN/A 5412292SN/A _status = Inactive; 5422292SN/A } 5431060SN/A} 5441060SN/A 5451062SN/Atemplate <class Impl> 54610331Smitch.hayenga@arm.comvoid 54710331Smitch.hayenga@arm.comDefaultFetch<Impl>::deactivateThread(ThreadID tid) 54810331Smitch.hayenga@arm.com{ 54910331Smitch.hayenga@arm.com // Update priority list 55010331Smitch.hayenga@arm.com auto thread_it = std::find(priorityList.begin(), priorityList.end(), tid); 55110331Smitch.hayenga@arm.com if (thread_it != priorityList.end()) { 55210331Smitch.hayenga@arm.com priorityList.erase(thread_it); 55310331Smitch.hayenga@arm.com } 55410331Smitch.hayenga@arm.com} 55510331Smitch.hayenga@arm.com 55610331Smitch.hayenga@arm.comtemplate <class Impl> 5571061SN/Abool 5587720Sgblack@eecs.umich.eduDefaultFetch<Impl>::lookupAndUpdateNextPC( 55913429Srekai.gonzalezalberquilla@arm.com const DynInstPtr &inst, TheISA::PCState &nextPC) 5601061SN/A{ 5611061SN/A // Do branch prediction check here. 5621062SN/A // A bit of a misnomer...next_PC is actually the current PC until 5631062SN/A // this function updates it. 5641062SN/A bool predict_taken; 5651062SN/A 5661062SN/A if (!inst->isControl()) { 5677720Sgblack@eecs.umich.edu TheISA::advancePC(nextPC, inst->staticInst); 5687720Sgblack@eecs.umich.edu inst->setPredTarg(nextPC); 5693795Sgblack@eecs.umich.edu inst->setPredTaken(false); 5701062SN/A return false; 5711062SN/A } 5721062SN/A 5736221Snate@binkert.org ThreadID tid = inst->threadNumber; 5749480Snilay@cs.wisc.edu predict_taken = branchPred->predict(inst->staticInst, inst->seqNum, 5759480Snilay@cs.wisc.edu nextPC, tid); 5762935Sksewell@umich.edu 5776036Sksewell@umich.edu if (predict_taken) { 57813831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] [sn:%llu] Branch at PC %#x " 57913831SAndrea.Mondelli@ucf.edu "predicted to be taken to %s\n", 58013831SAndrea.Mondelli@ucf.edu tid, inst->seqNum, inst->pcState().instAddr(), nextPC); 5812935Sksewell@umich.edu } else { 58213831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] [sn:%llu] Branch at PC %#x " 58313831SAndrea.Mondelli@ucf.edu "predicted to be not taken\n", 58413831SAndrea.Mondelli@ucf.edu tid, inst->seqNum, inst->pcState().instAddr()); 5856036Sksewell@umich.edu } 5862935Sksewell@umich.edu 58713831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] [sn:%llu] Branch at PC %#x " 58813831SAndrea.Mondelli@ucf.edu "predicted to go to %s\n", 58913831SAndrea.Mondelli@ucf.edu tid, inst->seqNum, inst->pcState().instAddr(), nextPC); 5907720Sgblack@eecs.umich.edu inst->setPredTarg(nextPC); 5913795Sgblack@eecs.umich.edu inst->setPredTaken(predict_taken); 5922132SN/A 5932301SN/A ++fetchedBranches; 5941062SN/A 5951062SN/A if (predict_taken) { 5961062SN/A ++predictedBranches; 5971061SN/A } 5981061SN/A 5991062SN/A return predict_taken; 6001061SN/A} 6011061SN/A 6021062SN/Atemplate <class Impl> 6032292SN/Abool 6047849SAli.Saidi@ARM.comDefaultFetch<Impl>::fetchCacheLine(Addr vaddr, ThreadID tid, Addr pc) 6051062SN/A{ 6062292SN/A Fault fault = NoFault; 6071062SN/A 6089444SAndreas.Sandberg@ARM.com assert(!cpu->switchedOut()); 6099444SAndreas.Sandberg@ARM.com 6107849SAli.Saidi@ARM.com // @todo: not sure if these should block translation. 6113521Sgblack@eecs.umich.edu //AlphaDep 6123633Sktlim@umich.edu if (cacheBlocked) { 6133633Sktlim@umich.edu DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, cache blocked\n", 6143633Sktlim@umich.edu tid); 6153633Sktlim@umich.edu return false; 6168824Snilay@cs.wisc.edu } else if (checkInterrupt(pc) && !delayedCommit[tid]) { 6172696Sktlim@umich.edu // Hold off fetch from getting new instructions when: 6182696Sktlim@umich.edu // Cache is blocked, or 6192696Sktlim@umich.edu // while an interrupt is pending and we're not in PAL mode, or 6202696Sktlim@umich.edu // fetch is switched out. 6213633Sktlim@umich.edu DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, interrupt pending\n", 6223633Sktlim@umich.edu tid); 6232292SN/A return false; 6242292SN/A } 6251062SN/A 6269982Satgutier@umich.edu // Align the fetch address to the start of a fetch buffer segment. 6279982Satgutier@umich.edu Addr fetchBufferBlockPC = fetchBufferAlignPC(vaddr); 6281062SN/A 6298064SAli.Saidi@ARM.com DPRINTF(Fetch, "[tid:%i] Fetching cache line %#x for addr %#x\n", 6309982Satgutier@umich.edu tid, fetchBufferBlockPC, vaddr); 6318064SAli.Saidi@ARM.com 6322292SN/A // Setup the memReq to do a read of the first instruction's address. 6331062SN/A // Set the appropriate read size and flags as well. 6342669Sktlim@umich.edu // Build request here. 63512749Sgiacomo.travaglini@arm.com RequestPtr mem_req = std::make_shared<Request>( 63612749Sgiacomo.travaglini@arm.com tid, fetchBufferBlockPC, fetchBufferSize, 63712749Sgiacomo.travaglini@arm.com Request::INST_FETCH, cpu->instMasterId(), pc, 63812749Sgiacomo.travaglini@arm.com cpu->thread[tid]->contextId()); 6392292SN/A 64010024Sdam.sunwoo@arm.com mem_req->taskId(cpu->taskId()); 64110024Sdam.sunwoo@arm.com 6422678Sktlim@umich.edu memReq[tid] = mem_req; 6431062SN/A 6447849SAli.Saidi@ARM.com // Initiate translation of the icache block 6457849SAli.Saidi@ARM.com fetchStatus[tid] = ItlbWait; 6467849SAli.Saidi@ARM.com FetchTranslation *trans = new FetchTranslation(this); 6477849SAli.Saidi@ARM.com cpu->itb->translateTiming(mem_req, cpu->thread[tid]->getTC(), 6487849SAli.Saidi@ARM.com trans, BaseTLB::Execute); 6497849SAli.Saidi@ARM.com return true; 6507849SAli.Saidi@ARM.com} 6511062SN/A 6527849SAli.Saidi@ARM.comtemplate <class Impl> 6537849SAli.Saidi@ARM.comvoid 65412749Sgiacomo.travaglini@arm.comDefaultFetch<Impl>::finishTranslation(const Fault &fault, 65512749Sgiacomo.travaglini@arm.com const RequestPtr &mem_req) 6567849SAli.Saidi@ARM.com{ 65711435Smitch.hayenga@arm.com ThreadID tid = cpu->contextToThread(mem_req->contextId()); 6589982Satgutier@umich.edu Addr fetchBufferBlockPC = mem_req->getVaddr(); 6591062SN/A 6609444SAndreas.Sandberg@ARM.com assert(!cpu->switchedOut()); 6619444SAndreas.Sandberg@ARM.com 6627947SGiacomo.Gabrielli@arm.com // Wake up CPU if it was idle 6637947SGiacomo.Gabrielli@arm.com cpu->wakeCPU(); 6647947SGiacomo.Gabrielli@arm.com 6658064SAli.Saidi@ARM.com if (fetchStatus[tid] != ItlbWait || mem_req != memReq[tid] || 6669444SAndreas.Sandberg@ARM.com mem_req->getVaddr() != memReq[tid]->getVaddr()) { 6678064SAli.Saidi@ARM.com DPRINTF(Fetch, "[tid:%i] Ignoring itlb completed after squash\n", 6688064SAli.Saidi@ARM.com tid); 6698064SAli.Saidi@ARM.com ++fetchTlbSquashes; 6708064SAli.Saidi@ARM.com return; 6718064SAli.Saidi@ARM.com } 6728064SAli.Saidi@ARM.com 6738064SAli.Saidi@ARM.com 6747849SAli.Saidi@ARM.com // If translation was successful, attempt to read the icache block. 6752090SN/A if (fault == NoFault) { 6768460SAli.Saidi@ARM.com // Check that we're not going off into random memory 6778460SAli.Saidi@ARM.com // If we have, just wait around for commit to squash something and put 6788460SAli.Saidi@ARM.com // us on the right track 6798931Sandreas.hansson@arm.com if (!cpu->system->isMemAddr(mem_req->getPaddr())) { 6808460SAli.Saidi@ARM.com warn("Address %#x is outside of physical memory, stopping fetch\n", 6818460SAli.Saidi@ARM.com mem_req->getPaddr()); 6828460SAli.Saidi@ARM.com fetchStatus[tid] = NoGoodAddr; 6838460SAli.Saidi@ARM.com memReq[tid] = NULL; 6848460SAli.Saidi@ARM.com return; 6858460SAli.Saidi@ARM.com } 6868460SAli.Saidi@ARM.com 6872669Sktlim@umich.edu // Build packet here. 6888949Sandreas.hansson@arm.com PacketPtr data_pkt = new Packet(mem_req, MemCmd::ReadReq); 68910566Sandreas.hansson@arm.com data_pkt->dataDynamic(new uint8_t[fetchBufferSize]); 6902669Sktlim@umich.edu 6919982Satgutier@umich.edu fetchBufferPC[tid] = fetchBufferBlockPC; 6929982Satgutier@umich.edu fetchBufferValid[tid] = false; 6931062SN/A DPRINTF(Fetch, "Fetch: Doing instruction read.\n"); 6941062SN/A 6951062SN/A fetchedCacheLines++; 6962632Sstever@eecs.umich.edu 6977849SAli.Saidi@ARM.com // Access the cache. 69814195Sgabeblack@google.com if (!icachePort.sendTimingReq(data_pkt)) { 6992696Sktlim@umich.edu assert(retryPkt == NULL); 7006221Snate@binkert.org assert(retryTid == InvalidThreadID); 7012292SN/A DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid); 7027849SAli.Saidi@ARM.com 7032696Sktlim@umich.edu fetchStatus[tid] = IcacheWaitRetry; 7042696Sktlim@umich.edu retryPkt = data_pkt; 7052696Sktlim@umich.edu retryTid = tid; 7062696Sktlim@umich.edu cacheBlocked = true; 7077849SAli.Saidi@ARM.com } else { 70813831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Doing Icache access.\n", tid); 70913831SAndrea.Mondelli@ucf.edu DPRINTF(Activity, "[tid:%i] Activity: Waiting on I-cache " 7107849SAli.Saidi@ARM.com "response.\n", tid); 7117849SAli.Saidi@ARM.com lastIcacheStall[tid] = curTick(); 7127849SAli.Saidi@ARM.com fetchStatus[tid] = IcacheWaitResponse; 71311246Sradhika.jagtap@ARM.com // Notify Fetch Request probe when a packet containing a fetch 71411246Sradhika.jagtap@ARM.com // request is successfully sent 71511246Sradhika.jagtap@ARM.com ppFetchRequestSent->notify(mem_req); 7162632Sstever@eecs.umich.edu } 7172678Sktlim@umich.edu } else { 71810329Smitch.hayenga@arm.com // Don't send an instruction to decode if we can't handle it. 71910331Smitch.hayenga@arm.com if (!(numInst < fetchWidth) || !(fetchQueue[tid].size() < fetchQueueSize)) { 7208462Sgeoffrey.blake@arm.com assert(!finishTranslationEvent.scheduled()); 7218462Sgeoffrey.blake@arm.com finishTranslationEvent.setFault(fault); 7228462Sgeoffrey.blake@arm.com finishTranslationEvent.setReq(mem_req); 7239180Sandreas.hansson@arm.com cpu->schedule(finishTranslationEvent, 7249180Sandreas.hansson@arm.com cpu->clockEdge(Cycles(1))); 7258462Sgeoffrey.blake@arm.com return; 7268462Sgeoffrey.blake@arm.com } 7278064SAli.Saidi@ARM.com DPRINTF(Fetch, "[tid:%i] Got back req with addr %#x but expected %#x\n", 7288462Sgeoffrey.blake@arm.com tid, mem_req->getVaddr(), memReq[tid]->getVaddr()); 7297849SAli.Saidi@ARM.com // Translation faulted, icache request won't be sent. 7302678Sktlim@umich.edu memReq[tid] = NULL; 7317849SAli.Saidi@ARM.com 7327849SAli.Saidi@ARM.com // Send the fault to commit. This thread will not do anything 7337849SAli.Saidi@ARM.com // until commit handles the fault. The only other way it can 7347849SAli.Saidi@ARM.com // wake up is if a squash comes along and changes the PC. 7357849SAli.Saidi@ARM.com TheISA::PCState fetchPC = pc[tid]; 7367849SAli.Saidi@ARM.com 73713831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Translation faulted, building noop.\n", tid); 7387849SAli.Saidi@ARM.com // We will use a nop in ordier to carry the fault. 73912405Sgabeblack@google.com DynInstPtr instruction = buildInst(tid, StaticInst::nopStaticInstPtr, 74012405Sgabeblack@google.com NULL, fetchPC, fetchPC, false); 74112422Sgabeblack@google.com instruction->setNotAnInst(); 7427849SAli.Saidi@ARM.com 7437849SAli.Saidi@ARM.com instruction->setPredTarg(fetchPC); 7447849SAli.Saidi@ARM.com instruction->fault = fault; 7457849SAli.Saidi@ARM.com wroteToTimeBuffer = true; 7467849SAli.Saidi@ARM.com 7477947SGiacomo.Gabrielli@arm.com DPRINTF(Activity, "Activity this cycle.\n"); 7487947SGiacomo.Gabrielli@arm.com cpu->activityThisCycle(); 7497947SGiacomo.Gabrielli@arm.com 7507849SAli.Saidi@ARM.com fetchStatus[tid] = TrapPending; 7517849SAli.Saidi@ARM.com 75213831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Blocked, need to handle the trap.\n", tid); 75313831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] fault (%s) detected @ PC %s.\n", 7547849SAli.Saidi@ARM.com tid, fault->name(), pc[tid]); 7551062SN/A } 7567849SAli.Saidi@ARM.com _status = updateFetchStatus(); 7571062SN/A} 7581062SN/A 7591062SN/Atemplate <class Impl> 7601062SN/Ainline void 7618503Sgblack@eecs.umich.eduDefaultFetch<Impl>::doSquash(const TheISA::PCState &newPC, 7628503Sgblack@eecs.umich.edu const DynInstPtr squashInst, ThreadID tid) 7631060SN/A{ 76413831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Squashing, setting PC to: %s.\n", 7657720Sgblack@eecs.umich.edu tid, newPC); 7661061SN/A 7677720Sgblack@eecs.umich.edu pc[tid] = newPC; 7687764Sgblack@eecs.umich.edu fetchOffset[tid] = 0; 7698503Sgblack@eecs.umich.edu if (squashInst && squashInst->pcState().instAddr() == newPC.instAddr()) 7708503Sgblack@eecs.umich.edu macroop[tid] = squashInst->macroop; 7718503Sgblack@eecs.umich.edu else 7728503Sgblack@eecs.umich.edu macroop[tid] = NULL; 7739023Sgblack@eecs.umich.edu decoder[tid]->reset(); 7741060SN/A 7751061SN/A // Clear the icache miss if it's outstanding. 7762669Sktlim@umich.edu if (fetchStatus[tid] == IcacheWaitResponse) { 77713831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Squashing outstanding Icache miss.\n", 7782292SN/A tid); 7792678Sktlim@umich.edu memReq[tid] = NULL; 7808064SAli.Saidi@ARM.com } else if (fetchStatus[tid] == ItlbWait) { 78113831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Squashing outstanding ITLB miss.\n", 7828064SAli.Saidi@ARM.com tid); 7838064SAli.Saidi@ARM.com memReq[tid] = NULL; 7841061SN/A } 7851060SN/A 7862696Sktlim@umich.edu // Get rid of the retrying packet if it was from this thread. 7872696Sktlim@umich.edu if (retryTid == tid) { 7882696Sktlim@umich.edu assert(cacheBlocked); 7894032Sktlim@umich.edu if (retryPkt) { 7904032Sktlim@umich.edu delete retryPkt; 7914032Sktlim@umich.edu } 7924032Sktlim@umich.edu retryPkt = NULL; 7936221Snate@binkert.org retryTid = InvalidThreadID; 7942696Sktlim@umich.edu } 7952696Sktlim@umich.edu 7962292SN/A fetchStatus[tid] = Squashing; 7971062SN/A 79810329Smitch.hayenga@arm.com // Empty fetch queue 79910331Smitch.hayenga@arm.com fetchQueue[tid].clear(); 80010329Smitch.hayenga@arm.com 8018824Snilay@cs.wisc.edu // microops are being squashed, it is not known wheather the 8028824Snilay@cs.wisc.edu // youngest non-squashed microop was marked delayed commit 8038824Snilay@cs.wisc.edu // or not. Setting the flag to true ensures that the 8048824Snilay@cs.wisc.edu // interrupts are not handled when they cannot be, though 8058824Snilay@cs.wisc.edu // some opportunities to handle interrupts may be missed. 8068824Snilay@cs.wisc.edu delayedCommit[tid] = true; 8078824Snilay@cs.wisc.edu 8081062SN/A ++fetchSquashCycles; 8091062SN/A} 8101062SN/A 8111062SN/Atemplate<class Impl> 8121062SN/Avoid 8137720Sgblack@eecs.umich.eduDefaultFetch<Impl>::squashFromDecode(const TheISA::PCState &newPC, 8148503Sgblack@eecs.umich.edu const DynInstPtr squashInst, 8158503Sgblack@eecs.umich.edu const InstSeqNum seq_num, ThreadID tid) 8161062SN/A{ 81713831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Squashing from decode.\n", tid); 8181062SN/A 8198503Sgblack@eecs.umich.edu doSquash(newPC, squashInst, tid); 8202935Sksewell@umich.edu 8211062SN/A // Tell the CPU to remove any instructions that are in flight between 8221062SN/A // fetch and decode. 8232292SN/A cpu->removeInstsUntil(seq_num, tid); 8242292SN/A} 8252292SN/A 8262292SN/Atemplate<class Impl> 8272292SN/Abool 8286221Snate@binkert.orgDefaultFetch<Impl>::checkStall(ThreadID tid) const 8292292SN/A{ 8302292SN/A bool ret_val = false; 8312292SN/A 83210407Smitch.hayenga@arm.com if (stalls[tid].drain) { 8339444SAndreas.Sandberg@ARM.com assert(cpu->isDraining()); 83413831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch,"[tid:%i] Drain stall detected.\n",tid); 8359444SAndreas.Sandberg@ARM.com ret_val = true; 8362292SN/A } 8372292SN/A 8382292SN/A return ret_val; 8392292SN/A} 8402292SN/A 8412292SN/Atemplate<class Impl> 8422292SN/Atypename DefaultFetch<Impl>::FetchStatus 8432292SN/ADefaultFetch<Impl>::updateFetchStatus() 8442292SN/A{ 8452292SN/A //Check Running 8466221Snate@binkert.org list<ThreadID>::iterator threads = activeThreads->begin(); 8476221Snate@binkert.org list<ThreadID>::iterator end = activeThreads->end(); 8482292SN/A 8493867Sbinkertn@umich.edu while (threads != end) { 8506221Snate@binkert.org ThreadID tid = *threads++; 8512292SN/A 8522292SN/A if (fetchStatus[tid] == Running || 8532292SN/A fetchStatus[tid] == Squashing || 8542669Sktlim@umich.edu fetchStatus[tid] == IcacheAccessComplete) { 8552292SN/A 8562292SN/A if (_status == Inactive) { 85713831SAndrea.Mondelli@ucf.edu DPRINTF(Activity, "[tid:%i] Activating stage.\n",tid); 8582292SN/A 8592669Sktlim@umich.edu if (fetchStatus[tid] == IcacheAccessComplete) { 86013831SAndrea.Mondelli@ucf.edu DPRINTF(Activity, "[tid:%i] Activating fetch due to cache" 8612292SN/A "completion\n",tid); 8622292SN/A } 8632292SN/A 8642733Sktlim@umich.edu cpu->activateStage(O3CPU::FetchIdx); 8652292SN/A } 8662292SN/A 8672292SN/A return Active; 8682292SN/A } 8692292SN/A } 8702292SN/A 8712292SN/A // Stage is switching from active to inactive, notify CPU of it. 8722292SN/A if (_status == Active) { 8732292SN/A DPRINTF(Activity, "Deactivating stage.\n"); 8742292SN/A 8752733Sktlim@umich.edu cpu->deactivateStage(O3CPU::FetchIdx); 8762292SN/A } 8772292SN/A 8782292SN/A return Inactive; 8791062SN/A} 8801062SN/A 8811062SN/Atemplate <class Impl> 8821062SN/Avoid 8837720Sgblack@eecs.umich.eduDefaultFetch<Impl>::squash(const TheISA::PCState &newPC, 8848503Sgblack@eecs.umich.edu const InstSeqNum seq_num, DynInstPtr squashInst, 8858138SAli.Saidi@ARM.com ThreadID tid) 8861062SN/A{ 88713831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Squash from commit.\n", tid); 8881062SN/A 8898503Sgblack@eecs.umich.edu doSquash(newPC, squashInst, tid); 8901062SN/A 8912935Sksewell@umich.edu // Tell the CPU to remove any instructions that are not in the ROB. 8924632Sgblack@eecs.umich.edu cpu->removeInstsNotInROB(tid); 8932292SN/A} 8942292SN/A 8952292SN/Atemplate <class Impl> 8962292SN/Avoid 8972292SN/ADefaultFetch<Impl>::tick() 8982292SN/A{ 8996221Snate@binkert.org list<ThreadID>::iterator threads = activeThreads->begin(); 9006221Snate@binkert.org list<ThreadID>::iterator end = activeThreads->end(); 9012292SN/A bool status_change = false; 9022292SN/A 9032292SN/A wroteToTimeBuffer = false; 9042292SN/A 90510363Smitch.hayenga@arm.com for (ThreadID i = 0; i < numThreads; ++i) { 9068462Sgeoffrey.blake@arm.com issuePipelinedIfetch[i] = false; 9078462Sgeoffrey.blake@arm.com } 9088462Sgeoffrey.blake@arm.com 9093867Sbinkertn@umich.edu while (threads != end) { 9106221Snate@binkert.org ThreadID tid = *threads++; 9112292SN/A 9122292SN/A // Check the signals for each thread to determine the proper status 9132292SN/A // for each thread. 9142292SN/A bool updated_status = checkSignalsAndUpdate(tid); 9152292SN/A status_change = status_change || updated_status; 9162292SN/A } 9172292SN/A 9182292SN/A DPRINTF(Fetch, "Running stage.\n"); 9192292SN/A 9208793Sgblack@eecs.umich.edu if (FullSystem) { 9218793Sgblack@eecs.umich.edu if (fromCommit->commitInfo[0].interruptPending) { 9228793Sgblack@eecs.umich.edu interruptPending = true; 9238793Sgblack@eecs.umich.edu } 9248793Sgblack@eecs.umich.edu 9258793Sgblack@eecs.umich.edu if (fromCommit->commitInfo[0].clearInterrupt) { 9268793Sgblack@eecs.umich.edu interruptPending = false; 9278793Sgblack@eecs.umich.edu } 9282292SN/A } 9292831Sksewell@umich.edu 9302292SN/A for (threadFetched = 0; threadFetched < numFetchingThreads; 9312292SN/A threadFetched++) { 9322292SN/A // Fetch each of the actively fetching threads. 9332292SN/A fetch(status_change); 9342292SN/A } 9352292SN/A 9362292SN/A // Record number of instructions fetched this cycle for distribution. 9372292SN/A fetchNisnDist.sample(numInst); 9382292SN/A 9392292SN/A if (status_change) { 9402292SN/A // Change the fetch stage status if there was a status change. 9412292SN/A _status = updateFetchStatus(); 9422292SN/A } 9432292SN/A 9448462Sgeoffrey.blake@arm.com // Issue the next I-cache request if possible. 94510363Smitch.hayenga@arm.com for (ThreadID i = 0; i < numThreads; ++i) { 9468462Sgeoffrey.blake@arm.com if (issuePipelinedIfetch[i]) { 9478462Sgeoffrey.blake@arm.com pipelineIcacheAccesses(i); 9488462Sgeoffrey.blake@arm.com } 9498462Sgeoffrey.blake@arm.com } 9508462Sgeoffrey.blake@arm.com 95110329Smitch.hayenga@arm.com // Send instructions enqueued into the fetch queue to decode. 95210329Smitch.hayenga@arm.com // Limit rate by fetchWidth. Stall if decode is stalled. 95310331Smitch.hayenga@arm.com unsigned insts_to_decode = 0; 95410331Smitch.hayenga@arm.com unsigned available_insts = 0; 95510331Smitch.hayenga@arm.com 95610331Smitch.hayenga@arm.com for (auto tid : *activeThreads) { 95710331Smitch.hayenga@arm.com if (!stalls[tid].decode) { 95810331Smitch.hayenga@arm.com available_insts += fetchQueue[tid].size(); 95910331Smitch.hayenga@arm.com } 96010331Smitch.hayenga@arm.com } 96110331Smitch.hayenga@arm.com 96210331Smitch.hayenga@arm.com // Pick a random thread to start trying to grab instructions from 96310331Smitch.hayenga@arm.com auto tid_itr = activeThreads->begin(); 96410331Smitch.hayenga@arm.com std::advance(tid_itr, random_mt.random<uint8_t>(0, activeThreads->size() - 1)); 96510331Smitch.hayenga@arm.com 96610331Smitch.hayenga@arm.com while (available_insts != 0 && insts_to_decode < decodeWidth) { 96710331Smitch.hayenga@arm.com ThreadID tid = *tid_itr; 96810331Smitch.hayenga@arm.com if (!stalls[tid].decode && !fetchQueue[tid].empty()) { 96913429Srekai.gonzalezalberquilla@arm.com const auto& inst = fetchQueue[tid].front(); 97010331Smitch.hayenga@arm.com toDecode->insts[toDecode->size++] = inst; 97113831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] [sn:%llu] Sending instruction to decode " 97213831SAndrea.Mondelli@ucf.edu "from fetch queue. Fetch queue size: %i.\n", 97310331Smitch.hayenga@arm.com tid, inst->seqNum, fetchQueue[tid].size()); 97410331Smitch.hayenga@arm.com 97510331Smitch.hayenga@arm.com wroteToTimeBuffer = true; 97610331Smitch.hayenga@arm.com fetchQueue[tid].pop_front(); 97710331Smitch.hayenga@arm.com insts_to_decode++; 97810331Smitch.hayenga@arm.com available_insts--; 97910331Smitch.hayenga@arm.com } 98010331Smitch.hayenga@arm.com 98110331Smitch.hayenga@arm.com tid_itr++; 98210331Smitch.hayenga@arm.com // Wrap around if at end of active threads list 98310331Smitch.hayenga@arm.com if (tid_itr == activeThreads->end()) 98410331Smitch.hayenga@arm.com tid_itr = activeThreads->begin(); 98510331Smitch.hayenga@arm.com } 98610331Smitch.hayenga@arm.com 98710331Smitch.hayenga@arm.com // If there was activity this cycle, inform the CPU of it. 98810407Smitch.hayenga@arm.com if (wroteToTimeBuffer) { 98910331Smitch.hayenga@arm.com DPRINTF(Activity, "Activity this cycle.\n"); 99010331Smitch.hayenga@arm.com cpu->activityThisCycle(); 99110329Smitch.hayenga@arm.com } 99210329Smitch.hayenga@arm.com 9938462Sgeoffrey.blake@arm.com // Reset the number of the instruction we've fetched. 9948462Sgeoffrey.blake@arm.com numInst = 0; 9952292SN/A} 9962292SN/A 9972292SN/Atemplate <class Impl> 9982292SN/Abool 9996221Snate@binkert.orgDefaultFetch<Impl>::checkSignalsAndUpdate(ThreadID tid) 10002292SN/A{ 10012292SN/A // Update the per thread stall statuses. 10022292SN/A if (fromDecode->decodeBlock[tid]) { 10032292SN/A stalls[tid].decode = true; 10042292SN/A } 10052292SN/A 10062292SN/A if (fromDecode->decodeUnblock[tid]) { 10072292SN/A assert(stalls[tid].decode); 10082292SN/A assert(!fromDecode->decodeBlock[tid]); 10092292SN/A stalls[tid].decode = false; 10102292SN/A } 10112292SN/A 10122292SN/A // Check squash signals from commit. 10132292SN/A if (fromCommit->commitInfo[tid].squash) { 10142292SN/A 101513831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Squashing instructions due to squash " 10162292SN/A "from commit.\n",tid); 10172292SN/A // In any case, squash. 10187720Sgblack@eecs.umich.edu squash(fromCommit->commitInfo[tid].pc, 10194632Sgblack@eecs.umich.edu fromCommit->commitInfo[tid].doneSeqNum, 10208137SAli.Saidi@ARM.com fromCommit->commitInfo[tid].squashInst, tid); 10212292SN/A 10227851SMatt.Horsnell@arm.com // If it was a branch mispredict on a control instruction, update the 10237851SMatt.Horsnell@arm.com // branch predictor with that instruction, otherwise just kill the 10247851SMatt.Horsnell@arm.com // invalid state we generated in after sequence number 10258137SAli.Saidi@ARM.com if (fromCommit->commitInfo[tid].mispredictInst && 10267851SMatt.Horsnell@arm.com fromCommit->commitInfo[tid].mispredictInst->isControl()) { 10279480Snilay@cs.wisc.edu branchPred->squash(fromCommit->commitInfo[tid].doneSeqNum, 10287720Sgblack@eecs.umich.edu fromCommit->commitInfo[tid].pc, 10292292SN/A fromCommit->commitInfo[tid].branchTaken, 10302292SN/A tid); 10312292SN/A } else { 10329480Snilay@cs.wisc.edu branchPred->squash(fromCommit->commitInfo[tid].doneSeqNum, 10332292SN/A tid); 10342292SN/A } 10352292SN/A 10362292SN/A return true; 10372292SN/A } else if (fromCommit->commitInfo[tid].doneSeqNum) { 10382292SN/A // Update the branch predictor if it wasn't a squashed instruction 10392292SN/A // that was broadcasted. 10409480Snilay@cs.wisc.edu branchPred->update(fromCommit->commitInfo[tid].doneSeqNum, tid); 10412292SN/A } 10422292SN/A 10432292SN/A // Check squash signals from decode. 10442292SN/A if (fromDecode->decodeInfo[tid].squash) { 104513831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Squashing instructions due to squash " 10462292SN/A "from decode.\n",tid); 10472292SN/A 10482292SN/A // Update the branch predictor. 10492292SN/A if (fromDecode->decodeInfo[tid].branchMispredict) { 10509480Snilay@cs.wisc.edu branchPred->squash(fromDecode->decodeInfo[tid].doneSeqNum, 10512292SN/A fromDecode->decodeInfo[tid].nextPC, 10522292SN/A fromDecode->decodeInfo[tid].branchTaken, 10532292SN/A tid); 10542292SN/A } else { 10559480Snilay@cs.wisc.edu branchPred->squash(fromDecode->decodeInfo[tid].doneSeqNum, 10562292SN/A tid); 10572292SN/A } 10582292SN/A 10592292SN/A if (fetchStatus[tid] != Squashing) { 10602935Sksewell@umich.edu 10618641Snate@binkert.org DPRINTF(Fetch, "Squashing from decode with PC = %s\n", 10628641Snate@binkert.org fromDecode->decodeInfo[tid].nextPC); 10632292SN/A // Squash unless we're already squashing 10642292SN/A squashFromDecode(fromDecode->decodeInfo[tid].nextPC, 10658503Sgblack@eecs.umich.edu fromDecode->decodeInfo[tid].squashInst, 10664632Sgblack@eecs.umich.edu fromDecode->decodeInfo[tid].doneSeqNum, 10672292SN/A tid); 10682292SN/A 10692292SN/A return true; 10702292SN/A } 10712292SN/A } 10722292SN/A 10733636Sktlim@umich.edu if (checkStall(tid) && 10743636Sktlim@umich.edu fetchStatus[tid] != IcacheWaitResponse && 10759574Ssaidi@eecs.umich.edu fetchStatus[tid] != IcacheWaitRetry && 10769644SAli.Saidi@ARM.com fetchStatus[tid] != ItlbWait && 10779644SAli.Saidi@ARM.com fetchStatus[tid] != QuiescePending) { 107813831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Setting to blocked\n",tid); 10792292SN/A 10802292SN/A fetchStatus[tid] = Blocked; 10812292SN/A 10822292SN/A return true; 10832292SN/A } 10842292SN/A 10852292SN/A if (fetchStatus[tid] == Blocked || 10862292SN/A fetchStatus[tid] == Squashing) { 10872292SN/A // Switch status to running if fetch isn't being told to block or 10882292SN/A // squash this cycle. 108913831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Done squashing, switching to running.\n", 10902292SN/A tid); 10912292SN/A 10922292SN/A fetchStatus[tid] = Running; 10932292SN/A 10942292SN/A return true; 10952292SN/A } 10962292SN/A 10972292SN/A // If we've reached this point, we have not gotten any signals that 10982292SN/A // cause fetch to change its status. Fetch remains the same as before. 10992292SN/A return false; 11001060SN/A} 11011060SN/A 11021060SN/Atemplate<class Impl> 11037764Sgblack@eecs.umich.edutypename Impl::DynInstPtr 11047764Sgblack@eecs.umich.eduDefaultFetch<Impl>::buildInst(ThreadID tid, StaticInstPtr staticInst, 11057764Sgblack@eecs.umich.edu StaticInstPtr curMacroop, TheISA::PCState thisPC, 11067764Sgblack@eecs.umich.edu TheISA::PCState nextPC, bool trace) 11077764Sgblack@eecs.umich.edu{ 11087764Sgblack@eecs.umich.edu // Get a sequence number. 11097764Sgblack@eecs.umich.edu InstSeqNum seq = cpu->getAndIncrementInstSeq(); 11107764Sgblack@eecs.umich.edu 11117764Sgblack@eecs.umich.edu // Create a new DynInst from the instruction fetched. 11127764Sgblack@eecs.umich.edu DynInstPtr instruction = 11138502Sgblack@eecs.umich.edu new DynInst(staticInst, curMacroop, thisPC, nextPC, seq, cpu); 11147764Sgblack@eecs.umich.edu instruction->setTid(tid); 11157764Sgblack@eecs.umich.edu 11167764Sgblack@eecs.umich.edu instruction->setASID(tid); 11177764Sgblack@eecs.umich.edu 11187764Sgblack@eecs.umich.edu instruction->setThreadState(cpu->thread[tid]); 11197764Sgblack@eecs.umich.edu 112013831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Instruction PC %#x (%d) created " 11217857SMatt.Horsnell@arm.com "[sn:%lli].\n", tid, thisPC.instAddr(), 11227764Sgblack@eecs.umich.edu thisPC.microPC(), seq); 11237764Sgblack@eecs.umich.edu 112413831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Instruction is: %s\n", tid, 11257764Sgblack@eecs.umich.edu instruction->staticInst-> 11267764Sgblack@eecs.umich.edu disassemble(thisPC.instAddr())); 11277764Sgblack@eecs.umich.edu 11287764Sgblack@eecs.umich.edu#if TRACING_ON 11297764Sgblack@eecs.umich.edu if (trace) { 11307764Sgblack@eecs.umich.edu instruction->traceData = 11317823Ssteve.reinhardt@amd.com cpu->getTracer()->getInstRecord(curTick(), cpu->tcBase(tid), 11327764Sgblack@eecs.umich.edu instruction->staticInst, thisPC, curMacroop); 11337764Sgblack@eecs.umich.edu } 11347764Sgblack@eecs.umich.edu#else 11357764Sgblack@eecs.umich.edu instruction->traceData = NULL; 11367764Sgblack@eecs.umich.edu#endif 11377764Sgblack@eecs.umich.edu 11387764Sgblack@eecs.umich.edu // Add instruction to the CPU's list of instructions. 11397764Sgblack@eecs.umich.edu instruction->setInstListIt(cpu->addInst(instruction)); 11407764Sgblack@eecs.umich.edu 11417764Sgblack@eecs.umich.edu // Write the instruction to the first slot in the queue 11427764Sgblack@eecs.umich.edu // that heads to decode. 11437764Sgblack@eecs.umich.edu assert(numInst < fetchWidth); 114410331Smitch.hayenga@arm.com fetchQueue[tid].push_back(instruction); 114510331Smitch.hayenga@arm.com assert(fetchQueue[tid].size() <= fetchQueueSize); 114613831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Fetch queue entry created (%i/%i).\n", 114710331Smitch.hayenga@arm.com tid, fetchQueue[tid].size(), fetchQueueSize); 114810329Smitch.hayenga@arm.com //toDecode->insts[toDecode->size++] = instruction; 11497764Sgblack@eecs.umich.edu 11508314Sgeoffrey.blake@arm.com // Keep track of if we can take an interrupt at this boundary 11518314Sgeoffrey.blake@arm.com delayedCommit[tid] = instruction->isDelayedCommit(); 11528314Sgeoffrey.blake@arm.com 11537764Sgblack@eecs.umich.edu return instruction; 11547764Sgblack@eecs.umich.edu} 11557764Sgblack@eecs.umich.edu 11567764Sgblack@eecs.umich.edutemplate<class Impl> 11571060SN/Avoid 11582292SN/ADefaultFetch<Impl>::fetch(bool &status_change) 11591060SN/A{ 11601060SN/A ////////////////////////////////////////// 11611060SN/A // Start actual fetch 11621060SN/A ////////////////////////////////////////// 116313559Snikos.nikoleris@arm.com ThreadID tid = getFetchingThread(); 11642292SN/A 11659444SAndreas.Sandberg@ARM.com assert(!cpu->switchedOut()); 11669444SAndreas.Sandberg@ARM.com 11679444SAndreas.Sandberg@ARM.com if (tid == InvalidThreadID) { 11682292SN/A // Breaks looping condition in tick() 11692292SN/A threadFetched = numFetchingThreads; 11708462Sgeoffrey.blake@arm.com 11718462Sgeoffrey.blake@arm.com if (numThreads == 1) { // @todo Per-thread stats 11728462Sgeoffrey.blake@arm.com profileStall(0); 11738462Sgeoffrey.blake@arm.com } 11748462Sgeoffrey.blake@arm.com 11752292SN/A return; 11762292SN/A } 11771060SN/A 11782831Sksewell@umich.edu DPRINTF(Fetch, "Attempting to fetch from [tid:%i]\n", tid); 11792831Sksewell@umich.edu 11801060SN/A // The current PC. 11817764Sgblack@eecs.umich.edu TheISA::PCState thisPC = pc[tid]; 11823795Sgblack@eecs.umich.edu 11837764Sgblack@eecs.umich.edu Addr pcOffset = fetchOffset[tid]; 11847764Sgblack@eecs.umich.edu Addr fetchAddr = (thisPC.instAddr() + pcOffset) & BaseCPU::PCMask; 11857764Sgblack@eecs.umich.edu 11867963Sgblack@eecs.umich.edu bool inRom = isRomMicroPC(thisPC.microPC()); 11877963Sgblack@eecs.umich.edu 11881060SN/A // If returning from the delay of a cache miss, then update the status 11891061SN/A // to running, otherwise do the cache access. Possibly move this up 11901061SN/A // to tick() function. 11912669Sktlim@umich.edu if (fetchStatus[tid] == IcacheAccessComplete) { 119213831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Icache miss is complete.\n", tid); 11931060SN/A 11942292SN/A fetchStatus[tid] = Running; 11952292SN/A status_change = true; 11962292SN/A } else if (fetchStatus[tid] == Running) { 11979982Satgutier@umich.edu // Align the fetch PC so its at the start of a fetch buffer segment. 11989982Satgutier@umich.edu Addr fetchBufferBlockPC = fetchBufferAlignPC(fetchAddr); 11991060SN/A 12008314Sgeoffrey.blake@arm.com // If buffer is no longer valid or fetchAddr has moved to point 12018314Sgeoffrey.blake@arm.com // to the next cache block, AND we have no remaining ucode 12028314Sgeoffrey.blake@arm.com // from a macro-op, then start fetch from icache. 12039982Satgutier@umich.edu if (!(fetchBufferValid[tid] && fetchBufferBlockPC == fetchBufferPC[tid]) 12048314Sgeoffrey.blake@arm.com && !inRom && !macroop[tid]) { 120513831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Attempting to translate and read " 12067849SAli.Saidi@ARM.com "instruction, starting at PC %s.\n", tid, thisPC); 12077849SAli.Saidi@ARM.com 12087849SAli.Saidi@ARM.com fetchCacheLine(fetchAddr, tid, thisPC.instAddr()); 12097849SAli.Saidi@ARM.com 12107849SAli.Saidi@ARM.com if (fetchStatus[tid] == IcacheWaitResponse) 12112727Sktlim@umich.edu ++icacheStallCycles; 12127849SAli.Saidi@ARM.com else if (fetchStatus[tid] == ItlbWait) 12137849SAli.Saidi@ARM.com ++fetchTlbCycles; 12147849SAli.Saidi@ARM.com else 12152727Sktlim@umich.edu ++fetchMiscStallCycles; 12167849SAli.Saidi@ARM.com return; 12179444SAndreas.Sandberg@ARM.com } else if ((checkInterrupt(thisPC.instAddr()) && !delayedCommit[tid])) { 12188314Sgeoffrey.blake@arm.com // Stall CPU if an interrupt is posted and we're not issuing 12198314Sgeoffrey.blake@arm.com // an delayed commit micro-op currently (delayed commit instructions 12208314Sgeoffrey.blake@arm.com // are not interruptable by interrupts, only faults) 12217849SAli.Saidi@ARM.com ++fetchMiscStallCycles; 122213831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Fetch is stalled!\n", tid); 12232292SN/A return; 12242307SN/A } 12251060SN/A } else { 12262301SN/A if (fetchStatus[tid] == Idle) { 12272301SN/A ++fetchIdleCycles; 122813831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Fetch is idle!\n", tid); 12292292SN/A } 12301060SN/A 12318462Sgeoffrey.blake@arm.com // Status is Idle, so fetch should do nothing. 12321062SN/A return; 12331060SN/A } 12341060SN/A 12352292SN/A ++fetchCycles; 12362292SN/A 12377764Sgblack@eecs.umich.edu TheISA::PCState nextPC = thisPC; 12381060SN/A 12394636Sgblack@eecs.umich.edu StaticInstPtr staticInst = NULL; 12407764Sgblack@eecs.umich.edu StaticInstPtr curMacroop = macroop[tid]; 12414636Sgblack@eecs.umich.edu 12427849SAli.Saidi@ARM.com // If the read of the first instruction was successful, then grab the 12437849SAli.Saidi@ARM.com // instructions from the rest of the cache line and put them into the 12447849SAli.Saidi@ARM.com // queue heading to decode. 12457720Sgblack@eecs.umich.edu 124613831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Adding instructions to queue to " 12477849SAli.Saidi@ARM.com "decode.\n", tid); 12481062SN/A 12497849SAli.Saidi@ARM.com // Need to keep track of whether or not a predicted branch 12507849SAli.Saidi@ARM.com // ended this fetch block. 12517849SAli.Saidi@ARM.com bool predictedBranch = false; 12521061SN/A 125310332Smitch.hayenga@arm.com // Need to halt fetch if quiesce instruction detected 125410332Smitch.hayenga@arm.com bool quiesce = false; 125510332Smitch.hayenga@arm.com 12567849SAli.Saidi@ARM.com TheISA::MachInst *cacheInsts = 12579982Satgutier@umich.edu reinterpret_cast<TheISA::MachInst *>(fetchBuffer[tid]); 12581060SN/A 12599982Satgutier@umich.edu const unsigned numInsts = fetchBufferSize / instSize; 12609982Satgutier@umich.edu unsigned blkOffset = (fetchAddr - fetchBufferPC[tid]) / instSize; 12617764Sgblack@eecs.umich.edu 12627849SAli.Saidi@ARM.com // Loop through instruction memory from the cache. 12638479Sgblack@eecs.umich.edu // Keep issuing while fetchWidth is available and branch is not 12648314Sgeoffrey.blake@arm.com // predicted taken 126510331Smitch.hayenga@arm.com while (numInst < fetchWidth && fetchQueue[tid].size() < fetchQueueSize 126610332Smitch.hayenga@arm.com && !predictedBranch && !quiesce) { 12678479Sgblack@eecs.umich.edu // We need to process more memory if we aren't going to get a 12688479Sgblack@eecs.umich.edu // StaticInst from the rom, the current macroop, or what's already 12699023Sgblack@eecs.umich.edu // in the decoder. 12709023Sgblack@eecs.umich.edu bool needMem = !inRom && !curMacroop && 12719023Sgblack@eecs.umich.edu !decoder[tid]->instReady(); 12728822Snilay@cs.wisc.edu fetchAddr = (thisPC.instAddr() + pcOffset) & BaseCPU::PCMask; 12739982Satgutier@umich.edu Addr fetchBufferBlockPC = fetchBufferAlignPC(fetchAddr); 12748479Sgblack@eecs.umich.edu 12758479Sgblack@eecs.umich.edu if (needMem) { 12768822Snilay@cs.wisc.edu // If buffer is no longer valid or fetchAddr has moved to point 12778822Snilay@cs.wisc.edu // to the next cache block then start fetch from icache. 12789982Satgutier@umich.edu if (!fetchBufferValid[tid] || 12799982Satgutier@umich.edu fetchBufferBlockPC != fetchBufferPC[tid]) 12808822Snilay@cs.wisc.edu break; 12818822Snilay@cs.wisc.edu 12828479Sgblack@eecs.umich.edu if (blkOffset >= numInsts) { 12838479Sgblack@eecs.umich.edu // We need to process more memory, but we've run out of the 12848479Sgblack@eecs.umich.edu // current block. 12858479Sgblack@eecs.umich.edu break; 12868479Sgblack@eecs.umich.edu } 12878479Sgblack@eecs.umich.edu 12887849SAli.Saidi@ARM.com MachInst inst = TheISA::gtoh(cacheInsts[blkOffset]); 12899023Sgblack@eecs.umich.edu decoder[tid]->moreBytes(thisPC, fetchAddr, inst); 12907849SAli.Saidi@ARM.com 12919023Sgblack@eecs.umich.edu if (decoder[tid]->needMoreBytes()) { 12927849SAli.Saidi@ARM.com blkOffset++; 12937849SAli.Saidi@ARM.com fetchAddr += instSize; 12947849SAli.Saidi@ARM.com pcOffset += instSize; 12957849SAli.Saidi@ARM.com } 12967849SAli.Saidi@ARM.com } 12977849SAli.Saidi@ARM.com 12987849SAli.Saidi@ARM.com // Extract as many instructions and/or microops as we can from 12997849SAli.Saidi@ARM.com // the memory we've processed so far. 13007849SAli.Saidi@ARM.com do { 13017963Sgblack@eecs.umich.edu if (!(curMacroop || inRom)) { 13029023Sgblack@eecs.umich.edu if (decoder[tid]->instReady()) { 13039023Sgblack@eecs.umich.edu staticInst = decoder[tid]->decode(thisPC); 13047849SAli.Saidi@ARM.com 13057849SAli.Saidi@ARM.com // Increment stat of fetched instructions. 13067849SAli.Saidi@ARM.com ++fetchedInsts; 13077849SAli.Saidi@ARM.com 13087875Sgblack@eecs.umich.edu if (staticInst->isMacroop()) { 13097849SAli.Saidi@ARM.com curMacroop = staticInst; 13107875Sgblack@eecs.umich.edu } else { 13117857SMatt.Horsnell@arm.com pcOffset = 0; 13127857SMatt.Horsnell@arm.com } 13137849SAli.Saidi@ARM.com } else { 13148314Sgeoffrey.blake@arm.com // We need more bytes for this instruction so blkOffset and 13158314Sgeoffrey.blake@arm.com // pcOffset will be updated 13167849SAli.Saidi@ARM.com break; 13177764Sgblack@eecs.umich.edu } 13184636Sgblack@eecs.umich.edu } 13198495Sgblack@eecs.umich.edu // Whether we're moving to a new macroop because we're at the 13208495Sgblack@eecs.umich.edu // end of the current one, or the branch predictor incorrectly 13218495Sgblack@eecs.umich.edu // thinks we are... 13228495Sgblack@eecs.umich.edu bool newMacro = false; 13237963Sgblack@eecs.umich.edu if (curMacroop || inRom) { 13247963Sgblack@eecs.umich.edu if (inRom) { 13257963Sgblack@eecs.umich.edu staticInst = cpu->microcodeRom.fetchMicroop( 13267963Sgblack@eecs.umich.edu thisPC.microPC(), curMacroop); 13277963Sgblack@eecs.umich.edu } else { 13287963Sgblack@eecs.umich.edu staticInst = curMacroop->fetchMicroop(thisPC.microPC()); 13297963Sgblack@eecs.umich.edu } 13308495Sgblack@eecs.umich.edu newMacro |= staticInst->isLastMicroop(); 13317849SAli.Saidi@ARM.com } 13327764Sgblack@eecs.umich.edu 13337849SAli.Saidi@ARM.com DynInstPtr instruction = 13347849SAli.Saidi@ARM.com buildInst(tid, staticInst, curMacroop, 13357849SAli.Saidi@ARM.com thisPC, nextPC, true); 13367764Sgblack@eecs.umich.edu 133710023Smatt.horsnell@ARM.com ppFetch->notify(instruction); 13387849SAli.Saidi@ARM.com numInst++; 13397764Sgblack@eecs.umich.edu 13408471SGiacomo.Gabrielli@arm.com#if TRACING_ON 13419527SMatt.Horsnell@arm.com if (DTRACE(O3PipeView)) { 13429527SMatt.Horsnell@arm.com instruction->fetchTick = curTick(); 13439527SMatt.Horsnell@arm.com } 13448471SGiacomo.Gabrielli@arm.com#endif 13458471SGiacomo.Gabrielli@arm.com 13467849SAli.Saidi@ARM.com nextPC = thisPC; 13477764Sgblack@eecs.umich.edu 134810244Satgutier@umich.edu // If we're branching after this instruction, quit fetching 134910244Satgutier@umich.edu // from the same block. 13507849SAli.Saidi@ARM.com predictedBranch |= thisPC.branching(); 13517849SAli.Saidi@ARM.com predictedBranch |= 13527849SAli.Saidi@ARM.com lookupAndUpdateNextPC(instruction, nextPC); 13537849SAli.Saidi@ARM.com if (predictedBranch) { 13547849SAli.Saidi@ARM.com DPRINTF(Fetch, "Branch detected with PC = %s\n", thisPC); 13557849SAli.Saidi@ARM.com } 13561062SN/A 13578495Sgblack@eecs.umich.edu newMacro |= thisPC.instAddr() != nextPC.instAddr(); 13588495Sgblack@eecs.umich.edu 13597849SAli.Saidi@ARM.com // Move to the next instruction, unless we have a branch. 13607849SAli.Saidi@ARM.com thisPC = nextPC; 13618821Snilay@cs.wisc.edu inRom = isRomMicroPC(thisPC.microPC()); 13621062SN/A 13638495Sgblack@eecs.umich.edu if (newMacro) { 13648499Sgblack@eecs.umich.edu fetchAddr = thisPC.instAddr() & BaseCPU::PCMask; 13659982Satgutier@umich.edu blkOffset = (fetchAddr - fetchBufferPC[tid]) / instSize; 13668495Sgblack@eecs.umich.edu pcOffset = 0; 13678495Sgblack@eecs.umich.edu curMacroop = NULL; 13688495Sgblack@eecs.umich.edu } 13698495Sgblack@eecs.umich.edu 13707849SAli.Saidi@ARM.com if (instruction->isQuiesce()) { 13717849SAli.Saidi@ARM.com DPRINTF(Fetch, 137210332Smitch.hayenga@arm.com "Quiesce instruction encountered, halting fetch!\n"); 13737849SAli.Saidi@ARM.com fetchStatus[tid] = QuiescePending; 13747849SAli.Saidi@ARM.com status_change = true; 137510332Smitch.hayenga@arm.com quiesce = true; 13767849SAli.Saidi@ARM.com break; 13777849SAli.Saidi@ARM.com } 13789023Sgblack@eecs.umich.edu } while ((curMacroop || decoder[tid]->instReady()) && 137910331Smitch.hayenga@arm.com numInst < fetchWidth && 138010331Smitch.hayenga@arm.com fetchQueue[tid].size() < fetchQueueSize); 138110960Sdavid.hashe@amd.com 138210960Sdavid.hashe@amd.com // Re-evaluate whether the next instruction to fetch is in micro-op ROM 138310960Sdavid.hashe@amd.com // or not. 138410960Sdavid.hashe@amd.com inRom = isRomMicroPC(thisPC.microPC()); 13857849SAli.Saidi@ARM.com } 13861062SN/A 13877849SAli.Saidi@ARM.com if (predictedBranch) { 138813831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Done fetching, predicted branch " 13897849SAli.Saidi@ARM.com "instruction encountered.\n", tid); 13907849SAli.Saidi@ARM.com } else if (numInst >= fetchWidth) { 139113831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Done fetching, reached fetch bandwidth " 13927849SAli.Saidi@ARM.com "for this cycle.\n", tid); 13939982Satgutier@umich.edu } else if (blkOffset >= fetchBufferSize) { 139413831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Done fetching, reached the end of the" 13959982Satgutier@umich.edu "fetch buffer.\n", tid); 13962292SN/A } 13971060SN/A 13987764Sgblack@eecs.umich.edu macroop[tid] = curMacroop; 13997764Sgblack@eecs.umich.edu fetchOffset[tid] = pcOffset; 14007764Sgblack@eecs.umich.edu 14012292SN/A if (numInst > 0) { 14022292SN/A wroteToTimeBuffer = true; 14031060SN/A } 14041060SN/A 14057849SAli.Saidi@ARM.com pc[tid] = thisPC; 14068462Sgeoffrey.blake@arm.com 14079982Satgutier@umich.edu // pipeline a fetch if we're crossing a fetch buffer boundary and not in 14088462Sgeoffrey.blake@arm.com // a state that would preclude fetching 14098462Sgeoffrey.blake@arm.com fetchAddr = (thisPC.instAddr() + pcOffset) & BaseCPU::PCMask; 14109982Satgutier@umich.edu Addr fetchBufferBlockPC = fetchBufferAlignPC(fetchAddr); 14119982Satgutier@umich.edu issuePipelinedIfetch[tid] = fetchBufferBlockPC != fetchBufferPC[tid] && 14128462Sgeoffrey.blake@arm.com fetchStatus[tid] != IcacheWaitResponse && 14138462Sgeoffrey.blake@arm.com fetchStatus[tid] != ItlbWait && 14148462Sgeoffrey.blake@arm.com fetchStatus[tid] != IcacheWaitRetry && 14158462Sgeoffrey.blake@arm.com fetchStatus[tid] != QuiescePending && 14168462Sgeoffrey.blake@arm.com !curMacroop; 14171060SN/A} 14182292SN/A 14192696Sktlim@umich.edutemplate<class Impl> 14202696Sktlim@umich.eduvoid 142110713Sandreas.hansson@arm.comDefaultFetch<Impl>::recvReqRetry() 14222696Sktlim@umich.edu{ 14232696Sktlim@umich.edu if (retryPkt != NULL) { 14243300Sktlim@umich.edu assert(cacheBlocked); 14256221Snate@binkert.org assert(retryTid != InvalidThreadID); 14262696Sktlim@umich.edu assert(fetchStatus[retryTid] == IcacheWaitRetry); 14272696Sktlim@umich.edu 142814195Sgabeblack@google.com if (icachePort.sendTimingReq(retryPkt)) { 14292696Sktlim@umich.edu fetchStatus[retryTid] = IcacheWaitResponse; 143011246Sradhika.jagtap@ARM.com // Notify Fetch Request probe when a retryPkt is successfully sent. 143111246Sradhika.jagtap@ARM.com // Note that notify must be called before retryPkt is set to NULL. 143211246Sradhika.jagtap@ARM.com ppFetchRequestSent->notify(retryPkt->req); 14332696Sktlim@umich.edu retryPkt = NULL; 14346221Snate@binkert.org retryTid = InvalidThreadID; 14352696Sktlim@umich.edu cacheBlocked = false; 14362696Sktlim@umich.edu } 14372696Sktlim@umich.edu } else { 14386221Snate@binkert.org assert(retryTid == InvalidThreadID); 14392696Sktlim@umich.edu // Access has been squashed since it was sent out. Just clear 14402696Sktlim@umich.edu // the cache being blocked. 14412696Sktlim@umich.edu cacheBlocked = false; 14422696Sktlim@umich.edu } 14432696Sktlim@umich.edu} 14442292SN/A 14452292SN/A/////////////////////////////////////// 14462292SN/A// // 14472292SN/A// SMT FETCH POLICY MAINTAINED HERE // 14482292SN/A// // 14492292SN/A/////////////////////////////////////// 14502292SN/Atemplate<class Impl> 14516221Snate@binkert.orgThreadID 145213559Snikos.nikoleris@arm.comDefaultFetch<Impl>::getFetchingThread() 14532292SN/A{ 14542292SN/A if (numThreads > 1) { 145513559Snikos.nikoleris@arm.com switch (fetchPolicy) { 145613559Snikos.nikoleris@arm.com case FetchPolicy::RoundRobin: 14572292SN/A return roundRobin(); 145813559Snikos.nikoleris@arm.com case FetchPolicy::IQCount: 14592292SN/A return iqCount(); 146013559Snikos.nikoleris@arm.com case FetchPolicy::LSQCount: 14612292SN/A return lsqCount(); 146213559Snikos.nikoleris@arm.com case FetchPolicy::Branch: 14632292SN/A return branchCount(); 14642292SN/A default: 14656221Snate@binkert.org return InvalidThreadID; 14662292SN/A } 14672292SN/A } else { 14686221Snate@binkert.org list<ThreadID>::iterator thread = activeThreads->begin(); 14696033Ssteve.reinhardt@amd.com if (thread == activeThreads->end()) { 14706221Snate@binkert.org return InvalidThreadID; 14716033Ssteve.reinhardt@amd.com } 14726033Ssteve.reinhardt@amd.com 14736221Snate@binkert.org ThreadID tid = *thread; 14742292SN/A 14752292SN/A if (fetchStatus[tid] == Running || 14762669Sktlim@umich.edu fetchStatus[tid] == IcacheAccessComplete || 14772292SN/A fetchStatus[tid] == Idle) { 14782292SN/A return tid; 14792292SN/A } else { 14806221Snate@binkert.org return InvalidThreadID; 14812292SN/A } 14822292SN/A } 14832292SN/A} 14842292SN/A 14852292SN/A 14862292SN/Atemplate<class Impl> 14876221Snate@binkert.orgThreadID 14882292SN/ADefaultFetch<Impl>::roundRobin() 14892292SN/A{ 14906221Snate@binkert.org list<ThreadID>::iterator pri_iter = priorityList.begin(); 14916221Snate@binkert.org list<ThreadID>::iterator end = priorityList.end(); 14922292SN/A 14936221Snate@binkert.org ThreadID high_pri; 14942292SN/A 14952292SN/A while (pri_iter != end) { 14962292SN/A high_pri = *pri_iter; 14972292SN/A 14982292SN/A assert(high_pri <= numThreads); 14992292SN/A 15002292SN/A if (fetchStatus[high_pri] == Running || 15012669Sktlim@umich.edu fetchStatus[high_pri] == IcacheAccessComplete || 15022292SN/A fetchStatus[high_pri] == Idle) { 15032292SN/A 15042292SN/A priorityList.erase(pri_iter); 15052292SN/A priorityList.push_back(high_pri); 15062292SN/A 15072292SN/A return high_pri; 15082292SN/A } 15092292SN/A 15102292SN/A pri_iter++; 15112292SN/A } 15122292SN/A 15136221Snate@binkert.org return InvalidThreadID; 15142292SN/A} 15152292SN/A 15162292SN/Atemplate<class Impl> 15176221Snate@binkert.orgThreadID 15182292SN/ADefaultFetch<Impl>::iqCount() 15192292SN/A{ 152010450Slukefahr@umich.edu //sorted from lowest->highest 152110450Slukefahr@umich.edu std::priority_queue<unsigned,vector<unsigned>, 152210450Slukefahr@umich.edu std::greater<unsigned> > PQ; 15238089Stimothy.jones@cl.cam.ac.uk std::map<unsigned, ThreadID> threadMap; 15242292SN/A 15256221Snate@binkert.org list<ThreadID>::iterator threads = activeThreads->begin(); 15266221Snate@binkert.org list<ThreadID>::iterator end = activeThreads->end(); 15272292SN/A 15283867Sbinkertn@umich.edu while (threads != end) { 15296221Snate@binkert.org ThreadID tid = *threads++; 15308089Stimothy.jones@cl.cam.ac.uk unsigned iqCount = fromIEW->iewInfo[tid].iqCount; 15312292SN/A 153210450Slukefahr@umich.edu //we can potentially get tid collisions if two threads 153310450Slukefahr@umich.edu //have the same iqCount, but this should be rare. 15348089Stimothy.jones@cl.cam.ac.uk PQ.push(iqCount); 15358089Stimothy.jones@cl.cam.ac.uk threadMap[iqCount] = tid; 15362292SN/A } 15372292SN/A 15382292SN/A while (!PQ.empty()) { 15398089Stimothy.jones@cl.cam.ac.uk ThreadID high_pri = threadMap[PQ.top()]; 15402292SN/A 15412292SN/A if (fetchStatus[high_pri] == Running || 15422669Sktlim@umich.edu fetchStatus[high_pri] == IcacheAccessComplete || 15432292SN/A fetchStatus[high_pri] == Idle) 15442292SN/A return high_pri; 15452292SN/A else 15462292SN/A PQ.pop(); 15472292SN/A 15482292SN/A } 15492292SN/A 15506221Snate@binkert.org return InvalidThreadID; 15512292SN/A} 15522292SN/A 15532292SN/Atemplate<class Impl> 15546221Snate@binkert.orgThreadID 15552292SN/ADefaultFetch<Impl>::lsqCount() 15562292SN/A{ 155710450Slukefahr@umich.edu //sorted from lowest->highest 155810450Slukefahr@umich.edu std::priority_queue<unsigned,vector<unsigned>, 155910450Slukefahr@umich.edu std::greater<unsigned> > PQ; 15608089Stimothy.jones@cl.cam.ac.uk std::map<unsigned, ThreadID> threadMap; 15612292SN/A 15626221Snate@binkert.org list<ThreadID>::iterator threads = activeThreads->begin(); 15636221Snate@binkert.org list<ThreadID>::iterator end = activeThreads->end(); 15642292SN/A 15653867Sbinkertn@umich.edu while (threads != end) { 15666221Snate@binkert.org ThreadID tid = *threads++; 15678089Stimothy.jones@cl.cam.ac.uk unsigned ldstqCount = fromIEW->iewInfo[tid].ldstqCount; 15682292SN/A 156910450Slukefahr@umich.edu //we can potentially get tid collisions if two threads 157010450Slukefahr@umich.edu //have the same iqCount, but this should be rare. 15718089Stimothy.jones@cl.cam.ac.uk PQ.push(ldstqCount); 15728089Stimothy.jones@cl.cam.ac.uk threadMap[ldstqCount] = tid; 15732292SN/A } 15742292SN/A 15752292SN/A while (!PQ.empty()) { 15768089Stimothy.jones@cl.cam.ac.uk ThreadID high_pri = threadMap[PQ.top()]; 15772292SN/A 15782292SN/A if (fetchStatus[high_pri] == Running || 15792669Sktlim@umich.edu fetchStatus[high_pri] == IcacheAccessComplete || 15802348SN/A fetchStatus[high_pri] == Idle) 15812292SN/A return high_pri; 15822292SN/A else 15832292SN/A PQ.pop(); 15842292SN/A } 15852292SN/A 15866221Snate@binkert.org return InvalidThreadID; 15872292SN/A} 15882292SN/A 15892292SN/Atemplate<class Impl> 15906221Snate@binkert.orgThreadID 15912292SN/ADefaultFetch<Impl>::branchCount() 15922292SN/A{ 15932831Sksewell@umich.edu panic("Branch Count Fetch policy unimplemented\n"); 15946221Snate@binkert.org return InvalidThreadID; 15952292SN/A} 15968462Sgeoffrey.blake@arm.com 15978462Sgeoffrey.blake@arm.comtemplate<class Impl> 15988462Sgeoffrey.blake@arm.comvoid 15998462Sgeoffrey.blake@arm.comDefaultFetch<Impl>::pipelineIcacheAccesses(ThreadID tid) 16008462Sgeoffrey.blake@arm.com{ 16018462Sgeoffrey.blake@arm.com if (!issuePipelinedIfetch[tid]) { 16028462Sgeoffrey.blake@arm.com return; 16038462Sgeoffrey.blake@arm.com } 16048462Sgeoffrey.blake@arm.com 16058462Sgeoffrey.blake@arm.com // The next PC to access. 16068462Sgeoffrey.blake@arm.com TheISA::PCState thisPC = pc[tid]; 16078462Sgeoffrey.blake@arm.com 16088462Sgeoffrey.blake@arm.com if (isRomMicroPC(thisPC.microPC())) { 16098462Sgeoffrey.blake@arm.com return; 16108462Sgeoffrey.blake@arm.com } 16118462Sgeoffrey.blake@arm.com 16128462Sgeoffrey.blake@arm.com Addr pcOffset = fetchOffset[tid]; 16138462Sgeoffrey.blake@arm.com Addr fetchAddr = (thisPC.instAddr() + pcOffset) & BaseCPU::PCMask; 16148462Sgeoffrey.blake@arm.com 16159982Satgutier@umich.edu // Align the fetch PC so its at the start of a fetch buffer segment. 16169982Satgutier@umich.edu Addr fetchBufferBlockPC = fetchBufferAlignPC(fetchAddr); 16178462Sgeoffrey.blake@arm.com 16188462Sgeoffrey.blake@arm.com // Unless buffer already got the block, fetch it from icache. 16199982Satgutier@umich.edu if (!(fetchBufferValid[tid] && fetchBufferBlockPC == fetchBufferPC[tid])) { 162013831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Issuing a pipelined I-cache access, " 16218462Sgeoffrey.blake@arm.com "starting at PC %s.\n", tid, thisPC); 16228462Sgeoffrey.blake@arm.com 16238462Sgeoffrey.blake@arm.com fetchCacheLine(fetchAddr, tid, thisPC.instAddr()); 16248462Sgeoffrey.blake@arm.com } 16258462Sgeoffrey.blake@arm.com} 16268462Sgeoffrey.blake@arm.com 16278462Sgeoffrey.blake@arm.comtemplate<class Impl> 16288462Sgeoffrey.blake@arm.comvoid 16298462Sgeoffrey.blake@arm.comDefaultFetch<Impl>::profileStall(ThreadID tid) { 16308462Sgeoffrey.blake@arm.com DPRINTF(Fetch,"There are no more threads available to fetch from.\n"); 16318462Sgeoffrey.blake@arm.com 16328462Sgeoffrey.blake@arm.com // @todo Per-thread stats 16338462Sgeoffrey.blake@arm.com 16349444SAndreas.Sandberg@ARM.com if (stalls[tid].drain) { 16358462Sgeoffrey.blake@arm.com ++fetchPendingDrainCycles; 16368462Sgeoffrey.blake@arm.com DPRINTF(Fetch, "Fetch is waiting for a drain!\n"); 16378462Sgeoffrey.blake@arm.com } else if (activeThreads->empty()) { 16388462Sgeoffrey.blake@arm.com ++fetchNoActiveThreadStallCycles; 16398462Sgeoffrey.blake@arm.com DPRINTF(Fetch, "Fetch has no active thread!\n"); 16408462Sgeoffrey.blake@arm.com } else if (fetchStatus[tid] == Blocked) { 16418462Sgeoffrey.blake@arm.com ++fetchBlockedCycles; 164213831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Fetch is blocked!\n", tid); 16438462Sgeoffrey.blake@arm.com } else if (fetchStatus[tid] == Squashing) { 16448462Sgeoffrey.blake@arm.com ++fetchSquashCycles; 164513831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Fetch is squashing!\n", tid); 16468462Sgeoffrey.blake@arm.com } else if (fetchStatus[tid] == IcacheWaitResponse) { 16478462Sgeoffrey.blake@arm.com ++icacheStallCycles; 164813831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Fetch is waiting cache response!\n", 16498462Sgeoffrey.blake@arm.com tid); 16508462Sgeoffrey.blake@arm.com } else if (fetchStatus[tid] == ItlbWait) { 16518462Sgeoffrey.blake@arm.com ++fetchTlbCycles; 165213831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Fetch is waiting ITLB walk to " 16538462Sgeoffrey.blake@arm.com "finish!\n", tid); 16548462Sgeoffrey.blake@arm.com } else if (fetchStatus[tid] == TrapPending) { 16558462Sgeoffrey.blake@arm.com ++fetchPendingTrapStallCycles; 165613831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Fetch is waiting for a pending trap!\n", 16578462Sgeoffrey.blake@arm.com tid); 16588462Sgeoffrey.blake@arm.com } else if (fetchStatus[tid] == QuiescePending) { 16598462Sgeoffrey.blake@arm.com ++fetchPendingQuiesceStallCycles; 166013831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Fetch is waiting for a pending quiesce " 16618462Sgeoffrey.blake@arm.com "instruction!\n", tid); 16628462Sgeoffrey.blake@arm.com } else if (fetchStatus[tid] == IcacheWaitRetry) { 16638462Sgeoffrey.blake@arm.com ++fetchIcacheWaitRetryStallCycles; 166413831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Fetch is waiting for an I-cache retry!\n", 16658462Sgeoffrey.blake@arm.com tid); 16668462Sgeoffrey.blake@arm.com } else if (fetchStatus[tid] == NoGoodAddr) { 166713831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Fetch predicted non-executable address\n", 16688462Sgeoffrey.blake@arm.com tid); 16698462Sgeoffrey.blake@arm.com } else { 167013831SAndrea.Mondelli@ucf.edu DPRINTF(Fetch, "[tid:%i] Unexpected fetch stall reason " 167113831SAndrea.Mondelli@ucf.edu "(Status: %i)\n", 167213831SAndrea.Mondelli@ucf.edu tid, fetchStatus[tid]); 16738462Sgeoffrey.blake@arm.com } 16748462Sgeoffrey.blake@arm.com} 16759944Smatt.horsnell@ARM.com 167614195Sgabeblack@google.comtemplate<class Impl> 167714195Sgabeblack@google.combool 167814195Sgabeblack@google.comDefaultFetch<Impl>::IcachePort::recvTimingResp(PacketPtr pkt) 167914195Sgabeblack@google.com{ 168014195Sgabeblack@google.com DPRINTF(O3CPU, "Fetch unit received timing\n"); 168114195Sgabeblack@google.com // We shouldn't ever get a cacheable block in Modified state 168214195Sgabeblack@google.com assert(pkt->req->isUncacheable() || 168314195Sgabeblack@google.com !(pkt->cacheResponding() && !pkt->hasSharers())); 168414195Sgabeblack@google.com fetch->processCacheCompletion(pkt); 168514195Sgabeblack@google.com 168614195Sgabeblack@google.com return true; 168714195Sgabeblack@google.com} 168814195Sgabeblack@google.com 168914195Sgabeblack@google.comtemplate<class Impl> 169014195Sgabeblack@google.comvoid 169114195Sgabeblack@google.comDefaultFetch<Impl>::IcachePort::recvReqRetry() 169214195Sgabeblack@google.com{ 169314195Sgabeblack@google.com fetch->recvReqRetry(); 169414195Sgabeblack@google.com} 169514195Sgabeblack@google.com 16969944Smatt.horsnell@ARM.com#endif//__CPU_O3_FETCH_IMPL_HH__ 1697