55#include "debug/Cache.hh"
56#include "debug/CacheTags.hh"
57#include "debug/CacheVerbose.hh"
58#include "enums/Clusivity.hh"
65#include "params/Cache.hh"
75 assert(
p.replacement_policy);
80 bool deferred_response,
bool pending_downgrade)
117 if (!deferred_response) {
166 if (pkt->
req->isUncacheable()) {
170 "Should never see a write in a read-only cache %s\n",
176 CacheBlk *old_blk(
tags->findBlock({pkt->getAddr(), pkt->isSecure()}));
177 if (old_blk && old_blk->
isValid()) {
193 while (!writebacks.empty()) {
228 writebacks.pop_front();
235 while (!writebacks.empty()) {
258 writebacks.pop_front();
278 if (!forwardAsSnoop) {
285 DPRINTF(
Cache,
"Got prefetch response from above for addr "
298 memSidePort.schedTimingSnoopResp(pkt, snoop_resp_time);
309 DPRINTF(
Cache,
"packet promoted from Write to WriteLineReq\n");
319 assert(!pkt->
req->isUncacheable());
331 if (pkt->
req->isUncacheable()) {
336 assert(!blk || !blk->
isValid());
338 stats.cmdStats(pkt).mshrUncacheable[pkt->
req->requestorId()]++;
383 assert(pkt->
req->hasPaddr());
384 assert(!pkt->
req->isUncacheable());
394 RequestPtr req = std::make_shared<Request>(pkt->
req->getPaddr(),
396 pkt->
req->getFlags(),
397 pkt->
req->requestorId());
400 assert(
pf->matchAddr(pkt));
421 DPRINTF(CacheTags,
"%s tags:\n%s\n", __func__,
tags->print());
429 DPRINTF(
Cache,
"Cache above responding to %s: not responding\n",
471 [[maybe_unused]]
bool success =
memSidePort.sendTimingReq(snoop_pkt);
495 bool is_whole_line_write)
const
500 bool blkValid = blk && blk->
isValid();
502 if (cpu_pkt->
req->isUncacheable() ||
517 const bool useUpgrades =
true;
519 if (is_whole_line_write) {
525 }
else if (blkValid && useUpgrades) {
528 assert(needsWritable);
558 if (cpu_pkt->
hasSharers() && !needsWritable) {
564 DPRINTF(
Cache,
"%s: passing hasSharers from %s to %s\n",
585 (pkt->
req->isUncacheable() && pkt->
isWrite())) {
591 assert(!(pkt->
req->isUncacheable() && pkt->
isWrite()) ||
602 bool is_forward = (bus_pkt ==
nullptr);
613 const std::string old_state = blk ? blk->
print() :
"";
620 DPRINTF(
Cache,
"%s: Receive response: %s for %s\n", __func__,
621 bus_pkt->
print(), old_state);
640 blk =
handleFill(bus_pkt, blk, writebacks, allocate);
642 is_invalidate =
false;
644 }
else if (bus_pkt->
isRead() ||
661 if (is_invalidate && blk && blk->
isValid()) {
676 assert(!pkt->
req->isCacheInvalidate());
677 DPRINTF(
Cache,
"Cache above responding to %s: not responding\n",
706 const bool is_error = pkt->
isError();
712 bool from_core =
false;
713 bool from_pref =
false;
725 delete initial_tgt->
pkt;
727 initial_tgt =
nullptr;
731 for (
auto &target: targets) {
732 Packet *tgt_pkt = target.pkt;
733 switch (target.source) {
737 Tick completion_time;
767 "read-only cache %s\n",
name());
801 int transfer_offset =
803 if (transfer_offset < 0) {
814 assert(!tgt_pkt->
req->isUncacheable());
816 assert(tgt_pkt->
req->requestorId() <
system->maxRequestors());
817 stats.cmdStats(tgt_pkt)
818 .missLatency[tgt_pkt->
req->requestorId()] +=
819 completion_time - target.recvTime;
845 tgt_pkt->
req->setExtraData(0);
852 if (is_invalidate && blk && blk->
isValid()) {
906 cpuSidePort.schedTimingResp(tgt_pkt, completion_time);
931 pkt->
req->isCacheMaintenance() ||
937 panic(
"Illegal target->source enum %d\n", target.source);
941 if (blk && !from_core && from_pref) {
1002 bool already_copied,
bool pending_inval)
1012 if (!already_copied)
1040 DPRINTF(CacheVerbose,
"%s: created response: %s tick: %lu\n", __func__,
1041 pkt->
print(), forward_time);
1042 memSidePort.schedTimingSnoopResp(pkt, forward_time);
1047 bool is_deferred,
bool pending_inval)
1049 DPRINTF(CacheVerbose,
"%s: for %s\n", __func__, pkt->
print());
1051 assert(!(is_deferred && !is_timing));
1053 assert(!(pending_inval && !is_deferred));
1060 [[maybe_unused]]
bool needs_writable = pkt->
needsWritable();
1066 "%s got an invalidating uncacheable snoop request %s",
1069 uint32_t snoop_delay = 0;
1080 Packet snoopPkt(pkt,
true,
true);
1118 bool respond =
false;
1119 bool blk_valid = blk && blk->
isValid();
1122 DPRINTF(CacheVerbose,
"%s: packet (snoop) %s found block: %s\n",
1127 writebacks.push_back(wb_pkt);
1140 }
else if (!blk_valid) {
1141 DPRINTF(CacheVerbose,
"%s: snoop miss for %s\n", __func__,
1157 DPRINTF(
Cache,
"%s: snoop hit for %s, old state is %s\n", __func__,
1170 "Should never have a dirty block in a read-only cache %s\n",
1179 DPRINTF(
Cache,
"Found addr %#llx in upper level cache for snoop %s "
1185 if (pkt->
isRead() && !invalidate) {
1187 assert(!needs_writable);
1195 if (!pkt->
req->isUncacheable()) {
1225 "%s is passing a Modified line through %s, "
1226 "but keeping the block",
name(), pkt->
print());
1241 snoop_delay +=
compressor->getDecompressionLatency(blk);
1245 if (!respond && is_deferred) {
1252 if (blk_valid && invalidate) {
1264 DPRINTF(CacheVerbose,
"%s: for %s\n", __func__, pkt->
print());
1288 DPRINTF(
Cache,
"Setting block cached for %s from lower cache on "
1289 "mshr hit\n", pkt->
print());
1297 DPRINTF(
Cache,
"Deferring snoop on in-service MSHR to blk %#llx (%s)."
1298 "mshrs: %s\n", blk_addr, is_secure ?
"s" :
"ns",
1302 warn(
"allocating bonus target for snoop");
1309 DPRINTF(
Cache,
"Snoop hit in writeback to addr %#llx (%s)\n",
1310 pkt->
getAddr(), is_secure ?
"s" :
"ns");
1326 DPRINTF(
Cache,
"%s: Squashing %s from lower cache on writequeue "
1327 "hit\n", __func__, pkt->
print());
1341 if (!pkt->
req->isUncacheable() && pkt->
isRead() && !invalidate) {
1350 if (have_writable) {
1371 uint32_t snoop_delay =
handleSnoop(pkt, blk,
true,
false,
false);
1388 uint32_t snoop_delay =
handleSnoop(pkt, blk,
false,
false,
false);
1403 Packet snoop_pkt(pkt,
true,
false);
1433 assert(!
tags->findBlock({mshr->blkAddr, mshr->isSecure}));
1440 Packet snoop_pkt(tgt_pkt,
true,
false);
1467 bool pending_modified_resp = !snoop_pkt.
hasSharers();
1477 DPRINTF(
Cache,
"Block present, prefetch squashed by cache. "
1478 "Deallocating mshr target %#x.\n",
1482 if (
mshrQueue.forceDeallocateTarget(mshr)) {
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
Definitions of a simple cache block class.
const bool isReadOnly
Is this cache read only, for example the instruction cache, or table-walker cache.
virtual void recvTimingReq(PacketPtr pkt)
Performs the access specified by the request.
MSHR * allocateMissBuffer(PacketPtr pkt, Tick time, bool sched_send=true)
void invalidateBlock(CacheBlk *blk)
Invalidate a cache block.
const bool writebackClean
Determine if clean lines should be written back or not.
bool inRange(Addr addr) const
Determine if an address is in the ranges covered by this cache.
virtual void handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk, Tick forward_time, Tick request_time)=0
bool allocOnFill(MemCmd cmd) const
Determine whether we should allocate on a fill or not.
bool forwardSnoops
Do we forward snoops from mem side port through to cpu side port?
uint64_t order
Increasing order number assigned to each incoming request.
virtual void satisfyRequest(PacketPtr pkt, CacheBlk *blk, bool deferred_response=false, bool pending_downgrade=false)
Perform any necessary updates to the block and perform any data exchange between the packet and the b...
gem5::BaseCache::CacheStats stats
const Cycles lookupLatency
The latency of tag lookup of a cache.
MSHRQueue mshrQueue
Miss status registers.
const unsigned blkSize
Block size of this cache.
const Cycles forwardLatency
This is the forward latency of the cache.
compression::Base * compressor
Compression method being used.
const Cycles responseLatency
The latency of sending reponse to its upper level cache/core on a linefill.
PacketPtr writecleanBlk(CacheBlk *blk, Request::Flags dest, PacketId id)
Create a writeclean request for the given block.
virtual void handleTimingReqHit(PacketPtr pkt, CacheBlk *blk, Tick request_time)
virtual Tick recvAtomic(PacketPtr pkt)
Performs the access specified by the request.
virtual void recvTimingResp(PacketPtr pkt)
Handles a response (cache line fill/write ack) from the bus.
virtual bool access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat, PacketList &writebacks)
Does all the processing necessary to perform the provided request.
BaseCache(const BaseCacheParams &p, unsigned blk_size)
Addr regenerateBlkAddr(CacheBlk *blk)
Regenerate block address using tags.
std::unique_ptr< Packet > pendingDelete
Upstream caches need this packet until true is returned, so hold it for deletion until a subsequent c...
const int numTarget
The number of targets for each MSHR.
WriteAllocator *const writeAllocator
The writeAllocator drive optimizations for streaming writes.
void markInService(MSHR *mshr, bool pending_modified_resp)
Mark a request as in service (sent downstream in the memory system), effectively making this MSHR the...
void allocateWriteBuffer(PacketPtr pkt, Tick time)
CacheBlk * handleFill(PacketPtr pkt, CacheBlk *blk, PacketList &writebacks, bool allocate)
Handle a fill operation caused by a received packet.
WriteQueue writeBuffer
Write/writeback buffer.
PacketPtr writebackBlk(CacheBlk *blk)
Create a writeback request for the given block.
void clearBlocked(BlockedCause cause)
Marks the cache as unblocked for the given cause.
virtual PacketPtr evictBlock(CacheBlk *blk)=0
Evict a cache block.
BaseTags * tags
Tag and data Storage.
const enums::Clusivity clusivity
Clusivity with respect to the upstream cache, determining if we fill into both this cache and the cac...
virtual bool sendMSHRQueuePacket(MSHR *mshr)
Take an MSHR, turn it into a suitable downstream packet, and send it out.
void maintainClusivity(bool from_cache, CacheBlk *blk)
Maintain the clusivity of this cache by potentially invalidating a block.
System * system
System we are currently operating in.
@ ReadableBit
Read permission.
@ WritableBit
write permission
@ DirtyBit
dirty (modified)
void setPrefetched()
Marks this blocks as a recently prefetched block.
std::string print() const override
Pretty-print tag, set and way, and interpret state bits to readable form including mapping to a MOESI...
bool isSet(unsigned bits) const
Checks the given coherence bits are set.
void clearCoherenceBits(unsigned bits)
Clear the corresponding coherence bits.
uint32_t getTaskId() const
Get the task id associated to this block.
uint8_t * data
Contains a copy of the data in this block for easy access.
void setCoherenceBits(unsigned bits)
Sets the corresponding coherence bits.
PacketPtr cleanEvictBlk(CacheBlk *blk)
Create a CleanEvict request for the given block.
Cache(const CacheParams &p)
Instantiates a basic cache object.
void recvTimingSnoopReq(PacketPtr pkt) override
Snoops bus transactions to maintain coherence.
bool isCachedAbove(PacketPtr pkt, bool is_timing=true)
Send up a snoop request and find cached copies.
void promoteWholeLineWrites(PacketPtr pkt)
Turn line-sized writes into WriteInvalidate transactions.
void serviceMSHRTargets(MSHR *mshr, const PacketPtr pkt, CacheBlk *blk) override
Service non-deferred MSHR targets using the received response.
Cycles handleAtomicReqMiss(PacketPtr pkt, CacheBlk *&blk, PacketList &writebacks) override
Handle a request in atomic mode that missed in this cache.
Tick recvAtomicSnoop(PacketPtr pkt) override
Snoop for the provided request in the cache and return the estimated time taken.
std::unordered_set< RequestPtr > outstandingSnoop
Store the outstanding requests that we are expecting snoop responses from so we can determine which s...
void satisfyRequest(PacketPtr pkt, CacheBlk *blk, bool deferred_response=false, bool pending_downgrade=false) override
Perform any necessary updates to the block and perform any data exchange between the packet and the b...
void recvTimingSnoopResp(PacketPtr pkt) override
Handle a snoop response.
void recvTimingReq(PacketPtr pkt) override
Performs the access specified by the request.
Tick recvAtomic(PacketPtr pkt) override
Performs the access specified by the request.
void handleTimingReqMiss(PacketPtr pkt, CacheBlk *blk, Tick forward_time, Tick request_time) override
bool sendMSHRQueuePacket(MSHR *mshr) override
Take an MSHR, turn it into a suitable downstream packet, and send it out.
void doTimingSupplyResponse(PacketPtr req_pkt, const uint8_t *blk_data, bool already_copied, bool pending_inval)
PacketPtr createMissPacket(PacketPtr cpu_pkt, CacheBlk *blk, bool needs_writable, bool is_whole_line_write) const override
Create an appropriate downstream bus request packet.
void handleTimingReqHit(PacketPtr pkt, CacheBlk *blk, Tick request_time) override
uint32_t handleSnoop(PacketPtr pkt, CacheBlk *blk, bool is_timing, bool is_deferred, bool pending_inval)
Perform an upward snoop if needed, and update the block state (possibly invalidating the block).
PacketPtr evictBlock(CacheBlk *blk) override
Evict a cache block.
const bool doFastWrites
This cache should allocate a block on a line-sized write miss.
void doWritebacks(PacketList &writebacks, Tick forward_time) override
Insert writebacks into the write buffer.
bool access(PacketPtr pkt, CacheBlk *&blk, Cycles &lat, PacketList &writebacks) override
Does all the processing necessary to perform the provided request.
void doWritebacksAtomic(PacketList &writebacks) override
Send writebacks down the memory hierarchy in atomic mode.
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
Cycles ticksToCycles(Tick t) const
Cycles is a wrapper class for representing cycle counts, i.e.
bool hasFromCache
Determine whether there was at least one non-snooping target coming from another cache.
Miss Status and handling Register.
bool wasWholeLineWrite
Track if we sent this as a whole line write or not.
void updateLockedRMWReadTarget(PacketPtr pkt)
Replaces the matching packet in the Targets list with a dummy packet to ensure the MSHR remains alloc...
TargetList extractServiceableTargets(PacketPtr pkt)
Extracts the subset of the targets that can be serviced given a received response.
void popTarget()
Pop first target.
void print(std::ostream &os, int verbosity=0, const std::string &prefix="") const override
Prints the contents of this MSHR for debugging.
int getNumTargets() const
Returns the current number of allocated targets.
bool hasPostDowngrade() const
QueueEntry::Target * getTarget() override
Returns a reference to the first target.
bool handleSnoop(PacketPtr target, Counter order)
bool isForward
True if the entry is just a simple forward from an upper level.
bool hasLockedRMWReadTarget()
Determine if there are any LockedRMWReads in the Targets list.
bool hasPostInvalidate() const
bool isSWPrefetch() const
virtual std::string name() const
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
void setExpressSnoop()
The express snoop flag is used for two purposes.
bool responderHadWritable() const
uint32_t snoopDelay
Keep track of the extra delay incurred by snooping upwards before sending a request down the memory s...
void makeTimingResponse()
bool needsWritable() const
void print(std::ostream &o, int verbosity=0, const std::string &prefix="") const
void copyError(Packet *pkt)
bool needsResponse() const
SenderState * senderState
This packet's sender state.
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
bool matchAddr(const Addr addr, const bool is_secure) const
Check if packet corresponds to a given address and address space.
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
void setResponderHadWritable()
On responding to a snoop request (which only happens for Modified or Owned lines),...
Addr getOffset(unsigned int blk_size) const
bool mustCheckAbove() const
Does the request need to check for cached copies of the same block in the memory hierarchy above.
void copyResponderFlags(const PacketPtr pkt)
Copy the reponse flags from an input packet to this packet.
void setData(const uint8_t *p)
Copy data into the packet from the provided pointer.
void setDataFromBlock(const uint8_t *blk_data, int blkSize)
Copy data into the packet from the provided block pointer, which is aligned to the given block size.
Addr getBlockAddr(unsigned int blk_size) const
RequestPtr req
A pointer to the original request.
bool isCleanInvalidateRequest() const
Is this packet a clean invalidate request, e.g., clflush/clflushopt?
void setCacheResponding()
Snoop flags.
const T * getConstPtr() const
void setHasSharers()
On fills, the hasSharers flag is used by the caches in combination with the cacheResponding flag,...
bool cacheResponding() const
void makeAtomicResponse()
void setSatisfied()
Set when a request hits in a cache and the cache is not going to respond.
MemCmd cmd
The command field of the packet.
bool isMaskedWrite() const
bool isInvalidate() const
bool isWholeLineWrite(unsigned blk_size)
bool isBlockCached() const
void allocate()
Allocate memory for the packet.
A queue entry is holding packets that will be serviced as soon as resources are available.
PacketPtr pkt
Pending request packet.
bool isUncacheable() const
Addr blkAddr
Block aligned address.
@ SECURE
The request targets the secure memory space.
@ wbRequestorId
This requestor id is used for writeback requests by the caches.
virtual bool isValid() const
Checks if the entry is valid.
bool isSecure() const
Check if this block holds data from the secure memory space.
int getNumTargets() const
Returns the current number of allocated targets.
Target * getTarget() override
Returns a reference to the first target.
#define panic(...)
This implements a cprintf based panic() function.
#define gem5_assert(cond,...)
The assert macro will function like a normal assert, but will use panic instead of straight abort().
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition of a basic cache compressor.
Miss Status and Handling Register (MSHR) declaration.
Copyright (c) 2024 Arm Limited All rights reserved.
std::shared_ptr< Request > RequestPtr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
uint64_t Tick
Tick count type.
std::list< PacketPtr > PacketList
Declaration of a request, the overall memory request consisting of the parts of the request that are ...