PacketPtr getTimingPacket();
/**
- * Marks a request as in service (sent on the bus). This can have side
- * effect since storage for no response commands is deallocated once they
- * are successfully sent.
- * @param pkt The request that was sent on the bus.
+ * Marks a request as in service (sent on the bus). This can have
+ * side effect since storage for no response commands is
+ * deallocated once they are successfully sent. Also remember if
+ * we are expecting a dirty response from another cache,
+ * effectively making this MSHR the ordering point.
*/
- void markInService(MSHR *mshr, PacketPtr pkt = NULL);
+ void markInService(MSHR *mshr, bool pending_dirty_resp);
/**
* Return whether there are any outstanding misses.
template<class TagStore>
void
-Cache<TagStore>::markInService(MSHR *mshr, PacketPtr pkt)
+Cache<TagStore>::markInService(MSHR *mshr, bool pending_dirty_resp)
{
- // packet can be either a request or response
-
- markInServiceInternal(mshr, pkt);
+ markInServiceInternal(mshr, pending_dirty_resp);
#if 0
if (mshr->originalCmd == MemCmd::HardPFReq) {
DPRINTF(HWPrefetch, "%s:Marking a HW_PF in service\n",
if (pkt->isInvalidate()) {
// Invalidation trumps our writeback... discard here
- markInService(mshr);
+ markInService(mshr, false);
delete wb_pkt;
}
} // writebacks.size()
snoop_pkt.senderState = mshr;
cpuSidePort->sendTimingSnoopReq(&snoop_pkt);
- // Check to see if the prefetch was squashed by an upper cache
- // Or if a writeback arrived between the time the prefetch was
- // placed in the MSHRs and when it was selected to send.
+ // Check to see if the prefetch was squashed by an upper
+ // cache (to prevent us from grabbing the line) or if a
+ // writeback arrived between the time the prefetch was
+ // placed in the MSHRs and when it was selected to be sent.
if (snoop_pkt.prefetchSquashed() || blk != NULL) {
DPRINTF(Cache, "Prefetch squashed by cache. "
"Deallocating mshr target %#x.\n", mshr->addr);
return NULL;
}
+ // Check if the prefetch hit a writeback in an upper cache
+ // and if so we will eventually get a HardPFResp from
+ // above
if (snoop_pkt.memInhibitAsserted()) {
- markInService(mshr, &snoop_pkt);
+ // If we are getting a non-shared response it is dirty
+ bool pending_dirty_resp = !snoop_pkt.sharedAsserted();
+ markInService(mshr, pending_dirty_resp);
DPRINTF(Cache, "Upward snoop of prefetch for addr"
" %#x (%s) hit\n",
tgt_pkt->getAddr(), tgt_pkt->isSecure()? "s": "ns");
// care about this packet and might override it before
// it gets retried
} else {
- cache.markInService(mshr, pkt);
+ // As part of the call to sendTimingReq the packet is
+ // forwarded to all neighbouring caches (and any
+ // caches above them) as a snoop. The packet is also
+ // sent to any potential cache below as the
+ // interconnect is not allowed to buffer the
+ // packet. Thus at this point we know if any of the
+ // neighbouring, or the downstream cache is
+ // responding, and if so, if it is with a dirty line
+ // or not.
+ bool pending_dirty_resp = !pkt->sharedAsserted() &&
+ pkt->memInhibitAsserted();
+
+ cache.markInService(mshr, pending_dirty_resp);
}
}
}
/**
* Mark the given MSHR as in service. This removes the MSHR from the
- * readyList. Deallocates the MSHR if it does not expect a response.
+ * readyList or deallocates the MSHR if it does not expect a response.
+ *
* @param mshr The MSHR to mark in service.
+ * @param pending_dirty_resp Whether we expect a dirty response
+ * from another cache
*/
- void markInService(MSHR *mshr, PacketPtr pkt);
+ void markInService(MSHR *mshr, bool pending_dirty_resp);
/**
* Mark an in service entry as pending, used to resend a request.