mshr.hh revision 13351
12810SN/A/* 212599Snikos.nikoleris@arm.com * Copyright (c) 2012-2013, 2015-2016, 2018 ARM Limited 39663Suri.wiener@arm.com * All rights reserved. 49663Suri.wiener@arm.com * 59663Suri.wiener@arm.com * The license below extends only to copyright in the software and shall 69663Suri.wiener@arm.com * not be construed as granting a license to any other intellectual 79663Suri.wiener@arm.com * property including but not limited to intellectual property relating 89663Suri.wiener@arm.com * to a hardware implementation of the functionality of the software 99663Suri.wiener@arm.com * licensed hereunder. You may use the software subject to the license 109663Suri.wiener@arm.com * terms below provided that you ensure that this notice is replicated 119663Suri.wiener@arm.com * unmodified and in its entirety in all distributions of the software, 129663Suri.wiener@arm.com * modified or unmodified, in source code or in binary form. 139663Suri.wiener@arm.com * 142810SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 152810SN/A * All rights reserved. 162810SN/A * 172810SN/A * Redistribution and use in source and binary forms, with or without 182810SN/A * modification, are permitted provided that the following conditions are 192810SN/A * met: redistributions of source code must retain the above copyright 202810SN/A * notice, this list of conditions and the following disclaimer; 212810SN/A * redistributions in binary form must reproduce the above copyright 222810SN/A * notice, this list of conditions and the following disclaimer in the 232810SN/A * documentation and/or other materials provided with the distribution; 242810SN/A * neither the name of the copyright holders nor the names of its 252810SN/A * contributors may be used to endorse or promote products derived from 262810SN/A * this software without specific prior written permission. 272810SN/A * 282810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 312810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 322810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 342810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 352810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 372810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 382810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392810SN/A * 402810SN/A * Authors: Erik Hallnor 4113349Snikos.nikoleris@arm.com * Nikos Nikoleris 422810SN/A */ 432810SN/A 442810SN/A/** 452810SN/A * @file 462810SN/A * Miss Status and Handling Register (MSHR) declaration. 472810SN/A */ 482810SN/A 4910764Sandreas.hansson@arm.com#ifndef __MEM_CACHE_MSHR_HH__ 5010764Sandreas.hansson@arm.com#define __MEM_CACHE_MSHR_HH__ 512810SN/A 5212727Snikos.nikoleris@arm.com#include <cassert> 5312727Snikos.nikoleris@arm.com#include <iosfwd> 544626SN/A#include <list> 5512727Snikos.nikoleris@arm.com#include <string> 5613349Snikos.nikoleris@arm.com#include <vector> 574626SN/A 585314SN/A#include "base/printable.hh" 5912727Snikos.nikoleris@arm.com#include "base/types.hh" 6011375Sandreas.hansson@arm.com#include "mem/cache/queue_entry.hh" 6112727Snikos.nikoleris@arm.com#include "mem/packet.hh" 6213349Snikos.nikoleris@arm.com#include "mem/request.hh" 6312727Snikos.nikoleris@arm.com#include "sim/core.hh" 642810SN/A 6512724Snikos.nikoleris@arm.comclass BaseCache; 662810SN/A 672810SN/A/** 682810SN/A * Miss Status and handling Register. This class keeps all the information 693374SN/A * needed to handle a cache miss including a list of target requests. 709264Sdjordje.kovacevic@arm.com * @sa \ref gem5MemorySystem "gem5 Memory System" 712810SN/A */ 7211375Sandreas.hansson@arm.comclass MSHR : public QueueEntry, public Printable 734626SN/A{ 744626SN/A 759725Sandreas.hansson@arm.com /** 7611375Sandreas.hansson@arm.com * Consider the queues friends to avoid making everything public. 779725Sandreas.hansson@arm.com */ 7811375Sandreas.hansson@arm.com template<typename Entry> 7911375Sandreas.hansson@arm.com friend class Queue; 809725Sandreas.hansson@arm.com friend class MSHRQueue; 819725Sandreas.hansson@arm.com 829725Sandreas.hansson@arm.com private: 839725Sandreas.hansson@arm.com 849725Sandreas.hansson@arm.com /** Flag set by downstream caches */ 859725Sandreas.hansson@arm.com bool downstreamPending; 869725Sandreas.hansson@arm.com 8711284Sandreas.hansson@arm.com /** 8811284Sandreas.hansson@arm.com * Here we use one flag to track both if: 8911284Sandreas.hansson@arm.com * 9011284Sandreas.hansson@arm.com * 1. We are going to become owner or not, i.e., we will get the 9111284Sandreas.hansson@arm.com * block in an ownership state (Owned or Modified) with BlkDirty 9211284Sandreas.hansson@arm.com * set. This determines whether or not we are going to become the 9311284Sandreas.hansson@arm.com * responder and ordering point for future requests that we snoop. 9411284Sandreas.hansson@arm.com * 9511284Sandreas.hansson@arm.com * 2. We know that we are going to get a writable block, i.e. we 9611284Sandreas.hansson@arm.com * will get the block in writable state (Exclusive or Modified 9711284Sandreas.hansson@arm.com * state) with BlkWritable set. That determines whether additional 9811284Sandreas.hansson@arm.com * targets with needsWritable set will be able to be satisfied, or 9911284Sandreas.hansson@arm.com * if not should be put on the deferred list to possibly wait for 10011284Sandreas.hansson@arm.com * another request that does give us writable access. 10111284Sandreas.hansson@arm.com * 10211284Sandreas.hansson@arm.com * Condition 2 is actually just a shortcut that saves us from 10311284Sandreas.hansson@arm.com * possibly building a deferred target list and calling 10411284Sandreas.hansson@arm.com * promoteWritable() every time we get a writable block. Condition 10511284Sandreas.hansson@arm.com * 1, tracking ownership, is what is important. However, we never 10611284Sandreas.hansson@arm.com * receive ownership without marking the block dirty, and 10711284Sandreas.hansson@arm.com * consequently use pendingModified to track both ownership and 10811284Sandreas.hansson@arm.com * writability rather than having separate pendingDirty and 10911284Sandreas.hansson@arm.com * pendingWritable flags. 11011284Sandreas.hansson@arm.com */ 11111284Sandreas.hansson@arm.com bool pendingModified; 1129725Sandreas.hansson@arm.com 1139725Sandreas.hansson@arm.com /** Did we snoop an invalidate while waiting for data? */ 1149725Sandreas.hansson@arm.com bool postInvalidate; 1159725Sandreas.hansson@arm.com 1169725Sandreas.hansson@arm.com /** Did we snoop a read while waiting for data? */ 1179725Sandreas.hansson@arm.com bool postDowngrade; 1189725Sandreas.hansson@arm.com 1192810SN/A public: 1204626SN/A 12113349Snikos.nikoleris@arm.com /** Track if we sent this as a whole line write or not */ 12213349Snikos.nikoleris@arm.com bool wasWholeLineWrite; 12313349Snikos.nikoleris@arm.com 12411375Sandreas.hansson@arm.com /** True if the entry is just a simple forward from an upper level */ 12511375Sandreas.hansson@arm.com bool isForward; 12611375Sandreas.hansson@arm.com 1274626SN/A class Target { 1284626SN/A public: 1295875Ssteve.reinhardt@amd.com 1305875Ssteve.reinhardt@amd.com enum Source { 1315875Ssteve.reinhardt@amd.com FromCPU, 1325875Ssteve.reinhardt@amd.com FromSnoop, 1335875Ssteve.reinhardt@amd.com FromPrefetcher 1345875Ssteve.reinhardt@amd.com }; 1355875Ssteve.reinhardt@amd.com 13610766Sandreas.hansson@arm.com const Tick recvTime; //!< Time when request was received (for stats) 13710766Sandreas.hansson@arm.com const Tick readyTime; //!< Time when request is ready to be serviced 13810766Sandreas.hansson@arm.com const Counter order; //!< Global order (for memory consistency mgmt) 13910766Sandreas.hansson@arm.com const PacketPtr pkt; //!< Pending request packet. 14010766Sandreas.hansson@arm.com const Source source; //!< Request from cpu, memory, or prefetcher? 14111742Snikos.nikoleris@arm.com 14211742Snikos.nikoleris@arm.com /** 14311742Snikos.nikoleris@arm.com * We use this flag to track whether we have cleared the 14411742Snikos.nikoleris@arm.com * downstreamPending flag for the MSHR of the cache above 14511742Snikos.nikoleris@arm.com * where this packet originates from and guard noninitial 14611742Snikos.nikoleris@arm.com * attempts to clear it. 14711742Snikos.nikoleris@arm.com * 14811742Snikos.nikoleris@arm.com * The flag markedPending needs to be updated when the 14911742Snikos.nikoleris@arm.com * TargetList is in service which can be: 15011742Snikos.nikoleris@arm.com * 1) during the Target instantiation if the MSHR is in 15111742Snikos.nikoleris@arm.com * service and the target is not deferred, 15211742Snikos.nikoleris@arm.com * 2) when the MSHR becomes in service if the target is not 15311742Snikos.nikoleris@arm.com * deferred, 15411742Snikos.nikoleris@arm.com * 3) or when the TargetList is promoted (deferredTargets -> 15511742Snikos.nikoleris@arm.com * targets). 15611742Snikos.nikoleris@arm.com */ 15711742Snikos.nikoleris@arm.com bool markedPending; 15811742Snikos.nikoleris@arm.com 15911741Snikos.nikoleris@arm.com const bool allocOnFill; //!< Should the response servicing this 16011741Snikos.nikoleris@arm.com //!< target list allocate in the cache? 1614626SN/A 1625318SN/A Target(PacketPtr _pkt, Tick _readyTime, Counter _order, 16311741Snikos.nikoleris@arm.com Source _source, bool _markedPending, bool alloc_on_fill) 1647823Ssteve.reinhardt@amd.com : recvTime(curTick()), readyTime(_readyTime), order(_order), 16511741Snikos.nikoleris@arm.com pkt(_pkt), source(_source), markedPending(_markedPending), 16611741Snikos.nikoleris@arm.com allocOnFill(alloc_on_fill) 1674626SN/A {} 1684626SN/A }; 1694626SN/A 1704903SN/A class TargetList : public std::list<Target> { 1714903SN/A 1724903SN/A public: 17311284Sandreas.hansson@arm.com bool needsWritable; 1744903SN/A bool hasUpgrade; 17511741Snikos.nikoleris@arm.com /** Set when the response should allocate on fill */ 17611741Snikos.nikoleris@arm.com bool allocOnFill; 17712715Snikos.nikoleris@arm.com /** 17812715Snikos.nikoleris@arm.com * Determine whether there was at least one non-snooping 17912715Snikos.nikoleris@arm.com * target coming from another cache. 18012715Snikos.nikoleris@arm.com */ 18112715Snikos.nikoleris@arm.com bool hasFromCache; 1824903SN/A 1834903SN/A TargetList(); 18411740Snikos.nikoleris@arm.com 18511740Snikos.nikoleris@arm.com /** 18611740Snikos.nikoleris@arm.com * Use the provided packet and the source to update the 18711740Snikos.nikoleris@arm.com * flags of this TargetList. 18811740Snikos.nikoleris@arm.com * 18911740Snikos.nikoleris@arm.com * @param pkt Packet considered for the flag update 19011740Snikos.nikoleris@arm.com * @param source Indicates the source of the packet 19111741Snikos.nikoleris@arm.com * @param alloc_on_fill Whether the pkt would allocate on a fill 19211740Snikos.nikoleris@arm.com */ 19311741Snikos.nikoleris@arm.com void updateFlags(PacketPtr pkt, Target::Source source, 19411741Snikos.nikoleris@arm.com bool alloc_on_fill); 19511740Snikos.nikoleris@arm.com 19613349Snikos.nikoleris@arm.com /** 19713349Snikos.nikoleris@arm.com * Reset state 19813349Snikos.nikoleris@arm.com * 19913349Snikos.nikoleris@arm.com * @param blk_addr Address of the cache block 20013349Snikos.nikoleris@arm.com * @param blk_size Size of the cache block 20113349Snikos.nikoleris@arm.com */ 20213349Snikos.nikoleris@arm.com void init(Addr blk_addr, Addr blk_size) { 20313349Snikos.nikoleris@arm.com blkAddr = blk_addr; 20413349Snikos.nikoleris@arm.com blkSize = blk_size; 20513349Snikos.nikoleris@arm.com writesBitmap.resize(blk_size); 20613349Snikos.nikoleris@arm.com 20713349Snikos.nikoleris@arm.com resetFlags(); 20813349Snikos.nikoleris@arm.com } 20913349Snikos.nikoleris@arm.com 21012715Snikos.nikoleris@arm.com void resetFlags() { 21113349Snikos.nikoleris@arm.com onlyWrites = true; 21213349Snikos.nikoleris@arm.com std::fill(writesBitmap.begin(), writesBitmap.end(), false); 21313349Snikos.nikoleris@arm.com 21412715Snikos.nikoleris@arm.com needsWritable = false; 21512715Snikos.nikoleris@arm.com hasUpgrade = false; 21612715Snikos.nikoleris@arm.com allocOnFill = false; 21712715Snikos.nikoleris@arm.com hasFromCache = false; 21812715Snikos.nikoleris@arm.com } 21911740Snikos.nikoleris@arm.com 22011740Snikos.nikoleris@arm.com /** 22111740Snikos.nikoleris@arm.com * Goes through the list of targets and uses them to populate 22211740Snikos.nikoleris@arm.com * the flags of this TargetList. When the function returns the 22311740Snikos.nikoleris@arm.com * flags are consistent with the properties of packets in the 22411740Snikos.nikoleris@arm.com * list. 22511740Snikos.nikoleris@arm.com */ 22611740Snikos.nikoleris@arm.com void populateFlags(); 22711740Snikos.nikoleris@arm.com 22811741Snikos.nikoleris@arm.com /** 22913349Snikos.nikoleris@arm.com * Add the specified packet in the TargetList. This function 23013349Snikos.nikoleris@arm.com * stores information related to the added packet and updates 23113349Snikos.nikoleris@arm.com * accordingly the flags. 23213349Snikos.nikoleris@arm.com * 23313349Snikos.nikoleris@arm.com * @param pkt Packet considered for adding 23413349Snikos.nikoleris@arm.com */ 23513349Snikos.nikoleris@arm.com void updateWriteFlags(PacketPtr pkt) { 23613349Snikos.nikoleris@arm.com const Request::FlagsType noMergeFlags = 23713349Snikos.nikoleris@arm.com Request::UNCACHEABLE | 23813349Snikos.nikoleris@arm.com Request::STRICT_ORDER | Request::MMAPPED_IPR | 23913349Snikos.nikoleris@arm.com Request::PRIVILEGED | Request::LLSC | 24013349Snikos.nikoleris@arm.com Request::MEM_SWAP | Request::MEM_SWAP_COND | 24113349Snikos.nikoleris@arm.com Request::SECURE; 24213349Snikos.nikoleris@arm.com 24313349Snikos.nikoleris@arm.com // if we have already seen writes for the full block stop 24413349Snikos.nikoleris@arm.com // here, this might be a full line write followed by 24513349Snikos.nikoleris@arm.com // other compatible requests (e.g., reads) 24613349Snikos.nikoleris@arm.com if (!isWholeLineWrite()) { 24713349Snikos.nikoleris@arm.com bool can_merge_write = pkt->isWrite() && 24813349Snikos.nikoleris@arm.com ((pkt->req->getFlags() & noMergeFlags) == 0); 24913349Snikos.nikoleris@arm.com onlyWrites &= can_merge_write; 25013349Snikos.nikoleris@arm.com if (onlyWrites) { 25113349Snikos.nikoleris@arm.com auto offset = pkt->getOffset(blkSize); 25213349Snikos.nikoleris@arm.com auto begin = writesBitmap.begin() + offset; 25313349Snikos.nikoleris@arm.com std::fill(begin, begin + pkt->getSize(), true); 25413349Snikos.nikoleris@arm.com } 25513349Snikos.nikoleris@arm.com } 25613349Snikos.nikoleris@arm.com } 25713349Snikos.nikoleris@arm.com 25813349Snikos.nikoleris@arm.com /** 25911741Snikos.nikoleris@arm.com * Tests if the flags of this TargetList have their default 26011741Snikos.nikoleris@arm.com * values. 26113349Snikos.nikoleris@arm.com * 26213349Snikos.nikoleris@arm.com * @return True if the TargetList are reset, false otherwise. 26311741Snikos.nikoleris@arm.com */ 26411741Snikos.nikoleris@arm.com bool isReset() const { 26512715Snikos.nikoleris@arm.com return !needsWritable && !hasUpgrade && !allocOnFill && 26613349Snikos.nikoleris@arm.com !hasFromCache && onlyWrites; 26711741Snikos.nikoleris@arm.com } 26811741Snikos.nikoleris@arm.com 26911741Snikos.nikoleris@arm.com /** 27011741Snikos.nikoleris@arm.com * Add the specified packet in the TargetList. This function 27111741Snikos.nikoleris@arm.com * stores information related to the added packet and updates 27211741Snikos.nikoleris@arm.com * accordingly the flags. 27311741Snikos.nikoleris@arm.com * 27411741Snikos.nikoleris@arm.com * @param pkt Packet considered for adding 27511741Snikos.nikoleris@arm.com * @param readTime Tick at which the packet is processed by this cache 27611741Snikos.nikoleris@arm.com * @param order A counter giving a unique id to each target 27711741Snikos.nikoleris@arm.com * @param source Indicates the source agent of the packet 27811741Snikos.nikoleris@arm.com * @param markPending Set for deferred targets or pending MSHRs 27911741Snikos.nikoleris@arm.com * @param alloc_on_fill Whether it should allocate on a fill 28011741Snikos.nikoleris@arm.com */ 2815318SN/A void add(PacketPtr pkt, Tick readyTime, Counter order, 28213349Snikos.nikoleris@arm.com Target::Source source, bool markPending, bool alloc_on_fill); 28311357Sstephan.diestelhorst@arm.com 28411357Sstephan.diestelhorst@arm.com /** 28511357Sstephan.diestelhorst@arm.com * Convert upgrades to the equivalent request if the cache line they 28611357Sstephan.diestelhorst@arm.com * refer to would have been invalid (Upgrade -> ReadEx, SC* -> Fail). 28711357Sstephan.diestelhorst@arm.com * Used to rejig ordering between targets waiting on an MSHR. */ 2884903SN/A void replaceUpgrades(); 28911357Sstephan.diestelhorst@arm.com 2904908SN/A void clearDownstreamPending(); 29112791Snikos.nikoleris@arm.com void clearDownstreamPending(iterator begin, iterator end); 29212823Srmk35@cl.cam.ac.uk bool trySatisfyFunctional(PacketPtr pkt); 2935314SN/A void print(std::ostream &os, int verbosity, 2945314SN/A const std::string &prefix) const; 29513349Snikos.nikoleris@arm.com 29613349Snikos.nikoleris@arm.com /** 29713349Snikos.nikoleris@arm.com * Check if this list contains only compatible writes, and if they 29813349Snikos.nikoleris@arm.com * span the entire cache line. This is used as part of the 29913349Snikos.nikoleris@arm.com * miss-packet creation. Note that new requests may arrive after a 30013349Snikos.nikoleris@arm.com * miss-packet has been created, and for the fill we therefore use 30113349Snikos.nikoleris@arm.com * the wasWholeLineWrite field. 30213349Snikos.nikoleris@arm.com */ 30313349Snikos.nikoleris@arm.com bool isWholeLineWrite() const 30413349Snikos.nikoleris@arm.com { 30513349Snikos.nikoleris@arm.com return onlyWrites && 30613349Snikos.nikoleris@arm.com std::all_of(writesBitmap.begin(), 30713349Snikos.nikoleris@arm.com writesBitmap.end(), [](bool i) { return i; }); 30813349Snikos.nikoleris@arm.com } 30913349Snikos.nikoleris@arm.com 31013349Snikos.nikoleris@arm.com private: 31113349Snikos.nikoleris@arm.com /** Address of the cache block for this list of targets. */ 31213349Snikos.nikoleris@arm.com Addr blkAddr; 31313349Snikos.nikoleris@arm.com 31413349Snikos.nikoleris@arm.com /** Size of the cache block. */ 31513349Snikos.nikoleris@arm.com Addr blkSize; 31613349Snikos.nikoleris@arm.com 31713349Snikos.nikoleris@arm.com /** Are we only dealing with writes. */ 31813349Snikos.nikoleris@arm.com bool onlyWrites; 31913349Snikos.nikoleris@arm.com 32013349Snikos.nikoleris@arm.com // NOTE: std::vector<bool> might not meet satisfy the 32113349Snikos.nikoleris@arm.com // ForwardIterator requirement and therefore cannot be used 32213349Snikos.nikoleris@arm.com // for writesBitmap. 32313349Snikos.nikoleris@arm.com /** 32413349Snikos.nikoleris@arm.com * Track which bytes are written by requests in this target 32513349Snikos.nikoleris@arm.com * list. 32613349Snikos.nikoleris@arm.com */ 32713349Snikos.nikoleris@arm.com std::vector<char> writesBitmap; 3284903SN/A }; 3294903SN/A 3302810SN/A /** A list of MSHRs. */ 3312810SN/A typedef std::list<MSHR *> List; 3322810SN/A /** MSHR list iterator. */ 3332810SN/A typedef List::iterator Iterator; 3344903SN/A 3357667Ssteve.reinhardt@amd.com /** The pending* and post* flags are only valid if inService is 3367667Ssteve.reinhardt@amd.com * true. Using the accessor functions lets us detect if these 3377667Ssteve.reinhardt@amd.com * flags are accessed improperly. 3387667Ssteve.reinhardt@amd.com */ 3397667Ssteve.reinhardt@amd.com 34011284Sandreas.hansson@arm.com /** True if we need to get a writable copy of the block. */ 34111284Sandreas.hansson@arm.com bool needsWritable() const { return targets.needsWritable; } 3429725Sandreas.hansson@arm.com 34312599Snikos.nikoleris@arm.com bool isCleaning() const { 34412599Snikos.nikoleris@arm.com PacketPtr pkt = targets.front().pkt; 34512599Snikos.nikoleris@arm.com return pkt->isClean(); 34612599Snikos.nikoleris@arm.com } 34712599Snikos.nikoleris@arm.com 34811284Sandreas.hansson@arm.com bool isPendingModified() const { 34911284Sandreas.hansson@arm.com assert(inService); return pendingModified; 3507667Ssteve.reinhardt@amd.com } 3517667Ssteve.reinhardt@amd.com 3527667Ssteve.reinhardt@amd.com bool hasPostInvalidate() const { 3537667Ssteve.reinhardt@amd.com assert(inService); return postInvalidate; 3547667Ssteve.reinhardt@amd.com } 3557667Ssteve.reinhardt@amd.com 3567667Ssteve.reinhardt@amd.com bool hasPostDowngrade() const { 3577667Ssteve.reinhardt@amd.com assert(inService); return postDowngrade; 3587667Ssteve.reinhardt@amd.com } 3594665SN/A 36012724Snikos.nikoleris@arm.com bool sendPacket(BaseCache &cache); 36111375Sandreas.hansson@arm.com 36211741Snikos.nikoleris@arm.com bool allocOnFill() const { 36311741Snikos.nikoleris@arm.com return targets.allocOnFill; 36411741Snikos.nikoleris@arm.com } 36512715Snikos.nikoleris@arm.com 36612715Snikos.nikoleris@arm.com /** 36712715Snikos.nikoleris@arm.com * Determine if there are non-deferred requests from other caches 36812715Snikos.nikoleris@arm.com * 36912715Snikos.nikoleris@arm.com * @return true if any of the targets is from another cache 37012715Snikos.nikoleris@arm.com */ 37112715Snikos.nikoleris@arm.com bool hasFromCache() const { 37212715Snikos.nikoleris@arm.com return targets.hasFromCache; 37312715Snikos.nikoleris@arm.com } 37412715Snikos.nikoleris@arm.com 3759725Sandreas.hansson@arm.com private: 37612793Snikos.nikoleris@arm.com /** 37712793Snikos.nikoleris@arm.com * Promotes deferred targets that satisfy a predicate 37812793Snikos.nikoleris@arm.com * 37912793Snikos.nikoleris@arm.com * Deferred targets are promoted to the target list if they 38012793Snikos.nikoleris@arm.com * satisfy a given condition. The operation stops at the first 38112793Snikos.nikoleris@arm.com * deferred target that doesn't satisfy the condition. 38212793Snikos.nikoleris@arm.com * 38312793Snikos.nikoleris@arm.com * @param pred A condition on a Target 38412793Snikos.nikoleris@arm.com */ 38512793Snikos.nikoleris@arm.com void promoteIf(const std::function<bool (Target &)>& pred); 3864668SN/A 3872810SN/A /** 3882810SN/A * Pointer to this MSHR on the ready list. 3892810SN/A * @sa MissQueue, MSHRQueue::readyList 3902810SN/A */ 3912810SN/A Iterator readyIter; 3924626SN/A 3932810SN/A /** 3942810SN/A * Pointer to this MSHR on the allocated list. 3952810SN/A * @sa MissQueue, MSHRQueue::allocatedList 3962810SN/A */ 3972810SN/A Iterator allocIter; 3982810SN/A 3993374SN/A /** List of all requests that match the address */ 4009725Sandreas.hansson@arm.com TargetList targets; 4012810SN/A 4029725Sandreas.hansson@arm.com TargetList deferredTargets; 4034665SN/A 4049725Sandreas.hansson@arm.com public: 40513349Snikos.nikoleris@arm.com /** 40613349Snikos.nikoleris@arm.com * Check if this MSHR contains only compatible writes, and if they 40713349Snikos.nikoleris@arm.com * span the entire cache line. This is used as part of the 40813349Snikos.nikoleris@arm.com * miss-packet creation. Note that new requests may arrive after a 40913349Snikos.nikoleris@arm.com * miss-packet has been created, and for the fill we therefore use 41013349Snikos.nikoleris@arm.com * the wasWholeLineWrite field. 41113349Snikos.nikoleris@arm.com */ 41213349Snikos.nikoleris@arm.com bool isWholeLineWrite() const { 41313349Snikos.nikoleris@arm.com return targets.isWholeLineWrite(); 41413349Snikos.nikoleris@arm.com } 4154626SN/A 4162810SN/A /** 4172810SN/A * Allocate a miss to this MSHR. 41810764Sandreas.hansson@arm.com * @param blk_addr The address of the block. 41910764Sandreas.hansson@arm.com * @param blk_size The number of bytes to request. 42010764Sandreas.hansson@arm.com * @param pkt The original miss. 42110764Sandreas.hansson@arm.com * @param when_ready When should the MSHR be ready to act upon. 42210764Sandreas.hansson@arm.com * @param _order The logical order of this MSHR 42311197Sandreas.hansson@arm.com * @param alloc_on_fill Should the cache allocate a block on fill 4242810SN/A */ 42510764Sandreas.hansson@arm.com void allocate(Addr blk_addr, unsigned blk_size, PacketPtr pkt, 42611197Sandreas.hansson@arm.com Tick when_ready, Counter _order, bool alloc_on_fill); 4272810SN/A 42811375Sandreas.hansson@arm.com void markInService(bool pending_modified_resp); 4294908SN/A 4305318SN/A void clearDownstreamPending(); 4315318SN/A 4322810SN/A /** 4332810SN/A * Mark this MSHR as free. 4342810SN/A */ 4352810SN/A void deallocate(); 4362810SN/A 4372810SN/A /** 4383374SN/A * Add a request to the list of targets. 4392810SN/A * @param target The target. 4402810SN/A */ 44111197Sandreas.hansson@arm.com void allocateTarget(PacketPtr target, Tick when, Counter order, 44211197Sandreas.hansson@arm.com bool alloc_on_fill); 4434902SN/A bool handleSnoop(PacketPtr target, Counter order); 4442810SN/A 4452810SN/A /** A simple constructor. */ 4462810SN/A MSHR(); 4472810SN/A 4482810SN/A /** 4492810SN/A * Returns the current number of allocated targets. 4502810SN/A * @return The current number of allocated targets. 4512810SN/A */ 4529725Sandreas.hansson@arm.com int getNumTargets() const 4539725Sandreas.hansson@arm.com { return targets.size() + deferredTargets.size(); } 4542810SN/A 4552810SN/A /** 45611742Snikos.nikoleris@arm.com * Extracts the subset of the targets that can be serviced given a 45711742Snikos.nikoleris@arm.com * received response. This function returns the targets list 45811742Snikos.nikoleris@arm.com * unless the response is a ReadRespWithInvalidate. The 45911742Snikos.nikoleris@arm.com * ReadRespWithInvalidate is only invalidating response that its 46011742Snikos.nikoleris@arm.com * invalidation was not expected when the request (a 46111742Snikos.nikoleris@arm.com * ReadSharedReq) was sent out. For ReadRespWithInvalidate we can 46211742Snikos.nikoleris@arm.com * safely service only the first FromCPU target and all FromSnoop 46311742Snikos.nikoleris@arm.com * targets (inform all snoopers that we no longer have the block). 46411742Snikos.nikoleris@arm.com * 46511742Snikos.nikoleris@arm.com * @param pkt The response from the downstream memory 46611742Snikos.nikoleris@arm.com */ 46711742Snikos.nikoleris@arm.com TargetList extractServiceableTargets(PacketPtr pkt); 46811742Snikos.nikoleris@arm.com 46911742Snikos.nikoleris@arm.com /** 4704899SN/A * Returns true if there are targets left. 4714899SN/A * @return true if there are targets 4724899SN/A */ 4739725Sandreas.hansson@arm.com bool hasTargets() const { return !targets.empty(); } 4744899SN/A 4754899SN/A /** 4762810SN/A * Returns a reference to the first target. 4772810SN/A * @return A pointer to the first target. 4782810SN/A */ 4799725Sandreas.hansson@arm.com Target *getTarget() 4805730SSteve.Reinhardt@amd.com { 4815730SSteve.Reinhardt@amd.com assert(hasTargets()); 4829725Sandreas.hansson@arm.com return &targets.front(); 4835730SSteve.Reinhardt@amd.com } 4842810SN/A 4852810SN/A /** 4862810SN/A * Pop first target. 4872810SN/A */ 4882810SN/A void popTarget() 4892810SN/A { 4909725Sandreas.hansson@arm.com targets.pop_front(); 4912810SN/A } 4922810SN/A 4934665SN/A bool promoteDeferredTargets(); 4944665SN/A 49512792Snikos.nikoleris@arm.com /** 49612792Snikos.nikoleris@arm.com * Promotes deferred targets that do not require writable 49712792Snikos.nikoleris@arm.com * 49812793Snikos.nikoleris@arm.com * Move targets from the deferred targets list to the target list 49912793Snikos.nikoleris@arm.com * starting from the first deferred target until the first target 50012793Snikos.nikoleris@arm.com * that is a cache maintenance operation or needs a writable copy 50112793Snikos.nikoleris@arm.com * of the block 50212793Snikos.nikoleris@arm.com */ 50312793Snikos.nikoleris@arm.com void promoteReadable(); 50412793Snikos.nikoleris@arm.com 50512793Snikos.nikoleris@arm.com /** 50612793Snikos.nikoleris@arm.com * Promotes deferred targets that do not require writable 50712793Snikos.nikoleris@arm.com * 50812792Snikos.nikoleris@arm.com * Requests in the deferred target list are moved to the target 50912792Snikos.nikoleris@arm.com * list up until the first target that is a cache maintenance 51012792Snikos.nikoleris@arm.com * operation or needs a writable copy of the block 51112792Snikos.nikoleris@arm.com */ 51211284Sandreas.hansson@arm.com void promoteWritable(); 5134668SN/A 51412823Srmk35@cl.cam.ac.uk bool trySatisfyFunctional(PacketPtr pkt); 5154920SN/A 5162810SN/A /** 51713351Snikos.nikoleris@arm.com * Adds a delay relative to the current tick to the current MSHR 51813351Snikos.nikoleris@arm.com * @param delay_ticks the desired delay in ticks 51913351Snikos.nikoleris@arm.com */ 52013351Snikos.nikoleris@arm.com void delay(Tick delay_ticks) 52113351Snikos.nikoleris@arm.com { 52213351Snikos.nikoleris@arm.com assert(readyTime <= curTick()); 52313351Snikos.nikoleris@arm.com readyTime = curTick() + delay_ticks; 52413351Snikos.nikoleris@arm.com } 52513351Snikos.nikoleris@arm.com 52613351Snikos.nikoleris@arm.com /** 5275314SN/A * Prints the contents of this MSHR for debugging. 5282810SN/A */ 5295314SN/A void print(std::ostream &os, 5305314SN/A int verbosity = 0, 5315314SN/A const std::string &prefix = "") const; 5329663Suri.wiener@arm.com /** 5339663Suri.wiener@arm.com * A no-args wrapper of print(std::ostream...) meant to be 5349663Suri.wiener@arm.com * invoked from DPRINTFs avoiding string overheads in fast mode 5359663Suri.wiener@arm.com * 5369663Suri.wiener@arm.com * @return string with mshr fields + [deferred]targets 5379663Suri.wiener@arm.com */ 5389663Suri.wiener@arm.com std::string print() const; 5392810SN/A}; 5402810SN/A 54110764Sandreas.hansson@arm.com#endif // __MEM_CACHE_MSHR_HH__ 542