base.hh revision 14035
12810SN/A/* 212724Snikos.nikoleris@arm.com * Copyright (c) 2012-2013, 2015-2016, 2018 ARM Limited 38856Sandreas.hansson@arm.com * All rights reserved. 48856Sandreas.hansson@arm.com * 58856Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 68856Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 78856Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 88856Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 98856Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 108856Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 118856Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 128856Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 138856Sandreas.hansson@arm.com * 142810SN/A * Copyright (c) 2003-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 414458SN/A * Steve Reinhardt 424458SN/A * Ron Dreslinski 4312724Snikos.nikoleris@arm.com * Andreas Hansson 4412724Snikos.nikoleris@arm.com * Nikos Nikoleris 452810SN/A */ 462810SN/A 472810SN/A/** 482810SN/A * @file 492810SN/A * Declares a basic cache interface BaseCache. 502810SN/A */ 512810SN/A 5211051Sandreas.hansson@arm.com#ifndef __MEM_CACHE_BASE_HH__ 5311051Sandreas.hansson@arm.com#define __MEM_CACHE_BASE_HH__ 542810SN/A 5512724Snikos.nikoleris@arm.com#include <cassert> 5612724Snikos.nikoleris@arm.com#include <cstdint> 577676Snate@binkert.org#include <string> 582810SN/A 5912724Snikos.nikoleris@arm.com#include "base/addr_range.hh" 602810SN/A#include "base/statistics.hh" 612810SN/A#include "base/trace.hh" 626215Snate@binkert.org#include "base/types.hh" 638232Snate@binkert.org#include "debug/Cache.hh" 648232Snate@binkert.org#include "debug/CachePort.hh" 6512724Snikos.nikoleris@arm.com#include "enums/Clusivity.hh" 6613223Sodanrc@yahoo.com.br#include "mem/cache/cache_blk.hh" 6713945Sodanrc@yahoo.com.br#include "mem/cache/compressors/base.hh" 685338Sstever@gmail.com#include "mem/cache/mshr_queue.hh" 6912724Snikos.nikoleris@arm.com#include "mem/cache/tags/base.hh" 7011375Sandreas.hansson@arm.com#include "mem/cache/write_queue.hh" 7112724Snikos.nikoleris@arm.com#include "mem/cache/write_queue_entry.hh" 722810SN/A#include "mem/packet.hh" 7312724Snikos.nikoleris@arm.com#include "mem/packet_queue.hh" 748914Sandreas.hansson@arm.com#include "mem/qport.hh" 758229Snate@binkert.org#include "mem/request.hh" 7613352Snikos.nikoleris@arm.com#include "params/WriteAllocator.hh" 7713892Sgabeblack@google.com#include "sim/clocked_object.hh" 782811SN/A#include "sim/eventq.hh" 7913416Sjavier.bueno@metempsy.com#include "sim/probe/probe.hh" 8012724Snikos.nikoleris@arm.com#include "sim/serialize.hh" 814626SN/A#include "sim/sim_exit.hh" 828833Sdam.sunwoo@arm.com#include "sim/system.hh" 832810SN/A 8412724Snikos.nikoleris@arm.comclass BaseMasterPort; 8512724Snikos.nikoleris@arm.comclass BasePrefetcher; 8612724Snikos.nikoleris@arm.comclass BaseSlavePort; 8712724Snikos.nikoleris@arm.comclass MSHR; 8812724Snikos.nikoleris@arm.comclass MasterPort; 8912724Snikos.nikoleris@arm.comclass QueueEntry; 9012724Snikos.nikoleris@arm.comstruct BaseCacheParams; 9112724Snikos.nikoleris@arm.com 922810SN/A/** 932810SN/A * A basic cache interface. Implements some common functions for speed. 942810SN/A */ 9513892Sgabeblack@google.comclass BaseCache : public ClockedObject 962810SN/A{ 9711375Sandreas.hansson@arm.com protected: 984628SN/A /** 994628SN/A * Indexes to enumerate the MSHR queues. 1004628SN/A */ 1014628SN/A enum MSHRQueueIndex { 1024628SN/A MSHRQueue_MSHRs, 1034628SN/A MSHRQueue_WriteBuffer 1044628SN/A }; 1054628SN/A 1068737Skoansin.tan@gmail.com public: 1074628SN/A /** 1084628SN/A * Reasons for caches to be blocked. 1094628SN/A */ 1104628SN/A enum BlockedCause { 1114628SN/A Blocked_NoMSHRs = MSHRQueue_MSHRs, 1124628SN/A Blocked_NoWBBuffers = MSHRQueue_WriteBuffer, 1134628SN/A Blocked_NoTargets, 1144628SN/A NUM_BLOCKED_CAUSES 1154628SN/A }; 1164628SN/A 1178737Skoansin.tan@gmail.com protected: 1184628SN/A 1198856Sandreas.hansson@arm.com /** 1208856Sandreas.hansson@arm.com * A cache master port is used for the memory-side port of the 1218856Sandreas.hansson@arm.com * cache, and in addition to the basic timing port that only sends 1228856Sandreas.hansson@arm.com * response packets through a transmit list, it also offers the 1238856Sandreas.hansson@arm.com * ability to schedule and send request packets (requests & 12410942Sandreas.hansson@arm.com * writebacks). The send event is scheduled through schedSendEvent, 1258856Sandreas.hansson@arm.com * and the sendDeferredPacket of the timing port is modified to 1268856Sandreas.hansson@arm.com * consider both the transmit list and the requests from the MSHR. 1278856Sandreas.hansson@arm.com */ 1288922Swilliam.wang@arm.com class CacheMasterPort : public QueuedMasterPort 1292810SN/A { 1308856Sandreas.hansson@arm.com 1312844SN/A public: 1328856Sandreas.hansson@arm.com 1338856Sandreas.hansson@arm.com /** 1348856Sandreas.hansson@arm.com * Schedule a send of a request packet (from the MSHR). Note 13510713Sandreas.hansson@arm.com * that we could already have a retry outstanding. 1368856Sandreas.hansson@arm.com */ 13710942Sandreas.hansson@arm.com void schedSendEvent(Tick time) 1388856Sandreas.hansson@arm.com { 13910942Sandreas.hansson@arm.com DPRINTF(CachePort, "Scheduling send event at %llu\n", time); 14010713Sandreas.hansson@arm.com reqQueue.schedSendEvent(time); 1418856Sandreas.hansson@arm.com } 1428856Sandreas.hansson@arm.com 1433738SN/A protected: 1444458SN/A 1458856Sandreas.hansson@arm.com CacheMasterPort(const std::string &_name, BaseCache *_cache, 14610713Sandreas.hansson@arm.com ReqPacketQueue &_reqQueue, 14710713Sandreas.hansson@arm.com SnoopRespPacketQueue &_snoopRespQueue) : 14810713Sandreas.hansson@arm.com QueuedMasterPort(_name, _cache, _reqQueue, _snoopRespQueue) 1498914Sandreas.hansson@arm.com { } 1502810SN/A 1518856Sandreas.hansson@arm.com /** 1528856Sandreas.hansson@arm.com * Memory-side port always snoops. 1538856Sandreas.hansson@arm.com * 1548914Sandreas.hansson@arm.com * @return always true 1558856Sandreas.hansson@arm.com */ 1568922Swilliam.wang@arm.com virtual bool isSnooping() const { return true; } 1578856Sandreas.hansson@arm.com }; 1583013SN/A 1598856Sandreas.hansson@arm.com /** 16012724Snikos.nikoleris@arm.com * Override the default behaviour of sendDeferredPacket to enable 16112724Snikos.nikoleris@arm.com * the memory-side cache port to also send requests based on the 16212724Snikos.nikoleris@arm.com * current MSHR status. This queue has a pointer to our specific 16312724Snikos.nikoleris@arm.com * cache implementation and is used by the MemSidePort. 16412724Snikos.nikoleris@arm.com */ 16512724Snikos.nikoleris@arm.com class CacheReqPacketQueue : public ReqPacketQueue 16612724Snikos.nikoleris@arm.com { 16712724Snikos.nikoleris@arm.com 16812724Snikos.nikoleris@arm.com protected: 16912724Snikos.nikoleris@arm.com 17012724Snikos.nikoleris@arm.com BaseCache &cache; 17112724Snikos.nikoleris@arm.com SnoopRespPacketQueue &snoopRespQueue; 17212724Snikos.nikoleris@arm.com 17312724Snikos.nikoleris@arm.com public: 17412724Snikos.nikoleris@arm.com 17512724Snikos.nikoleris@arm.com CacheReqPacketQueue(BaseCache &cache, MasterPort &port, 17612724Snikos.nikoleris@arm.com SnoopRespPacketQueue &snoop_resp_queue, 17712724Snikos.nikoleris@arm.com const std::string &label) : 17812724Snikos.nikoleris@arm.com ReqPacketQueue(cache, port, label), cache(cache), 17912724Snikos.nikoleris@arm.com snoopRespQueue(snoop_resp_queue) { } 18012724Snikos.nikoleris@arm.com 18112724Snikos.nikoleris@arm.com /** 18212724Snikos.nikoleris@arm.com * Override the normal sendDeferredPacket and do not only 18312724Snikos.nikoleris@arm.com * consider the transmit list (used for responses), but also 18412724Snikos.nikoleris@arm.com * requests. 18512724Snikos.nikoleris@arm.com */ 18612724Snikos.nikoleris@arm.com virtual void sendDeferredPacket(); 18712724Snikos.nikoleris@arm.com 18812724Snikos.nikoleris@arm.com /** 18912724Snikos.nikoleris@arm.com * Check if there is a conflicting snoop response about to be 19012724Snikos.nikoleris@arm.com * send out, and if so simply stall any requests, and schedule 19112724Snikos.nikoleris@arm.com * a send event at the same time as the next snoop response is 19212724Snikos.nikoleris@arm.com * being sent out. 19313860Sodanrc@yahoo.com.br * 19413860Sodanrc@yahoo.com.br * @param pkt The packet to check for conflicts against. 19512724Snikos.nikoleris@arm.com */ 19613860Sodanrc@yahoo.com.br bool checkConflictingSnoop(const PacketPtr pkt) 19712724Snikos.nikoleris@arm.com { 19813860Sodanrc@yahoo.com.br if (snoopRespQueue.checkConflict(pkt, cache.blkSize)) { 19912724Snikos.nikoleris@arm.com DPRINTF(CachePort, "Waiting for snoop response to be " 20012724Snikos.nikoleris@arm.com "sent\n"); 20112724Snikos.nikoleris@arm.com Tick when = snoopRespQueue.deferredPacketReadyTime(); 20212724Snikos.nikoleris@arm.com schedSendEvent(when); 20312724Snikos.nikoleris@arm.com return true; 20412724Snikos.nikoleris@arm.com } 20512724Snikos.nikoleris@arm.com return false; 20612724Snikos.nikoleris@arm.com } 20712724Snikos.nikoleris@arm.com }; 20812724Snikos.nikoleris@arm.com 20912724Snikos.nikoleris@arm.com 21012724Snikos.nikoleris@arm.com /** 21112724Snikos.nikoleris@arm.com * The memory-side port extends the base cache master port with 21212724Snikos.nikoleris@arm.com * access functions for functional, atomic and timing snoops. 21312724Snikos.nikoleris@arm.com */ 21412724Snikos.nikoleris@arm.com class MemSidePort : public CacheMasterPort 21512724Snikos.nikoleris@arm.com { 21612724Snikos.nikoleris@arm.com private: 21712724Snikos.nikoleris@arm.com 21812724Snikos.nikoleris@arm.com /** The cache-specific queue. */ 21912724Snikos.nikoleris@arm.com CacheReqPacketQueue _reqQueue; 22012724Snikos.nikoleris@arm.com 22112724Snikos.nikoleris@arm.com SnoopRespPacketQueue _snoopRespQueue; 22212724Snikos.nikoleris@arm.com 22312724Snikos.nikoleris@arm.com // a pointer to our specific cache implementation 22412724Snikos.nikoleris@arm.com BaseCache *cache; 22512724Snikos.nikoleris@arm.com 22612724Snikos.nikoleris@arm.com protected: 22712724Snikos.nikoleris@arm.com 22812724Snikos.nikoleris@arm.com virtual void recvTimingSnoopReq(PacketPtr pkt); 22912724Snikos.nikoleris@arm.com 23012724Snikos.nikoleris@arm.com virtual bool recvTimingResp(PacketPtr pkt); 23112724Snikos.nikoleris@arm.com 23212724Snikos.nikoleris@arm.com virtual Tick recvAtomicSnoop(PacketPtr pkt); 23312724Snikos.nikoleris@arm.com 23412724Snikos.nikoleris@arm.com virtual void recvFunctionalSnoop(PacketPtr pkt); 23512724Snikos.nikoleris@arm.com 23612724Snikos.nikoleris@arm.com public: 23712724Snikos.nikoleris@arm.com 23812724Snikos.nikoleris@arm.com MemSidePort(const std::string &_name, BaseCache *_cache, 23912724Snikos.nikoleris@arm.com const std::string &_label); 24012724Snikos.nikoleris@arm.com }; 24112724Snikos.nikoleris@arm.com 24212724Snikos.nikoleris@arm.com /** 2438856Sandreas.hansson@arm.com * A cache slave port is used for the CPU-side port of the cache, 2448856Sandreas.hansson@arm.com * and it is basically a simple timing port that uses a transmit 2458856Sandreas.hansson@arm.com * list for responses to the CPU (or connected master). In 2468856Sandreas.hansson@arm.com * addition, it has the functionality to block the port for 2478856Sandreas.hansson@arm.com * incoming requests. If blocked, the port will issue a retry once 2488856Sandreas.hansson@arm.com * unblocked. 2498856Sandreas.hansson@arm.com */ 2508922Swilliam.wang@arm.com class CacheSlavePort : public QueuedSlavePort 2518856Sandreas.hansson@arm.com { 2525314SN/A 2532811SN/A public: 2548856Sandreas.hansson@arm.com 2558856Sandreas.hansson@arm.com /** Do not accept any new requests. */ 2562810SN/A void setBlocked(); 2572810SN/A 2588856Sandreas.hansson@arm.com /** Return to normal operation and accept new requests. */ 2592810SN/A void clearBlocked(); 2602810SN/A 26110345SCurtis.Dunham@arm.com bool isBlocked() const { return blocked; } 26210345SCurtis.Dunham@arm.com 2638856Sandreas.hansson@arm.com protected: 2648856Sandreas.hansson@arm.com 2658856Sandreas.hansson@arm.com CacheSlavePort(const std::string &_name, BaseCache *_cache, 2668856Sandreas.hansson@arm.com const std::string &_label); 2673606SN/A 2688914Sandreas.hansson@arm.com /** A normal packet queue used to store responses. */ 26910713Sandreas.hansson@arm.com RespPacketQueue queue; 2708914Sandreas.hansson@arm.com 2712810SN/A bool blocked; 2722810SN/A 2732897SN/A bool mustSendRetry; 2742897SN/A 2758856Sandreas.hansson@arm.com private: 2764458SN/A 27710344Sandreas.hansson@arm.com void processSendRetry(); 27810344Sandreas.hansson@arm.com 27912084Sspwilson2@wisc.edu EventFunctionWrapper sendRetryEvent; 2808856Sandreas.hansson@arm.com 2812811SN/A }; 2822810SN/A 28312724Snikos.nikoleris@arm.com /** 28412724Snikos.nikoleris@arm.com * The CPU-side port extends the base cache slave port with access 28512724Snikos.nikoleris@arm.com * functions for functional, atomic and timing requests. 28612724Snikos.nikoleris@arm.com */ 28712724Snikos.nikoleris@arm.com class CpuSidePort : public CacheSlavePort 28812724Snikos.nikoleris@arm.com { 28912724Snikos.nikoleris@arm.com private: 29012724Snikos.nikoleris@arm.com 29112724Snikos.nikoleris@arm.com // a pointer to our specific cache implementation 29212724Snikos.nikoleris@arm.com BaseCache *cache; 29312724Snikos.nikoleris@arm.com 29412724Snikos.nikoleris@arm.com protected: 29512724Snikos.nikoleris@arm.com virtual bool recvTimingSnoopResp(PacketPtr pkt) override; 29612724Snikos.nikoleris@arm.com 29712724Snikos.nikoleris@arm.com virtual bool tryTiming(PacketPtr pkt) override; 29812724Snikos.nikoleris@arm.com 29912724Snikos.nikoleris@arm.com virtual bool recvTimingReq(PacketPtr pkt) override; 30012724Snikos.nikoleris@arm.com 30112724Snikos.nikoleris@arm.com virtual Tick recvAtomic(PacketPtr pkt) override; 30212724Snikos.nikoleris@arm.com 30312724Snikos.nikoleris@arm.com virtual void recvFunctional(PacketPtr pkt) override; 30412724Snikos.nikoleris@arm.com 30512724Snikos.nikoleris@arm.com virtual AddrRangeList getAddrRanges() const override; 30612724Snikos.nikoleris@arm.com 30712724Snikos.nikoleris@arm.com public: 30812724Snikos.nikoleris@arm.com 30912724Snikos.nikoleris@arm.com CpuSidePort(const std::string &_name, BaseCache *_cache, 31012724Snikos.nikoleris@arm.com const std::string &_label); 31112724Snikos.nikoleris@arm.com 31212724Snikos.nikoleris@arm.com }; 31312724Snikos.nikoleris@arm.com 31412724Snikos.nikoleris@arm.com CpuSidePort cpuSidePort; 31512724Snikos.nikoleris@arm.com MemSidePort memSidePort; 3163338SN/A 3174626SN/A protected: 3184626SN/A 3194626SN/A /** Miss status registers */ 3204626SN/A MSHRQueue mshrQueue; 3214626SN/A 3224626SN/A /** Write/writeback buffer */ 32311375Sandreas.hansson@arm.com WriteQueue writeBuffer; 3244626SN/A 32512724Snikos.nikoleris@arm.com /** Tag and data Storage */ 32612724Snikos.nikoleris@arm.com BaseTags *tags; 32712724Snikos.nikoleris@arm.com 32813945Sodanrc@yahoo.com.br /** Compression method being used. */ 32913945Sodanrc@yahoo.com.br BaseCacheCompressor* compressor; 33013945Sodanrc@yahoo.com.br 33112724Snikos.nikoleris@arm.com /** Prefetcher */ 33212724Snikos.nikoleris@arm.com BasePrefetcher *prefetcher; 33312724Snikos.nikoleris@arm.com 33413416Sjavier.bueno@metempsy.com /** To probe when a cache hit occurs */ 33513416Sjavier.bueno@metempsy.com ProbePointArg<PacketPtr> *ppHit; 33613416Sjavier.bueno@metempsy.com 33713416Sjavier.bueno@metempsy.com /** To probe when a cache miss occurs */ 33813416Sjavier.bueno@metempsy.com ProbePointArg<PacketPtr> *ppMiss; 33912724Snikos.nikoleris@arm.com 34013717Sivan.pizarro@metempsy.com /** To probe when a cache fill occurs */ 34113717Sivan.pizarro@metempsy.com ProbePointArg<PacketPtr> *ppFill; 34213717Sivan.pizarro@metempsy.com 34312724Snikos.nikoleris@arm.com /** 34413352Snikos.nikoleris@arm.com * The writeAllocator drive optimizations for streaming writes. 34513352Snikos.nikoleris@arm.com * It first determines whether a WriteReq MSHR should be delayed, 34613352Snikos.nikoleris@arm.com * thus ensuring that we wait longer in cases when we are write 34713352Snikos.nikoleris@arm.com * coalescing and allowing all the bytes of the line to be written 34813352Snikos.nikoleris@arm.com * before the MSHR packet is sent downstream. This works in unison 34913352Snikos.nikoleris@arm.com * with the tracking in the MSHR to check if the entire line is 35013352Snikos.nikoleris@arm.com * written. The write mode also affects the behaviour on filling 35113352Snikos.nikoleris@arm.com * any whole-line writes. Normally the cache allocates the line 35213352Snikos.nikoleris@arm.com * when receiving the InvalidateResp, but after seeing enough 35313352Snikos.nikoleris@arm.com * consecutive lines we switch to using the tempBlock, and thus 35413352Snikos.nikoleris@arm.com * end up not allocating the line, and instead turning the 35513352Snikos.nikoleris@arm.com * whole-line write into a writeback straight away. 35613352Snikos.nikoleris@arm.com */ 35713352Snikos.nikoleris@arm.com WriteAllocator * const writeAllocator; 35813352Snikos.nikoleris@arm.com 35913352Snikos.nikoleris@arm.com /** 36012724Snikos.nikoleris@arm.com * Temporary cache block for occasional transitory use. We use 36112724Snikos.nikoleris@arm.com * the tempBlock to fill when allocation fails (e.g., when there 36212724Snikos.nikoleris@arm.com * is an outstanding request that accesses the victim block) or 36312724Snikos.nikoleris@arm.com * when we want to avoid allocation (e.g., exclusive caches) 36412724Snikos.nikoleris@arm.com */ 36512730Sodanrc@yahoo.com.br TempCacheBlk *tempBlock; 36612724Snikos.nikoleris@arm.com 36712724Snikos.nikoleris@arm.com /** 36812724Snikos.nikoleris@arm.com * Upstream caches need this packet until true is returned, so 36912724Snikos.nikoleris@arm.com * hold it for deletion until a subsequent call 37012724Snikos.nikoleris@arm.com */ 37112724Snikos.nikoleris@arm.com std::unique_ptr<Packet> pendingDelete; 37212724Snikos.nikoleris@arm.com 37310693SMarco.Balboni@ARM.com /** 37411375Sandreas.hansson@arm.com * Mark a request as in service (sent downstream in the memory 37511375Sandreas.hansson@arm.com * system), effectively making this MSHR the ordering point. 37610693SMarco.Balboni@ARM.com */ 37711375Sandreas.hansson@arm.com void markInService(MSHR *mshr, bool pending_modified_resp) 3784628SN/A { 37911375Sandreas.hansson@arm.com bool wasFull = mshrQueue.isFull(); 38011375Sandreas.hansson@arm.com mshrQueue.markInService(mshr, pending_modified_resp); 38110764Sandreas.hansson@arm.com 38211375Sandreas.hansson@arm.com if (wasFull && !mshrQueue.isFull()) { 38311375Sandreas.hansson@arm.com clearBlocked(Blocked_NoMSHRs); 3844628SN/A } 3854628SN/A } 3864628SN/A 38711375Sandreas.hansson@arm.com void markInService(WriteQueueEntry *entry) 3884628SN/A { 38911375Sandreas.hansson@arm.com bool wasFull = writeBuffer.isFull(); 39011375Sandreas.hansson@arm.com writeBuffer.markInService(entry); 39111375Sandreas.hansson@arm.com 39211375Sandreas.hansson@arm.com if (wasFull && !writeBuffer.isFull()) { 39311375Sandreas.hansson@arm.com clearBlocked(Blocked_NoWBBuffers); 3944628SN/A } 3954628SN/A } 3964628SN/A 3979347SAndreas.Sandberg@arm.com /** 39812724Snikos.nikoleris@arm.com * Determine whether we should allocate on a fill or not. If this 39912724Snikos.nikoleris@arm.com * cache is mostly inclusive with regards to the upstream cache(s) 40012724Snikos.nikoleris@arm.com * we always allocate (for any non-forwarded and cacheable 40112724Snikos.nikoleris@arm.com * requests). In the case of a mostly exclusive cache, we allocate 40212724Snikos.nikoleris@arm.com * on fill if the packet did not come from a cache, thus if we: 40312724Snikos.nikoleris@arm.com * are dealing with a whole-line write (the latter behaves much 40412724Snikos.nikoleris@arm.com * like a writeback), the original target packet came from a 40512724Snikos.nikoleris@arm.com * non-caching source, or if we are performing a prefetch or LLSC. 40611197Sandreas.hansson@arm.com * 40712724Snikos.nikoleris@arm.com * @param cmd Command of the incoming requesting packet 40812724Snikos.nikoleris@arm.com * @return Whether we should allocate on the fill 40912724Snikos.nikoleris@arm.com */ 41012724Snikos.nikoleris@arm.com inline bool allocOnFill(MemCmd cmd) const 41112724Snikos.nikoleris@arm.com { 41212724Snikos.nikoleris@arm.com return clusivity == Enums::mostly_incl || 41312724Snikos.nikoleris@arm.com cmd == MemCmd::WriteLineReq || 41412724Snikos.nikoleris@arm.com cmd == MemCmd::ReadReq || 41512724Snikos.nikoleris@arm.com cmd == MemCmd::WriteReq || 41612724Snikos.nikoleris@arm.com cmd.isPrefetch() || 41712724Snikos.nikoleris@arm.com cmd.isLLSC(); 41812724Snikos.nikoleris@arm.com } 41912724Snikos.nikoleris@arm.com 42012724Snikos.nikoleris@arm.com /** 42112730Sodanrc@yahoo.com.br * Regenerate block address using tags. 42212730Sodanrc@yahoo.com.br * Block address regeneration depends on whether we're using a temporary 42312730Sodanrc@yahoo.com.br * block or not. 42412730Sodanrc@yahoo.com.br * 42512730Sodanrc@yahoo.com.br * @param blk The block to regenerate address. 42612730Sodanrc@yahoo.com.br * @return The block's address. 42712730Sodanrc@yahoo.com.br */ 42812730Sodanrc@yahoo.com.br Addr regenerateBlkAddr(CacheBlk* blk); 42912730Sodanrc@yahoo.com.br 43012730Sodanrc@yahoo.com.br /** 43113749Sodanrc@yahoo.com.br * Calculate latency of accesses that only touch the tag array. 43213749Sodanrc@yahoo.com.br * @sa calculateAccessLatency 43313749Sodanrc@yahoo.com.br * 43413749Sodanrc@yahoo.com.br * @param delay The delay until the packet's metadata is present. 43513749Sodanrc@yahoo.com.br * @param lookup_lat Latency of the respective tag lookup. 43613749Sodanrc@yahoo.com.br * @return The number of ticks that pass due to a tag-only access. 43713749Sodanrc@yahoo.com.br */ 43813749Sodanrc@yahoo.com.br Cycles calculateTagOnlyLatency(const uint32_t delay, 43913749Sodanrc@yahoo.com.br const Cycles lookup_lat) const; 44013749Sodanrc@yahoo.com.br /** 44113418Sodanrc@yahoo.com.br * Calculate access latency in ticks given a tag lookup latency, and 44213418Sodanrc@yahoo.com.br * whether access was a hit or miss. 44313418Sodanrc@yahoo.com.br * 44413418Sodanrc@yahoo.com.br * @param blk The cache block that was accessed. 44513746Sodanrc@yahoo.com.br * @param delay The delay until the packet's metadata is present. 44613418Sodanrc@yahoo.com.br * @param lookup_lat Latency of the respective tag lookup. 44713418Sodanrc@yahoo.com.br * @return The number of ticks that pass due to a block access. 44813418Sodanrc@yahoo.com.br */ 44913746Sodanrc@yahoo.com.br Cycles calculateAccessLatency(const CacheBlk* blk, const uint32_t delay, 45013418Sodanrc@yahoo.com.br const Cycles lookup_lat) const; 45113418Sodanrc@yahoo.com.br 45213418Sodanrc@yahoo.com.br /** 45312724Snikos.nikoleris@arm.com * Does all the processing necessary to perform the provided request. 45412724Snikos.nikoleris@arm.com * @param pkt The memory request to perform. 45512724Snikos.nikoleris@arm.com * @param blk The cache block to be updated. 45612724Snikos.nikoleris@arm.com * @param lat The latency of the access. 45714035Sodanrc@yahoo.com.br * @param writebacks List for any writebacks that need to be performed. 45812724Snikos.nikoleris@arm.com * @return Boolean indicating whether the request was satisfied. 45912724Snikos.nikoleris@arm.com */ 46014035Sodanrc@yahoo.com.br virtual bool access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat, 46114035Sodanrc@yahoo.com.br PacketList &writebacks); 46212724Snikos.nikoleris@arm.com 46312724Snikos.nikoleris@arm.com /* 46412724Snikos.nikoleris@arm.com * Handle a timing request that hit in the cache 46511197Sandreas.hansson@arm.com * 46612724Snikos.nikoleris@arm.com * @param ptk The request packet 46712724Snikos.nikoleris@arm.com * @param blk The referenced block 46812724Snikos.nikoleris@arm.com * @param request_time The tick at which the block lookup is compete 46911197Sandreas.hansson@arm.com */ 47012724Snikos.nikoleris@arm.com virtual void handleTimingReqHit(PacketPtr pkt, CacheBlk *blk, 47112724Snikos.nikoleris@arm.com Tick request_time); 47212724Snikos.nikoleris@arm.com 47312724Snikos.nikoleris@arm.com /* 47412724Snikos.nikoleris@arm.com * Handle a timing request that missed in the cache 47512724Snikos.nikoleris@arm.com * 47612724Snikos.nikoleris@arm.com * Implementation specific handling for different cache 47712724Snikos.nikoleris@arm.com * implementations 47812724Snikos.nikoleris@arm.com * 47912724Snikos.nikoleris@arm.com * @param ptk The request packet 48012724Snikos.nikoleris@arm.com * @param blk The referenced block 48112724Snikos.nikoleris@arm.com * @param forward_time The tick at which we can process dependent requests 48212724Snikos.nikoleris@arm.com * @param request_time The tick at which the block lookup is compete 48312724Snikos.nikoleris@arm.com */ 48412724Snikos.nikoleris@arm.com virtual void handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk, 48512724Snikos.nikoleris@arm.com Tick forward_time, 48612724Snikos.nikoleris@arm.com Tick request_time) = 0; 48712724Snikos.nikoleris@arm.com 48812724Snikos.nikoleris@arm.com /* 48912724Snikos.nikoleris@arm.com * Handle a timing request that missed in the cache 49012724Snikos.nikoleris@arm.com * 49112724Snikos.nikoleris@arm.com * Common functionality across different cache implementations 49212724Snikos.nikoleris@arm.com * 49312724Snikos.nikoleris@arm.com * @param ptk The request packet 49412724Snikos.nikoleris@arm.com * @param blk The referenced block 49512724Snikos.nikoleris@arm.com * @param mshr Any existing mshr for the referenced cache block 49612724Snikos.nikoleris@arm.com * @param forward_time The tick at which we can process dependent requests 49712724Snikos.nikoleris@arm.com * @param request_time The tick at which the block lookup is compete 49812724Snikos.nikoleris@arm.com */ 49912724Snikos.nikoleris@arm.com void handleTimingReqMiss(PacketPtr pkt, MSHR *mshr, CacheBlk *blk, 50012724Snikos.nikoleris@arm.com Tick forward_time, Tick request_time); 50112724Snikos.nikoleris@arm.com 50212724Snikos.nikoleris@arm.com /** 50312724Snikos.nikoleris@arm.com * Performs the access specified by the request. 50412724Snikos.nikoleris@arm.com * @param pkt The request to perform. 50512724Snikos.nikoleris@arm.com */ 50612724Snikos.nikoleris@arm.com virtual void recvTimingReq(PacketPtr pkt); 50712724Snikos.nikoleris@arm.com 50812724Snikos.nikoleris@arm.com /** 50912724Snikos.nikoleris@arm.com * Handling the special case of uncacheable write responses to 51012724Snikos.nikoleris@arm.com * make recvTimingResp less cluttered. 51112724Snikos.nikoleris@arm.com */ 51212724Snikos.nikoleris@arm.com void handleUncacheableWriteResp(PacketPtr pkt); 51312724Snikos.nikoleris@arm.com 51412724Snikos.nikoleris@arm.com /** 51512724Snikos.nikoleris@arm.com * Service non-deferred MSHR targets using the received response 51612724Snikos.nikoleris@arm.com * 51712724Snikos.nikoleris@arm.com * Iterates through the list of targets that can be serviced with 51813478Sodanrc@yahoo.com.br * the current response. 51912724Snikos.nikoleris@arm.com * 52012724Snikos.nikoleris@arm.com * @param mshr The MSHR that corresponds to the reponse 52112724Snikos.nikoleris@arm.com * @param pkt The response packet 52212724Snikos.nikoleris@arm.com * @param blk The reference block 52312724Snikos.nikoleris@arm.com */ 52412724Snikos.nikoleris@arm.com virtual void serviceMSHRTargets(MSHR *mshr, const PacketPtr pkt, 52513478Sodanrc@yahoo.com.br CacheBlk *blk) = 0; 52612724Snikos.nikoleris@arm.com 52712724Snikos.nikoleris@arm.com /** 52812724Snikos.nikoleris@arm.com * Handles a response (cache line fill/write ack) from the bus. 52912724Snikos.nikoleris@arm.com * @param pkt The response packet 53012724Snikos.nikoleris@arm.com */ 53112724Snikos.nikoleris@arm.com virtual void recvTimingResp(PacketPtr pkt); 53212724Snikos.nikoleris@arm.com 53312724Snikos.nikoleris@arm.com /** 53412724Snikos.nikoleris@arm.com * Snoops bus transactions to maintain coherence. 53512724Snikos.nikoleris@arm.com * @param pkt The current bus transaction. 53612724Snikos.nikoleris@arm.com */ 53712724Snikos.nikoleris@arm.com virtual void recvTimingSnoopReq(PacketPtr pkt) = 0; 53812724Snikos.nikoleris@arm.com 53912724Snikos.nikoleris@arm.com /** 54012724Snikos.nikoleris@arm.com * Handle a snoop response. 54112724Snikos.nikoleris@arm.com * @param pkt Snoop response packet 54212724Snikos.nikoleris@arm.com */ 54312724Snikos.nikoleris@arm.com virtual void recvTimingSnoopResp(PacketPtr pkt) = 0; 54412724Snikos.nikoleris@arm.com 54512724Snikos.nikoleris@arm.com /** 54612724Snikos.nikoleris@arm.com * Handle a request in atomic mode that missed in this cache 54712724Snikos.nikoleris@arm.com * 54812724Snikos.nikoleris@arm.com * Creates a downstream request, sends it to the memory below and 54912724Snikos.nikoleris@arm.com * handles the response. As we are in atomic mode all operations 55012724Snikos.nikoleris@arm.com * are performed immediately. 55112724Snikos.nikoleris@arm.com * 55212724Snikos.nikoleris@arm.com * @param pkt The packet with the requests 55312724Snikos.nikoleris@arm.com * @param blk The referenced block 55414035Sodanrc@yahoo.com.br * @param writebacks A list with packets for any performed writebacks 55512724Snikos.nikoleris@arm.com * @return Cycles for handling the request 55612724Snikos.nikoleris@arm.com */ 55714035Sodanrc@yahoo.com.br virtual Cycles handleAtomicReqMiss(PacketPtr pkt, CacheBlk *&blk, 55814035Sodanrc@yahoo.com.br PacketList &writebacks) = 0; 55912724Snikos.nikoleris@arm.com 56012724Snikos.nikoleris@arm.com /** 56112724Snikos.nikoleris@arm.com * Performs the access specified by the request. 56212724Snikos.nikoleris@arm.com * @param pkt The request to perform. 56312724Snikos.nikoleris@arm.com * @return The number of ticks required for the access. 56412724Snikos.nikoleris@arm.com */ 56512724Snikos.nikoleris@arm.com virtual Tick recvAtomic(PacketPtr pkt); 56612724Snikos.nikoleris@arm.com 56712724Snikos.nikoleris@arm.com /** 56812724Snikos.nikoleris@arm.com * Snoop for the provided request in the cache and return the estimated 56912724Snikos.nikoleris@arm.com * time taken. 57012724Snikos.nikoleris@arm.com * @param pkt The memory request to snoop 57112724Snikos.nikoleris@arm.com * @return The number of ticks required for the snoop. 57212724Snikos.nikoleris@arm.com */ 57312724Snikos.nikoleris@arm.com virtual Tick recvAtomicSnoop(PacketPtr pkt) = 0; 57412724Snikos.nikoleris@arm.com 57512724Snikos.nikoleris@arm.com /** 57612724Snikos.nikoleris@arm.com * Performs the access specified by the request. 57712724Snikos.nikoleris@arm.com * 57812724Snikos.nikoleris@arm.com * @param pkt The request to perform. 57912724Snikos.nikoleris@arm.com * @param fromCpuSide from the CPU side port or the memory side port 58012724Snikos.nikoleris@arm.com */ 58112724Snikos.nikoleris@arm.com virtual void functionalAccess(PacketPtr pkt, bool from_cpu_side); 58212724Snikos.nikoleris@arm.com 58312724Snikos.nikoleris@arm.com /** 58412724Snikos.nikoleris@arm.com * Handle doing the Compare and Swap function for SPARC. 58512724Snikos.nikoleris@arm.com */ 58612724Snikos.nikoleris@arm.com void cmpAndSwap(CacheBlk *blk, PacketPtr pkt); 58712724Snikos.nikoleris@arm.com 58812724Snikos.nikoleris@arm.com /** 58912724Snikos.nikoleris@arm.com * Return the next queue entry to service, either a pending miss 59012724Snikos.nikoleris@arm.com * from the MSHR queue, a buffered write from the write buffer, or 59112724Snikos.nikoleris@arm.com * something from the prefetcher. This function is responsible 59212724Snikos.nikoleris@arm.com * for prioritizing among those sources on the fly. 59312724Snikos.nikoleris@arm.com */ 59412724Snikos.nikoleris@arm.com QueueEntry* getNextQueueEntry(); 59512724Snikos.nikoleris@arm.com 59612724Snikos.nikoleris@arm.com /** 59712724Snikos.nikoleris@arm.com * Insert writebacks into the write buffer 59812724Snikos.nikoleris@arm.com */ 59914035Sodanrc@yahoo.com.br virtual void doWritebacks(PacketList& writebacks, Tick forward_time) = 0; 60012724Snikos.nikoleris@arm.com 60112724Snikos.nikoleris@arm.com /** 60214035Sodanrc@yahoo.com.br * Send writebacks down the memory hierarchy in atomic mode 60312724Snikos.nikoleris@arm.com */ 60414035Sodanrc@yahoo.com.br virtual void doWritebacksAtomic(PacketList& writebacks) = 0; 60512724Snikos.nikoleris@arm.com 60612724Snikos.nikoleris@arm.com /** 60712724Snikos.nikoleris@arm.com * Create an appropriate downstream bus request packet. 60812724Snikos.nikoleris@arm.com * 60912724Snikos.nikoleris@arm.com * Creates a new packet with the request to be send to the memory 61012724Snikos.nikoleris@arm.com * below, or nullptr if the current request in cpu_pkt should just 61112724Snikos.nikoleris@arm.com * be forwarded on. 61212724Snikos.nikoleris@arm.com * 61312724Snikos.nikoleris@arm.com * @param cpu_pkt The miss packet that needs to be satisfied. 61412724Snikos.nikoleris@arm.com * @param blk The referenced block, can be nullptr. 61512724Snikos.nikoleris@arm.com * @param needs_writable Indicates that the block must be writable 61612724Snikos.nikoleris@arm.com * even if the request in cpu_pkt doesn't indicate that. 61713350Snikos.nikoleris@arm.com * @param is_whole_line_write True if there are writes for the 61813350Snikos.nikoleris@arm.com * whole line 61912724Snikos.nikoleris@arm.com * @return A packet send to the memory below 62012724Snikos.nikoleris@arm.com */ 62112724Snikos.nikoleris@arm.com virtual PacketPtr createMissPacket(PacketPtr cpu_pkt, CacheBlk *blk, 62213350Snikos.nikoleris@arm.com bool needs_writable, 62313350Snikos.nikoleris@arm.com bool is_whole_line_write) const = 0; 62412724Snikos.nikoleris@arm.com 62512724Snikos.nikoleris@arm.com /** 62612724Snikos.nikoleris@arm.com * Determine if clean lines should be written back or not. In 62712724Snikos.nikoleris@arm.com * cases where a downstream cache is mostly inclusive we likely 62812724Snikos.nikoleris@arm.com * want it to act as a victim cache also for lines that have not 62912724Snikos.nikoleris@arm.com * been modified. Hence, we cannot simply drop the line (or send a 63012724Snikos.nikoleris@arm.com * clean evict), but rather need to send the actual data. 63112724Snikos.nikoleris@arm.com */ 63212724Snikos.nikoleris@arm.com const bool writebackClean; 63312724Snikos.nikoleris@arm.com 63412724Snikos.nikoleris@arm.com /** 63512724Snikos.nikoleris@arm.com * Writebacks from the tempBlock, resulting on the response path 63612724Snikos.nikoleris@arm.com * in atomic mode, must happen after the call to recvAtomic has 63712724Snikos.nikoleris@arm.com * finished (for the right ordering of the packets). We therefore 63812724Snikos.nikoleris@arm.com * need to hold on to the packets, and have a method and an event 63912724Snikos.nikoleris@arm.com * to send them. 64012724Snikos.nikoleris@arm.com */ 64112724Snikos.nikoleris@arm.com PacketPtr tempBlockWriteback; 64212724Snikos.nikoleris@arm.com 64312724Snikos.nikoleris@arm.com /** 64412724Snikos.nikoleris@arm.com * Send the outstanding tempBlock writeback. To be called after 64512724Snikos.nikoleris@arm.com * recvAtomic finishes in cases where the block we filled is in 64612724Snikos.nikoleris@arm.com * fact the tempBlock, and now needs to be written back. 64712724Snikos.nikoleris@arm.com */ 64812724Snikos.nikoleris@arm.com void writebackTempBlockAtomic() { 64912724Snikos.nikoleris@arm.com assert(tempBlockWriteback != nullptr); 65014035Sodanrc@yahoo.com.br PacketList writebacks{tempBlockWriteback}; 65114035Sodanrc@yahoo.com.br doWritebacksAtomic(writebacks); 65212724Snikos.nikoleris@arm.com tempBlockWriteback = nullptr; 65312724Snikos.nikoleris@arm.com } 65412724Snikos.nikoleris@arm.com 65512724Snikos.nikoleris@arm.com /** 65612724Snikos.nikoleris@arm.com * An event to writeback the tempBlock after recvAtomic 65712724Snikos.nikoleris@arm.com * finishes. To avoid other calls to recvAtomic getting in 65812724Snikos.nikoleris@arm.com * between, we create this event with a higher priority. 65912724Snikos.nikoleris@arm.com */ 66012724Snikos.nikoleris@arm.com EventFunctionWrapper writebackTempBlockAtomicEvent; 66112724Snikos.nikoleris@arm.com 66212724Snikos.nikoleris@arm.com /** 66313947Sodanrc@yahoo.com.br * When a block is overwriten, its compression information must be updated, 66413947Sodanrc@yahoo.com.br * and it may need to be recompressed. If the compression size changes, the 66513947Sodanrc@yahoo.com.br * block may either become smaller, in which case there is no side effect, 66613947Sodanrc@yahoo.com.br * or bigger (data expansion; fat write), in which case the block might not 66713947Sodanrc@yahoo.com.br * fit in its current location anymore. If that happens, there are usually 66813947Sodanrc@yahoo.com.br * two options to be taken: 66913947Sodanrc@yahoo.com.br * 67013947Sodanrc@yahoo.com.br * - The co-allocated blocks must be evicted to make room for this block. 67113947Sodanrc@yahoo.com.br * Simpler, but ignores replacement data. 67213947Sodanrc@yahoo.com.br * - The block itself is moved elsewhere (used in policies where the CF 67313947Sodanrc@yahoo.com.br * determines the location of the block). 67413947Sodanrc@yahoo.com.br * 67513947Sodanrc@yahoo.com.br * This implementation uses the first approach. 67613947Sodanrc@yahoo.com.br * 67713947Sodanrc@yahoo.com.br * Notice that this is only called for writebacks, which means that L1 67813947Sodanrc@yahoo.com.br * caches (which see regular Writes), do not support compression. 67913947Sodanrc@yahoo.com.br * @sa CompressedTags 68013947Sodanrc@yahoo.com.br * 68113947Sodanrc@yahoo.com.br * @param blk The block to be overwriten. 68213947Sodanrc@yahoo.com.br * @param data A pointer to the data to be compressed (blk's new data). 68314035Sodanrc@yahoo.com.br * @param writebacks List for any writebacks that need to be performed. 68413947Sodanrc@yahoo.com.br * @return Whether operation is successful or not. 68513947Sodanrc@yahoo.com.br */ 68613947Sodanrc@yahoo.com.br bool updateCompressionData(CacheBlk *blk, const uint64_t* data, 68714035Sodanrc@yahoo.com.br PacketList &writebacks); 68813947Sodanrc@yahoo.com.br 68913947Sodanrc@yahoo.com.br /** 69012724Snikos.nikoleris@arm.com * Perform any necessary updates to the block and perform any data 69112724Snikos.nikoleris@arm.com * exchange between the packet and the block. The flags of the 69212724Snikos.nikoleris@arm.com * packet are also set accordingly. 69312724Snikos.nikoleris@arm.com * 69412724Snikos.nikoleris@arm.com * @param pkt Request packet from upstream that hit a block 69512724Snikos.nikoleris@arm.com * @param blk Cache block that the packet hit 69612724Snikos.nikoleris@arm.com * @param deferred_response Whether this request originally missed 69712724Snikos.nikoleris@arm.com * @param pending_downgrade Whether the writable flag is to be removed 69812724Snikos.nikoleris@arm.com */ 69912724Snikos.nikoleris@arm.com virtual void satisfyRequest(PacketPtr pkt, CacheBlk *blk, 70012724Snikos.nikoleris@arm.com bool deferred_response = false, 70112724Snikos.nikoleris@arm.com bool pending_downgrade = false); 70212724Snikos.nikoleris@arm.com 70312724Snikos.nikoleris@arm.com /** 70412724Snikos.nikoleris@arm.com * Maintain the clusivity of this cache by potentially 70512724Snikos.nikoleris@arm.com * invalidating a block. This method works in conjunction with 70612724Snikos.nikoleris@arm.com * satisfyRequest, but is separate to allow us to handle all MSHR 70712724Snikos.nikoleris@arm.com * targets before potentially dropping a block. 70812724Snikos.nikoleris@arm.com * 70912724Snikos.nikoleris@arm.com * @param from_cache Whether we have dealt with a packet from a cache 71012724Snikos.nikoleris@arm.com * @param blk The block that should potentially be dropped 71112724Snikos.nikoleris@arm.com */ 71212724Snikos.nikoleris@arm.com void maintainClusivity(bool from_cache, CacheBlk *blk); 71312724Snikos.nikoleris@arm.com 71412724Snikos.nikoleris@arm.com /** 71512724Snikos.nikoleris@arm.com * Handle a fill operation caused by a received packet. 71612724Snikos.nikoleris@arm.com * 71712724Snikos.nikoleris@arm.com * Populates a cache block and handles all outstanding requests for the 71812724Snikos.nikoleris@arm.com * satisfied fill request. This version takes two memory requests. One 71912724Snikos.nikoleris@arm.com * contains the fill data, the other is an optional target to satisfy. 72014035Sodanrc@yahoo.com.br * Note that the reason we return a list of writebacks rather than 72114035Sodanrc@yahoo.com.br * inserting them directly in the write buffer is that this function 72214035Sodanrc@yahoo.com.br * is called by both atomic and timing-mode accesses, and in atomic 72314035Sodanrc@yahoo.com.br * mode we don't mess with the write buffer (we just perform the 72414035Sodanrc@yahoo.com.br * writebacks atomically once the original request is complete). 72512724Snikos.nikoleris@arm.com * 72612724Snikos.nikoleris@arm.com * @param pkt The memory request with the fill data. 72712724Snikos.nikoleris@arm.com * @param blk The cache block if it already exists. 72814035Sodanrc@yahoo.com.br * @param writebacks List for any writebacks that need to be performed. 72912724Snikos.nikoleris@arm.com * @param allocate Whether to allocate a block or use the temp block 73012724Snikos.nikoleris@arm.com * @return Pointer to the new cache block. 73112724Snikos.nikoleris@arm.com */ 73214035Sodanrc@yahoo.com.br CacheBlk *handleFill(PacketPtr pkt, CacheBlk *blk, 73314035Sodanrc@yahoo.com.br PacketList &writebacks, bool allocate); 73412724Snikos.nikoleris@arm.com 73512724Snikos.nikoleris@arm.com /** 73614035Sodanrc@yahoo.com.br * Allocate a new block and perform any necessary writebacks 73714035Sodanrc@yahoo.com.br * 73814035Sodanrc@yahoo.com.br * Find a victim block and if necessary prepare writebacks for any 73914035Sodanrc@yahoo.com.br * existing data. May return nullptr if there are no replaceable 74014035Sodanrc@yahoo.com.br * blocks. If a replaceable block is found, it inserts the new block in 74114035Sodanrc@yahoo.com.br * its place. The new block, however, is not set as valid yet. 74212724Snikos.nikoleris@arm.com * 74312754Sodanrc@yahoo.com.br * @param pkt Packet holding the address to update 74414035Sodanrc@yahoo.com.br * @param writebacks A list of writeback packets for the evicted blocks 74512724Snikos.nikoleris@arm.com * @return the allocated block 74612724Snikos.nikoleris@arm.com */ 74714035Sodanrc@yahoo.com.br CacheBlk *allocateBlock(const PacketPtr pkt, PacketList &writebacks); 74812724Snikos.nikoleris@arm.com /** 74912724Snikos.nikoleris@arm.com * Evict a cache block. 75012724Snikos.nikoleris@arm.com * 75112724Snikos.nikoleris@arm.com * Performs a writeback if necesssary and invalidates the block 75212724Snikos.nikoleris@arm.com * 75312724Snikos.nikoleris@arm.com * @param blk Block to invalidate 75412724Snikos.nikoleris@arm.com * @return A packet with the writeback, can be nullptr 75512724Snikos.nikoleris@arm.com */ 75612724Snikos.nikoleris@arm.com M5_NODISCARD virtual PacketPtr evictBlock(CacheBlk *blk) = 0; 75712724Snikos.nikoleris@arm.com 75812724Snikos.nikoleris@arm.com /** 75912724Snikos.nikoleris@arm.com * Evict a cache block. 76012724Snikos.nikoleris@arm.com * 76112724Snikos.nikoleris@arm.com * Performs a writeback if necesssary and invalidates the block 76212724Snikos.nikoleris@arm.com * 76312724Snikos.nikoleris@arm.com * @param blk Block to invalidate 76414035Sodanrc@yahoo.com.br * @param writebacks Return a list of packets with writebacks 76512724Snikos.nikoleris@arm.com */ 76614035Sodanrc@yahoo.com.br void evictBlock(CacheBlk *blk, PacketList &writebacks); 76712724Snikos.nikoleris@arm.com 76812724Snikos.nikoleris@arm.com /** 76912724Snikos.nikoleris@arm.com * Invalidate a cache block. 77012724Snikos.nikoleris@arm.com * 77112724Snikos.nikoleris@arm.com * @param blk Block to invalidate 77212724Snikos.nikoleris@arm.com */ 77312724Snikos.nikoleris@arm.com void invalidateBlock(CacheBlk *blk); 77412724Snikos.nikoleris@arm.com 77512724Snikos.nikoleris@arm.com /** 77612724Snikos.nikoleris@arm.com * Create a writeback request for the given block. 77712724Snikos.nikoleris@arm.com * 77812724Snikos.nikoleris@arm.com * @param blk The block to writeback. 77912724Snikos.nikoleris@arm.com * @return The writeback request for the block. 78012724Snikos.nikoleris@arm.com */ 78112724Snikos.nikoleris@arm.com PacketPtr writebackBlk(CacheBlk *blk); 78212724Snikos.nikoleris@arm.com 78312724Snikos.nikoleris@arm.com /** 78412724Snikos.nikoleris@arm.com * Create a writeclean request for the given block. 78512724Snikos.nikoleris@arm.com * 78612724Snikos.nikoleris@arm.com * Creates a request that writes the block to the cache below 78712724Snikos.nikoleris@arm.com * without evicting the block from the current cache. 78812724Snikos.nikoleris@arm.com * 78912724Snikos.nikoleris@arm.com * @param blk The block to write clean. 79012724Snikos.nikoleris@arm.com * @param dest The destination of the write clean operation. 79112724Snikos.nikoleris@arm.com * @param id Use the given packet id for the write clean operation. 79212724Snikos.nikoleris@arm.com * @return The generated write clean packet. 79312724Snikos.nikoleris@arm.com */ 79412724Snikos.nikoleris@arm.com PacketPtr writecleanBlk(CacheBlk *blk, Request::Flags dest, PacketId id); 79511197Sandreas.hansson@arm.com 79611197Sandreas.hansson@arm.com /** 7979347SAndreas.Sandberg@arm.com * Write back dirty blocks in the cache using functional accesses. 7989347SAndreas.Sandberg@arm.com */ 79912724Snikos.nikoleris@arm.com virtual void memWriteback() override; 80012724Snikos.nikoleris@arm.com 8019347SAndreas.Sandberg@arm.com /** 8029347SAndreas.Sandberg@arm.com * Invalidates all blocks in the cache. 8039347SAndreas.Sandberg@arm.com * 8049347SAndreas.Sandberg@arm.com * @warn Dirty cache lines will not be written back to 8059347SAndreas.Sandberg@arm.com * memory. Make sure to call functionalWriteback() first if you 8069347SAndreas.Sandberg@arm.com * want the to write them to memory. 8079347SAndreas.Sandberg@arm.com */ 80812724Snikos.nikoleris@arm.com virtual void memInvalidate() override; 80912724Snikos.nikoleris@arm.com 8109347SAndreas.Sandberg@arm.com /** 8119347SAndreas.Sandberg@arm.com * Determine if there are any dirty blocks in the cache. 8129347SAndreas.Sandberg@arm.com * 81312724Snikos.nikoleris@arm.com * @return true if at least one block is dirty, false otherwise. 8149347SAndreas.Sandberg@arm.com */ 81512724Snikos.nikoleris@arm.com bool isDirty() const; 8169347SAndreas.Sandberg@arm.com 81710821Sandreas.hansson@arm.com /** 81810821Sandreas.hansson@arm.com * Determine if an address is in the ranges covered by this 81910821Sandreas.hansson@arm.com * cache. This is useful to filter snoops. 82010821Sandreas.hansson@arm.com * 82110821Sandreas.hansson@arm.com * @param addr Address to check against 82210821Sandreas.hansson@arm.com * 82310821Sandreas.hansson@arm.com * @return If the address in question is in range 82410821Sandreas.hansson@arm.com */ 82510821Sandreas.hansson@arm.com bool inRange(Addr addr) const; 82610821Sandreas.hansson@arm.com 82712724Snikos.nikoleris@arm.com /** 82812724Snikos.nikoleris@arm.com * Find next request ready time from among possible sources. 82912724Snikos.nikoleris@arm.com */ 83012724Snikos.nikoleris@arm.com Tick nextQueueReadyTime() const; 83112724Snikos.nikoleris@arm.com 8324626SN/A /** Block size of this cache */ 8336227Snate@binkert.org const unsigned blkSize; 8344626SN/A 8354630SN/A /** 83610693SMarco.Balboni@ARM.com * The latency of tag lookup of a cache. It occurs when there is 83710693SMarco.Balboni@ARM.com * an access to the cache. 8384630SN/A */ 83910693SMarco.Balboni@ARM.com const Cycles lookupLatency; 8409263Smrinmoy.ghosh@arm.com 8419263Smrinmoy.ghosh@arm.com /** 84211722Ssophiane.senni@gmail.com * The latency of data access of a cache. It occurs when there is 84311722Ssophiane.senni@gmail.com * an access to the cache. 84411722Ssophiane.senni@gmail.com */ 84511722Ssophiane.senni@gmail.com const Cycles dataLatency; 84611722Ssophiane.senni@gmail.com 84711722Ssophiane.senni@gmail.com /** 84810693SMarco.Balboni@ARM.com * This is the forward latency of the cache. It occurs when there 84910693SMarco.Balboni@ARM.com * is a cache miss and a request is forwarded downstream, in 85010693SMarco.Balboni@ARM.com * particular an outbound miss. 85110693SMarco.Balboni@ARM.com */ 85210693SMarco.Balboni@ARM.com const Cycles forwardLatency; 85310693SMarco.Balboni@ARM.com 85410693SMarco.Balboni@ARM.com /** The latency to fill a cache block */ 85510693SMarco.Balboni@ARM.com const Cycles fillLatency; 85610693SMarco.Balboni@ARM.com 85710693SMarco.Balboni@ARM.com /** 85810693SMarco.Balboni@ARM.com * The latency of sending reponse to its upper level cache/core on 85910693SMarco.Balboni@ARM.com * a linefill. The responseLatency parameter captures this 86010693SMarco.Balboni@ARM.com * latency. 8619263Smrinmoy.ghosh@arm.com */ 8629288Sandreas.hansson@arm.com const Cycles responseLatency; 8634630SN/A 86413418Sodanrc@yahoo.com.br /** 86513418Sodanrc@yahoo.com.br * Whether tags and data are accessed sequentially. 86613418Sodanrc@yahoo.com.br */ 86713418Sodanrc@yahoo.com.br const bool sequentialAccess; 86813418Sodanrc@yahoo.com.br 8694626SN/A /** The number of targets for each MSHR. */ 8704626SN/A const int numTarget; 8714626SN/A 8726122SSteve.Reinhardt@amd.com /** Do we forward snoops from mem side port through to cpu side port? */ 87311331Sandreas.hansson@arm.com bool forwardSnoops; 8744626SN/A 8752810SN/A /** 87612724Snikos.nikoleris@arm.com * Clusivity with respect to the upstream cache, determining if we 87712724Snikos.nikoleris@arm.com * fill into both this cache and the cache above on a miss. Note 87812724Snikos.nikoleris@arm.com * that we currently do not support strict clusivity policies. 87912724Snikos.nikoleris@arm.com */ 88012724Snikos.nikoleris@arm.com const Enums::Clusivity clusivity; 88112724Snikos.nikoleris@arm.com 88212724Snikos.nikoleris@arm.com /** 88310884Sandreas.hansson@arm.com * Is this cache read only, for example the instruction cache, or 88410884Sandreas.hansson@arm.com * table-walker cache. A cache that is read only should never see 88510884Sandreas.hansson@arm.com * any writes, and should never get any dirty data (and hence 88610884Sandreas.hansson@arm.com * never have to do any writebacks). 88710884Sandreas.hansson@arm.com */ 88810884Sandreas.hansson@arm.com const bool isReadOnly; 88910884Sandreas.hansson@arm.com 89010884Sandreas.hansson@arm.com /** 8912810SN/A * Bit vector of the blocking reasons for the access path. 8922810SN/A * @sa #BlockedCause 8932810SN/A */ 8942810SN/A uint8_t blocked; 8952810SN/A 8966122SSteve.Reinhardt@amd.com /** Increasing order number assigned to each incoming request. */ 8976122SSteve.Reinhardt@amd.com uint64_t order; 8986122SSteve.Reinhardt@amd.com 8992810SN/A /** Stores time the cache blocked for statistics. */ 9009288Sandreas.hansson@arm.com Cycles blockedCycle; 9012810SN/A 9024626SN/A /** Pointer to the MSHR that has no targets. */ 9034626SN/A MSHR *noTargetMSHR; 9042810SN/A 9052810SN/A /** The number of misses to trigger an exit event. */ 9062810SN/A Counter missCount; 9072810SN/A 9086122SSteve.Reinhardt@amd.com /** 9096122SSteve.Reinhardt@amd.com * The address range to which the cache responds on the CPU side. 9106122SSteve.Reinhardt@amd.com * Normally this is all possible memory addresses. */ 9119529Sandreas.hansson@arm.com const AddrRangeList addrRanges; 9126122SSteve.Reinhardt@amd.com 9138833Sdam.sunwoo@arm.com public: 9148833Sdam.sunwoo@arm.com /** System we are currently operating in. */ 9158833Sdam.sunwoo@arm.com System *system; 9166978SLisa.Hsu@amd.com 9172810SN/A // Statistics 9182810SN/A /** 9192810SN/A * @addtogroup CacheStatistics 9202810SN/A * @{ 9212810SN/A */ 9222810SN/A 92311483Snikos.nikoleris@arm.com /** Number of hits per thread for each type of command. 92411483Snikos.nikoleris@arm.com @sa Packet::Command */ 9255999Snate@binkert.org Stats::Vector hits[MemCmd::NUM_MEM_CMDS]; 9262810SN/A /** Number of hits for demand accesses. */ 9272810SN/A Stats::Formula demandHits; 9282810SN/A /** Number of hit for all accesses. */ 9292810SN/A Stats::Formula overallHits; 9302810SN/A 93111483Snikos.nikoleris@arm.com /** Number of misses per thread for each type of command. 93211483Snikos.nikoleris@arm.com @sa Packet::Command */ 9335999Snate@binkert.org Stats::Vector misses[MemCmd::NUM_MEM_CMDS]; 9342810SN/A /** Number of misses for demand accesses. */ 9352810SN/A Stats::Formula demandMisses; 9362810SN/A /** Number of misses for all accesses. */ 9372810SN/A Stats::Formula overallMisses; 9382810SN/A 9392810SN/A /** 9402810SN/A * Total number of cycles per thread/command spent waiting for a miss. 9412810SN/A * Used to calculate the average miss latency. 9422810SN/A */ 9435999Snate@binkert.org Stats::Vector missLatency[MemCmd::NUM_MEM_CMDS]; 9442810SN/A /** Total number of cycles spent waiting for demand misses. */ 9452810SN/A Stats::Formula demandMissLatency; 9462810SN/A /** Total number of cycles spent waiting for all misses. */ 9472810SN/A Stats::Formula overallMissLatency; 9482810SN/A 9492810SN/A /** The number of accesses per command and thread. */ 9504022SN/A Stats::Formula accesses[MemCmd::NUM_MEM_CMDS]; 9512810SN/A /** The number of demand accesses. */ 9522810SN/A Stats::Formula demandAccesses; 9532810SN/A /** The number of overall accesses. */ 9542810SN/A Stats::Formula overallAccesses; 9552810SN/A 9562810SN/A /** The miss rate per command and thread. */ 9574022SN/A Stats::Formula missRate[MemCmd::NUM_MEM_CMDS]; 9582810SN/A /** The miss rate of all demand accesses. */ 9592810SN/A Stats::Formula demandMissRate; 9602810SN/A /** The miss rate for all accesses. */ 9612810SN/A Stats::Formula overallMissRate; 9622810SN/A 9632810SN/A /** The average miss latency per command and thread. */ 9644022SN/A Stats::Formula avgMissLatency[MemCmd::NUM_MEM_CMDS]; 9652810SN/A /** The average miss latency for demand misses. */ 9662810SN/A Stats::Formula demandAvgMissLatency; 9672810SN/A /** The average miss latency for all misses. */ 9682810SN/A Stats::Formula overallAvgMissLatency; 9692810SN/A 9702810SN/A /** The total number of cycles blocked for each blocked cause. */ 9715999Snate@binkert.org Stats::Vector blocked_cycles; 9722810SN/A /** The number of times this cache blocked for each blocked cause. */ 9735999Snate@binkert.org Stats::Vector blocked_causes; 9742810SN/A 9752810SN/A /** The average number of cycles blocked for each blocked cause. */ 9762810SN/A Stats::Formula avg_blocked; 9772810SN/A 97811436SRekai.GonzalezAlberquilla@arm.com /** The number of times a HW-prefetched block is evicted w/o reference. */ 97911436SRekai.GonzalezAlberquilla@arm.com Stats::Scalar unusedPrefetches; 98011436SRekai.GonzalezAlberquilla@arm.com 9814626SN/A /** Number of blocks written back per thread. */ 9825999Snate@binkert.org Stats::Vector writebacks; 9834626SN/A 9844626SN/A /** Number of misses that hit in the MSHRs per command and thread. */ 9855999Snate@binkert.org Stats::Vector mshr_hits[MemCmd::NUM_MEM_CMDS]; 9864626SN/A /** Demand misses that hit in the MSHRs. */ 9874626SN/A Stats::Formula demandMshrHits; 9884626SN/A /** Total number of misses that hit in the MSHRs. */ 9894626SN/A Stats::Formula overallMshrHits; 9904626SN/A 9914626SN/A /** Number of misses that miss in the MSHRs, per command and thread. */ 9925999Snate@binkert.org Stats::Vector mshr_misses[MemCmd::NUM_MEM_CMDS]; 9934626SN/A /** Demand misses that miss in the MSHRs. */ 9944626SN/A Stats::Formula demandMshrMisses; 9954626SN/A /** Total number of misses that miss in the MSHRs. */ 9964626SN/A Stats::Formula overallMshrMisses; 9974626SN/A 9984626SN/A /** Number of misses that miss in the MSHRs, per command and thread. */ 9995999Snate@binkert.org Stats::Vector mshr_uncacheable[MemCmd::NUM_MEM_CMDS]; 10004626SN/A /** Total number of misses that miss in the MSHRs. */ 10014626SN/A Stats::Formula overallMshrUncacheable; 10024626SN/A 10034626SN/A /** Total cycle latency of each MSHR miss, per command and thread. */ 10045999Snate@binkert.org Stats::Vector mshr_miss_latency[MemCmd::NUM_MEM_CMDS]; 10054626SN/A /** Total cycle latency of demand MSHR misses. */ 10064626SN/A Stats::Formula demandMshrMissLatency; 10074626SN/A /** Total cycle latency of overall MSHR misses. */ 10084626SN/A Stats::Formula overallMshrMissLatency; 10094626SN/A 10104626SN/A /** Total cycle latency of each MSHR miss, per command and thread. */ 10115999Snate@binkert.org Stats::Vector mshr_uncacheable_lat[MemCmd::NUM_MEM_CMDS]; 10124626SN/A /** Total cycle latency of overall MSHR misses. */ 10134626SN/A Stats::Formula overallMshrUncacheableLatency; 10144626SN/A 10154626SN/A /** The miss rate in the MSHRs pre command and thread. */ 10164626SN/A Stats::Formula mshrMissRate[MemCmd::NUM_MEM_CMDS]; 10174626SN/A /** The demand miss rate in the MSHRs. */ 10184626SN/A Stats::Formula demandMshrMissRate; 10194626SN/A /** The overall miss rate in the MSHRs. */ 10204626SN/A Stats::Formula overallMshrMissRate; 10214626SN/A 10224626SN/A /** The average latency of an MSHR miss, per command and thread. */ 10234626SN/A Stats::Formula avgMshrMissLatency[MemCmd::NUM_MEM_CMDS]; 10244626SN/A /** The average latency of a demand MSHR miss. */ 10254626SN/A Stats::Formula demandAvgMshrMissLatency; 10264626SN/A /** The average overall latency of an MSHR miss. */ 10274626SN/A Stats::Formula overallAvgMshrMissLatency; 10284626SN/A 10294626SN/A /** The average latency of an MSHR miss, per command and thread. */ 10304626SN/A Stats::Formula avgMshrUncacheableLatency[MemCmd::NUM_MEM_CMDS]; 10314626SN/A /** The average overall latency of an MSHR miss. */ 10324626SN/A Stats::Formula overallAvgMshrUncacheableLatency; 10334626SN/A 103412702Snikos.nikoleris@arm.com /** Number of replacements of valid blocks. */ 103512702Snikos.nikoleris@arm.com Stats::Scalar replacements; 103612702Snikos.nikoleris@arm.com 103713947Sodanrc@yahoo.com.br /** Number of data expansions. */ 103813947Sodanrc@yahoo.com.br Stats::Scalar dataExpansions; 103913947Sodanrc@yahoo.com.br 10402810SN/A /** 10412810SN/A * @} 10422810SN/A */ 10432810SN/A 10442810SN/A /** 10452810SN/A * Register stats for this object. 10462810SN/A */ 104712724Snikos.nikoleris@arm.com void regStats() override; 10482810SN/A 104913416Sjavier.bueno@metempsy.com /** Registers probes. */ 105013416Sjavier.bueno@metempsy.com void regProbePoints() override; 105113416Sjavier.bueno@metempsy.com 10522810SN/A public: 105311053Sandreas.hansson@arm.com BaseCache(const BaseCacheParams *p, unsigned blk_size); 105412724Snikos.nikoleris@arm.com ~BaseCache(); 10553606SN/A 105612724Snikos.nikoleris@arm.com void init() override; 10572858SN/A 105813784Sgabeblack@google.com Port &getPort(const std::string &if_name, 105913784Sgabeblack@google.com PortID idx=InvalidPortID) override; 10608922Swilliam.wang@arm.com 10612810SN/A /** 10622810SN/A * Query block size of a cache. 10632810SN/A * @return The block size 10642810SN/A */ 10656227Snate@binkert.org unsigned 10666227Snate@binkert.org getBlockSize() const 10672810SN/A { 10682810SN/A return blkSize; 10692810SN/A } 10702810SN/A 10718883SAli.Saidi@ARM.com const AddrRangeList &getAddrRanges() const { return addrRanges; } 10726122SSteve.Reinhardt@amd.com 107310942Sandreas.hansson@arm.com MSHR *allocateMissBuffer(PacketPtr pkt, Tick time, bool sched_send = true) 10744628SN/A { 107511892Snikos.nikoleris@arm.com MSHR *mshr = mshrQueue.allocate(pkt->getBlockAddr(blkSize), blkSize, 107611375Sandreas.hansson@arm.com pkt, time, order++, 107711375Sandreas.hansson@arm.com allocOnFill(pkt->cmd)); 107811375Sandreas.hansson@arm.com 107911375Sandreas.hansson@arm.com if (mshrQueue.isFull()) { 108011375Sandreas.hansson@arm.com setBlocked((BlockedCause)MSHRQueue_MSHRs); 108111375Sandreas.hansson@arm.com } 108211375Sandreas.hansson@arm.com 108311375Sandreas.hansson@arm.com if (sched_send) { 108411375Sandreas.hansson@arm.com // schedule the send 108511375Sandreas.hansson@arm.com schedMemSideSendEvent(time); 108611375Sandreas.hansson@arm.com } 108711375Sandreas.hansson@arm.com 108811375Sandreas.hansson@arm.com return mshr; 10894628SN/A } 10904628SN/A 109111375Sandreas.hansson@arm.com void allocateWriteBuffer(PacketPtr pkt, Tick time) 10924628SN/A { 109311191Sandreas.hansson@arm.com // should only see writes or clean evicts here 109411191Sandreas.hansson@arm.com assert(pkt->isWrite() || pkt->cmd == MemCmd::CleanEvict); 109511191Sandreas.hansson@arm.com 109611892Snikos.nikoleris@arm.com Addr blk_addr = pkt->getBlockAddr(blkSize); 109711375Sandreas.hansson@arm.com 109813945Sodanrc@yahoo.com.br // If using compression, on evictions the block is decompressed and 109913945Sodanrc@yahoo.com.br // the operation's latency is added to the payload delay. Consume 110013945Sodanrc@yahoo.com.br // that payload delay here, meaning that the data is always stored 110113945Sodanrc@yahoo.com.br // uncompressed in the writebuffer 110213945Sodanrc@yahoo.com.br if (compressor) { 110313945Sodanrc@yahoo.com.br time += pkt->payloadDelay; 110413945Sodanrc@yahoo.com.br pkt->payloadDelay = 0; 110513945Sodanrc@yahoo.com.br } 110613945Sodanrc@yahoo.com.br 110711375Sandreas.hansson@arm.com WriteQueueEntry *wq_entry = 110811375Sandreas.hansson@arm.com writeBuffer.findMatch(blk_addr, pkt->isSecure()); 110911375Sandreas.hansson@arm.com if (wq_entry && !wq_entry->inService) { 111011744Snikos.nikoleris@arm.com DPRINTF(Cache, "Potential to merge writeback %s", pkt->print()); 111111375Sandreas.hansson@arm.com } 111211375Sandreas.hansson@arm.com 111311375Sandreas.hansson@arm.com writeBuffer.allocate(blk_addr, blkSize, pkt, time, order++); 111411375Sandreas.hansson@arm.com 111511375Sandreas.hansson@arm.com if (writeBuffer.isFull()) { 111611375Sandreas.hansson@arm.com setBlocked((BlockedCause)MSHRQueue_WriteBuffer); 111711375Sandreas.hansson@arm.com } 111811375Sandreas.hansson@arm.com 111911375Sandreas.hansson@arm.com // schedule the send 112011375Sandreas.hansson@arm.com schedMemSideSendEvent(time); 11214628SN/A } 11224628SN/A 11232810SN/A /** 11242810SN/A * Returns true if the cache is blocked for accesses. 11252810SN/A */ 11269529Sandreas.hansson@arm.com bool isBlocked() const 11272810SN/A { 11282810SN/A return blocked != 0; 11292810SN/A } 11302810SN/A 11312810SN/A /** 11322810SN/A * Marks the access path of the cache as blocked for the given cause. This 11332810SN/A * also sets the blocked flag in the slave interface. 11342810SN/A * @param cause The reason for the cache blocking. 11352810SN/A */ 11362810SN/A void setBlocked(BlockedCause cause) 11372810SN/A { 11382810SN/A uint8_t flag = 1 << cause; 11392810SN/A if (blocked == 0) { 11402810SN/A blocked_causes[cause]++; 11419288Sandreas.hansson@arm.com blockedCycle = curCycle(); 114212724Snikos.nikoleris@arm.com cpuSidePort.setBlocked(); 11432810SN/A } 11444630SN/A blocked |= flag; 11454630SN/A DPRINTF(Cache,"Blocking for cause %d, mask=%d\n", cause, blocked); 11462810SN/A } 11472810SN/A 11482810SN/A /** 11492810SN/A * Marks the cache as unblocked for the given cause. This also clears the 11502810SN/A * blocked flags in the appropriate interfaces. 11512810SN/A * @param cause The newly unblocked cause. 11522810SN/A * @warning Calling this function can cause a blocked request on the bus to 11532810SN/A * access the cache. The cache must be in a state to handle that request. 11542810SN/A */ 11552810SN/A void clearBlocked(BlockedCause cause) 11562810SN/A { 11572810SN/A uint8_t flag = 1 << cause; 11584630SN/A blocked &= ~flag; 11594630SN/A DPRINTF(Cache,"Unblocking for cause %d, mask=%d\n", cause, blocked); 11604630SN/A if (blocked == 0) { 11619288Sandreas.hansson@arm.com blocked_cycles[cause] += curCycle() - blockedCycle; 116212724Snikos.nikoleris@arm.com cpuSidePort.clearBlocked(); 11632810SN/A } 11642810SN/A } 11652810SN/A 11662810SN/A /** 116710942Sandreas.hansson@arm.com * Schedule a send event for the memory-side port. If already 116810942Sandreas.hansson@arm.com * scheduled, this may reschedule the event at an earlier 116910942Sandreas.hansson@arm.com * time. When the specified time is reached, the port is free to 117010942Sandreas.hansson@arm.com * send either a response, a request, or a prefetch request. 117110942Sandreas.hansson@arm.com * 117210942Sandreas.hansson@arm.com * @param time The time when to attempt sending a packet. 11732810SN/A */ 117410942Sandreas.hansson@arm.com void schedMemSideSendEvent(Tick time) 11752810SN/A { 117612724Snikos.nikoleris@arm.com memSidePort.schedSendEvent(time); 11772811SN/A } 11783503SN/A 117912724Snikos.nikoleris@arm.com bool inCache(Addr addr, bool is_secure) const { 118012724Snikos.nikoleris@arm.com return tags->findBlock(addr, is_secure); 118112724Snikos.nikoleris@arm.com } 11824626SN/A 118313624Sjavier.bueno@metempsy.com bool hasBeenPrefetched(Addr addr, bool is_secure) const { 118413624Sjavier.bueno@metempsy.com CacheBlk *block = tags->findBlock(addr, is_secure); 118513624Sjavier.bueno@metempsy.com if (block) { 118613624Sjavier.bueno@metempsy.com return block->wasPrefetched(); 118713624Sjavier.bueno@metempsy.com } else { 118813624Sjavier.bueno@metempsy.com return false; 118913624Sjavier.bueno@metempsy.com } 119013624Sjavier.bueno@metempsy.com } 119113624Sjavier.bueno@metempsy.com 119212724Snikos.nikoleris@arm.com bool inMissQueue(Addr addr, bool is_secure) const { 119312724Snikos.nikoleris@arm.com return mshrQueue.findMatch(addr, is_secure); 119412724Snikos.nikoleris@arm.com } 11954626SN/A 11968833Sdam.sunwoo@arm.com void incMissCount(PacketPtr pkt) 11973503SN/A { 11988833Sdam.sunwoo@arm.com assert(pkt->req->masterId() < system->maxMasters()); 11998833Sdam.sunwoo@arm.com misses[pkt->cmdToIndex()][pkt->req->masterId()]++; 120010020Smatt.horsnell@ARM.com pkt->req->incAccessDepth(); 12014626SN/A if (missCount) { 12024626SN/A --missCount; 12034626SN/A if (missCount == 0) 12044626SN/A exitSimLoop("A cache reached the maximum miss count"); 12053503SN/A } 12063503SN/A } 12078833Sdam.sunwoo@arm.com void incHitCount(PacketPtr pkt) 12086978SLisa.Hsu@amd.com { 12098833Sdam.sunwoo@arm.com assert(pkt->req->masterId() < system->maxMasters()); 12108833Sdam.sunwoo@arm.com hits[pkt->cmdToIndex()][pkt->req->masterId()]++; 12116978SLisa.Hsu@amd.com 12126978SLisa.Hsu@amd.com } 12133503SN/A 121412724Snikos.nikoleris@arm.com /** 121513416Sjavier.bueno@metempsy.com * Checks if the cache is coalescing writes 121613416Sjavier.bueno@metempsy.com * 121713416Sjavier.bueno@metempsy.com * @return True if the cache is coalescing writes 121813416Sjavier.bueno@metempsy.com */ 121913416Sjavier.bueno@metempsy.com bool coalesce() const; 122013416Sjavier.bueno@metempsy.com 122113416Sjavier.bueno@metempsy.com 122213416Sjavier.bueno@metempsy.com /** 122312724Snikos.nikoleris@arm.com * Cache block visitor that writes back dirty cache blocks using 122412724Snikos.nikoleris@arm.com * functional writes. 122512724Snikos.nikoleris@arm.com */ 122612728Snikos.nikoleris@arm.com void writebackVisitor(CacheBlk &blk); 122712724Snikos.nikoleris@arm.com 122812724Snikos.nikoleris@arm.com /** 122912724Snikos.nikoleris@arm.com * Cache block visitor that invalidates all blocks in the cache. 123012724Snikos.nikoleris@arm.com * 123112724Snikos.nikoleris@arm.com * @warn Dirty cache lines will not be written back to memory. 123212724Snikos.nikoleris@arm.com */ 123312728Snikos.nikoleris@arm.com void invalidateVisitor(CacheBlk &blk); 123412724Snikos.nikoleris@arm.com 123512724Snikos.nikoleris@arm.com /** 123612724Snikos.nikoleris@arm.com * Take an MSHR, turn it into a suitable downstream packet, and 123712724Snikos.nikoleris@arm.com * send it out. This construct allows a queue entry to choose a suitable 123812724Snikos.nikoleris@arm.com * approach based on its type. 123912724Snikos.nikoleris@arm.com * 124012724Snikos.nikoleris@arm.com * @param mshr The MSHR to turn into a packet and send 124112724Snikos.nikoleris@arm.com * @return True if the port is waiting for a retry 124212724Snikos.nikoleris@arm.com */ 124312724Snikos.nikoleris@arm.com virtual bool sendMSHRQueuePacket(MSHR* mshr); 124412724Snikos.nikoleris@arm.com 124512724Snikos.nikoleris@arm.com /** 124612724Snikos.nikoleris@arm.com * Similar to sendMSHR, but for a write-queue entry 124712724Snikos.nikoleris@arm.com * instead. Create the packet, and send it, and if successful also 124812724Snikos.nikoleris@arm.com * mark the entry in service. 124912724Snikos.nikoleris@arm.com * 125012724Snikos.nikoleris@arm.com * @param wq_entry The write-queue entry to turn into a packet and send 125112724Snikos.nikoleris@arm.com * @return True if the port is waiting for a retry 125212724Snikos.nikoleris@arm.com */ 125312724Snikos.nikoleris@arm.com bool sendWriteQueuePacket(WriteQueueEntry* wq_entry); 125412724Snikos.nikoleris@arm.com 125512724Snikos.nikoleris@arm.com /** 125612724Snikos.nikoleris@arm.com * Serialize the state of the caches 125712724Snikos.nikoleris@arm.com * 125812724Snikos.nikoleris@arm.com * We currently don't support checkpointing cache state, so this panics. 125912724Snikos.nikoleris@arm.com */ 126012724Snikos.nikoleris@arm.com void serialize(CheckpointOut &cp) const override; 126112724Snikos.nikoleris@arm.com void unserialize(CheckpointIn &cp) override; 126212724Snikos.nikoleris@arm.com}; 126312724Snikos.nikoleris@arm.com 126413352Snikos.nikoleris@arm.com/** 126513352Snikos.nikoleris@arm.com * The write allocator inspects write packets and detects streaming 126613352Snikos.nikoleris@arm.com * patterns. The write allocator supports a single stream where writes 126713352Snikos.nikoleris@arm.com * are expected to access consecutive locations and keeps track of 126813352Snikos.nikoleris@arm.com * size of the area covered by the concecutive writes in byteCount. 126913352Snikos.nikoleris@arm.com * 127013352Snikos.nikoleris@arm.com * 1) When byteCount has surpassed the coallesceLimit the mode 127113352Snikos.nikoleris@arm.com * switches from ALLOCATE to COALESCE where writes should be delayed 127213352Snikos.nikoleris@arm.com * until the whole block is written at which point a single packet 127313352Snikos.nikoleris@arm.com * (whole line write) can service them. 127413352Snikos.nikoleris@arm.com * 127513352Snikos.nikoleris@arm.com * 2) When byteCount has also exceeded the noAllocateLimit (whole 127613352Snikos.nikoleris@arm.com * line) we switch to NO_ALLOCATE when writes should not allocate in 127713352Snikos.nikoleris@arm.com * the cache but rather send a whole line write to the memory below. 127813352Snikos.nikoleris@arm.com */ 127913352Snikos.nikoleris@arm.comclass WriteAllocator : public SimObject { 128013352Snikos.nikoleris@arm.com public: 128113352Snikos.nikoleris@arm.com WriteAllocator(const WriteAllocatorParams *p) : 128213352Snikos.nikoleris@arm.com SimObject(p), 128313352Snikos.nikoleris@arm.com coalesceLimit(p->coalesce_limit * p->block_size), 128413352Snikos.nikoleris@arm.com noAllocateLimit(p->no_allocate_limit * p->block_size), 128513352Snikos.nikoleris@arm.com delayThreshold(p->delay_threshold) 128613352Snikos.nikoleris@arm.com { 128713352Snikos.nikoleris@arm.com reset(); 128813352Snikos.nikoleris@arm.com } 128913352Snikos.nikoleris@arm.com 129013352Snikos.nikoleris@arm.com /** 129113352Snikos.nikoleris@arm.com * Should writes be coalesced? This is true if the mode is set to 129213352Snikos.nikoleris@arm.com * NO_ALLOCATE. 129313352Snikos.nikoleris@arm.com * 129413352Snikos.nikoleris@arm.com * @return return true if the cache should coalesce writes. 129513352Snikos.nikoleris@arm.com */ 129613352Snikos.nikoleris@arm.com bool coalesce() const { 129713352Snikos.nikoleris@arm.com return mode != WriteMode::ALLOCATE; 129813352Snikos.nikoleris@arm.com } 129913352Snikos.nikoleris@arm.com 130013352Snikos.nikoleris@arm.com /** 130113352Snikos.nikoleris@arm.com * Should writes allocate? 130213352Snikos.nikoleris@arm.com * 130313352Snikos.nikoleris@arm.com * @return return true if the cache should not allocate for writes. 130413352Snikos.nikoleris@arm.com */ 130513352Snikos.nikoleris@arm.com bool allocate() const { 130613352Snikos.nikoleris@arm.com return mode != WriteMode::NO_ALLOCATE; 130713352Snikos.nikoleris@arm.com } 130813352Snikos.nikoleris@arm.com 130913352Snikos.nikoleris@arm.com /** 131013352Snikos.nikoleris@arm.com * Reset the write allocator state, meaning that it allocates for 131113352Snikos.nikoleris@arm.com * writes and has not recorded any information about qualifying 131213352Snikos.nikoleris@arm.com * writes that might trigger a switch to coalescing and later no 131313352Snikos.nikoleris@arm.com * allocation. 131413352Snikos.nikoleris@arm.com */ 131513352Snikos.nikoleris@arm.com void reset() { 131613352Snikos.nikoleris@arm.com mode = WriteMode::ALLOCATE; 131713352Snikos.nikoleris@arm.com byteCount = 0; 131813352Snikos.nikoleris@arm.com nextAddr = 0; 131913352Snikos.nikoleris@arm.com } 132013352Snikos.nikoleris@arm.com 132113352Snikos.nikoleris@arm.com /** 132213352Snikos.nikoleris@arm.com * Access whether we need to delay the current write. 132313352Snikos.nikoleris@arm.com * 132413352Snikos.nikoleris@arm.com * @param blk_addr The block address the packet writes to 132513352Snikos.nikoleris@arm.com * @return true if the current packet should be delayed 132613352Snikos.nikoleris@arm.com */ 132713352Snikos.nikoleris@arm.com bool delay(Addr blk_addr) { 132813352Snikos.nikoleris@arm.com if (delayCtr[blk_addr] > 0) { 132913352Snikos.nikoleris@arm.com --delayCtr[blk_addr]; 133013352Snikos.nikoleris@arm.com return true; 133113352Snikos.nikoleris@arm.com } else { 133213352Snikos.nikoleris@arm.com return false; 133313352Snikos.nikoleris@arm.com } 133413352Snikos.nikoleris@arm.com } 133513352Snikos.nikoleris@arm.com 133613352Snikos.nikoleris@arm.com /** 133713352Snikos.nikoleris@arm.com * Clear delay counter for the input block 133813352Snikos.nikoleris@arm.com * 133913352Snikos.nikoleris@arm.com * @param blk_addr The accessed cache block 134013352Snikos.nikoleris@arm.com */ 134113352Snikos.nikoleris@arm.com void resetDelay(Addr blk_addr) { 134213352Snikos.nikoleris@arm.com delayCtr.erase(blk_addr); 134313352Snikos.nikoleris@arm.com } 134413352Snikos.nikoleris@arm.com 134513352Snikos.nikoleris@arm.com /** 134613352Snikos.nikoleris@arm.com * Update the write mode based on the current write 134713352Snikos.nikoleris@arm.com * packet. This method compares the packet's address with any 134813352Snikos.nikoleris@arm.com * current stream, and updates the tracking and the mode 134913352Snikos.nikoleris@arm.com * accordingly. 135013352Snikos.nikoleris@arm.com * 135113352Snikos.nikoleris@arm.com * @param write_addr Start address of the write request 135213352Snikos.nikoleris@arm.com * @param write_size Size of the write request 135313352Snikos.nikoleris@arm.com * @param blk_addr The block address that this packet writes to 135413352Snikos.nikoleris@arm.com */ 135513352Snikos.nikoleris@arm.com void updateMode(Addr write_addr, unsigned write_size, Addr blk_addr); 135613352Snikos.nikoleris@arm.com 135713352Snikos.nikoleris@arm.com private: 135813352Snikos.nikoleris@arm.com /** 135913352Snikos.nikoleris@arm.com * The current mode for write coalescing and allocation, either 136013352Snikos.nikoleris@arm.com * normal operation (ALLOCATE), write coalescing (COALESCE), or 136113352Snikos.nikoleris@arm.com * write coalescing without allocation (NO_ALLOCATE). 136213352Snikos.nikoleris@arm.com */ 136313352Snikos.nikoleris@arm.com enum class WriteMode : char { 136413352Snikos.nikoleris@arm.com ALLOCATE, 136513352Snikos.nikoleris@arm.com COALESCE, 136613352Snikos.nikoleris@arm.com NO_ALLOCATE, 136713352Snikos.nikoleris@arm.com }; 136813352Snikos.nikoleris@arm.com WriteMode mode; 136913352Snikos.nikoleris@arm.com 137013352Snikos.nikoleris@arm.com /** Address to match writes against to detect streams. */ 137113352Snikos.nikoleris@arm.com Addr nextAddr; 137213352Snikos.nikoleris@arm.com 137313352Snikos.nikoleris@arm.com /** 137413352Snikos.nikoleris@arm.com * Bytes written contiguously. Saturating once we no longer 137513352Snikos.nikoleris@arm.com * allocate. 137613352Snikos.nikoleris@arm.com */ 137713352Snikos.nikoleris@arm.com uint32_t byteCount; 137813352Snikos.nikoleris@arm.com 137913352Snikos.nikoleris@arm.com /** 138013352Snikos.nikoleris@arm.com * Limits for when to switch between the different write modes. 138113352Snikos.nikoleris@arm.com */ 138213352Snikos.nikoleris@arm.com const uint32_t coalesceLimit; 138313352Snikos.nikoleris@arm.com const uint32_t noAllocateLimit; 138413352Snikos.nikoleris@arm.com /** 138513352Snikos.nikoleris@arm.com * The number of times the allocator will delay an WriteReq MSHR. 138613352Snikos.nikoleris@arm.com */ 138713352Snikos.nikoleris@arm.com const uint32_t delayThreshold; 138813352Snikos.nikoleris@arm.com 138913352Snikos.nikoleris@arm.com /** 139013352Snikos.nikoleris@arm.com * Keep track of the number of times the allocator has delayed an 139113352Snikos.nikoleris@arm.com * WriteReq MSHR. 139213352Snikos.nikoleris@arm.com */ 139313352Snikos.nikoleris@arm.com std::unordered_map<Addr, Counter> delayCtr; 139413352Snikos.nikoleris@arm.com}; 139513352Snikos.nikoleris@arm.com 139611051Sandreas.hansson@arm.com#endif //__MEM_CACHE_BASE_HH__ 1397