Cache: Refactor packet forwarding a bit.

Makes adding write-through operations easier.
This commit is contained in:
Steve Reinhardt
2008-11-10 14:10:28 -08:00
parent c981b7ed50
commit 42bd460d7f
3 changed files with 54 additions and 32 deletions

View File

@@ -613,38 +613,53 @@ Cache<TagStore>::atomicAccess(PacketPtr pkt)
if (!access(pkt, blk, lat, writebacks)) {
// MISS
PacketPtr busPkt = getBusPacket(pkt, blk, pkt->needsExclusive());
PacketPtr bus_pkt = getBusPacket(pkt, blk, pkt->needsExclusive());
bool isCacheFill = (busPkt != NULL);
bool is_forward = (bus_pkt == NULL);
if (busPkt == NULL) {
if (is_forward) {
// just forwarding the same request to the next level
// no local cache operation involved
busPkt = pkt;
bus_pkt = pkt;
}
DPRINTF(Cache, "Sending an atomic %s for %x\n",
busPkt->cmdString(), busPkt->getAddr());
bus_pkt->cmdString(), bus_pkt->getAddr());
#if TRACING_ON
CacheBlk::State old_state = blk ? blk->status : 0;
#endif
lat += memSidePort->sendAtomic(busPkt);
lat += memSidePort->sendAtomic(bus_pkt);
DPRINTF(Cache, "Receive response: %s for addr %x in state %i\n",
busPkt->cmdString(), busPkt->getAddr(), old_state);
bus_pkt->cmdString(), bus_pkt->getAddr(), old_state);
bool is_error = busPkt->isError();
assert(!busPkt->wasNacked());
assert(!bus_pkt->wasNacked());
if (is_error && pkt->needsResponse()) {
pkt->makeAtomicResponse();
pkt->copyError(busPkt);
} else if (isCacheFill && !is_error) {
blk = handleFill(busPkt, blk, writebacks);
satisfyCpuSideRequest(pkt, blk);
delete busPkt;
// If packet was a forward, the response (if any) is already
// in place in the bus_pkt == pkt structure, so we don't need
// to do anything. Otherwise, use the separate bus_pkt to
// generate response to pkt and then delete it.
if (!is_forward) {
if (pkt->needsResponse()) {
assert(bus_pkt->isResponse());
if (bus_pkt->isError()) {
pkt->makeAtomicResponse();
pkt->copyError(bus_pkt);
} else if (bus_pkt->isRead() ||
bus_pkt->cmd == MemCmd::UpgradeResp) {
// we're updating cache state to allow us to
// satisfy the upstream request from the cache
blk = handleFill(bus_pkt, blk, writebacks);
satisfyCpuSideRequest(pkt, blk);
} else {
// we're satisfying the upstream request without
// modifying cache state, e.g., a write-through
pkt->makeAtomicResponse();
}
}
delete bus_pkt;
}
}
@@ -748,7 +763,10 @@ Cache<TagStore>::handleResponse(PacketPtr pkt)
miss_latency;
}
if (mshr->isCacheFill && !is_error) {
bool is_fill = !mshr->isForward &&
(pkt->isRead() || pkt->cmd == MemCmd::UpgradeResp);
if (is_fill && !is_error) {
DPRINTF(Cache, "Block for addr %x being updated in Cache\n",
pkt->getAddr());
@@ -771,7 +789,7 @@ Cache<TagStore>::handleResponse(PacketPtr pkt)
if (target->isCpuSide()) {
Tick completion_time;
if (blk != NULL) {
if (is_fill) {
satisfyCpuSideRequest(target->pkt, blk);
// How many bytes past the first request is this one
int transfer_offset =
@@ -1287,7 +1305,7 @@ Cache<TagStore>::getTimingPacket()
PacketPtr tgt_pkt = mshr->getTarget()->pkt;
PacketPtr pkt = NULL;
if (mshr->isSimpleForward()) {
if (mshr->isForwardNoResponse()) {
// no response expected, just forward packet as it is
assert(tags->findBlock(mshr->addr) == NULL);
pkt = tgt_pkt;
@@ -1295,11 +1313,10 @@ Cache<TagStore>::getTimingPacket()
BlkType *blk = tags->findBlock(mshr->addr);
pkt = getBusPacket(tgt_pkt, blk, mshr->needsExclusive());
mshr->isCacheFill = (pkt != NULL);
mshr->isForward = (pkt == NULL);
if (pkt == NULL) {
if (mshr->isForward) {
// not a cache block request, but a response is expected
assert(!mshr->isSimpleForward());
// make copy of current packet to forward, keep current
// copy for response handling
pkt = new Packet(tgt_pkt);
@@ -1473,7 +1490,7 @@ Cache<TagStore>::MemSidePort::sendPacket()
waitingOnRetry = !success;
if (waitingOnRetry) {
DPRINTF(CachePort, "now waiting on a retry\n");
if (!mshr->isSimpleForward()) {
if (!mshr->isForwardNoResponse()) {
delete pkt;
}
} else {

View File

@@ -156,7 +156,7 @@ MSHR::allocate(Addr _addr, int _size, PacketPtr target,
readyTime = whenReady;
order = _order;
assert(target);
isCacheFill = false;
isForward = false;
_isUncacheable = target->req->isUncacheable();
inService = false;
downstreamPending = false;
@@ -187,7 +187,7 @@ bool
MSHR::markInService()
{
assert(!inService);
if (isSimpleForward()) {
if (isForwardNoResponse()) {
// we just forwarded the request packet & don't expect a
// response, so get rid of it
assert(getNumTargets() == 1);
@@ -403,7 +403,8 @@ MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const
{
ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s\n",
prefix, addr, addr+size-1,
isCacheFill ? "Fill" : "",
isForward ? "Forward" : "",
isForwardNoResponse() ? "ForwNoResp" : "",
needsExclusive() ? "Excl" : "",
_isUncacheable ? "Unc" : "",
inService ? "InSvc" : "",

16
src/mem/cache/mshr.hh vendored
View File

@@ -118,8 +118,8 @@ class MSHR : public Packet::SenderState, public Printable
/** True if the request has been sent to the bus. */
bool inService;
/** True if we will be putting the returned block in the cache */
bool isCacheFill;
/** True if the request is just a simple forward from an upper level */
bool isForward;
/** True if we need to get an exclusive copy of the block. */
bool needsExclusive() const { return targets->needsExclusive; }
@@ -200,7 +200,7 @@ public:
* Returns the current number of allocated targets.
* @return The current number of allocated targets.
*/
int getNumTargets() { return ntargets; }
int getNumTargets() const { return ntargets; }
/**
* Returns a pointer to the target list.
@@ -212,13 +212,17 @@ public:
* Returns true if there are targets left.
* @return true if there are targets
*/
bool hasTargets() { return !targets->empty(); }
bool hasTargets() const { return !targets->empty(); }
/**
* Returns a reference to the first target.
* @return A pointer to the first target.
*/
Target *getTarget() { assert(hasTargets()); return &targets->front(); }
Target *getTarget() const
{
assert(hasTargets());
return &targets->front();
}
/**
* Pop first target.
@@ -229,7 +233,7 @@ public:
targets->pop_front();
}
bool isSimpleForward()
bool isForwardNoResponse() const
{
if (getNumTargets() != 1)
return false;