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