return true;
}
-
-// See comment in cache.hh.
PacketPtr
-Cache::getBusPacket(PacketPtr cpu_pkt, CacheBlk *blk,
- bool needsWritable) const
+Cache::createMissPacket(PacketPtr cpu_pkt, CacheBlk *blk,
+ bool needsWritable) const
{
- bool blkValid = blk && blk->isValid();
+ // should never see evictions here
+ assert(!cpu_pkt->isEviction());
- if (cpu_pkt->req->isUncacheable()) {
- // note that at the point we see the uncacheable request we
- // flush any block, but there could be an outstanding MSHR,
- // and the cache could have filled again before we actually
- // send out the forwarded uncacheable request (blk could thus
- // be non-null)
- return NULL;
- }
+ bool blkValid = blk && blk->isValid();
- if (!blkValid &&
- (cpu_pkt->isUpgrade() ||
- cpu_pkt->isEviction())) {
- // Writebacks that weren't allocated in access() and upgrades
- // from upper-level caches that missed completely just go
- // through.
- return NULL;
+ if (cpu_pkt->req->isUncacheable() ||
+ (!blkValid && cpu_pkt->isUpgrade())) {
+ // uncacheable requests and upgrades from upper-level caches
+ // that missed completely just go through as is
+ return nullptr;
}
assert(cpu_pkt->needsResponse());
if (!satisfied) {
// MISS
- PacketPtr bus_pkt = getBusPacket(pkt, blk, pkt->needsWritable());
+ // deal with the packets that go through the write path of
+ // the cache, i.e. any evictions and uncacheable writes
+ if (pkt->isEviction() ||
+ (pkt->req->isUncacheable() && pkt->isWrite())) {
+ lat += ticksToCycles(memSidePort->sendAtomic(pkt));
+ return lat * clockPeriod();
+ }
+ // only misses left
+
+ PacketPtr bus_pkt = createMissPacket(pkt, blk, pkt->needsWritable());
bool is_forward = (bus_pkt == NULL);
lat += ticksToCycles(memSidePort->sendAtomic(bus_pkt));
+ bool is_invalidate = bus_pkt->isInvalidate();
+
// We are now dealing with the response handling
DPRINTF(Cache, "Receive response: %s for addr %#llx (%s) in state %i\n",
bus_pkt->cmdString(), bus_pkt->getAddr(),
if (bus_pkt->isError()) {
pkt->makeAtomicResponse();
pkt->copyError(bus_pkt);
- } else if (pkt->cmd == MemCmd::InvalidateReq) {
- if (blk) {
- // invalidate response to a cache that received
- // an invalidate request
- satisfyCpuSideRequest(pkt, blk);
- }
} else if (pkt->cmd == MemCmd::WriteLineReq) {
// note the use of pkt, not bus_pkt here.
// the write to a whole line
blk = handleFill(pkt, blk, writebacks,
allocOnFill(pkt->cmd));
+ assert(blk != NULL);
+ is_invalidate = false;
satisfyCpuSideRequest(pkt, blk);
} else if (bus_pkt->isRead() ||
bus_pkt->cmd == MemCmd::UpgradeResp) {
}
delete bus_pkt;
}
+
+ if (is_invalidate && blk && blk->isValid()) {
+ invalidateBlock(blk);
+ }
}
// Note that we don't invoke the prefetcher at all in atomic mode.
// either a prefetch that is not present upstream, or a normal
// MSHR request, proceed to get the packet to send downstream
- PacketPtr pkt = getBusPacket(tgt_pkt, blk, mshr->needsWritable());
+ PacketPtr pkt = createMissPacket(tgt_pkt, blk, mshr->needsWritable());
mshr->isForward = (pkt == NULL);
bool invalidateVisitor(CacheBlk &blk);
/**
- * Generate an appropriate downstream bus request packet for the
+ * Create an appropriate downstream bus request packet for the
* given parameters.
- * @param cpu_pkt The upstream request that needs to be satisfied.
+ * @param cpu_pkt The miss that needs to be satisfied.
* @param blk The block currently in the cache corresponding to
* cpu_pkt (NULL if none).
- * @param needsExclusive Indicates that an exclusive copy is required
+ * @param needsWritable Indicates that the block must be writable
* even if the request in cpu_pkt doesn't indicate that.
* @return A new Packet containing the request, or NULL if the
* current request in cpu_pkt should just be forwarded on.
*/
- PacketPtr getBusPacket(PacketPtr cpu_pkt, CacheBlk *blk,
- bool needsExclusive) const;
+ PacketPtr createMissPacket(PacketPtr cpu_pkt, CacheBlk *blk,
+ bool needsWritable) const;
/**
* Return the next queue entry to service, either a pending miss