fetch_impl.hh revision 10020:2f33cb012383
17396Sgblack@eecs.umich.edu/* 210037SARM gem5 Developers * Copyright (c) 2010-2013 ARM Limited 37396Sgblack@eecs.umich.edu * All rights reserved. 47396Sgblack@eecs.umich.edu * 57396Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall 67396Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual 77396Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating 87396Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software 97396Sgblack@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 107396Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 117396Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 127396Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form. 137396Sgblack@eecs.umich.edu * 147396Sgblack@eecs.umich.edu * Copyright (c) 2004-2006 The Regents of The University of Michigan 157396Sgblack@eecs.umich.edu * All rights reserved. 167396Sgblack@eecs.umich.edu * 177396Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 187396Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 197396Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 207396Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 217396Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 227396Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 237396Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 247396Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 257396Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 267396Sgblack@eecs.umich.edu * this software without specific prior written permission. 277396Sgblack@eecs.umich.edu * 287396Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 297396Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 307396Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 317396Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 327396Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 337396Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 347396Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 357396Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 367396Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 377396Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 387396Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 397396Sgblack@eecs.umich.edu * 407396Sgblack@eecs.umich.edu * Authors: Kevin Lim 417396Sgblack@eecs.umich.edu * Korey Sewell 427434Sgblack@eecs.umich.edu */ 437434Sgblack@eecs.umich.edu 447434Sgblack@eecs.umich.edu#ifndef __CPU_O3_FETCH_IMPL_HH__ 457434Sgblack@eecs.umich.edu#define __CPU_O3_FETCH_IMPL_HH__ 467434Sgblack@eecs.umich.edu 477434Sgblack@eecs.umich.edu#include <algorithm> 487396Sgblack@eecs.umich.edu#include <cstring> 4910037SARM gem5 Developers#include <list> 5010037SARM gem5 Developers#include <map> 5110037SARM gem5 Developers#include <queue> 5210037SARM gem5 Developers 5310037SARM gem5 Developers#include "arch/isa_traits.hh" 5412104Snathanael.premillieu@arm.com#include "arch/tlb.hh" 5510037SARM gem5 Developers#include "arch/utility.hh" 5612104Snathanael.premillieu@arm.com#include "arch/vtophys.hh" 5710037SARM gem5 Developers#include "base/types.hh" 5810037SARM gem5 Developers#include "config/the_isa.hh" 5910037SARM gem5 Developers#include "cpu/base.hh" 6010037SARM gem5 Developers//#include "cpu/checker/cpu.hh" 6110037SARM gem5 Developers#include "cpu/o3/fetch.hh" 6210037SARM gem5 Developers#include "cpu/exetrace.hh" 6310037SARM gem5 Developers#include "debug/Activity.hh" 6410037SARM gem5 Developers#include "debug/Drain.hh" 6510037SARM gem5 Developers#include "debug/Fetch.hh" 6610037SARM gem5 Developers#include "debug/O3PipeView.hh" 6710037SARM gem5 Developers#include "mem/packet.hh" 6810037SARM gem5 Developers#include "params/DerivO3CPU.hh" 6912104Snathanael.premillieu@arm.com#include "sim/byteswap.hh" 7010037SARM gem5 Developers#include "sim/core.hh" 7112104Snathanael.premillieu@arm.com#include "sim/eventq.hh" 7210037SARM gem5 Developers#include "sim/full_system.hh" 7312104Snathanael.premillieu@arm.com#include "sim/system.hh" 7410037SARM gem5 Developers 7510037SARM gem5 Developersusing namespace std; 7610037SARM gem5 Developers 7710037SARM gem5 Developerstemplate<class Impl> 7810037SARM gem5 DevelopersDefaultFetch<Impl>::DefaultFetch(O3CPU *_cpu, DerivO3CPUParams *params) 7910037SARM gem5 Developers : cpu(_cpu), 807396Sgblack@eecs.umich.edu decodeToFetchDelay(params->decodeToFetchDelay), 817396Sgblack@eecs.umich.edu renameToFetchDelay(params->renameToFetchDelay), 827396Sgblack@eecs.umich.edu iewToFetchDelay(params->iewToFetchDelay), 837396Sgblack@eecs.umich.edu commitToFetchDelay(params->commitToFetchDelay), 8412104Snathanael.premillieu@arm.com fetchWidth(params->fetchWidth), 857396Sgblack@eecs.umich.edu retryPkt(NULL), 8612104Snathanael.premillieu@arm.com retryTid(InvalidThreadID), 877396Sgblack@eecs.umich.edu cacheBlkSize(cpu->cacheLineSize()), 887396Sgblack@eecs.umich.edu fetchBufferSize(params->fetchBufferSize), 897396Sgblack@eecs.umich.edu fetchBufferMask(fetchBufferSize - 1), 907396Sgblack@eecs.umich.edu numThreads(params->numThreads), 917396Sgblack@eecs.umich.edu numFetchingThreads(params->smtNumFetchingThreads), 927396Sgblack@eecs.umich.edu finishTranslationEvent(this) 937396Sgblack@eecs.umich.edu{ 947396Sgblack@eecs.umich.edu if (numThreads > Impl::MaxThreads) 9512104Snathanael.premillieu@arm.com fatal("numThreads (%d) is larger than compiled limit (%d),\n" 967396Sgblack@eecs.umich.edu "\tincrease MaxThreads in src/cpu/o3/impl.hh\n", 977396Sgblack@eecs.umich.edu numThreads, static_cast<int>(Impl::MaxThreads)); 987396Sgblack@eecs.umich.edu if (fetchWidth > Impl::MaxWidth) 997396Sgblack@eecs.umich.edu fatal("fetchWidth (%d) is larger than compiled limit (%d),\n" 1007396Sgblack@eecs.umich.edu "\tincrease MaxWidth in src/cpu/o3/impl.hh\n", 1017396Sgblack@eecs.umich.edu fetchWidth, static_cast<int>(Impl::MaxWidth)); 1027396Sgblack@eecs.umich.edu if (fetchBufferSize > cacheBlkSize) 1037396Sgblack@eecs.umich.edu fatal("fetch buffer size (%u bytes) is greater than the cache " 1047396Sgblack@eecs.umich.edu "block size (%u bytes)\n", fetchBufferSize, cacheBlkSize); 10512104Snathanael.premillieu@arm.com if (cacheBlkSize % fetchBufferSize) 1067396Sgblack@eecs.umich.edu fatal("cache block (%u bytes) is not a multiple of the " 10712104Snathanael.premillieu@arm.com "fetch buffer (%u bytes)\n", cacheBlkSize, fetchBufferSize); 1087396Sgblack@eecs.umich.edu 1097396Sgblack@eecs.umich.edu std::string policy = params->smtFetchPolicy; 1107396Sgblack@eecs.umich.edu 1117396Sgblack@eecs.umich.edu // Convert string to lowercase 1127396Sgblack@eecs.umich.edu std::transform(policy.begin(), policy.end(), policy.begin(), 1137396Sgblack@eecs.umich.edu (int(*)(int)) tolower); 1147396Sgblack@eecs.umich.edu 1157396Sgblack@eecs.umich.edu // Figure out fetch policy 1167396Sgblack@eecs.umich.edu if (policy == "singlethread") { 11712104Snathanael.premillieu@arm.com fetchPolicy = SingleThread; 1187396Sgblack@eecs.umich.edu if (numThreads > 1) 11912104Snathanael.premillieu@arm.com panic("Invalid Fetch Policy for a SMT workload."); 1207396Sgblack@eecs.umich.edu } else if (policy == "roundrobin") { 12112104Snathanael.premillieu@arm.com fetchPolicy = RoundRobin; 1227396Sgblack@eecs.umich.edu DPRINTF(Fetch, "Fetch policy set to Round Robin\n"); 1237396Sgblack@eecs.umich.edu } else if (policy == "branch") { 1247430Sgblack@eecs.umich.edu fetchPolicy = Branch; 1257639Sgblack@eecs.umich.edu DPRINTF(Fetch, "Fetch policy set to Branch Count\n"); 12611671Smitch.hayenga@arm.com } else if (policy == "iqcount") { 12711671Smitch.hayenga@arm.com fetchPolicy = IQ; 12811671Smitch.hayenga@arm.com DPRINTF(Fetch, "Fetch policy set to IQ count\n"); 12911671Smitch.hayenga@arm.com } else if (policy == "lsqcount") { 13011671Smitch.hayenga@arm.com fetchPolicy = LSQ; 13111671Smitch.hayenga@arm.com DPRINTF(Fetch, "Fetch policy set to LSQ count\n"); 13212104Snathanael.premillieu@arm.com } else { 13311671Smitch.hayenga@arm.com fatal("Invalid Fetch Policy. Options Are: {SingleThread," 13412104Snathanael.premillieu@arm.com " RoundRobin,LSQcount,IQcount}\n"); 13511671Smitch.hayenga@arm.com } 13612104Snathanael.premillieu@arm.com 13711671Smitch.hayenga@arm.com // Get the size of an instruction. 13811671Smitch.hayenga@arm.com instSize = sizeof(TheISA::MachInst); 13911671Smitch.hayenga@arm.com 14011671Smitch.hayenga@arm.com for (int i = 0; i < Impl::MaxThreads; i++) { 14110037SARM gem5 Developers decoder[i] = NULL; 14210037SARM gem5 Developers fetchBuffer[i] = NULL; 14310037SARM gem5 Developers fetchBufferPC[i] = 0; 14410037SARM gem5 Developers fetchBufferValid[i] = false; 14512104Snathanael.premillieu@arm.com } 14610037SARM gem5 Developers 14712104Snathanael.premillieu@arm.com branchPred = params->branchPred; 14810037SARM gem5 Developers 14912104Snathanael.premillieu@arm.com for (ThreadID tid = 0; tid < numThreads; tid++) { 15010037SARM gem5 Developers decoder[tid] = new TheISA::Decoder; 15112104Snathanael.premillieu@arm.com // Create space to buffer the cache line data, 15210037SARM gem5 Developers // which may not hold the entire cache line. 15310037SARM gem5 Developers fetchBuffer[tid] = new uint8_t[fetchBufferSize]; 15410037SARM gem5 Developers } 15510037SARM gem5 Developers} 1567639Sgblack@eecs.umich.edu 1577639Sgblack@eecs.umich.edutemplate <class Impl> 1587639Sgblack@eecs.umich.edustd::string 1597639Sgblack@eecs.umich.eduDefaultFetch<Impl>::name() const 16012104Snathanael.premillieu@arm.com{ 1617639Sgblack@eecs.umich.edu return cpu->name() + ".fetch"; 16212104Snathanael.premillieu@arm.com} 1637639Sgblack@eecs.umich.edu 16412104Snathanael.premillieu@arm.comtemplate <class Impl> 1657639Sgblack@eecs.umich.eduvoid 1667639Sgblack@eecs.umich.eduDefaultFetch<Impl>::regStats() 1677639Sgblack@eecs.umich.edu{ 1687639Sgblack@eecs.umich.edu icacheStallCycles 1697430Sgblack@eecs.umich.edu .name(name() + ".icacheStallCycles") 1707430Sgblack@eecs.umich.edu .desc("Number of cycles fetch is stalled on an Icache miss") 1717430Sgblack@eecs.umich.edu .prereq(icacheStallCycles); 1727430Sgblack@eecs.umich.edu 1737430Sgblack@eecs.umich.edu fetchedInsts 1747430Sgblack@eecs.umich.edu .name(name() + ".Insts") 1757430Sgblack@eecs.umich.edu .desc("Number of instructions fetch has processed") 1767430Sgblack@eecs.umich.edu .prereq(fetchedInsts); 1777430Sgblack@eecs.umich.edu 1787430Sgblack@eecs.umich.edu fetchedBranches 1797430Sgblack@eecs.umich.edu .name(name() + ".Branches") 1807430Sgblack@eecs.umich.edu .desc("Number of branches that fetch encountered") 1817430Sgblack@eecs.umich.edu .prereq(fetchedBranches); 1827430Sgblack@eecs.umich.edu 1837430Sgblack@eecs.umich.edu predictedBranches 1847430Sgblack@eecs.umich.edu .name(name() + ".predictedBranches") 1857430Sgblack@eecs.umich.edu .desc("Number of branches that fetch has predicted taken") 1867430Sgblack@eecs.umich.edu .prereq(predictedBranches); 1877430Sgblack@eecs.umich.edu 1887430Sgblack@eecs.umich.edu fetchCycles 1897430Sgblack@eecs.umich.edu .name(name() + ".Cycles") 1907430Sgblack@eecs.umich.edu .desc("Number of cycles fetch has run and was not squashing or" 1917430Sgblack@eecs.umich.edu " blocked") 1927430Sgblack@eecs.umich.edu .prereq(fetchCycles); 1937430Sgblack@eecs.umich.edu 1947430Sgblack@eecs.umich.edu fetchSquashCycles 19510037SARM gem5 Developers .name(name() + ".SquashCycles") 1967430Sgblack@eecs.umich.edu .desc("Number of cycles fetch has spent squashing") 1977430Sgblack@eecs.umich.edu .prereq(fetchSquashCycles); 1987430Sgblack@eecs.umich.edu 19910037SARM gem5 Developers fetchTlbCycles 2007430Sgblack@eecs.umich.edu .name(name() + ".TlbCycles") 2017430Sgblack@eecs.umich.edu .desc("Number of cycles fetch has spent waiting for tlb") 20210037SARM gem5 Developers .prereq(fetchTlbCycles); 2037430Sgblack@eecs.umich.edu 2047430Sgblack@eecs.umich.edu fetchIdleCycles 20510037SARM gem5 Developers .name(name() + ".IdleCycles") 2067430Sgblack@eecs.umich.edu .desc("Number of cycles fetch was idle") 2077430Sgblack@eecs.umich.edu .prereq(fetchIdleCycles); 2087430Sgblack@eecs.umich.edu 2097430Sgblack@eecs.umich.edu fetchBlockedCycles 21010037SARM gem5 Developers .name(name() + ".BlockedCycles") 21110037SARM gem5 Developers .desc("Number of cycles fetch has spent blocked") 2127430Sgblack@eecs.umich.edu .prereq(fetchBlockedCycles); 21310037SARM gem5 Developers 2147430Sgblack@eecs.umich.edu fetchedCacheLines 2157430Sgblack@eecs.umich.edu .name(name() + ".CacheLines") 2167430Sgblack@eecs.umich.edu .desc("Number of cache lines fetched") 2177430Sgblack@eecs.umich.edu .prereq(fetchedCacheLines); 2187430Sgblack@eecs.umich.edu 2197430Sgblack@eecs.umich.edu fetchMiscStallCycles 2207430Sgblack@eecs.umich.edu .name(name() + ".MiscStallCycles") 2217639Sgblack@eecs.umich.edu .desc("Number of cycles fetch has spent waiting on interrupts, or " 2227430Sgblack@eecs.umich.edu "bad addresses, or out of MSHRs") 2237430Sgblack@eecs.umich.edu .prereq(fetchMiscStallCycles); 2247430Sgblack@eecs.umich.edu 2257430Sgblack@eecs.umich.edu fetchPendingDrainCycles 2267430Sgblack@eecs.umich.edu .name(name() + ".PendingDrainCycles") 2277430Sgblack@eecs.umich.edu .desc("Number of cycles fetch has spent waiting on pipes to drain") 2287430Sgblack@eecs.umich.edu .prereq(fetchPendingDrainCycles); 2297639Sgblack@eecs.umich.edu 2307430Sgblack@eecs.umich.edu fetchNoActiveThreadStallCycles 2317430Sgblack@eecs.umich.edu .name(name() + ".NoActiveThreadStallCycles") 2327430Sgblack@eecs.umich.edu .desc("Number of stall cycles due to no active thread to fetch from") 2337430Sgblack@eecs.umich.edu .prereq(fetchNoActiveThreadStallCycles); 2347639Sgblack@eecs.umich.edu 2357430Sgblack@eecs.umich.edu fetchPendingTrapStallCycles 2367430Sgblack@eecs.umich.edu .name(name() + ".PendingTrapStallCycles") 2377430Sgblack@eecs.umich.edu .desc("Number of stall cycles due to pending traps") 2387430Sgblack@eecs.umich.edu .prereq(fetchPendingTrapStallCycles); 2397430Sgblack@eecs.umich.edu 2407430Sgblack@eecs.umich.edu fetchPendingQuiesceStallCycles 2417430Sgblack@eecs.umich.edu .name(name() + ".PendingQuiesceStallCycles") 2427430Sgblack@eecs.umich.edu .desc("Number of stall cycles due to pending quiesce instructions") 2437430Sgblack@eecs.umich.edu .prereq(fetchPendingQuiesceStallCycles); 2447430Sgblack@eecs.umich.edu 2457639Sgblack@eecs.umich.edu fetchIcacheWaitRetryStallCycles 2467430Sgblack@eecs.umich.edu .name(name() + ".IcacheWaitRetryStallCycles") 2477639Sgblack@eecs.umich.edu .desc("Number of stall cycles due to full MSHR") 2487430Sgblack@eecs.umich.edu .prereq(fetchIcacheWaitRetryStallCycles); 2497430Sgblack@eecs.umich.edu 2507430Sgblack@eecs.umich.edu fetchIcacheSquashes 2517639Sgblack@eecs.umich.edu .name(name() + ".IcacheSquashes") 2527430Sgblack@eecs.umich.edu .desc("Number of outstanding Icache misses that were squashed") 2537430Sgblack@eecs.umich.edu .prereq(fetchIcacheSquashes); 2547430Sgblack@eecs.umich.edu 2557430Sgblack@eecs.umich.edu fetchTlbSquashes 2567430Sgblack@eecs.umich.edu .name(name() + ".ItlbSquashes") 2577430Sgblack@eecs.umich.edu .desc("Number of outstanding ITLB misses that were squashed") 2587430Sgblack@eecs.umich.edu .prereq(fetchTlbSquashes); 2597430Sgblack@eecs.umich.edu 2607430Sgblack@eecs.umich.edu fetchNisnDist 2617430Sgblack@eecs.umich.edu .init(/* base value */ 0, 2627639Sgblack@eecs.umich.edu /* last value */ fetchWidth, 2637430Sgblack@eecs.umich.edu /* bucket size */ 1) 2647430Sgblack@eecs.umich.edu .name(name() + ".rateDist") 2657430Sgblack@eecs.umich.edu .desc("Number of instructions fetched each cycle (Total)") 2667430Sgblack@eecs.umich.edu .flags(Stats::pdf); 2677430Sgblack@eecs.umich.edu 2687430Sgblack@eecs.umich.edu idleRate 2697430Sgblack@eecs.umich.edu .name(name() + ".idleRate") 2707430Sgblack@eecs.umich.edu .desc("Percent of cycles fetch was idle") 2717430Sgblack@eecs.umich.edu .prereq(idleRate); 2727430Sgblack@eecs.umich.edu idleRate = fetchIdleCycles * 100 / cpu->numCycles; 2737639Sgblack@eecs.umich.edu 2747430Sgblack@eecs.umich.edu branchRate 2757430Sgblack@eecs.umich.edu .name(name() + ".branchRate") 2767430Sgblack@eecs.umich.edu .desc("Number of branch fetches per cycle") 2777430Sgblack@eecs.umich.edu .flags(Stats::total); 2787430Sgblack@eecs.umich.edu branchRate = fetchedBranches / cpu->numCycles; 2797430Sgblack@eecs.umich.edu 2807430Sgblack@eecs.umich.edu fetchRate 2817430Sgblack@eecs.umich.edu .name(name() + ".rate") 2827430Sgblack@eecs.umich.edu .desc("Number of inst fetches per cycle") 2837430Sgblack@eecs.umich.edu .flags(Stats::total); 2847639Sgblack@eecs.umich.edu fetchRate = fetchedInsts / cpu->numCycles; 2857639Sgblack@eecs.umich.edu} 2867430Sgblack@eecs.umich.edu 2877639Sgblack@eecs.umich.edutemplate<class Impl> 2887639Sgblack@eecs.umich.eduvoid 2897430Sgblack@eecs.umich.eduDefaultFetch<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *time_buffer) 2907430Sgblack@eecs.umich.edu{ 2917430Sgblack@eecs.umich.edu timeBuffer = time_buffer; 2927639Sgblack@eecs.umich.edu 2937430Sgblack@eecs.umich.edu // Create wires to get information from proper places in time buffer. 2947639Sgblack@eecs.umich.edu fromDecode = timeBuffer->getWire(-decodeToFetchDelay); 2957430Sgblack@eecs.umich.edu fromRename = timeBuffer->getWire(-renameToFetchDelay); 2967430Sgblack@eecs.umich.edu fromIEW = timeBuffer->getWire(-iewToFetchDelay); 2977430Sgblack@eecs.umich.edu fromCommit = timeBuffer->getWire(-commitToFetchDelay); 2987430Sgblack@eecs.umich.edu} 2997430Sgblack@eecs.umich.edu 3007430Sgblack@eecs.umich.edutemplate<class Impl> 3017430Sgblack@eecs.umich.eduvoid 3027430Sgblack@eecs.umich.eduDefaultFetch<Impl>::setActiveThreads(std::list<ThreadID> *at_ptr) 3037430Sgblack@eecs.umich.edu{ 3047430Sgblack@eecs.umich.edu activeThreads = at_ptr; 3057430Sgblack@eecs.umich.edu} 3067430Sgblack@eecs.umich.edu 3077430Sgblack@eecs.umich.edutemplate<class Impl> 3087430Sgblack@eecs.umich.eduvoid 3097639Sgblack@eecs.umich.eduDefaultFetch<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr) 3107430Sgblack@eecs.umich.edu{ 3117430Sgblack@eecs.umich.edu fetchQueue = fq_ptr; 3127430Sgblack@eecs.umich.edu 3137430Sgblack@eecs.umich.edu // Create wire to write information to proper place in fetch queue. 3147430Sgblack@eecs.umich.edu toDecode = fetchQueue->getWire(0); 3157430Sgblack@eecs.umich.edu} 3167430Sgblack@eecs.umich.edu 3177430Sgblack@eecs.umich.edutemplate<class Impl> 3187430Sgblack@eecs.umich.eduvoid 3197430Sgblack@eecs.umich.eduDefaultFetch<Impl>::startupStage() 3207639Sgblack@eecs.umich.edu{ 3217639Sgblack@eecs.umich.edu assert(priorityList.empty()); 3227430Sgblack@eecs.umich.edu resetStage(); 3237639Sgblack@eecs.umich.edu 3247639Sgblack@eecs.umich.edu // Fetch needs to start fetching instructions at the very beginning, 3257430Sgblack@eecs.umich.edu // so it must start up in active state. 3267430Sgblack@eecs.umich.edu switchToActive(); 3277430Sgblack@eecs.umich.edu} 3287430Sgblack@eecs.umich.edu 3297430Sgblack@eecs.umich.edutemplate<class Impl> 3307430Sgblack@eecs.umich.eduvoid 3317430Sgblack@eecs.umich.eduDefaultFetch<Impl>::resetStage() 3327430Sgblack@eecs.umich.edu{ 3337430Sgblack@eecs.umich.edu numInst = 0; 3347430Sgblack@eecs.umich.edu interruptPending = false; 3357430Sgblack@eecs.umich.edu cacheBlocked = false; 3367430Sgblack@eecs.umich.edu 3377430Sgblack@eecs.umich.edu priorityList.clear(); 3387639Sgblack@eecs.umich.edu 3397430Sgblack@eecs.umich.edu // Setup PC and nextPC with initial state. 3407430Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; ++tid) { 3417430Sgblack@eecs.umich.edu fetchStatus[tid] = Running; 3427430Sgblack@eecs.umich.edu pc[tid] = cpu->pcState(tid); 3437430Sgblack@eecs.umich.edu fetchOffset[tid] = 0; 3447430Sgblack@eecs.umich.edu macroop[tid] = NULL; 3457430Sgblack@eecs.umich.edu 3467430Sgblack@eecs.umich.edu delayedCommit[tid] = false; 3477430Sgblack@eecs.umich.edu memReq[tid] = NULL; 3487430Sgblack@eecs.umich.edu 3497430Sgblack@eecs.umich.edu stalls[tid].decode = false; 3507430Sgblack@eecs.umich.edu stalls[tid].rename = false; 3517430Sgblack@eecs.umich.edu stalls[tid].iew = false; 3527430Sgblack@eecs.umich.edu stalls[tid].commit = false; 3537430Sgblack@eecs.umich.edu stalls[tid].drain = false; 3547430Sgblack@eecs.umich.edu 3557430Sgblack@eecs.umich.edu fetchBufferPC[tid] = 0; 3567430Sgblack@eecs.umich.edu fetchBufferValid[tid] = false; 3577430Sgblack@eecs.umich.edu 3587430Sgblack@eecs.umich.edu priorityList.push_back(tid); 3597430Sgblack@eecs.umich.edu } 3607430Sgblack@eecs.umich.edu 3617430Sgblack@eecs.umich.edu wroteToTimeBuffer = false; 3627430Sgblack@eecs.umich.edu _status = Inactive; 3637430Sgblack@eecs.umich.edu} 3647430Sgblack@eecs.umich.edu 3657430Sgblack@eecs.umich.edutemplate<class Impl> 3667430Sgblack@eecs.umich.eduvoid 3677430Sgblack@eecs.umich.eduDefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt) 3687430Sgblack@eecs.umich.edu{ 3697430Sgblack@eecs.umich.edu ThreadID tid = pkt->req->threadId(); 3707430Sgblack@eecs.umich.edu 3717430Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%u] Waking up from cache miss.\n", tid); 3727430Sgblack@eecs.umich.edu assert(!cpu->switchedOut()); 3737430Sgblack@eecs.umich.edu 3747639Sgblack@eecs.umich.edu // Only change the status if it's still waiting on the icache access 3757430Sgblack@eecs.umich.edu // to return. 3767430Sgblack@eecs.umich.edu if (fetchStatus[tid] != IcacheWaitResponse || 3777430Sgblack@eecs.umich.edu pkt->req != memReq[tid]) { 3787430Sgblack@eecs.umich.edu ++fetchIcacheSquashes; 3797430Sgblack@eecs.umich.edu delete pkt->req; 3807430Sgblack@eecs.umich.edu delete pkt; 3817430Sgblack@eecs.umich.edu return; 3827430Sgblack@eecs.umich.edu } 3837430Sgblack@eecs.umich.edu 3847430Sgblack@eecs.umich.edu memcpy(fetchBuffer[tid], pkt->getPtr<uint8_t>(), fetchBufferSize); 3857430Sgblack@eecs.umich.edu fetchBufferValid[tid] = true; 3867430Sgblack@eecs.umich.edu 3877430Sgblack@eecs.umich.edu // Wake up the CPU (if it went to sleep and was waiting on 3887430Sgblack@eecs.umich.edu // this completion event). 3897430Sgblack@eecs.umich.edu cpu->wakeCPU(); 3907430Sgblack@eecs.umich.edu 3917430Sgblack@eecs.umich.edu DPRINTF(Activity, "[tid:%u] Activating fetch due to cache completion\n", 3927430Sgblack@eecs.umich.edu tid); 3937430Sgblack@eecs.umich.edu 39410037SARM gem5 Developers switchToActive(); 39510037SARM gem5 Developers 39610037SARM gem5 Developers // Only switch to IcacheAccessComplete if we're not stalled as well. 3977430Sgblack@eecs.umich.edu if (checkStall(tid)) { 39810037SARM gem5 Developers fetchStatus[tid] = Blocked; 39910037SARM gem5 Developers } else { 40010037SARM gem5 Developers fetchStatus[tid] = IcacheAccessComplete; 40110037SARM gem5 Developers } 40210037SARM gem5 Developers 40310037SARM gem5 Developers pkt->req->setAccessLatency(); 40410037SARM gem5 Developers // Reset the mem req to NULL. 40510037SARM gem5 Developers delete pkt->req; 40610037SARM gem5 Developers delete pkt; 40710037SARM gem5 Developers memReq[tid] = NULL; 40810037SARM gem5 Developers} 40910037SARM gem5 Developers 41010037SARM gem5 Developerstemplate <class Impl> 41110037SARM gem5 Developersvoid 41210037SARM gem5 DevelopersDefaultFetch<Impl>::drainResume() 4137430Sgblack@eecs.umich.edu{ 41410037SARM gem5 Developers for (ThreadID i = 0; i < Impl::MaxThreads; ++i) 41510037SARM gem5 Developers stalls[i].drain = false; 41610037SARM gem5 Developers} 41710037SARM gem5 Developers 4187430Sgblack@eecs.umich.edutemplate <class Impl> 41910037SARM gem5 Developersvoid 42010037SARM gem5 DevelopersDefaultFetch<Impl>::drainSanityCheck() const 4217430Sgblack@eecs.umich.edu{ 4227430Sgblack@eecs.umich.edu assert(isDrained()); 4237430Sgblack@eecs.umich.edu assert(retryPkt == NULL); 4247430Sgblack@eecs.umich.edu assert(retryTid == InvalidThreadID); 4257430Sgblack@eecs.umich.edu assert(cacheBlocked == false); 4267430Sgblack@eecs.umich.edu assert(interruptPending == false); 4277639Sgblack@eecs.umich.edu 4287430Sgblack@eecs.umich.edu for (ThreadID i = 0; i < numThreads; ++i) { 4297430Sgblack@eecs.umich.edu assert(!memReq[i]); 4307430Sgblack@eecs.umich.edu assert(!stalls[i].decode); 4317639Sgblack@eecs.umich.edu assert(!stalls[i].rename); 4327430Sgblack@eecs.umich.edu assert(!stalls[i].iew); 4337430Sgblack@eecs.umich.edu assert(!stalls[i].commit); 4347430Sgblack@eecs.umich.edu assert(fetchStatus[i] == Idle || stalls[i].drain); 4357430Sgblack@eecs.umich.edu } 4367430Sgblack@eecs.umich.edu 4377430Sgblack@eecs.umich.edu branchPred->drainSanityCheck(); 4387430Sgblack@eecs.umich.edu} 4397430Sgblack@eecs.umich.edu 4407430Sgblack@eecs.umich.edutemplate <class Impl> 4417430Sgblack@eecs.umich.edubool 4427639Sgblack@eecs.umich.eduDefaultFetch<Impl>::isDrained() const 4437430Sgblack@eecs.umich.edu{ 4447430Sgblack@eecs.umich.edu /* Make sure that threads are either idle of that the commit stage 4457430Sgblack@eecs.umich.edu * has signaled that draining has completed by setting the drain 4467430Sgblack@eecs.umich.edu * stall flag. This effectively forces the pipeline to be disabled 4477430Sgblack@eecs.umich.edu * until the whole system is drained (simulation may continue to 4487430Sgblack@eecs.umich.edu * drain other components). 4497430Sgblack@eecs.umich.edu */ 4507430Sgblack@eecs.umich.edu for (ThreadID i = 0; i < numThreads; ++i) { 4517430Sgblack@eecs.umich.edu if (!(fetchStatus[i] == Idle || 4527430Sgblack@eecs.umich.edu (fetchStatus[i] == Blocked && stalls[i].drain))) 4537430Sgblack@eecs.umich.edu return false; 4547430Sgblack@eecs.umich.edu } 4557430Sgblack@eecs.umich.edu 4567430Sgblack@eecs.umich.edu /* The pipeline might start up again in the middle of the drain 4577430Sgblack@eecs.umich.edu * cycle if the finish translation event is scheduled, so make 4587430Sgblack@eecs.umich.edu * sure that's not the case. 4597639Sgblack@eecs.umich.edu */ 4607430Sgblack@eecs.umich.edu return !finishTranslationEvent.scheduled(); 4617430Sgblack@eecs.umich.edu} 4627430Sgblack@eecs.umich.edu 4637430Sgblack@eecs.umich.edutemplate <class Impl> 4647430Sgblack@eecs.umich.eduvoid 4657430Sgblack@eecs.umich.eduDefaultFetch<Impl>::takeOverFrom() 4667639Sgblack@eecs.umich.edu{ 4677430Sgblack@eecs.umich.edu assert(cpu->getInstPort().isConnected()); 4687430Sgblack@eecs.umich.edu resetStage(); 4697430Sgblack@eecs.umich.edu 4707430Sgblack@eecs.umich.edu} 4717430Sgblack@eecs.umich.edu 4727430Sgblack@eecs.umich.edutemplate <class Impl> 4737430Sgblack@eecs.umich.eduvoid 4747430Sgblack@eecs.umich.eduDefaultFetch<Impl>::drainStall(ThreadID tid) 4757430Sgblack@eecs.umich.edu{ 4767430Sgblack@eecs.umich.edu assert(cpu->isDraining()); 4777430Sgblack@eecs.umich.edu assert(!stalls[tid].drain); 4787430Sgblack@eecs.umich.edu DPRINTF(Drain, "%i: Thread drained.\n", tid); 4797430Sgblack@eecs.umich.edu stalls[tid].drain = true; 4807430Sgblack@eecs.umich.edu} 4817430Sgblack@eecs.umich.edu 4827430Sgblack@eecs.umich.edutemplate <class Impl> 4837430Sgblack@eecs.umich.eduvoid 4847430Sgblack@eecs.umich.eduDefaultFetch<Impl>::wakeFromQuiesce() 48510037SARM gem5 Developers{ 48610037SARM gem5 Developers DPRINTF(Fetch, "Waking up from quiesce\n"); 4877430Sgblack@eecs.umich.edu // Hopefully this is safe 48810037SARM gem5 Developers // @todo: Allow other threads to wake from quiesce. 4897430Sgblack@eecs.umich.edu fetchStatus[0] = Running; 4907430Sgblack@eecs.umich.edu} 49110037SARM gem5 Developers 4927430Sgblack@eecs.umich.edutemplate <class Impl> 4937430Sgblack@eecs.umich.eduinline void 4947430Sgblack@eecs.umich.eduDefaultFetch<Impl>::switchToActive() 4957430Sgblack@eecs.umich.edu{ 4967430Sgblack@eecs.umich.edu if (_status == Inactive) { 4977430Sgblack@eecs.umich.edu DPRINTF(Activity, "Activating stage.\n"); 4987430Sgblack@eecs.umich.edu 4997430Sgblack@eecs.umich.edu cpu->activateStage(O3CPU::FetchIdx); 5007430Sgblack@eecs.umich.edu 5017430Sgblack@eecs.umich.edu _status = Active; 50210037SARM gem5 Developers } 5037430Sgblack@eecs.umich.edu} 5047430Sgblack@eecs.umich.edu 5057430Sgblack@eecs.umich.edutemplate <class Impl> 5067430Sgblack@eecs.umich.eduinline void 5077430Sgblack@eecs.umich.eduDefaultFetch<Impl>::switchToInactive() 5087430Sgblack@eecs.umich.edu{ 5097430Sgblack@eecs.umich.edu if (_status == Active) { 5107430Sgblack@eecs.umich.edu DPRINTF(Activity, "Deactivating stage.\n"); 5117639Sgblack@eecs.umich.edu 5127430Sgblack@eecs.umich.edu cpu->deactivateStage(O3CPU::FetchIdx); 5137430Sgblack@eecs.umich.edu 5147430Sgblack@eecs.umich.edu _status = Inactive; 5157430Sgblack@eecs.umich.edu } 5167430Sgblack@eecs.umich.edu} 5177430Sgblack@eecs.umich.edu 5187430Sgblack@eecs.umich.edutemplate <class Impl> 5197430Sgblack@eecs.umich.edubool 5207430Sgblack@eecs.umich.eduDefaultFetch<Impl>::lookupAndUpdateNextPC( 5217430Sgblack@eecs.umich.edu DynInstPtr &inst, TheISA::PCState &nextPC) 5227430Sgblack@eecs.umich.edu{ 5237430Sgblack@eecs.umich.edu // Do branch prediction check here. 5247430Sgblack@eecs.umich.edu // A bit of a misnomer...next_PC is actually the current PC until 5257430Sgblack@eecs.umich.edu // this function updates it. 5267430Sgblack@eecs.umich.edu bool predict_taken; 5277639Sgblack@eecs.umich.edu 5287430Sgblack@eecs.umich.edu if (!inst->isControl()) { 5297430Sgblack@eecs.umich.edu TheISA::advancePC(nextPC, inst->staticInst); 5307430Sgblack@eecs.umich.edu inst->setPredTarg(nextPC); 5317430Sgblack@eecs.umich.edu inst->setPredTaken(false); 5327430Sgblack@eecs.umich.edu return false; 5337430Sgblack@eecs.umich.edu } 5347430Sgblack@eecs.umich.edu 5357430Sgblack@eecs.umich.edu ThreadID tid = inst->threadNumber; 5367430Sgblack@eecs.umich.edu predict_taken = branchPred->predict(inst->staticInst, inst->seqNum, 5377430Sgblack@eecs.umich.edu nextPC, tid); 5387430Sgblack@eecs.umich.edu 5397430Sgblack@eecs.umich.edu if (predict_taken) { 5407430Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%i]: [sn:%i]: Branch predicted to be taken to %s.\n", 5417430Sgblack@eecs.umich.edu tid, inst->seqNum, nextPC); 5427430Sgblack@eecs.umich.edu } else { 5437430Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%i]: [sn:%i]:Branch predicted to be not taken.\n", 5447430Sgblack@eecs.umich.edu tid, inst->seqNum); 5457430Sgblack@eecs.umich.edu } 5467430Sgblack@eecs.umich.edu 5477430Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%i]: [sn:%i] Branch predicted to go to %s.\n", 5487430Sgblack@eecs.umich.edu tid, inst->seqNum, nextPC); 5497430Sgblack@eecs.umich.edu inst->setPredTarg(nextPC); 5507430Sgblack@eecs.umich.edu inst->setPredTaken(predict_taken); 5517430Sgblack@eecs.umich.edu 5527430Sgblack@eecs.umich.edu ++fetchedBranches; 5537430Sgblack@eecs.umich.edu 5547430Sgblack@eecs.umich.edu if (predict_taken) { 5557430Sgblack@eecs.umich.edu ++predictedBranches; 5567430Sgblack@eecs.umich.edu } 5577430Sgblack@eecs.umich.edu 5587430Sgblack@eecs.umich.edu return predict_taken; 5597430Sgblack@eecs.umich.edu} 5607430Sgblack@eecs.umich.edu 5617430Sgblack@eecs.umich.edutemplate <class Impl> 5627430Sgblack@eecs.umich.edubool 5637639Sgblack@eecs.umich.eduDefaultFetch<Impl>::fetchCacheLine(Addr vaddr, ThreadID tid, Addr pc) 5647430Sgblack@eecs.umich.edu{ 5657430Sgblack@eecs.umich.edu Fault fault = NoFault; 56610037SARM gem5 Developers 56710037SARM gem5 Developers assert(!cpu->switchedOut()); 56810037SARM gem5 Developers 5697430Sgblack@eecs.umich.edu // @todo: not sure if these should block translation. 57010037SARM gem5 Developers //AlphaDep 57110037SARM gem5 Developers if (cacheBlocked) { 57210037SARM gem5 Developers DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, cache blocked\n", 57310037SARM gem5 Developers tid); 57410037SARM gem5 Developers return false; 57510037SARM gem5 Developers } else if (checkInterrupt(pc) && !delayedCommit[tid]) { 57610037SARM gem5 Developers // Hold off fetch from getting new instructions when: 57710037SARM gem5 Developers // Cache is blocked, or 57810037SARM gem5 Developers // while an interrupt is pending and we're not in PAL mode, or 57910037SARM gem5 Developers // fetch is switched out. 58010037SARM gem5 Developers DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, interrupt pending\n", 58110037SARM gem5 Developers tid); 58210037SARM gem5 Developers return false; 58310037SARM gem5 Developers } 58410037SARM gem5 Developers 58510037SARM gem5 Developers // Align the fetch address to the start of a fetch buffer segment. 58610037SARM gem5 Developers Addr fetchBufferBlockPC = fetchBufferAlignPC(vaddr); 58710037SARM gem5 Developers 58810037SARM gem5 Developers DPRINTF(Fetch, "[tid:%i] Fetching cache line %#x for addr %#x\n", 58910037SARM gem5 Developers tid, fetchBufferBlockPC, vaddr); 59010037SARM gem5 Developers 59110037SARM gem5 Developers // Setup the memReq to do a read of the first instruction's address. 59210037SARM gem5 Developers // Set the appropriate read size and flags as well. 59310037SARM gem5 Developers // Build request here. 59410037SARM gem5 Developers RequestPtr mem_req = 59510037SARM gem5 Developers new Request(tid, fetchBufferBlockPC, fetchBufferSize, 59610037SARM gem5 Developers Request::INST_FETCH, cpu->instMasterId(), pc, 59710037SARM gem5 Developers cpu->thread[tid]->contextId(), tid); 59810037SARM gem5 Developers 59910037SARM gem5 Developers memReq[tid] = mem_req; 6007430Sgblack@eecs.umich.edu 6017639Sgblack@eecs.umich.edu // Initiate translation of the icache block 6027639Sgblack@eecs.umich.edu fetchStatus[tid] = ItlbWait; 60310037SARM gem5 Developers FetchTranslation *trans = new FetchTranslation(this); 6047430Sgblack@eecs.umich.edu cpu->itb->translateTiming(mem_req, cpu->thread[tid]->getTC(), 6057430Sgblack@eecs.umich.edu trans, BaseTLB::Execute); 6067430Sgblack@eecs.umich.edu return true; 6077430Sgblack@eecs.umich.edu} 60810037SARM gem5 Developers 6097430Sgblack@eecs.umich.edutemplate <class Impl> 6107430Sgblack@eecs.umich.eduvoid 6117430Sgblack@eecs.umich.eduDefaultFetch<Impl>::finishTranslation(Fault fault, RequestPtr mem_req) 6127430Sgblack@eecs.umich.edu{ 6137430Sgblack@eecs.umich.edu ThreadID tid = mem_req->threadId(); 61410037SARM gem5 Developers Addr fetchBufferBlockPC = mem_req->getVaddr(); 6157639Sgblack@eecs.umich.edu 6167430Sgblack@eecs.umich.edu assert(!cpu->switchedOut()); 61710037SARM gem5 Developers 6187430Sgblack@eecs.umich.edu // Wake up CPU if it was idle 6197430Sgblack@eecs.umich.edu cpu->wakeCPU(); 62010037SARM gem5 Developers 62110037SARM gem5 Developers if (fetchStatus[tid] != ItlbWait || mem_req != memReq[tid] || 6227430Sgblack@eecs.umich.edu mem_req->getVaddr() != memReq[tid]->getVaddr()) { 6237430Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%i] Ignoring itlb completed after squash\n", 62410037SARM gem5 Developers tid); 6257430Sgblack@eecs.umich.edu ++fetchTlbSquashes; 6267639Sgblack@eecs.umich.edu delete mem_req; 62710037SARM gem5 Developers return; 6287430Sgblack@eecs.umich.edu } 6297430Sgblack@eecs.umich.edu 6307430Sgblack@eecs.umich.edu 6317430Sgblack@eecs.umich.edu // If translation was successful, attempt to read the icache block. 63210037SARM gem5 Developers if (fault == NoFault) { 63310037SARM gem5 Developers // Check that we're not going off into random memory 6347430Sgblack@eecs.umich.edu // If we have, just wait around for commit to squash something and put 6357430Sgblack@eecs.umich.edu // us on the right track 63610037SARM gem5 Developers if (!cpu->system->isMemAddr(mem_req->getPaddr())) { 63710037SARM gem5 Developers warn("Address %#x is outside of physical memory, stopping fetch\n", 63810037SARM gem5 Developers mem_req->getPaddr()); 63910037SARM gem5 Developers fetchStatus[tid] = NoGoodAddr; 64010037SARM gem5 Developers delete mem_req; 64110037SARM gem5 Developers memReq[tid] = NULL; 64210037SARM gem5 Developers return; 64310037SARM gem5 Developers } 64410037SARM gem5 Developers 64510037SARM gem5 Developers // Build packet here. 64610037SARM gem5 Developers PacketPtr data_pkt = new Packet(mem_req, MemCmd::ReadReq); 64710037SARM gem5 Developers data_pkt->dataDynamicArray(new uint8_t[fetchBufferSize]); 64810037SARM gem5 Developers 64910037SARM gem5 Developers fetchBufferPC[tid] = fetchBufferBlockPC; 65010037SARM gem5 Developers fetchBufferValid[tid] = false; 6517430Sgblack@eecs.umich.edu DPRINTF(Fetch, "Fetch: Doing instruction read.\n"); 6527430Sgblack@eecs.umich.edu 6537430Sgblack@eecs.umich.edu fetchedCacheLines++; 65410037SARM gem5 Developers 65510037SARM gem5 Developers // Access the cache. 6567430Sgblack@eecs.umich.edu if (!cpu->getInstPort().sendTimingReq(data_pkt)) { 65710037SARM gem5 Developers assert(retryPkt == NULL); 65810037SARM gem5 Developers assert(retryTid == InvalidThreadID); 6597430Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid); 66010037SARM gem5 Developers 66110037SARM gem5 Developers fetchStatus[tid] = IcacheWaitRetry; 6627430Sgblack@eecs.umich.edu retryPkt = data_pkt; 6637430Sgblack@eecs.umich.edu retryTid = tid; 6647430Sgblack@eecs.umich.edu cacheBlocked = true; 6657639Sgblack@eecs.umich.edu } else { 66610037SARM gem5 Developers DPRINTF(Fetch, "[tid:%i]: Doing Icache access.\n", tid); 6677430Sgblack@eecs.umich.edu DPRINTF(Activity, "[tid:%i]: Activity: Waiting on I-cache " 6687430Sgblack@eecs.umich.edu "response.\n", tid); 66910037SARM gem5 Developers 6707430Sgblack@eecs.umich.edu lastIcacheStall[tid] = curTick(); 67110037SARM gem5 Developers fetchStatus[tid] = IcacheWaitResponse; 67210037SARM gem5 Developers } 67310037SARM gem5 Developers } else { 67410037SARM gem5 Developers if (!(numInst < fetchWidth)) { 6757430Sgblack@eecs.umich.edu assert(!finishTranslationEvent.scheduled()); 6767430Sgblack@eecs.umich.edu finishTranslationEvent.setFault(fault); 6777430Sgblack@eecs.umich.edu finishTranslationEvent.setReq(mem_req); 6787430Sgblack@eecs.umich.edu cpu->schedule(finishTranslationEvent, 6797639Sgblack@eecs.umich.edu cpu->clockEdge(Cycles(1))); 6807430Sgblack@eecs.umich.edu return; 6817430Sgblack@eecs.umich.edu } 6827430Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%i] Got back req with addr %#x but expected %#x\n", 6837639Sgblack@eecs.umich.edu tid, mem_req->getVaddr(), memReq[tid]->getVaddr()); 68410037SARM gem5 Developers // Translation faulted, icache request won't be sent. 6857430Sgblack@eecs.umich.edu delete mem_req; 6867430Sgblack@eecs.umich.edu memReq[tid] = NULL; 68710037SARM gem5 Developers 6887430Sgblack@eecs.umich.edu // Send the fault to commit. This thread will not do anything 68910037SARM gem5 Developers // until commit handles the fault. The only other way it can 69010037SARM gem5 Developers // wake up is if a squash comes along and changes the PC. 69110037SARM gem5 Developers TheISA::PCState fetchPC = pc[tid]; 69210037SARM gem5 Developers 69310037SARM gem5 Developers DPRINTF(Fetch, "[tid:%i]: Translation faulted, building noop.\n", tid); 6947430Sgblack@eecs.umich.edu // We will use a nop in ordier to carry the fault. 6957430Sgblack@eecs.umich.edu DynInstPtr instruction = buildInst(tid, 6967430Sgblack@eecs.umich.edu decoder[tid]->decode(TheISA::NoopMachInst, fetchPC.instAddr()), 6977430Sgblack@eecs.umich.edu NULL, fetchPC, fetchPC, false); 6987639Sgblack@eecs.umich.edu 6997430Sgblack@eecs.umich.edu instruction->setPredTarg(fetchPC); 7007430Sgblack@eecs.umich.edu instruction->fault = fault; 7017430Sgblack@eecs.umich.edu wroteToTimeBuffer = true; 7027430Sgblack@eecs.umich.edu 7037639Sgblack@eecs.umich.edu DPRINTF(Activity, "Activity this cycle.\n"); 70410037SARM gem5 Developers cpu->activityThisCycle(); 7057430Sgblack@eecs.umich.edu 7067430Sgblack@eecs.umich.edu fetchStatus[tid] = TrapPending; 70710037SARM gem5 Developers 7087430Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%i]: Blocked, need to handle the trap.\n", tid); 70910037SARM gem5 Developers DPRINTF(Fetch, "[tid:%i]: fault (%s) detected @ PC %s.\n", 71010037SARM gem5 Developers tid, fault->name(), pc[tid]); 71110037SARM gem5 Developers } 71210037SARM gem5 Developers _status = updateFetchStatus(); 71310037SARM gem5 Developers} 7147430Sgblack@eecs.umich.edu 7157430Sgblack@eecs.umich.edutemplate <class Impl> 7167430Sgblack@eecs.umich.eduinline void 7177430Sgblack@eecs.umich.eduDefaultFetch<Impl>::doSquash(const TheISA::PCState &newPC, 7187639Sgblack@eecs.umich.edu const DynInstPtr squashInst, ThreadID tid) 7197430Sgblack@eecs.umich.edu{ 7207430Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%i]: Squashing, setting PC to: %s.\n", 7217430Sgblack@eecs.umich.edu tid, newPC); 7227639Sgblack@eecs.umich.edu 72310037SARM gem5 Developers pc[tid] = newPC; 7247430Sgblack@eecs.umich.edu fetchOffset[tid] = 0; 7257430Sgblack@eecs.umich.edu if (squashInst && squashInst->pcState().instAddr() == newPC.instAddr()) 72610037SARM gem5 Developers macroop[tid] = squashInst->macroop; 7277430Sgblack@eecs.umich.edu else 72810037SARM gem5 Developers macroop[tid] = NULL; 72910037SARM gem5 Developers decoder[tid]->reset(); 73010037SARM gem5 Developers 73110037SARM gem5 Developers // Clear the icache miss if it's outstanding. 73210037SARM gem5 Developers if (fetchStatus[tid] == IcacheWaitResponse) { 7337430Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%i]: Squashing outstanding Icache miss.\n", 7347430Sgblack@eecs.umich.edu tid); 7357430Sgblack@eecs.umich.edu memReq[tid] = NULL; 7367430Sgblack@eecs.umich.edu } else if (fetchStatus[tid] == ItlbWait) { 7377639Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%i]: Squashing outstanding ITLB miss.\n", 7387430Sgblack@eecs.umich.edu tid); 7397430Sgblack@eecs.umich.edu memReq[tid] = NULL; 7407639Sgblack@eecs.umich.edu } 7417639Sgblack@eecs.umich.edu 7427639Sgblack@eecs.umich.edu // Get rid of the retrying packet if it was from this thread. 7437639Sgblack@eecs.umich.edu if (retryTid == tid) { 7447639Sgblack@eecs.umich.edu assert(cacheBlocked); 7457639Sgblack@eecs.umich.edu if (retryPkt) { 7467639Sgblack@eecs.umich.edu delete retryPkt->req; 7477639Sgblack@eecs.umich.edu delete retryPkt; 7487639Sgblack@eecs.umich.edu } 7497639Sgblack@eecs.umich.edu retryPkt = NULL; 7507639Sgblack@eecs.umich.edu retryTid = InvalidThreadID; 7517639Sgblack@eecs.umich.edu } 7527639Sgblack@eecs.umich.edu 7537639Sgblack@eecs.umich.edu fetchStatus[tid] = Squashing; 7547639Sgblack@eecs.umich.edu 7557639Sgblack@eecs.umich.edu // microops are being squashed, it is not known wheather the 7567639Sgblack@eecs.umich.edu // youngest non-squashed microop was marked delayed commit 7577639Sgblack@eecs.umich.edu // or not. Setting the flag to true ensures that the 7587639Sgblack@eecs.umich.edu // interrupts are not handled when they cannot be, though 7597639Sgblack@eecs.umich.edu // some opportunities to handle interrupts may be missed. 7607639Sgblack@eecs.umich.edu delayedCommit[tid] = true; 7617639Sgblack@eecs.umich.edu 7627639Sgblack@eecs.umich.edu ++fetchSquashCycles; 7637639Sgblack@eecs.umich.edu} 7647639Sgblack@eecs.umich.edu 7657639Sgblack@eecs.umich.edutemplate<class Impl> 7667639Sgblack@eecs.umich.eduvoid 7677639Sgblack@eecs.umich.eduDefaultFetch<Impl>::squashFromDecode(const TheISA::PCState &newPC, 7687639Sgblack@eecs.umich.edu const DynInstPtr squashInst, 7697639Sgblack@eecs.umich.edu const InstSeqNum seq_num, ThreadID tid) 7707639Sgblack@eecs.umich.edu{ 7717639Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%i]: Squashing from decode.\n", tid); 7727639Sgblack@eecs.umich.edu 7737639Sgblack@eecs.umich.edu doSquash(newPC, squashInst, tid); 7747639Sgblack@eecs.umich.edu 7757639Sgblack@eecs.umich.edu // Tell the CPU to remove any instructions that are in flight between 7767639Sgblack@eecs.umich.edu // fetch and decode. 7777639Sgblack@eecs.umich.edu cpu->removeInstsUntil(seq_num, tid); 7787639Sgblack@eecs.umich.edu} 7797639Sgblack@eecs.umich.edu 7807639Sgblack@eecs.umich.edutemplate<class Impl> 7817639Sgblack@eecs.umich.edubool 7827639Sgblack@eecs.umich.eduDefaultFetch<Impl>::checkStall(ThreadID tid) const 7837639Sgblack@eecs.umich.edu{ 7847639Sgblack@eecs.umich.edu bool ret_val = false; 7857639Sgblack@eecs.umich.edu 7867639Sgblack@eecs.umich.edu if (cpu->contextSwitch) { 7877639Sgblack@eecs.umich.edu DPRINTF(Fetch,"[tid:%i]: Stalling for a context switch.\n",tid); 7887639Sgblack@eecs.umich.edu ret_val = true; 7897639Sgblack@eecs.umich.edu } else if (stalls[tid].drain) { 7907639Sgblack@eecs.umich.edu assert(cpu->isDraining()); 7917639Sgblack@eecs.umich.edu DPRINTF(Fetch,"[tid:%i]: Drain stall detected.\n",tid); 7927639Sgblack@eecs.umich.edu ret_val = true; 7937639Sgblack@eecs.umich.edu } else if (stalls[tid].decode) { 7947639Sgblack@eecs.umich.edu DPRINTF(Fetch,"[tid:%i]: Stall from Decode stage detected.\n",tid); 7957639Sgblack@eecs.umich.edu ret_val = true; 7967639Sgblack@eecs.umich.edu } else if (stalls[tid].rename) { 7977639Sgblack@eecs.umich.edu DPRINTF(Fetch,"[tid:%i]: Stall from Rename stage detected.\n",tid); 7987639Sgblack@eecs.umich.edu ret_val = true; 7997639Sgblack@eecs.umich.edu } else if (stalls[tid].iew) { 8007639Sgblack@eecs.umich.edu DPRINTF(Fetch,"[tid:%i]: Stall from IEW stage detected.\n",tid); 8017639Sgblack@eecs.umich.edu ret_val = true; 8027639Sgblack@eecs.umich.edu } else if (stalls[tid].commit) { 8037639Sgblack@eecs.umich.edu DPRINTF(Fetch,"[tid:%i]: Stall from Commit stage detected.\n",tid); 8047639Sgblack@eecs.umich.edu ret_val = true; 8057639Sgblack@eecs.umich.edu } 8067639Sgblack@eecs.umich.edu 8077639Sgblack@eecs.umich.edu return ret_val; 8087639Sgblack@eecs.umich.edu} 8097639Sgblack@eecs.umich.edu 8107639Sgblack@eecs.umich.edutemplate<class Impl> 8117639Sgblack@eecs.umich.edutypename DefaultFetch<Impl>::FetchStatus 8127639Sgblack@eecs.umich.eduDefaultFetch<Impl>::updateFetchStatus() 8137639Sgblack@eecs.umich.edu{ 8147639Sgblack@eecs.umich.edu //Check Running 8157639Sgblack@eecs.umich.edu list<ThreadID>::iterator threads = activeThreads->begin(); 8167639Sgblack@eecs.umich.edu list<ThreadID>::iterator end = activeThreads->end(); 8177639Sgblack@eecs.umich.edu 8187639Sgblack@eecs.umich.edu while (threads != end) { 8197639Sgblack@eecs.umich.edu ThreadID tid = *threads++; 8207639Sgblack@eecs.umich.edu 8217639Sgblack@eecs.umich.edu if (fetchStatus[tid] == Running || 8227639Sgblack@eecs.umich.edu fetchStatus[tid] == Squashing || 8237639Sgblack@eecs.umich.edu fetchStatus[tid] == IcacheAccessComplete) { 8247639Sgblack@eecs.umich.edu 8257639Sgblack@eecs.umich.edu if (_status == Inactive) { 8267639Sgblack@eecs.umich.edu DPRINTF(Activity, "[tid:%i]: Activating stage.\n",tid); 8277639Sgblack@eecs.umich.edu 8287639Sgblack@eecs.umich.edu if (fetchStatus[tid] == IcacheAccessComplete) { 8297639Sgblack@eecs.umich.edu DPRINTF(Activity, "[tid:%i]: Activating fetch due to cache" 8307639Sgblack@eecs.umich.edu "completion\n",tid); 8317639Sgblack@eecs.umich.edu } 8327639Sgblack@eecs.umich.edu 8337639Sgblack@eecs.umich.edu cpu->activateStage(O3CPU::FetchIdx); 8347639Sgblack@eecs.umich.edu } 8357639Sgblack@eecs.umich.edu 8367639Sgblack@eecs.umich.edu return Active; 8377639Sgblack@eecs.umich.edu } 8387639Sgblack@eecs.umich.edu } 8397639Sgblack@eecs.umich.edu 8407639Sgblack@eecs.umich.edu // Stage is switching from active to inactive, notify CPU of it. 8417639Sgblack@eecs.umich.edu if (_status == Active) { 8427639Sgblack@eecs.umich.edu DPRINTF(Activity, "Deactivating stage.\n"); 8437639Sgblack@eecs.umich.edu 8447639Sgblack@eecs.umich.edu cpu->deactivateStage(O3CPU::FetchIdx); 8457639Sgblack@eecs.umich.edu } 8467639Sgblack@eecs.umich.edu 8477639Sgblack@eecs.umich.edu return Inactive; 8487639Sgblack@eecs.umich.edu} 8497639Sgblack@eecs.umich.edu 8507639Sgblack@eecs.umich.edutemplate <class Impl> 8517639Sgblack@eecs.umich.eduvoid 8527639Sgblack@eecs.umich.eduDefaultFetch<Impl>::squash(const TheISA::PCState &newPC, 8537639Sgblack@eecs.umich.edu const InstSeqNum seq_num, DynInstPtr squashInst, 8547639Sgblack@eecs.umich.edu ThreadID tid) 8557639Sgblack@eecs.umich.edu{ 8567639Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n", tid); 8577639Sgblack@eecs.umich.edu 8587639Sgblack@eecs.umich.edu doSquash(newPC, squashInst, tid); 8597639Sgblack@eecs.umich.edu 8607639Sgblack@eecs.umich.edu // Tell the CPU to remove any instructions that are not in the ROB. 8617639Sgblack@eecs.umich.edu cpu->removeInstsNotInROB(tid); 8627639Sgblack@eecs.umich.edu} 8637639Sgblack@eecs.umich.edu 8647639Sgblack@eecs.umich.edutemplate <class Impl> 8657639Sgblack@eecs.umich.eduvoid 8667639Sgblack@eecs.umich.eduDefaultFetch<Impl>::tick() 8677639Sgblack@eecs.umich.edu{ 8687639Sgblack@eecs.umich.edu list<ThreadID>::iterator threads = activeThreads->begin(); 8697639Sgblack@eecs.umich.edu list<ThreadID>::iterator end = activeThreads->end(); 8707639Sgblack@eecs.umich.edu bool status_change = false; 8717639Sgblack@eecs.umich.edu 8727639Sgblack@eecs.umich.edu wroteToTimeBuffer = false; 8737639Sgblack@eecs.umich.edu 8747639Sgblack@eecs.umich.edu for (ThreadID i = 0; i < Impl::MaxThreads; ++i) { 8757639Sgblack@eecs.umich.edu issuePipelinedIfetch[i] = false; 8767639Sgblack@eecs.umich.edu } 8777639Sgblack@eecs.umich.edu 8787639Sgblack@eecs.umich.edu while (threads != end) { 8797639Sgblack@eecs.umich.edu ThreadID tid = *threads++; 8807639Sgblack@eecs.umich.edu 8817639Sgblack@eecs.umich.edu // Check the signals for each thread to determine the proper status 8827639Sgblack@eecs.umich.edu // for each thread. 8837639Sgblack@eecs.umich.edu bool updated_status = checkSignalsAndUpdate(tid); 8847639Sgblack@eecs.umich.edu status_change = status_change || updated_status; 8857639Sgblack@eecs.umich.edu } 8867639Sgblack@eecs.umich.edu 8877639Sgblack@eecs.umich.edu DPRINTF(Fetch, "Running stage.\n"); 8887639Sgblack@eecs.umich.edu 8897639Sgblack@eecs.umich.edu if (FullSystem) { 8907639Sgblack@eecs.umich.edu if (fromCommit->commitInfo[0].interruptPending) { 8917639Sgblack@eecs.umich.edu interruptPending = true; 8927639Sgblack@eecs.umich.edu } 8937639Sgblack@eecs.umich.edu 8947639Sgblack@eecs.umich.edu if (fromCommit->commitInfo[0].clearInterrupt) { 8957639Sgblack@eecs.umich.edu interruptPending = false; 8967639Sgblack@eecs.umich.edu } 8977639Sgblack@eecs.umich.edu } 8987639Sgblack@eecs.umich.edu 8997639Sgblack@eecs.umich.edu for (threadFetched = 0; threadFetched < numFetchingThreads; 9007639Sgblack@eecs.umich.edu threadFetched++) { 9017639Sgblack@eecs.umich.edu // Fetch each of the actively fetching threads. 9027639Sgblack@eecs.umich.edu fetch(status_change); 9037639Sgblack@eecs.umich.edu } 9047639Sgblack@eecs.umich.edu 9057639Sgblack@eecs.umich.edu // Record number of instructions fetched this cycle for distribution. 9067639Sgblack@eecs.umich.edu fetchNisnDist.sample(numInst); 9077639Sgblack@eecs.umich.edu 9087639Sgblack@eecs.umich.edu if (status_change) { 9097639Sgblack@eecs.umich.edu // Change the fetch stage status if there was a status change. 9107639Sgblack@eecs.umich.edu _status = updateFetchStatus(); 9117639Sgblack@eecs.umich.edu } 9127639Sgblack@eecs.umich.edu 9137639Sgblack@eecs.umich.edu // If there was activity this cycle, inform the CPU of it. 9147639Sgblack@eecs.umich.edu if (wroteToTimeBuffer || cpu->contextSwitch) { 9157639Sgblack@eecs.umich.edu DPRINTF(Activity, "Activity this cycle.\n"); 9167639Sgblack@eecs.umich.edu 9177639Sgblack@eecs.umich.edu cpu->activityThisCycle(); 9187639Sgblack@eecs.umich.edu } 9197639Sgblack@eecs.umich.edu 9207639Sgblack@eecs.umich.edu // Issue the next I-cache request if possible. 9217639Sgblack@eecs.umich.edu for (ThreadID i = 0; i < Impl::MaxThreads; ++i) { 9227639Sgblack@eecs.umich.edu if (issuePipelinedIfetch[i]) { 9237639Sgblack@eecs.umich.edu pipelineIcacheAccesses(i); 9247639Sgblack@eecs.umich.edu } 9257639Sgblack@eecs.umich.edu } 9267639Sgblack@eecs.umich.edu 9277639Sgblack@eecs.umich.edu // Reset the number of the instruction we've fetched. 9287639Sgblack@eecs.umich.edu numInst = 0; 9297639Sgblack@eecs.umich.edu} 9307639Sgblack@eecs.umich.edu 9317639Sgblack@eecs.umich.edutemplate <class Impl> 9327639Sgblack@eecs.umich.edubool 9337639Sgblack@eecs.umich.eduDefaultFetch<Impl>::checkSignalsAndUpdate(ThreadID tid) 9347639Sgblack@eecs.umich.edu{ 9357639Sgblack@eecs.umich.edu // Update the per thread stall statuses. 9367639Sgblack@eecs.umich.edu if (fromDecode->decodeBlock[tid]) { 93710037SARM gem5 Developers stalls[tid].decode = true; 93810037SARM gem5 Developers } 93910037SARM gem5 Developers 94010037SARM gem5 Developers if (fromDecode->decodeUnblock[tid]) { 94110037SARM gem5 Developers assert(stalls[tid].decode); 94210037SARM gem5 Developers assert(!fromDecode->decodeBlock[tid]); 94310037SARM gem5 Developers stalls[tid].decode = false; 94410037SARM gem5 Developers } 94510037SARM gem5 Developers 94610037SARM gem5 Developers if (fromRename->renameBlock[tid]) { 94710037SARM gem5 Developers stalls[tid].rename = true; 94810037SARM gem5 Developers } 94910037SARM gem5 Developers 95010037SARM gem5 Developers if (fromRename->renameUnblock[tid]) { 95110037SARM gem5 Developers assert(stalls[tid].rename); 95210037SARM gem5 Developers assert(!fromRename->renameBlock[tid]); 95310037SARM gem5 Developers stalls[tid].rename = false; 95410037SARM gem5 Developers } 95510037SARM gem5 Developers 95610037SARM gem5 Developers if (fromIEW->iewBlock[tid]) { 95710037SARM gem5 Developers stalls[tid].iew = true; 95810037SARM gem5 Developers } 95910037SARM gem5 Developers 96010037SARM gem5 Developers if (fromIEW->iewUnblock[tid]) { 96110037SARM gem5 Developers assert(stalls[tid].iew); 96210037SARM gem5 Developers assert(!fromIEW->iewBlock[tid]); 96310037SARM gem5 Developers stalls[tid].iew = false; 96410037SARM gem5 Developers } 96510037SARM gem5 Developers 96610037SARM gem5 Developers if (fromCommit->commitBlock[tid]) { 96710037SARM gem5 Developers stalls[tid].commit = true; 96810037SARM gem5 Developers } 96910037SARM gem5 Developers 97010037SARM gem5 Developers if (fromCommit->commitUnblock[tid]) { 97110037SARM gem5 Developers assert(stalls[tid].commit); 97210037SARM gem5 Developers assert(!fromCommit->commitBlock[tid]); 97310037SARM gem5 Developers stalls[tid].commit = false; 97410037SARM gem5 Developers } 97510037SARM gem5 Developers 97610037SARM gem5 Developers // Check squash signals from commit. 97710037SARM gem5 Developers if (fromCommit->commitInfo[tid].squash) { 97810037SARM gem5 Developers 97910037SARM gem5 Developers DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash " 98010037SARM gem5 Developers "from commit.\n",tid); 98110037SARM gem5 Developers // In any case, squash. 98210037SARM gem5 Developers squash(fromCommit->commitInfo[tid].pc, 98310037SARM gem5 Developers fromCommit->commitInfo[tid].doneSeqNum, 98410037SARM gem5 Developers fromCommit->commitInfo[tid].squashInst, tid); 98510037SARM gem5 Developers 98610037SARM gem5 Developers // If it was a branch mispredict on a control instruction, update the 98710037SARM gem5 Developers // branch predictor with that instruction, otherwise just kill the 98810037SARM gem5 Developers // invalid state we generated in after sequence number 98910037SARM gem5 Developers if (fromCommit->commitInfo[tid].mispredictInst && 99010037SARM gem5 Developers fromCommit->commitInfo[tid].mispredictInst->isControl()) { 99110037SARM gem5 Developers branchPred->squash(fromCommit->commitInfo[tid].doneSeqNum, 99210037SARM gem5 Developers fromCommit->commitInfo[tid].pc, 99310037SARM gem5 Developers fromCommit->commitInfo[tid].branchTaken, 99410037SARM gem5 Developers tid); 99510037SARM gem5 Developers } else { 99610037SARM gem5 Developers branchPred->squash(fromCommit->commitInfo[tid].doneSeqNum, 99710037SARM gem5 Developers tid); 99810037SARM gem5 Developers } 99910037SARM gem5 Developers 100010037SARM gem5 Developers return true; 100110037SARM gem5 Developers } else if (fromCommit->commitInfo[tid].doneSeqNum) { 100210037SARM gem5 Developers // Update the branch predictor if it wasn't a squashed instruction 100310037SARM gem5 Developers // that was broadcasted. 100410037SARM gem5 Developers branchPred->update(fromCommit->commitInfo[tid].doneSeqNum, tid); 100510037SARM gem5 Developers } 100610037SARM gem5 Developers 100710037SARM gem5 Developers // Check ROB squash signals from commit. 100810037SARM gem5 Developers if (fromCommit->commitInfo[tid].robSquashing) { 100910037SARM gem5 Developers DPRINTF(Fetch, "[tid:%u]: ROB is still squashing.\n", tid); 101010037SARM gem5 Developers 101110037SARM gem5 Developers // Continue to squash. 101210037SARM gem5 Developers fetchStatus[tid] = Squashing; 101310037SARM gem5 Developers 101410037SARM gem5 Developers return true; 101510037SARM gem5 Developers } 10167430Sgblack@eecs.umich.edu 10177430Sgblack@eecs.umich.edu // Check squash signals from decode. 10187430Sgblack@eecs.umich.edu if (fromDecode->decodeInfo[tid].squash) { 10197430Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash " 10207639Sgblack@eecs.umich.edu "from decode.\n",tid); 10217430Sgblack@eecs.umich.edu 10227430Sgblack@eecs.umich.edu // Update the branch predictor. 10237430Sgblack@eecs.umich.edu if (fromDecode->decodeInfo[tid].branchMispredict) { 10247430Sgblack@eecs.umich.edu branchPred->squash(fromDecode->decodeInfo[tid].doneSeqNum, 10257430Sgblack@eecs.umich.edu fromDecode->decodeInfo[tid].nextPC, 10267430Sgblack@eecs.umich.edu fromDecode->decodeInfo[tid].branchTaken, 10277430Sgblack@eecs.umich.edu tid); 10287430Sgblack@eecs.umich.edu } else { 10297430Sgblack@eecs.umich.edu branchPred->squash(fromDecode->decodeInfo[tid].doneSeqNum, 10307430Sgblack@eecs.umich.edu tid); 10317430Sgblack@eecs.umich.edu } 10327430Sgblack@eecs.umich.edu 10337430Sgblack@eecs.umich.edu if (fetchStatus[tid] != Squashing) { 10349515SAli.Saidi@ARM.com 10357430Sgblack@eecs.umich.edu DPRINTF(Fetch, "Squashing from decode with PC = %s\n", 10367430Sgblack@eecs.umich.edu fromDecode->decodeInfo[tid].nextPC); 10377430Sgblack@eecs.umich.edu // Squash unless we're already squashing 10387430Sgblack@eecs.umich.edu squashFromDecode(fromDecode->decodeInfo[tid].nextPC, 10397430Sgblack@eecs.umich.edu fromDecode->decodeInfo[tid].squashInst, 10407430Sgblack@eecs.umich.edu fromDecode->decodeInfo[tid].doneSeqNum, 10417639Sgblack@eecs.umich.edu tid); 10427430Sgblack@eecs.umich.edu 10437430Sgblack@eecs.umich.edu return true; 10447430Sgblack@eecs.umich.edu } 10457430Sgblack@eecs.umich.edu } 10467430Sgblack@eecs.umich.edu 10477430Sgblack@eecs.umich.edu if (checkStall(tid) && 10487430Sgblack@eecs.umich.edu fetchStatus[tid] != IcacheWaitResponse && 10497430Sgblack@eecs.umich.edu fetchStatus[tid] != IcacheWaitRetry && 10507430Sgblack@eecs.umich.edu fetchStatus[tid] != ItlbWait && 10517430Sgblack@eecs.umich.edu fetchStatus[tid] != QuiescePending) { 10527430Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%i]: Setting to blocked\n",tid); 10537430Sgblack@eecs.umich.edu 10547430Sgblack@eecs.umich.edu fetchStatus[tid] = Blocked; 10557430Sgblack@eecs.umich.edu 10567430Sgblack@eecs.umich.edu return true; 10577430Sgblack@eecs.umich.edu } 10587430Sgblack@eecs.umich.edu 10597430Sgblack@eecs.umich.edu if (fetchStatus[tid] == Blocked || 10607430Sgblack@eecs.umich.edu fetchStatus[tid] == Squashing) { 10617430Sgblack@eecs.umich.edu // Switch status to running if fetch isn't being told to block or 10627430Sgblack@eecs.umich.edu // squash this cycle. 10637430Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%i]: Done squashing, switching to running.\n", 10647430Sgblack@eecs.umich.edu tid); 10657430Sgblack@eecs.umich.edu 10667430Sgblack@eecs.umich.edu fetchStatus[tid] = Running; 10677430Sgblack@eecs.umich.edu 10687430Sgblack@eecs.umich.edu return true; 10697430Sgblack@eecs.umich.edu } 10707430Sgblack@eecs.umich.edu 10717430Sgblack@eecs.umich.edu // If we've reached this point, we have not gotten any signals that 10727430Sgblack@eecs.umich.edu // cause fetch to change its status. Fetch remains the same as before. 10737430Sgblack@eecs.umich.edu return false; 10747639Sgblack@eecs.umich.edu} 10757430Sgblack@eecs.umich.edu 10767430Sgblack@eecs.umich.edutemplate<class Impl> 10777430Sgblack@eecs.umich.edutypename Impl::DynInstPtr 10787430Sgblack@eecs.umich.eduDefaultFetch<Impl>::buildInst(ThreadID tid, StaticInstPtr staticInst, 10797430Sgblack@eecs.umich.edu StaticInstPtr curMacroop, TheISA::PCState thisPC, 10807430Sgblack@eecs.umich.edu TheISA::PCState nextPC, bool trace) 10817639Sgblack@eecs.umich.edu{ 10827430Sgblack@eecs.umich.edu // Get a sequence number. 10837430Sgblack@eecs.umich.edu InstSeqNum seq = cpu->getAndIncrementInstSeq(); 10847430Sgblack@eecs.umich.edu 10857639Sgblack@eecs.umich.edu // Create a new DynInst from the instruction fetched. 10867430Sgblack@eecs.umich.edu DynInstPtr instruction = 10877430Sgblack@eecs.umich.edu new DynInst(staticInst, curMacroop, thisPC, nextPC, seq, cpu); 10887430Sgblack@eecs.umich.edu instruction->setTid(tid); 10897430Sgblack@eecs.umich.edu 10907430Sgblack@eecs.umich.edu instruction->setASID(tid); 10917430Sgblack@eecs.umich.edu 10927430Sgblack@eecs.umich.edu instruction->setThreadState(cpu->thread[tid]); 10937430Sgblack@eecs.umich.edu 10947430Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%i]: Instruction PC %#x (%d) created " 10957430Sgblack@eecs.umich.edu "[sn:%lli].\n", tid, thisPC.instAddr(), 10967430Sgblack@eecs.umich.edu thisPC.microPC(), seq); 10977430Sgblack@eecs.umich.edu 10987430Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n", tid, 10997430Sgblack@eecs.umich.edu instruction->staticInst-> 11007430Sgblack@eecs.umich.edu disassemble(thisPC.instAddr())); 11017430Sgblack@eecs.umich.edu 11027430Sgblack@eecs.umich.edu#if TRACING_ON 11037430Sgblack@eecs.umich.edu if (trace) { 11049515SAli.Saidi@ARM.com instruction->traceData = 11057430Sgblack@eecs.umich.edu cpu->getTracer()->getInstRecord(curTick(), cpu->tcBase(tid), 11067430Sgblack@eecs.umich.edu instruction->staticInst, thisPC, curMacroop); 11077430Sgblack@eecs.umich.edu } 11087430Sgblack@eecs.umich.edu#else 11097430Sgblack@eecs.umich.edu instruction->traceData = NULL; 11107430Sgblack@eecs.umich.edu#endif 11117430Sgblack@eecs.umich.edu 11127430Sgblack@eecs.umich.edu // Add instruction to the CPU's list of instructions. 11137430Sgblack@eecs.umich.edu instruction->setInstListIt(cpu->addInst(instruction)); 11147430Sgblack@eecs.umich.edu 11157430Sgblack@eecs.umich.edu // Write the instruction to the first slot in the queue 11167430Sgblack@eecs.umich.edu // that heads to decode. 11177430Sgblack@eecs.umich.edu assert(numInst < fetchWidth); 11187430Sgblack@eecs.umich.edu toDecode->insts[toDecode->size++] = instruction; 11197430Sgblack@eecs.umich.edu 11207430Sgblack@eecs.umich.edu // Keep track of if we can take an interrupt at this boundary 11217430Sgblack@eecs.umich.edu delayedCommit[tid] = instruction->isDelayedCommit(); 11227430Sgblack@eecs.umich.edu 11237430Sgblack@eecs.umich.edu return instruction; 11247430Sgblack@eecs.umich.edu} 11257430Sgblack@eecs.umich.edu 11267430Sgblack@eecs.umich.edutemplate<class Impl> 11277430Sgblack@eecs.umich.eduvoid 11287430Sgblack@eecs.umich.eduDefaultFetch<Impl>::fetch(bool &status_change) 11297430Sgblack@eecs.umich.edu{ 11307430Sgblack@eecs.umich.edu ////////////////////////////////////////// 11317430Sgblack@eecs.umich.edu // Start actual fetch 11327430Sgblack@eecs.umich.edu ////////////////////////////////////////// 11337430Sgblack@eecs.umich.edu ThreadID tid = getFetchingThread(fetchPolicy); 11347639Sgblack@eecs.umich.edu 11357430Sgblack@eecs.umich.edu assert(!cpu->switchedOut()); 11367430Sgblack@eecs.umich.edu 11377430Sgblack@eecs.umich.edu if (tid == InvalidThreadID) { 11387430Sgblack@eecs.umich.edu // Breaks looping condition in tick() 11397430Sgblack@eecs.umich.edu threadFetched = numFetchingThreads; 11407430Sgblack@eecs.umich.edu 11417430Sgblack@eecs.umich.edu if (numThreads == 1) { // @todo Per-thread stats 11427430Sgblack@eecs.umich.edu profileStall(0); 11437430Sgblack@eecs.umich.edu } 11447430Sgblack@eecs.umich.edu 11457430Sgblack@eecs.umich.edu return; 11467430Sgblack@eecs.umich.edu } 11477430Sgblack@eecs.umich.edu 11487430Sgblack@eecs.umich.edu DPRINTF(Fetch, "Attempting to fetch from [tid:%i]\n", tid); 11497430Sgblack@eecs.umich.edu 11507430Sgblack@eecs.umich.edu // The current PC. 11517430Sgblack@eecs.umich.edu TheISA::PCState thisPC = pc[tid]; 11527430Sgblack@eecs.umich.edu 11537430Sgblack@eecs.umich.edu Addr pcOffset = fetchOffset[tid]; 11547430Sgblack@eecs.umich.edu Addr fetchAddr = (thisPC.instAddr() + pcOffset) & BaseCPU::PCMask; 11557430Sgblack@eecs.umich.edu 11567430Sgblack@eecs.umich.edu bool inRom = isRomMicroPC(thisPC.microPC()); 11577430Sgblack@eecs.umich.edu 11587430Sgblack@eecs.umich.edu // If returning from the delay of a cache miss, then update the status 11597430Sgblack@eecs.umich.edu // to running, otherwise do the cache access. Possibly move this up 11607430Sgblack@eecs.umich.edu // to tick() function. 11617430Sgblack@eecs.umich.edu if (fetchStatus[tid] == IcacheAccessComplete) { 11627430Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%i]: Icache miss is complete.\n", tid); 11637430Sgblack@eecs.umich.edu 11647430Sgblack@eecs.umich.edu fetchStatus[tid] = Running; 11657430Sgblack@eecs.umich.edu status_change = true; 11667430Sgblack@eecs.umich.edu } else if (fetchStatus[tid] == Running) { 11677430Sgblack@eecs.umich.edu // Align the fetch PC so its at the start of a fetch buffer segment. 11687430Sgblack@eecs.umich.edu Addr fetchBufferBlockPC = fetchBufferAlignPC(fetchAddr); 11697430Sgblack@eecs.umich.edu 11707430Sgblack@eecs.umich.edu // If buffer is no longer valid or fetchAddr has moved to point 11717430Sgblack@eecs.umich.edu // to the next cache block, AND we have no remaining ucode 11727430Sgblack@eecs.umich.edu // from a macro-op, then start fetch from icache. 11737430Sgblack@eecs.umich.edu if (!(fetchBufferValid[tid] && fetchBufferBlockPC == fetchBufferPC[tid]) 11747430Sgblack@eecs.umich.edu && !inRom && !macroop[tid]) { 11757430Sgblack@eecs.umich.edu DPRINTF(Fetch, "[tid:%i]: Attempting to translate and read " 11767430Sgblack@eecs.umich.edu "instruction, starting at PC %s.\n", tid, thisPC); 11777430Sgblack@eecs.umich.edu 11787430Sgblack@eecs.umich.edu fetchCacheLine(fetchAddr, tid, thisPC.instAddr()); 11797430Sgblack@eecs.umich.edu 11807430Sgblack@eecs.umich.edu if (fetchStatus[tid] == IcacheWaitResponse) 11817430Sgblack@eecs.umich.edu ++icacheStallCycles; 11827430Sgblack@eecs.umich.edu else if (fetchStatus[tid] == ItlbWait) 11837430Sgblack@eecs.umich.edu ++fetchTlbCycles; 11847430Sgblack@eecs.umich.edu else 11857430Sgblack@eecs.umich.edu ++fetchMiscStallCycles; 11867430Sgblack@eecs.umich.edu return; 11877430Sgblack@eecs.umich.edu } else if ((checkInterrupt(thisPC.instAddr()) && !delayedCommit[tid])) { 11887430Sgblack@eecs.umich.edu // Stall CPU if an interrupt is posted and we're not issuing 11897430Sgblack@eecs.umich.edu // an delayed commit micro-op currently (delayed commit instructions 1190 // are not interruptable by interrupts, only faults) 1191 ++fetchMiscStallCycles; 1192 DPRINTF(Fetch, "[tid:%i]: Fetch is stalled!\n", tid); 1193 return; 1194 } 1195 } else { 1196 if (fetchStatus[tid] == Idle) { 1197 ++fetchIdleCycles; 1198 DPRINTF(Fetch, "[tid:%i]: Fetch is idle!\n", tid); 1199 } 1200 1201 // Status is Idle, so fetch should do nothing. 1202 return; 1203 } 1204 1205 ++fetchCycles; 1206 1207 TheISA::PCState nextPC = thisPC; 1208 1209 StaticInstPtr staticInst = NULL; 1210 StaticInstPtr curMacroop = macroop[tid]; 1211 1212 // If the read of the first instruction was successful, then grab the 1213 // instructions from the rest of the cache line and put them into the 1214 // queue heading to decode. 1215 1216 DPRINTF(Fetch, "[tid:%i]: Adding instructions to queue to " 1217 "decode.\n", tid); 1218 1219 // Need to keep track of whether or not a predicted branch 1220 // ended this fetch block. 1221 bool predictedBranch = false; 1222 1223 TheISA::MachInst *cacheInsts = 1224 reinterpret_cast<TheISA::MachInst *>(fetchBuffer[tid]); 1225 1226 const unsigned numInsts = fetchBufferSize / instSize; 1227 unsigned blkOffset = (fetchAddr - fetchBufferPC[tid]) / instSize; 1228 1229 // Loop through instruction memory from the cache. 1230 // Keep issuing while fetchWidth is available and branch is not 1231 // predicted taken 1232 while (numInst < fetchWidth && !predictedBranch) { 1233 1234 // We need to process more memory if we aren't going to get a 1235 // StaticInst from the rom, the current macroop, or what's already 1236 // in the decoder. 1237 bool needMem = !inRom && !curMacroop && 1238 !decoder[tid]->instReady(); 1239 fetchAddr = (thisPC.instAddr() + pcOffset) & BaseCPU::PCMask; 1240 Addr fetchBufferBlockPC = fetchBufferAlignPC(fetchAddr); 1241 1242 if (needMem) { 1243 // If buffer is no longer valid or fetchAddr has moved to point 1244 // to the next cache block then start fetch from icache. 1245 if (!fetchBufferValid[tid] || 1246 fetchBufferBlockPC != fetchBufferPC[tid]) 1247 break; 1248 1249 if (blkOffset >= numInsts) { 1250 // We need to process more memory, but we've run out of the 1251 // current block. 1252 break; 1253 } 1254 1255 if (ISA_HAS_DELAY_SLOT && pcOffset == 0) { 1256 // Walk past any annulled delay slot instructions. 1257 Addr pcAddr = thisPC.instAddr() & BaseCPU::PCMask; 1258 while (fetchAddr != pcAddr && blkOffset < numInsts) { 1259 blkOffset++; 1260 fetchAddr += instSize; 1261 } 1262 if (blkOffset >= numInsts) 1263 break; 1264 } 1265 1266 MachInst inst = TheISA::gtoh(cacheInsts[blkOffset]); 1267 decoder[tid]->moreBytes(thisPC, fetchAddr, inst); 1268 1269 if (decoder[tid]->needMoreBytes()) { 1270 blkOffset++; 1271 fetchAddr += instSize; 1272 pcOffset += instSize; 1273 } 1274 } 1275 1276 // Extract as many instructions and/or microops as we can from 1277 // the memory we've processed so far. 1278 do { 1279 if (!(curMacroop || inRom)) { 1280 if (decoder[tid]->instReady()) { 1281 staticInst = decoder[tid]->decode(thisPC); 1282 1283 // Increment stat of fetched instructions. 1284 ++fetchedInsts; 1285 1286 if (staticInst->isMacroop()) { 1287 curMacroop = staticInst; 1288 } else { 1289 pcOffset = 0; 1290 } 1291 } else { 1292 // We need more bytes for this instruction so blkOffset and 1293 // pcOffset will be updated 1294 break; 1295 } 1296 } 1297 // Whether we're moving to a new macroop because we're at the 1298 // end of the current one, or the branch predictor incorrectly 1299 // thinks we are... 1300 bool newMacro = false; 1301 if (curMacroop || inRom) { 1302 if (inRom) { 1303 staticInst = cpu->microcodeRom.fetchMicroop( 1304 thisPC.microPC(), curMacroop); 1305 } else { 1306 staticInst = curMacroop->fetchMicroop(thisPC.microPC()); 1307 } 1308 newMacro |= staticInst->isLastMicroop(); 1309 } 1310 1311 DynInstPtr instruction = 1312 buildInst(tid, staticInst, curMacroop, 1313 thisPC, nextPC, true); 1314 1315 numInst++; 1316 1317#if TRACING_ON 1318 if (DTRACE(O3PipeView)) { 1319 instruction->fetchTick = curTick(); 1320 } 1321#endif 1322 1323 nextPC = thisPC; 1324 1325 // If we're branching after this instruction, quite fetching 1326 // from the same block then. 1327 predictedBranch |= thisPC.branching(); 1328 predictedBranch |= 1329 lookupAndUpdateNextPC(instruction, nextPC); 1330 if (predictedBranch) { 1331 DPRINTF(Fetch, "Branch detected with PC = %s\n", thisPC); 1332 } 1333 1334 newMacro |= thisPC.instAddr() != nextPC.instAddr(); 1335 1336 // Move to the next instruction, unless we have a branch. 1337 thisPC = nextPC; 1338 inRom = isRomMicroPC(thisPC.microPC()); 1339 1340 if (newMacro) { 1341 fetchAddr = thisPC.instAddr() & BaseCPU::PCMask; 1342 blkOffset = (fetchAddr - fetchBufferPC[tid]) / instSize; 1343 pcOffset = 0; 1344 curMacroop = NULL; 1345 } 1346 1347 if (instruction->isQuiesce()) { 1348 DPRINTF(Fetch, 1349 "Quiesce instruction encountered, halting fetch!"); 1350 fetchStatus[tid] = QuiescePending; 1351 status_change = true; 1352 break; 1353 } 1354 } while ((curMacroop || decoder[tid]->instReady()) && 1355 numInst < fetchWidth); 1356 } 1357 1358 if (predictedBranch) { 1359 DPRINTF(Fetch, "[tid:%i]: Done fetching, predicted branch " 1360 "instruction encountered.\n", tid); 1361 } else if (numInst >= fetchWidth) { 1362 DPRINTF(Fetch, "[tid:%i]: Done fetching, reached fetch bandwidth " 1363 "for this cycle.\n", tid); 1364 } else if (blkOffset >= fetchBufferSize) { 1365 DPRINTF(Fetch, "[tid:%i]: Done fetching, reached the end of the" 1366 "fetch buffer.\n", tid); 1367 } 1368 1369 macroop[tid] = curMacroop; 1370 fetchOffset[tid] = pcOffset; 1371 1372 if (numInst > 0) { 1373 wroteToTimeBuffer = true; 1374 } 1375 1376 pc[tid] = thisPC; 1377 1378 // pipeline a fetch if we're crossing a fetch buffer boundary and not in 1379 // a state that would preclude fetching 1380 fetchAddr = (thisPC.instAddr() + pcOffset) & BaseCPU::PCMask; 1381 Addr fetchBufferBlockPC = fetchBufferAlignPC(fetchAddr); 1382 issuePipelinedIfetch[tid] = fetchBufferBlockPC != fetchBufferPC[tid] && 1383 fetchStatus[tid] != IcacheWaitResponse && 1384 fetchStatus[tid] != ItlbWait && 1385 fetchStatus[tid] != IcacheWaitRetry && 1386 fetchStatus[tid] != QuiescePending && 1387 !curMacroop; 1388} 1389 1390template<class Impl> 1391void 1392DefaultFetch<Impl>::recvRetry() 1393{ 1394 if (retryPkt != NULL) { 1395 assert(cacheBlocked); 1396 assert(retryTid != InvalidThreadID); 1397 assert(fetchStatus[retryTid] == IcacheWaitRetry); 1398 1399 if (cpu->getInstPort().sendTimingReq(retryPkt)) { 1400 fetchStatus[retryTid] = IcacheWaitResponse; 1401 retryPkt = NULL; 1402 retryTid = InvalidThreadID; 1403 cacheBlocked = false; 1404 } 1405 } else { 1406 assert(retryTid == InvalidThreadID); 1407 // Access has been squashed since it was sent out. Just clear 1408 // the cache being blocked. 1409 cacheBlocked = false; 1410 } 1411} 1412 1413/////////////////////////////////////// 1414// // 1415// SMT FETCH POLICY MAINTAINED HERE // 1416// // 1417/////////////////////////////////////// 1418template<class Impl> 1419ThreadID 1420DefaultFetch<Impl>::getFetchingThread(FetchPriority &fetch_priority) 1421{ 1422 if (numThreads > 1) { 1423 switch (fetch_priority) { 1424 1425 case SingleThread: 1426 return 0; 1427 1428 case RoundRobin: 1429 return roundRobin(); 1430 1431 case IQ: 1432 return iqCount(); 1433 1434 case LSQ: 1435 return lsqCount(); 1436 1437 case Branch: 1438 return branchCount(); 1439 1440 default: 1441 return InvalidThreadID; 1442 } 1443 } else { 1444 list<ThreadID>::iterator thread = activeThreads->begin(); 1445 if (thread == activeThreads->end()) { 1446 return InvalidThreadID; 1447 } 1448 1449 ThreadID tid = *thread; 1450 1451 if (fetchStatus[tid] == Running || 1452 fetchStatus[tid] == IcacheAccessComplete || 1453 fetchStatus[tid] == Idle) { 1454 return tid; 1455 } else { 1456 return InvalidThreadID; 1457 } 1458 } 1459} 1460 1461 1462template<class Impl> 1463ThreadID 1464DefaultFetch<Impl>::roundRobin() 1465{ 1466 list<ThreadID>::iterator pri_iter = priorityList.begin(); 1467 list<ThreadID>::iterator end = priorityList.end(); 1468 1469 ThreadID high_pri; 1470 1471 while (pri_iter != end) { 1472 high_pri = *pri_iter; 1473 1474 assert(high_pri <= numThreads); 1475 1476 if (fetchStatus[high_pri] == Running || 1477 fetchStatus[high_pri] == IcacheAccessComplete || 1478 fetchStatus[high_pri] == Idle) { 1479 1480 priorityList.erase(pri_iter); 1481 priorityList.push_back(high_pri); 1482 1483 return high_pri; 1484 } 1485 1486 pri_iter++; 1487 } 1488 1489 return InvalidThreadID; 1490} 1491 1492template<class Impl> 1493ThreadID 1494DefaultFetch<Impl>::iqCount() 1495{ 1496 std::priority_queue<unsigned> PQ; 1497 std::map<unsigned, ThreadID> threadMap; 1498 1499 list<ThreadID>::iterator threads = activeThreads->begin(); 1500 list<ThreadID>::iterator end = activeThreads->end(); 1501 1502 while (threads != end) { 1503 ThreadID tid = *threads++; 1504 unsigned iqCount = fromIEW->iewInfo[tid].iqCount; 1505 1506 PQ.push(iqCount); 1507 threadMap[iqCount] = tid; 1508 } 1509 1510 while (!PQ.empty()) { 1511 ThreadID high_pri = threadMap[PQ.top()]; 1512 1513 if (fetchStatus[high_pri] == Running || 1514 fetchStatus[high_pri] == IcacheAccessComplete || 1515 fetchStatus[high_pri] == Idle) 1516 return high_pri; 1517 else 1518 PQ.pop(); 1519 1520 } 1521 1522 return InvalidThreadID; 1523} 1524 1525template<class Impl> 1526ThreadID 1527DefaultFetch<Impl>::lsqCount() 1528{ 1529 std::priority_queue<unsigned> PQ; 1530 std::map<unsigned, ThreadID> threadMap; 1531 1532 list<ThreadID>::iterator threads = activeThreads->begin(); 1533 list<ThreadID>::iterator end = activeThreads->end(); 1534 1535 while (threads != end) { 1536 ThreadID tid = *threads++; 1537 unsigned ldstqCount = fromIEW->iewInfo[tid].ldstqCount; 1538 1539 PQ.push(ldstqCount); 1540 threadMap[ldstqCount] = tid; 1541 } 1542 1543 while (!PQ.empty()) { 1544 ThreadID high_pri = threadMap[PQ.top()]; 1545 1546 if (fetchStatus[high_pri] == Running || 1547 fetchStatus[high_pri] == IcacheAccessComplete || 1548 fetchStatus[high_pri] == Idle) 1549 return high_pri; 1550 else 1551 PQ.pop(); 1552 } 1553 1554 return InvalidThreadID; 1555} 1556 1557template<class Impl> 1558ThreadID 1559DefaultFetch<Impl>::branchCount() 1560{ 1561#if 0 1562 list<ThreadID>::iterator thread = activeThreads->begin(); 1563 assert(thread != activeThreads->end()); 1564 ThreadID tid = *thread; 1565#endif 1566 1567 panic("Branch Count Fetch policy unimplemented\n"); 1568 return InvalidThreadID; 1569} 1570 1571template<class Impl> 1572void 1573DefaultFetch<Impl>::pipelineIcacheAccesses(ThreadID tid) 1574{ 1575 if (!issuePipelinedIfetch[tid]) { 1576 return; 1577 } 1578 1579 // The next PC to access. 1580 TheISA::PCState thisPC = pc[tid]; 1581 1582 if (isRomMicroPC(thisPC.microPC())) { 1583 return; 1584 } 1585 1586 Addr pcOffset = fetchOffset[tid]; 1587 Addr fetchAddr = (thisPC.instAddr() + pcOffset) & BaseCPU::PCMask; 1588 1589 // Align the fetch PC so its at the start of a fetch buffer segment. 1590 Addr fetchBufferBlockPC = fetchBufferAlignPC(fetchAddr); 1591 1592 // Unless buffer already got the block, fetch it from icache. 1593 if (!(fetchBufferValid[tid] && fetchBufferBlockPC == fetchBufferPC[tid])) { 1594 DPRINTF(Fetch, "[tid:%i]: Issuing a pipelined I-cache access, " 1595 "starting at PC %s.\n", tid, thisPC); 1596 1597 fetchCacheLine(fetchAddr, tid, thisPC.instAddr()); 1598 } 1599} 1600 1601template<class Impl> 1602void 1603DefaultFetch<Impl>::profileStall(ThreadID tid) { 1604 DPRINTF(Fetch,"There are no more threads available to fetch from.\n"); 1605 1606 // @todo Per-thread stats 1607 1608 if (stalls[tid].drain) { 1609 ++fetchPendingDrainCycles; 1610 DPRINTF(Fetch, "Fetch is waiting for a drain!\n"); 1611 } else if (activeThreads->empty()) { 1612 ++fetchNoActiveThreadStallCycles; 1613 DPRINTF(Fetch, "Fetch has no active thread!\n"); 1614 } else if (fetchStatus[tid] == Blocked) { 1615 ++fetchBlockedCycles; 1616 DPRINTF(Fetch, "[tid:%i]: Fetch is blocked!\n", tid); 1617 } else if (fetchStatus[tid] == Squashing) { 1618 ++fetchSquashCycles; 1619 DPRINTF(Fetch, "[tid:%i]: Fetch is squashing!\n", tid); 1620 } else if (fetchStatus[tid] == IcacheWaitResponse) { 1621 ++icacheStallCycles; 1622 DPRINTF(Fetch, "[tid:%i]: Fetch is waiting cache response!\n", 1623 tid); 1624 } else if (fetchStatus[tid] == ItlbWait) { 1625 ++fetchTlbCycles; 1626 DPRINTF(Fetch, "[tid:%i]: Fetch is waiting ITLB walk to " 1627 "finish!\n", tid); 1628 } else if (fetchStatus[tid] == TrapPending) { 1629 ++fetchPendingTrapStallCycles; 1630 DPRINTF(Fetch, "[tid:%i]: Fetch is waiting for a pending trap!\n", 1631 tid); 1632 } else if (fetchStatus[tid] == QuiescePending) { 1633 ++fetchPendingQuiesceStallCycles; 1634 DPRINTF(Fetch, "[tid:%i]: Fetch is waiting for a pending quiesce " 1635 "instruction!\n", tid); 1636 } else if (fetchStatus[tid] == IcacheWaitRetry) { 1637 ++fetchIcacheWaitRetryStallCycles; 1638 DPRINTF(Fetch, "[tid:%i]: Fetch is waiting for an I-cache retry!\n", 1639 tid); 1640 } else if (fetchStatus[tid] == NoGoodAddr) { 1641 DPRINTF(Fetch, "[tid:%i]: Fetch predicted non-executable address\n", 1642 tid); 1643 } else { 1644 DPRINTF(Fetch, "[tid:%i]: Unexpected fetch stall reason (Status: %i).\n", 1645 tid, fetchStatus[tid]); 1646 } 1647} 1648 1649#endif//__CPU_O3_FETCH_IMPL_HH__ 1650