From ec8a437b2c11453e9b94978b0c18a31f12ec04ac Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Mon, 9 Oct 2006 20:18:00 -0400 Subject: Handle NACK's that occur from devices on the same bus. Not fully implemented yet, but good enough for single level cache coherence src/mem/packet.hh: Add a bit to distinguish invalidates and upgrades --HG-- extra : convert_revision : 5bf50d535857cea37fbdaf7993915d1332cb757e --- src/mem/cache/cache_impl.hh | 14 ++++++++++---- src/mem/packet.hh | 5 +++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index c3c1c0881..5c12075cd 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -287,13 +287,17 @@ template void Cache::sendResult(PacketPtr &pkt, MSHR* mshr, bool success) { - if (success) { + if (success && !(pkt->flags & NACKED_LINE)) { missQueue->markInService(pkt, mshr); //Temp Hack for UPGRADES if (pkt->cmd == Packet::UpgradeReq) { + pkt->flags &= ~CACHE_LINE_FILL; handleResponse(pkt); } } else if (pkt && !pkt->req->isUncacheable()) { + pkt->flags &= ~NACKED_LINE; + pkt->flags &= ~SATISFIED; + pkt->flags &= ~SNOOP_COMMIT; missQueue->restoreOrigCmd(pkt); } } @@ -305,8 +309,9 @@ Cache::handleResponse(Packet * &pkt) BlkType *blk = NULL; if (pkt->senderState) { if (pkt->result == Packet::Nacked) { - pkt->reinitFromRequest(); - panic("Unimplemented NACK of packet\n"); + //pkt->reinitFromRequest(); + warn("NACKs from devices not connected to the same bus not implemented\n"); + return; } if (pkt->result == Packet::BadAddress) { //Make the response a Bad address and send it @@ -397,7 +402,8 @@ Cache::snoop(Packet * &pkt) assert(!(pkt->flags & SATISFIED)); pkt->flags |= SATISFIED; pkt->flags |= NACKED_LINE; - respondToSnoop(pkt, curTick + hitLatency); + warn("NACKs from devices not connected to the same bus not implemented\n"); + //respondToSnoop(pkt, curTick + hitLatency); return; } else { diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 56c4caffe..e8cbfd10e 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -174,7 +174,8 @@ class Packet IsResponse = 1 << 5, NeedsResponse = 1 << 6, IsSWPrefetch = 1 << 7, - IsHWPrefetch = 1 << 8 + IsHWPrefetch = 1 << 8, + IsUpgrade = 1 << 9 }; public: @@ -194,7 +195,7 @@ class Packet HardPFResp = IsRead | IsResponse | IsHWPrefetch | NeedsResponse, InvalidateReq = IsInvalidate | IsRequest, WriteInvalidateReq = IsWrite | IsInvalidate | IsRequest, - UpgradeReq = IsInvalidate | IsRequest, + UpgradeReq = IsInvalidate | IsRequest | IsUpgrade, ReadExReq = IsRead | IsInvalidate | IsRequest | NeedsResponse, ReadExResp = IsRead | IsInvalidate | IsResponse | NeedsResponse }; -- cgit v1.2.3 From cc78d86661dfccaca2f144d5bdcc75761bf52521 Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Tue, 10 Oct 2006 01:32:18 -0400 Subject: Fix several bugs pertaining to upgrades/mem leaks. src/mem/cache/base_cache.cc: Fix a bug about not having a request to send src/mem/cache/base_cache.hh: Fix a bug with the blocking code src/mem/cache/cache.hh: AFix a bug with snoop hits in WB buffer src/mem/cache/cache_impl.hh: Fix a bug with snoop hits in WB buffer Also, add better DPRINTF's src/mem/cache/miss/miss_queue.cc: Fix a bug with upgrades (Need to clean it up later) src/mem/cache/miss/mshr.cc: Fix a memory leak bug, still some outstanding with writebacks not being deleted src/mem/cache/miss/mshr_queue.cc: Fix a bug about upgrades (need to clean up later) src/mem/packet.hh: Fix for newly added cmd attribute for upgrades tests/configs/memtest.py: More interesting testcase --HG-- extra : convert_revision : fcb4f17dd58b537bb4f67a8c835f50e455e8c688 --- src/mem/cache/base_cache.cc | 15 ++++++++++++++ src/mem/cache/base_cache.hh | 10 +++++++--- src/mem/cache/cache.hh | 1 + src/mem/cache/cache_impl.hh | 42 +++++++++++++++++++++++++--------------- src/mem/cache/miss/miss_queue.cc | 8 ++++++++ src/mem/cache/miss/mshr.cc | 1 + src/mem/cache/miss/mshr_queue.cc | 2 +- src/mem/packet.hh | 4 ++-- tests/configs/memtest.py | 11 +++++------ 9 files changed, 66 insertions(+), 28 deletions(-) diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc index 8e2f4d233..c4d42c0a4 100644 --- a/src/mem/cache/base_cache.cc +++ b/src/mem/cache/base_cache.cc @@ -104,10 +104,12 @@ BaseCache::CachePort::recvRetry() if (result) drainList.pop_front(); } + if (!result) return; } if (!isCpuSide) { + if (!cache->doMasterRequest()) return; pkt = cache->getPacket(); MSHR* mshr = (MSHR*)pkt->senderState; bool success = sendTiming(pkt); @@ -179,10 +181,23 @@ BaseCache::CacheEvent::CacheEvent(CachePort *_cachePort, Packet *_pkt) void BaseCache::CacheEvent::process() { + if (!cachePort->drainList.empty()) { + //We have some responses to drain first + bool result = true; + while (result && !cachePort->drainList.empty()) { + result = cachePort->sendTiming(cachePort->drainList.front()); + if (result) + cachePort->drainList.pop_front(); + } + if (!result) return; + } + if (!pkt) { if (!cachePort->isCpuSide) { + //For now, doMasterRequest somehow is still getting set + if (!cachePort->cache->doMasterRequest()) return; //MSHR pkt = cachePort->cache->getPacket(); MSHR* mshr = (MSHR*) pkt->senderState; diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh index c45f3b71b..e0f12940f 100644 --- a/src/mem/cache/base_cache.hh +++ b/src/mem/cache/base_cache.hh @@ -392,11 +392,13 @@ class BaseCache : public MemObject blocked_causes[cause]++; blockedCycle = curTick; } + int old_state = blocked; if (!(blocked & flag)) { //Wasn't already blocked for this cause blocked |= flag; DPRINTF(Cache,"Blocking for cause %s\n", cause); - cpuSidePort->setBlocked(); + if (!old_state) + cpuSidePort->setBlocked(); } } @@ -408,10 +410,12 @@ class BaseCache : public MemObject void setBlockedForSnoop(BlockedCause cause) { uint8_t flag = 1 << cause; - if (!(blocked & flag)) { + uint8_t old_state = blockedSnoop; + if (!(blockedSnoop & flag)) { //Wasn't already blocked for this cause blockedSnoop |= flag; - memSidePort->setBlocked(); + if (!old_state) + memSidePort->setBlocked(); } } diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index 923bf8255..41b270030 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -103,6 +103,7 @@ class Cache : public BaseCache * Used to append to target list, to cause an invalidation. */ Packet * invalidatePkt; + Request *invalidateReq; /** * Temporarily move a block into a MSHR. diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 5c12075cd..8c0521b52 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -163,10 +163,8 @@ Cache(const std::string &_name, prefetcher->setCache(this); prefetcher->setTags(tags); prefetcher->setBuffer(missQueue); -#if 0 - invalidatePkt = new Packet; - invalidatePkt->cmd = Packet::InvalidateReq; -#endif + invalidateReq = new Request((Addr) NULL, blkSize, 0); + invalidatePkt = new Packet(invalidateReq, Packet::InvalidateReq, 0); } template @@ -267,6 +265,7 @@ template Packet * Cache::getPacket() { + assert(missQueue->havePending()); Packet * pkt = missQueue->getPacket(); if (pkt) { if (!pkt->req->isUncacheable()) { @@ -292,7 +291,17 @@ Cache::sendResult(PacketPtr &pkt, MSHR* mshr, bool //Temp Hack for UPGRADES if (pkt->cmd == Packet::UpgradeReq) { pkt->flags &= ~CACHE_LINE_FILL; - handleResponse(pkt); + BlkType *blk = tags->findBlock(pkt); + CacheBlk::State old_state = (blk) ? blk->status : 0; + CacheBlk::State new_state = coherence->getNewState(pkt,old_state); + DPRINTF(Cache, "Block for blk addr %x moving from state %i to %i\n", + pkt->getAddr() & (((ULL(1))<<48)-1), old_state, new_state); + //Set the state on the upgrade + memcpy(pkt->getPtr(), blk->data, blkSize); + PacketList writebacks; + tags->handleFill(blk, mshr, new_state, writebacks, pkt); + assert(writebacks.empty()); + missQueue->handleResponse(pkt, curTick + hitLatency); } } else if (pkt && !pkt->req->isUncacheable()) { pkt->flags &= ~NACKED_LINE; @@ -402,7 +411,8 @@ Cache::snoop(Packet * &pkt) assert(!(pkt->flags & SATISFIED)); pkt->flags |= SATISFIED; pkt->flags |= NACKED_LINE; - warn("NACKs from devices not connected to the same bus not implemented\n"); + ///@todo NACK's from other levels + //warn("NACKs from devices not connected to the same bus not implemented\n"); //respondToSnoop(pkt, curTick + hitLatency); return; } @@ -416,7 +426,7 @@ Cache::snoop(Packet * &pkt) //@todo Make it so that a read to a pending read can't be exclusive now. //Set the address so find match works - panic("Don't have invalidates yet\n"); + //panic("Don't have invalidates yet\n"); invalidatePkt->addrOverride(pkt->getAddr()); //Append the invalidate on @@ -447,7 +457,7 @@ Cache::snoop(Packet * &pkt) pkt->flags |= SHARED_LINE; assert(pkt->isRead()); - Addr offset = pkt->getAddr() & ~(blkSize - 1); + Addr offset = pkt->getAddr() & (blkSize - 1); assert(offset < blkSize); assert(pkt->getSize() <= blkSize); assert(offset + pkt->getSize() <=blkSize); @@ -468,16 +478,16 @@ Cache::snoop(Packet * &pkt) CacheBlk::State new_state; bool satisfy = coherence->handleBusRequest(pkt,blk,mshr, new_state); if (satisfy) { - DPRINTF(Cache, "Cache snooped a %s request and now supplying data," + DPRINTF(Cache, "Cache snooped a %s request for addr %x and now supplying data," "new state is %i\n", - pkt->cmdString(), new_state); + pkt->cmdString(), blk_addr, new_state); tags->handleSnoop(blk, new_state, pkt); respondToSnoop(pkt, curTick + hitLatency); return; } - if (blk) DPRINTF(Cache, "Cache snooped a %s request, new state is %i\n", - pkt->cmdString(), new_state); + if (blk) DPRINTF(Cache, "Cache snooped a %s request for addr %x, new state is %i\n", + pkt->cmdString(), blk_addr, new_state); tags->handleSnoop(blk, new_state); } @@ -695,15 +705,15 @@ Cache::snoopProbe(PacketPtr &pkt) CacheBlk::State new_state = 0; bool satisfy = coherence->handleBusRequest(pkt,blk,mshr, new_state); if (satisfy) { - DPRINTF(Cache, "Cache snooped a %s request and now supplying data," + DPRINTF(Cache, "Cache snooped a %s request for addr %x and now supplying data," "new state is %i\n", - pkt->cmdString(), new_state); + pkt->cmdString(), blk_addr, new_state); tags->handleSnoop(blk, new_state, pkt); return hitLatency; } - if (blk) DPRINTF(Cache, "Cache snooped a %s request, new state is %i\n", - pkt->cmdString(), new_state); + if (blk) DPRINTF(Cache, "Cache snooped a %s request for addr %x, new state is %i\n", + pkt->cmdString(), blk_addr, new_state); tags->handleSnoop(blk, new_state); return 0; } diff --git a/src/mem/cache/miss/miss_queue.cc b/src/mem/cache/miss/miss_queue.cc index bdb7a39c8..c7b0e0890 100644 --- a/src/mem/cache/miss/miss_queue.cc +++ b/src/mem/cache/miss/miss_queue.cc @@ -515,6 +515,14 @@ MissQueue::setBusCmd(Packet * &pkt, Packet::Command cmd) assert(pkt->senderState != 0); MSHR * mshr = (MSHR*)pkt->senderState; mshr->originalCmd = pkt->cmd; + if (cmd == Packet::UpgradeReq || cmd == Packet::InvalidateReq) { + pkt->flags |= NO_ALLOCATE; + pkt->flags &= ~CACHE_LINE_FILL; + } + else if (!pkt->req->isUncacheable() && !pkt->isNoAllocate() && + (cmd & (1 << 6)/*NeedsResponse*/)) { + pkt->flags |= CACHE_LINE_FILL; + } if (pkt->isCacheFill() || pkt->isNoAllocate()) pkt->cmd = cmd; } diff --git a/src/mem/cache/miss/mshr.cc b/src/mem/cache/miss/mshr.cc index f36032672..455798f15 100644 --- a/src/mem/cache/miss/mshr.cc +++ b/src/mem/cache/miss/mshr.cc @@ -100,6 +100,7 @@ MSHR::deallocate() { assert(targets.empty()); assert(ntargets == 0); + delete pkt; pkt = NULL; inService = false; //allocIter = NULL; diff --git a/src/mem/cache/miss/mshr_queue.cc b/src/mem/cache/miss/mshr_queue.cc index bd9667529..78897c8fb 100644 --- a/src/mem/cache/miss/mshr_queue.cc +++ b/src/mem/cache/miss/mshr_queue.cc @@ -213,7 +213,7 @@ void MSHRQueue::markInService(MSHR* mshr) { //assert(mshr == pendingList.front()); - if (!mshr->pkt->needsResponse()) { + if (!(mshr->pkt->needsResponse() || mshr->pkt->cmd == Packet::UpgradeReq)) { assert(mshr->getNumTargets() == 0); deallocate(mshr); return; diff --git a/src/mem/packet.hh b/src/mem/packet.hh index e8cbfd10e..8d9f8ee60 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -59,8 +59,8 @@ typedef std::list PacketList; #define SNOOP_COMMIT 1 << 6 //For statistics we need max number of commands, hard code it at -//20 for now. @todo fix later -#define NUM_MEM_CMDS 1 << 9 +//for now. @todo fix later +#define NUM_MEM_CMDS 1 << 10 /** * A Packet is used to encapsulate a transfer between two objects in diff --git a/tests/configs/memtest.py b/tests/configs/memtest.py index c5cd0246d..17992976c 100644 --- a/tests/configs/memtest.py +++ b/tests/configs/memtest.py @@ -36,7 +36,7 @@ from m5.objects import * class L1(BaseCache): latency = 1 block_size = 64 - mshrs = 4 + mshrs = 12 tgts_per_mshr = 8 protocol = CoherenceProtocol(protocol='moesi') @@ -46,14 +46,14 @@ class L1(BaseCache): class L2(BaseCache): block_size = 64 - latency = 100 + latency = 10 mshrs = 92 tgts_per_mshr = 16 write_buffers = 8 #MAX CORES IS 8 with the fals sharing method nb_cores = 8 -cpus = [ MemTest(max_loads=1e12) for i in xrange(nb_cores) ] +cpus = [ MemTest(max_loads=1e12, percent_uncacheable=0) for i in xrange(nb_cores) ] # system simulated system = System(cpu = cpus, funcmem = PhysicalMemory(), @@ -61,7 +61,7 @@ system = System(cpu = cpus, funcmem = PhysicalMemory(), # l2cache & bus system.toL2Bus = Bus() -system.l2c = L2(size='4MB', assoc=8) +system.l2c = L2(size='64kB', assoc=8) system.l2c.cpu_side = system.toL2Bus.port # connect l2c to membus @@ -90,5 +90,4 @@ system.physmem.port = system.membus.port root = Root( system = system ) root.system.mem_mode = 'timing' -#root.trace.flags="InstExec" -root.trace.flags="Bus" +root.trace.flags="Cache" -- cgit v1.2.3 From 89e80ccc203891f056a587b777fde9efddaba18f Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Tue, 10 Oct 2006 02:00:37 -0400 Subject: Fix another merge issue --HG-- extra : convert_revision : 2b33da5e8578ea6a8bdd2d89f183c2e6b942b0fc --- src/mem/packet.hh | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 426f14421..3d43615bf 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -178,9 +178,6 @@ class Packet IsUpgrade = 1 << 9, HasData = 1 << 10 }; -//For statistics we need max number of commands, hard code it at -//20 for now. @todo fix later -#define NUM_MEM_CMDS 1 << 10 public: /** List of all commands associated with a packet. */ -- cgit v1.2.3 From b40798070ba2e2b0a7c94f2afaf79574123a0592 Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Tue, 10 Oct 2006 02:21:03 -0400 Subject: Actually set the HasData attribute on Read Responses --HG-- extra : convert_revision : 129dadbf8091ab00fb7f16eace59df265fc3718c --- src/mem/packet.hh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 3d43615bf..998419156 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -325,6 +325,8 @@ class Packet int icmd = (int)cmd; icmd &= ~(IsRequest); icmd |= IsResponse; + if (isRead()) + icmd |= HasData; cmd = (Command)icmd; dest = src; srcValid = false; -- cgit v1.2.3 From 3fa5e4b6b8c402558caecb2a93ed0be38700e1bc Mon Sep 17 00:00:00 2001 From: Ron Dreslinski Date: Tue, 10 Oct 2006 02:33:30 -0400 Subject: Yet another fix to the HasData command attribute. --HG-- extra : convert_revision : dcf0d7eafa5168591c2b374b452821ca34dde7f9 --- src/mem/packet.hh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 998419156..7ec061710 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -327,6 +327,8 @@ class Packet icmd |= IsResponse; if (isRead()) icmd |= HasData; + if (isWrite()) + icmd &= ~HasData; cmd = (Command)icmd; dest = src; srcValid = false; -- cgit v1.2.3