mshr.hh revision 13875
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 12713859Sodanrc@yahoo.com.br class Target : public QueueEntry::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 Source source; //!< Request from cpu, memory, or prefetcher? 13711742Snikos.nikoleris@arm.com 13811742Snikos.nikoleris@arm.com /** 13911742Snikos.nikoleris@arm.com * We use this flag to track whether we have cleared the 14011742Snikos.nikoleris@arm.com * downstreamPending flag for the MSHR of the cache above 14111742Snikos.nikoleris@arm.com * where this packet originates from and guard noninitial 14211742Snikos.nikoleris@arm.com * attempts to clear it. 14311742Snikos.nikoleris@arm.com * 14411742Snikos.nikoleris@arm.com * The flag markedPending needs to be updated when the 14511742Snikos.nikoleris@arm.com * TargetList is in service which can be: 14611742Snikos.nikoleris@arm.com * 1) during the Target instantiation if the MSHR is in 14711742Snikos.nikoleris@arm.com * service and the target is not deferred, 14811742Snikos.nikoleris@arm.com * 2) when the MSHR becomes in service if the target is not 14911742Snikos.nikoleris@arm.com * deferred, 15011742Snikos.nikoleris@arm.com * 3) or when the TargetList is promoted (deferredTargets -> 15111742Snikos.nikoleris@arm.com * targets). 15211742Snikos.nikoleris@arm.com */ 15311742Snikos.nikoleris@arm.com bool markedPending; 15411742Snikos.nikoleris@arm.com 15511741Snikos.nikoleris@arm.com const bool allocOnFill; //!< Should the response servicing this 15611741Snikos.nikoleris@arm.com //!< target list allocate in the cache? 1574626SN/A 1585318SN/A Target(PacketPtr _pkt, Tick _readyTime, Counter _order, 15911741Snikos.nikoleris@arm.com Source _source, bool _markedPending, bool alloc_on_fill) 16013859Sodanrc@yahoo.com.br : QueueEntry::Target(_pkt, _readyTime, _order), source(_source), 16113859Sodanrc@yahoo.com.br markedPending(_markedPending), allocOnFill(alloc_on_fill) 1624626SN/A {} 1634626SN/A }; 1644626SN/A 1654903SN/A class TargetList : public std::list<Target> { 1664903SN/A 1674903SN/A public: 16811284Sandreas.hansson@arm.com bool needsWritable; 1694903SN/A bool hasUpgrade; 17011741Snikos.nikoleris@arm.com /** Set when the response should allocate on fill */ 17111741Snikos.nikoleris@arm.com bool allocOnFill; 17212715Snikos.nikoleris@arm.com /** 17312715Snikos.nikoleris@arm.com * Determine whether there was at least one non-snooping 17412715Snikos.nikoleris@arm.com * target coming from another cache. 17512715Snikos.nikoleris@arm.com */ 17612715Snikos.nikoleris@arm.com bool hasFromCache; 1774903SN/A 1784903SN/A TargetList(); 17911740Snikos.nikoleris@arm.com 18011740Snikos.nikoleris@arm.com /** 18111740Snikos.nikoleris@arm.com * Use the provided packet and the source to update the 18211740Snikos.nikoleris@arm.com * flags of this TargetList. 18311740Snikos.nikoleris@arm.com * 18411740Snikos.nikoleris@arm.com * @param pkt Packet considered for the flag update 18511740Snikos.nikoleris@arm.com * @param source Indicates the source of the packet 18611741Snikos.nikoleris@arm.com * @param alloc_on_fill Whether the pkt would allocate on a fill 18711740Snikos.nikoleris@arm.com */ 18811741Snikos.nikoleris@arm.com void updateFlags(PacketPtr pkt, Target::Source source, 18911741Snikos.nikoleris@arm.com bool alloc_on_fill); 19011740Snikos.nikoleris@arm.com 19113349Snikos.nikoleris@arm.com /** 19213349Snikos.nikoleris@arm.com * Reset state 19313349Snikos.nikoleris@arm.com * 19413349Snikos.nikoleris@arm.com * @param blk_addr Address of the cache block 19513349Snikos.nikoleris@arm.com * @param blk_size Size of the cache block 19613349Snikos.nikoleris@arm.com */ 19713349Snikos.nikoleris@arm.com void init(Addr blk_addr, Addr blk_size) { 19813349Snikos.nikoleris@arm.com blkAddr = blk_addr; 19913349Snikos.nikoleris@arm.com blkSize = blk_size; 20013349Snikos.nikoleris@arm.com writesBitmap.resize(blk_size); 20113349Snikos.nikoleris@arm.com 20213349Snikos.nikoleris@arm.com resetFlags(); 20313349Snikos.nikoleris@arm.com } 20413349Snikos.nikoleris@arm.com 20512715Snikos.nikoleris@arm.com void resetFlags() { 20613349Snikos.nikoleris@arm.com onlyWrites = true; 20713349Snikos.nikoleris@arm.com std::fill(writesBitmap.begin(), writesBitmap.end(), false); 20813349Snikos.nikoleris@arm.com 20912715Snikos.nikoleris@arm.com needsWritable = false; 21012715Snikos.nikoleris@arm.com hasUpgrade = false; 21112715Snikos.nikoleris@arm.com allocOnFill = false; 21212715Snikos.nikoleris@arm.com hasFromCache = false; 21312715Snikos.nikoleris@arm.com } 21411740Snikos.nikoleris@arm.com 21511740Snikos.nikoleris@arm.com /** 21611740Snikos.nikoleris@arm.com * Goes through the list of targets and uses them to populate 21711740Snikos.nikoleris@arm.com * the flags of this TargetList. When the function returns the 21811740Snikos.nikoleris@arm.com * flags are consistent with the properties of packets in the 21911740Snikos.nikoleris@arm.com * list. 22011740Snikos.nikoleris@arm.com */ 22111740Snikos.nikoleris@arm.com void populateFlags(); 22211740Snikos.nikoleris@arm.com 22311741Snikos.nikoleris@arm.com /** 22413349Snikos.nikoleris@arm.com * Add the specified packet in the TargetList. This function 22513349Snikos.nikoleris@arm.com * stores information related to the added packet and updates 22613349Snikos.nikoleris@arm.com * accordingly the flags. 22713349Snikos.nikoleris@arm.com * 22813349Snikos.nikoleris@arm.com * @param pkt Packet considered for adding 22913349Snikos.nikoleris@arm.com */ 23013349Snikos.nikoleris@arm.com void updateWriteFlags(PacketPtr pkt) { 23113349Snikos.nikoleris@arm.com const Request::FlagsType noMergeFlags = 23213349Snikos.nikoleris@arm.com Request::UNCACHEABLE | 23313349Snikos.nikoleris@arm.com Request::STRICT_ORDER | Request::MMAPPED_IPR | 23413349Snikos.nikoleris@arm.com Request::PRIVILEGED | Request::LLSC | 23513349Snikos.nikoleris@arm.com Request::MEM_SWAP | Request::MEM_SWAP_COND | 23613349Snikos.nikoleris@arm.com Request::SECURE; 23713349Snikos.nikoleris@arm.com 23813349Snikos.nikoleris@arm.com // if we have already seen writes for the full block stop 23913349Snikos.nikoleris@arm.com // here, this might be a full line write followed by 24013349Snikos.nikoleris@arm.com // other compatible requests (e.g., reads) 24113349Snikos.nikoleris@arm.com if (!isWholeLineWrite()) { 24213349Snikos.nikoleris@arm.com bool can_merge_write = pkt->isWrite() && 24313349Snikos.nikoleris@arm.com ((pkt->req->getFlags() & noMergeFlags) == 0); 24413349Snikos.nikoleris@arm.com onlyWrites &= can_merge_write; 24513349Snikos.nikoleris@arm.com if (onlyWrites) { 24613349Snikos.nikoleris@arm.com auto offset = pkt->getOffset(blkSize); 24713349Snikos.nikoleris@arm.com auto begin = writesBitmap.begin() + offset; 24813349Snikos.nikoleris@arm.com std::fill(begin, begin + pkt->getSize(), true); 24913349Snikos.nikoleris@arm.com } 25013349Snikos.nikoleris@arm.com } 25113349Snikos.nikoleris@arm.com } 25213349Snikos.nikoleris@arm.com 25313349Snikos.nikoleris@arm.com /** 25411741Snikos.nikoleris@arm.com * Tests if the flags of this TargetList have their default 25511741Snikos.nikoleris@arm.com * values. 25613349Snikos.nikoleris@arm.com * 25713349Snikos.nikoleris@arm.com * @return True if the TargetList are reset, false otherwise. 25811741Snikos.nikoleris@arm.com */ 25911741Snikos.nikoleris@arm.com bool isReset() const { 26012715Snikos.nikoleris@arm.com return !needsWritable && !hasUpgrade && !allocOnFill && 26113349Snikos.nikoleris@arm.com !hasFromCache && onlyWrites; 26211741Snikos.nikoleris@arm.com } 26311741Snikos.nikoleris@arm.com 26411741Snikos.nikoleris@arm.com /** 26511741Snikos.nikoleris@arm.com * Add the specified packet in the TargetList. This function 26611741Snikos.nikoleris@arm.com * stores information related to the added packet and updates 26711741Snikos.nikoleris@arm.com * accordingly the flags. 26811741Snikos.nikoleris@arm.com * 26911741Snikos.nikoleris@arm.com * @param pkt Packet considered for adding 27011741Snikos.nikoleris@arm.com * @param readTime Tick at which the packet is processed by this cache 27111741Snikos.nikoleris@arm.com * @param order A counter giving a unique id to each target 27211741Snikos.nikoleris@arm.com * @param source Indicates the source agent of the packet 27311741Snikos.nikoleris@arm.com * @param markPending Set for deferred targets or pending MSHRs 27411741Snikos.nikoleris@arm.com * @param alloc_on_fill Whether it should allocate on a fill 27511741Snikos.nikoleris@arm.com */ 2765318SN/A void add(PacketPtr pkt, Tick readyTime, Counter order, 27713349Snikos.nikoleris@arm.com Target::Source source, bool markPending, bool alloc_on_fill); 27811357Sstephan.diestelhorst@arm.com 27911357Sstephan.diestelhorst@arm.com /** 28011357Sstephan.diestelhorst@arm.com * Convert upgrades to the equivalent request if the cache line they 28111357Sstephan.diestelhorst@arm.com * refer to would have been invalid (Upgrade -> ReadEx, SC* -> Fail). 28211357Sstephan.diestelhorst@arm.com * Used to rejig ordering between targets waiting on an MSHR. */ 2834903SN/A void replaceUpgrades(); 28411357Sstephan.diestelhorst@arm.com 2854908SN/A void clearDownstreamPending(); 28612791Snikos.nikoleris@arm.com void clearDownstreamPending(iterator begin, iterator end); 28712823Srmk35@cl.cam.ac.uk bool trySatisfyFunctional(PacketPtr pkt); 2885314SN/A void print(std::ostream &os, int verbosity, 2895314SN/A const std::string &prefix) const; 29013349Snikos.nikoleris@arm.com 29113349Snikos.nikoleris@arm.com /** 29213349Snikos.nikoleris@arm.com * Check if this list contains only compatible writes, and if they 29313349Snikos.nikoleris@arm.com * span the entire cache line. This is used as part of the 29413349Snikos.nikoleris@arm.com * miss-packet creation. Note that new requests may arrive after a 29513349Snikos.nikoleris@arm.com * miss-packet has been created, and for the fill we therefore use 29613349Snikos.nikoleris@arm.com * the wasWholeLineWrite field. 29713349Snikos.nikoleris@arm.com */ 29813349Snikos.nikoleris@arm.com bool isWholeLineWrite() const 29913349Snikos.nikoleris@arm.com { 30013349Snikos.nikoleris@arm.com return onlyWrites && 30113349Snikos.nikoleris@arm.com std::all_of(writesBitmap.begin(), 30213349Snikos.nikoleris@arm.com writesBitmap.end(), [](bool i) { return i; }); 30313349Snikos.nikoleris@arm.com } 30413349Snikos.nikoleris@arm.com 30513349Snikos.nikoleris@arm.com private: 30613349Snikos.nikoleris@arm.com /** Address of the cache block for this list of targets. */ 30713349Snikos.nikoleris@arm.com Addr blkAddr; 30813349Snikos.nikoleris@arm.com 30913349Snikos.nikoleris@arm.com /** Size of the cache block. */ 31013349Snikos.nikoleris@arm.com Addr blkSize; 31113349Snikos.nikoleris@arm.com 31213349Snikos.nikoleris@arm.com /** Are we only dealing with writes. */ 31313349Snikos.nikoleris@arm.com bool onlyWrites; 31413349Snikos.nikoleris@arm.com 31513349Snikos.nikoleris@arm.com // NOTE: std::vector<bool> might not meet satisfy the 31613349Snikos.nikoleris@arm.com // ForwardIterator requirement and therefore cannot be used 31713349Snikos.nikoleris@arm.com // for writesBitmap. 31813349Snikos.nikoleris@arm.com /** 31913349Snikos.nikoleris@arm.com * Track which bytes are written by requests in this target 32013349Snikos.nikoleris@arm.com * list. 32113349Snikos.nikoleris@arm.com */ 32213349Snikos.nikoleris@arm.com std::vector<char> writesBitmap; 3234903SN/A }; 3244903SN/A 3252810SN/A /** A list of MSHRs. */ 3262810SN/A typedef std::list<MSHR *> List; 3272810SN/A /** MSHR list iterator. */ 3282810SN/A typedef List::iterator Iterator; 3294903SN/A 3307667Ssteve.reinhardt@amd.com /** The pending* and post* flags are only valid if inService is 3317667Ssteve.reinhardt@amd.com * true. Using the accessor functions lets us detect if these 3327667Ssteve.reinhardt@amd.com * flags are accessed improperly. 3337667Ssteve.reinhardt@amd.com */ 3347667Ssteve.reinhardt@amd.com 33511284Sandreas.hansson@arm.com /** True if we need to get a writable copy of the block. */ 33611284Sandreas.hansson@arm.com bool needsWritable() const { return targets.needsWritable; } 3379725Sandreas.hansson@arm.com 33812599Snikos.nikoleris@arm.com bool isCleaning() const { 33912599Snikos.nikoleris@arm.com PacketPtr pkt = targets.front().pkt; 34012599Snikos.nikoleris@arm.com return pkt->isClean(); 34112599Snikos.nikoleris@arm.com } 34212599Snikos.nikoleris@arm.com 34311284Sandreas.hansson@arm.com bool isPendingModified() const { 34411284Sandreas.hansson@arm.com assert(inService); return pendingModified; 3457667Ssteve.reinhardt@amd.com } 3467667Ssteve.reinhardt@amd.com 3477667Ssteve.reinhardt@amd.com bool hasPostInvalidate() const { 3487667Ssteve.reinhardt@amd.com assert(inService); return postInvalidate; 3497667Ssteve.reinhardt@amd.com } 3507667Ssteve.reinhardt@amd.com 3517667Ssteve.reinhardt@amd.com bool hasPostDowngrade() const { 3527667Ssteve.reinhardt@amd.com assert(inService); return postDowngrade; 3537667Ssteve.reinhardt@amd.com } 3544665SN/A 35513875SAndrea.Mondelli@ucf.edu bool sendPacket(BaseCache &cache) override; 35611375Sandreas.hansson@arm.com 35711741Snikos.nikoleris@arm.com bool allocOnFill() const { 35811741Snikos.nikoleris@arm.com return targets.allocOnFill; 35911741Snikos.nikoleris@arm.com } 36012715Snikos.nikoleris@arm.com 36112715Snikos.nikoleris@arm.com /** 36212715Snikos.nikoleris@arm.com * Determine if there are non-deferred requests from other caches 36312715Snikos.nikoleris@arm.com * 36412715Snikos.nikoleris@arm.com * @return true if any of the targets is from another cache 36512715Snikos.nikoleris@arm.com */ 36612715Snikos.nikoleris@arm.com bool hasFromCache() const { 36712715Snikos.nikoleris@arm.com return targets.hasFromCache; 36812715Snikos.nikoleris@arm.com } 36912715Snikos.nikoleris@arm.com 3709725Sandreas.hansson@arm.com private: 37112793Snikos.nikoleris@arm.com /** 37212793Snikos.nikoleris@arm.com * Promotes deferred targets that satisfy a predicate 37312793Snikos.nikoleris@arm.com * 37412793Snikos.nikoleris@arm.com * Deferred targets are promoted to the target list if they 37512793Snikos.nikoleris@arm.com * satisfy a given condition. The operation stops at the first 37612793Snikos.nikoleris@arm.com * deferred target that doesn't satisfy the condition. 37712793Snikos.nikoleris@arm.com * 37812793Snikos.nikoleris@arm.com * @param pred A condition on a Target 37912793Snikos.nikoleris@arm.com */ 38012793Snikos.nikoleris@arm.com void promoteIf(const std::function<bool (Target &)>& pred); 3814668SN/A 3822810SN/A /** 3832810SN/A * Pointer to this MSHR on the ready list. 3842810SN/A * @sa MissQueue, MSHRQueue::readyList 3852810SN/A */ 3862810SN/A Iterator readyIter; 3874626SN/A 3882810SN/A /** 3892810SN/A * Pointer to this MSHR on the allocated list. 3902810SN/A * @sa MissQueue, MSHRQueue::allocatedList 3912810SN/A */ 3922810SN/A Iterator allocIter; 3932810SN/A 3943374SN/A /** List of all requests that match the address */ 3959725Sandreas.hansson@arm.com TargetList targets; 3962810SN/A 3979725Sandreas.hansson@arm.com TargetList deferredTargets; 3984665SN/A 3999725Sandreas.hansson@arm.com public: 40013349Snikos.nikoleris@arm.com /** 40113349Snikos.nikoleris@arm.com * Check if this MSHR contains only compatible writes, and if they 40213349Snikos.nikoleris@arm.com * span the entire cache line. This is used as part of the 40313349Snikos.nikoleris@arm.com * miss-packet creation. Note that new requests may arrive after a 40413349Snikos.nikoleris@arm.com * miss-packet has been created, and for the fill we therefore use 40513349Snikos.nikoleris@arm.com * the wasWholeLineWrite field. 40613349Snikos.nikoleris@arm.com */ 40713349Snikos.nikoleris@arm.com bool isWholeLineWrite() const { 40813349Snikos.nikoleris@arm.com return targets.isWholeLineWrite(); 40913349Snikos.nikoleris@arm.com } 4104626SN/A 4112810SN/A /** 4122810SN/A * Allocate a miss to this MSHR. 41310764Sandreas.hansson@arm.com * @param blk_addr The address of the block. 41410764Sandreas.hansson@arm.com * @param blk_size The number of bytes to request. 41510764Sandreas.hansson@arm.com * @param pkt The original miss. 41610764Sandreas.hansson@arm.com * @param when_ready When should the MSHR be ready to act upon. 41710764Sandreas.hansson@arm.com * @param _order The logical order of this MSHR 41811197Sandreas.hansson@arm.com * @param alloc_on_fill Should the cache allocate a block on fill 4192810SN/A */ 42010764Sandreas.hansson@arm.com void allocate(Addr blk_addr, unsigned blk_size, PacketPtr pkt, 42111197Sandreas.hansson@arm.com Tick when_ready, Counter _order, bool alloc_on_fill); 4222810SN/A 42311375Sandreas.hansson@arm.com void markInService(bool pending_modified_resp); 4244908SN/A 4255318SN/A void clearDownstreamPending(); 4265318SN/A 4272810SN/A /** 4282810SN/A * Mark this MSHR as free. 4292810SN/A */ 4302810SN/A void deallocate(); 4312810SN/A 4322810SN/A /** 4333374SN/A * Add a request to the list of targets. 4342810SN/A * @param target The target. 4352810SN/A */ 43611197Sandreas.hansson@arm.com void allocateTarget(PacketPtr target, Tick when, Counter order, 43711197Sandreas.hansson@arm.com bool alloc_on_fill); 4384902SN/A bool handleSnoop(PacketPtr target, Counter order); 4392810SN/A 4402810SN/A /** A simple constructor. */ 4412810SN/A MSHR(); 4422810SN/A 4432810SN/A /** 4442810SN/A * Returns the current number of allocated targets. 4452810SN/A * @return The current number of allocated targets. 4462810SN/A */ 4479725Sandreas.hansson@arm.com int getNumTargets() const 4489725Sandreas.hansson@arm.com { return targets.size() + deferredTargets.size(); } 4492810SN/A 4502810SN/A /** 45111742Snikos.nikoleris@arm.com * Extracts the subset of the targets that can be serviced given a 45211742Snikos.nikoleris@arm.com * received response. This function returns the targets list 45311742Snikos.nikoleris@arm.com * unless the response is a ReadRespWithInvalidate. The 45411742Snikos.nikoleris@arm.com * ReadRespWithInvalidate is only invalidating response that its 45511742Snikos.nikoleris@arm.com * invalidation was not expected when the request (a 45611742Snikos.nikoleris@arm.com * ReadSharedReq) was sent out. For ReadRespWithInvalidate we can 45711742Snikos.nikoleris@arm.com * safely service only the first FromCPU target and all FromSnoop 45811742Snikos.nikoleris@arm.com * targets (inform all snoopers that we no longer have the block). 45911742Snikos.nikoleris@arm.com * 46011742Snikos.nikoleris@arm.com * @param pkt The response from the downstream memory 46111742Snikos.nikoleris@arm.com */ 46211742Snikos.nikoleris@arm.com TargetList extractServiceableTargets(PacketPtr pkt); 46311742Snikos.nikoleris@arm.com 46411742Snikos.nikoleris@arm.com /** 4654899SN/A * Returns true if there are targets left. 4664899SN/A * @return true if there are targets 4674899SN/A */ 4689725Sandreas.hansson@arm.com bool hasTargets() const { return !targets.empty(); } 4694899SN/A 4704899SN/A /** 4712810SN/A * Returns a reference to the first target. 4722810SN/A * @return A pointer to the first target. 4732810SN/A */ 47413859Sodanrc@yahoo.com.br QueueEntry::Target *getTarget() override 4755730SSteve.Reinhardt@amd.com { 4765730SSteve.Reinhardt@amd.com assert(hasTargets()); 4779725Sandreas.hansson@arm.com return &targets.front(); 4785730SSteve.Reinhardt@amd.com } 4792810SN/A 4802810SN/A /** 4812810SN/A * Pop first target. 4822810SN/A */ 4832810SN/A void popTarget() 4842810SN/A { 4859725Sandreas.hansson@arm.com targets.pop_front(); 4862810SN/A } 4872810SN/A 4884665SN/A bool promoteDeferredTargets(); 4894665SN/A 49012792Snikos.nikoleris@arm.com /** 49112792Snikos.nikoleris@arm.com * Promotes deferred targets that do not require writable 49212792Snikos.nikoleris@arm.com * 49312793Snikos.nikoleris@arm.com * Move targets from the deferred targets list to the target list 49412793Snikos.nikoleris@arm.com * starting from the first deferred target until the first target 49512793Snikos.nikoleris@arm.com * that is a cache maintenance operation or needs a writable copy 49612793Snikos.nikoleris@arm.com * of the block 49712793Snikos.nikoleris@arm.com */ 49812793Snikos.nikoleris@arm.com void promoteReadable(); 49912793Snikos.nikoleris@arm.com 50012793Snikos.nikoleris@arm.com /** 50112793Snikos.nikoleris@arm.com * Promotes deferred targets that do not require writable 50212793Snikos.nikoleris@arm.com * 50312792Snikos.nikoleris@arm.com * Requests in the deferred target list are moved to the target 50412792Snikos.nikoleris@arm.com * list up until the first target that is a cache maintenance 50512792Snikos.nikoleris@arm.com * operation or needs a writable copy of the block 50612792Snikos.nikoleris@arm.com */ 50711284Sandreas.hansson@arm.com void promoteWritable(); 5084668SN/A 50912823Srmk35@cl.cam.ac.uk bool trySatisfyFunctional(PacketPtr pkt); 5104920SN/A 5112810SN/A /** 51213351Snikos.nikoleris@arm.com * Adds a delay relative to the current tick to the current MSHR 51313351Snikos.nikoleris@arm.com * @param delay_ticks the desired delay in ticks 51413351Snikos.nikoleris@arm.com */ 51513351Snikos.nikoleris@arm.com void delay(Tick delay_ticks) 51613351Snikos.nikoleris@arm.com { 51713351Snikos.nikoleris@arm.com assert(readyTime <= curTick()); 51813351Snikos.nikoleris@arm.com readyTime = curTick() + delay_ticks; 51913351Snikos.nikoleris@arm.com } 52013351Snikos.nikoleris@arm.com 52113351Snikos.nikoleris@arm.com /** 5225314SN/A * Prints the contents of this MSHR for debugging. 5232810SN/A */ 5245314SN/A void print(std::ostream &os, 5255314SN/A int verbosity = 0, 52613875SAndrea.Mondelli@ucf.edu const std::string &prefix = "") const override; 5279663Suri.wiener@arm.com /** 5289663Suri.wiener@arm.com * A no-args wrapper of print(std::ostream...) meant to be 5299663Suri.wiener@arm.com * invoked from DPRINTFs avoiding string overheads in fast mode 5309663Suri.wiener@arm.com * 5319663Suri.wiener@arm.com * @return string with mshr fields + [deferred]targets 5329663Suri.wiener@arm.com */ 5339663Suri.wiener@arm.com std::string print() const; 53413861Sodanrc@yahoo.com.br 53513861Sodanrc@yahoo.com.br bool matchBlockAddr(const Addr addr, const bool is_secure) const override; 53613861Sodanrc@yahoo.com.br bool matchBlockAddr(const PacketPtr pkt) const override; 53713861Sodanrc@yahoo.com.br bool conflictAddr(const QueueEntry* entry) const override; 5382810SN/A}; 5392810SN/A 54010764Sandreas.hansson@arm.com#endif // __MEM_CACHE_MSHR_HH__ 541