First set of changes for reorganized cache coherence support.
authorSteve Reinhardt <stever@eecs.umich.edu>
Sat, 19 May 2007 05:35:04 +0000 (22:35 -0700)
committerSteve Reinhardt <stever@eecs.umich.edu>
Sat, 19 May 2007 05:35:04 +0000 (22:35 -0700)
Compiles but doesn't work... committing just so I can merge
(stupid bk!).

src/mem/bridge.cc:
    Get rid of SNOOP_COMMIT.
src/mem/bus.cc:
src/mem/packet.hh:
    Get rid of SNOOP_COMMIT & two-pass snoop.
    First bits of EXPRESS_SNOOP support.
src/mem/cache/base_cache.cc:
src/mem/cache/base_cache.hh:
src/mem/cache/cache.hh:
src/mem/cache/cache_impl.hh:
src/mem/cache/miss/blocking_buffer.cc:
src/mem/cache/miss/miss_queue.cc:
src/mem/cache/prefetch/base_prefetcher.cc:
    Big reorg of ports and port-related functions & events.
src/mem/cache/cache.cc:
src/mem/cache/cache_builder.cc:
src/mem/cache/coherence/SConscript:
    Get rid of UniCoherence object.

--HG--
extra : convert_revision : 7672434fa3115c9b1c94686f497e57e90413b7c3

15 files changed:
src/mem/bridge.cc
src/mem/bus.cc
src/mem/cache/base_cache.cc
src/mem/cache/base_cache.hh
src/mem/cache/cache.cc
src/mem/cache/cache.hh
src/mem/cache/cache_builder.cc
src/mem/cache/cache_impl.hh
src/mem/cache/coherence/SConscript
src/mem/cache/coherence/uni_coherence.cc [deleted file]
src/mem/cache/coherence/uni_coherence.hh [deleted file]
src/mem/cache/miss/blocking_buffer.cc
src/mem/cache/miss/miss_queue.cc
src/mem/cache/prefetch/base_prefetcher.cc
src/mem/packet.hh

index f525ccb48daab54c3b61deadd1a63e19f8596418..5460c88ddfff4e83405a391f643a8d28ec013d18 100644 (file)
@@ -112,10 +112,6 @@ Bridge::BridgePort::reqQueueFull()
 bool
 Bridge::BridgePort::recvTiming(PacketPtr pkt)
 {
-    if (!(pkt->flags & SNOOP_COMMIT))
-        return true;
-
-
     DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n",
                 pkt->getSrc(), pkt->getDest(), pkt->getAddr());
 
@@ -255,8 +251,6 @@ Bridge::BridgePort::trySend()
 
     PacketPtr pkt = buf->pkt;
 
-    pkt->flags &= ~SNOOP_COMMIT; //CLear it if it was set
-
     if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite &&
             pkt->result != Packet::Nacked && pkt->getOffset(pbs) &&
             pkt->getSize() != pbs) {
index 95d4e2873af9679247cb36d82a12dbc89e4929b9..895123f8b921e8c063ca8d93a7e13e21b0d24f58 100644 (file)
@@ -182,8 +182,10 @@ Bus::recvTiming(PacketPtr pkt)
 
     // If the bus is busy, or other devices are in line ahead of the current
     // one, put this device on the retry list.
-    if (tickNextIdle > curTick ||
-            (retryList.size() && (!inRetry || pktPort != retryList.front()))) {
+    if (!(pkt->flags & EXPRESS_SNOOP) &&
+        tickNextIdle > curTick ||
+        (retryList.size() && (!inRetry || pktPort != retryList.front())))
+    {
         addToRetryList(pktPort);
         DPRINTF(Bus, "recvTiming: Bus is busy, returning false\n");
         return false;
@@ -195,31 +197,18 @@ Bus::recvTiming(PacketPtr pkt)
     // access has been handled twice.
     if (dest == Packet::Broadcast) {
         port = findPort(pkt->getAddr(), pkt->getSrc());
-        pkt->flags &= ~SNOOP_COMMIT;
-        if (timingSnoop(pkt, port ? port : interfaces[pkt->getSrc()])) {
-            bool success;
-
-            pkt->flags |= SNOOP_COMMIT;
-            success = timingSnoop(pkt, port ? port : interfaces[pkt->getSrc()]);
-            assert(success);
-
-            if (pkt->flags & SATISFIED) {
-                //Cache-Cache transfer occuring
-                if (inRetry) {
-                    retryList.front()->onRetryList(false);
-                    retryList.pop_front();
-                    inRetry = false;
-                }
-                occupyBus(pkt);
-                DPRINTF(Bus, "recvTiming: Packet sucessfully sent\n");
-                return true;
+        timingSnoop(pkt, port ? port : interfaces[pkt->getSrc()]);
+
+        if (pkt->flags & SATISFIED) {
+            //Cache-Cache transfer occuring
+            if (inRetry) {
+                retryList.front()->onRetryList(false);
+                retryList.pop_front();
+                inRetry = false;
             }
-        } else {
-            //Snoop didn't succeed
-            DPRINTF(Bus, "Adding1 a retry to RETRY list %d\n",
-                    pktPort->getId());
-            addToRetryList(pktPort);
-            return false;
+            occupyBus(pkt);
+            DPRINTF(Bus, "recvTiming: Packet sucessfully sent\n");
+            return true;
         }
     } else {
         assert(dest >= 0 && dest < maxId);
@@ -426,7 +415,6 @@ Bus::recvAtomic(PacketPtr pkt)
     DPRINTF(Bus, "recvAtomic: packet src %d dest %d addr 0x%x cmd %s\n",
             pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
     assert(pkt->getDest() == Packet::Broadcast);
-    pkt->flags |= SNOOP_COMMIT;
 
     // Assume one bus cycle in order to get through.  This may have
     // some clock skew issues yet again...
@@ -451,7 +439,6 @@ Bus::recvFunctional(PacketPtr pkt)
     DPRINTF(Bus, "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n",
             pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
     assert(pkt->getDest() == Packet::Broadcast);
-    pkt->flags |= SNOOP_COMMIT;
 
     Port* port = findPort(pkt->getAddr(), pkt->getSrc());
     functionalSnoop(pkt, port ? port : interfaces[pkt->getSrc()]);
index 3ed4b84d110e2c1ab973bd17bfbb0337aff815ee..b699271f7c5d625d05229fc10d9464998496004e 100644 (file)
 
 using namespace std;
 
-BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache,
-                                bool _isCpuSide)
-    : Port(_name, _cache), cache(_cache), isCpuSide(_isCpuSide)
+BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache)
+    : Port(_name, _cache), cache(_cache), otherPort(NULL)
 {
     blocked = false;
     waitingOnRetry = false;
-    //Start ports at null if more than one is created we should panic
-    //cpuSidePort = NULL;
-    //memSidePort = NULL;
 }
 
 
+BaseCache::BaseCache(const std::string &name, Params &params)
+    : MemObject(name),
+      blocked(0), blockedSnoop(0),
+      blkSize(params.blkSize),
+      missCount(params.maxMisses), drainEvent(NULL)
+{
+}
+
+
+
 void
 BaseCache::CachePort::recvStatusChange(Port::Status status)
 {
-    cache->recvStatusChange(status, isCpuSide);
+    if (status == Port::RangeChange) {
+        otherPort->sendStatusChange(Port::RangeChange);
+    }
 }
 
 void
 BaseCache::CachePort::getDeviceAddressRanges(AddrRangeList &resp,
                                        AddrRangeList &snoop)
 {
-    cache->getAddressRanges(resp, snoop, isCpuSide);
+    AddrRangeList dummy;
+    otherPort->getPeerAddressRanges(resp, dummy);
 }
 
 int
@@ -115,92 +124,99 @@ BaseCache::CachePort::checkAndSendFunctional(PacketPtr pkt)
         sendFunctional(pkt);
 }
 
+
 void
-BaseCache::CachePort::recvRetry()
+BaseCache::CachePort::respond(PacketPtr pkt, Tick time)
 {
-    PacketPtr pkt;
-    assert(waitingOnRetry);
-    if (!drainList.empty()) {
-        DPRINTF(CachePort, "%s attempting to send a retry for response (%i waiting)\n"
-                , name(), drainList.size());
-        //We have some responses to drain first
-        pkt = drainList.front();
-        drainList.pop_front();
-        if (sendTiming(pkt)) {
-            DPRINTF(CachePort, "%s sucessful in sending a retry for"
-                    "response (%i still waiting)\n", name(), drainList.size());
-            if (!drainList.empty() ||
-                !isCpuSide && cache->doMasterRequest() ||
-                isCpuSide && cache->doSlaveRequest()) {
-
-                DPRINTF(CachePort, "%s has more responses/requests\n", name());
-                new BaseCache::RequestEvent(this, curTick + 1);
-            }
-            waitingOnRetry = false;
-        }
-        else {
-            drainList.push_front(pkt);
+    assert(time >= curTick);
+    if (pkt->needsResponse()) {
+        if (transmitList.empty()) {
+            assert(!responseEvent->scheduled());
+            responseEvent->schedule(time);
+            transmitList.push_back(std::pair<Tick,PacketPtr>(time,pkt));
+            return;
         }
-        // Check if we're done draining once this list is empty
-        if (drainList.empty())
-            cache->checkDrain();
-    }
-    else if (!isCpuSide)
-    {
-        DPRINTF(CachePort, "%s attempting to send a retry for MSHR\n", name());
-        if (!cache->doMasterRequest()) {
-            //This can happen if I am the owner of a block and see an upgrade
-            //while the block was in my WB Buffers.  I just remove the
-            //wb and de-assert the masterRequest
-            waitingOnRetry = false;
+
+        // something is on the list and this belongs at the end
+        if (time >= transmitList.back().first) {
+            transmitList.push_back(std::pair<Tick,PacketPtr>(time,pkt));
             return;
         }
-        pkt = cache->getPacket();
-        MSHR* mshr = (MSHR*) pkt->senderState;
-        //Copy the packet, it may be modified/destroyed elsewhere
-        PacketPtr copyPkt = new Packet(*pkt);
-        copyPkt->dataStatic<uint8_t>(pkt->getPtr<uint8_t>());
-        mshr->pkt = copyPkt;
-
-        bool success = sendTiming(pkt);
-        DPRINTF(Cache, "Address %x was %s in sending the timing request\n",
-                pkt->getAddr(), success ? "succesful" : "unsuccesful");
-
-        waitingOnRetry = !success;
-        if (waitingOnRetry) {
-            DPRINTF(CachePort, "%s now waiting on a retry\n", name());
+        // Something is on the list and this belongs somewhere else
+        std::list<std::pair<Tick,PacketPtr> >::iterator i =
+            transmitList.begin();
+        std::list<std::pair<Tick,PacketPtr> >::iterator end =
+            transmitList.end();
+        bool done = false;
+
+        while (i != end && !done) {
+            if (time < i->first) {
+                if (i == transmitList.begin()) {
+                    //Inserting at begining, reschedule
+                    responseEvent->reschedule(time);
+                }
+                transmitList.insert(i,std::pair<Tick,PacketPtr>(time,pkt));
+                done = true;
+            }
+            i++;
+        }
+    }
+    else {
+        assert(0);
+        // this code was on the cpuSidePort only... do we still need it?
+        if (pkt->cmd != MemCmd::UpgradeReq)
+        {
+            delete pkt->req;
+            delete pkt;
         }
+    }
+}
 
-        cache->sendResult(pkt, mshr, success);
+bool
+BaseCache::CachePort::drainResponse()
+{
+    DPRINTF(CachePort,
+            "%s attempting to send a retry for response (%i waiting)\n",
+            name(), drainList.size());
+    //We have some responses to drain first
+    PacketPtr pkt = drainList.front();
+    if (sendTiming(pkt)) {
+        drainList.pop_front();
+        DPRINTF(CachePort, "%s sucessful in sending a retry for"
+                "response (%i still waiting)\n", name(), drainList.size());
+        if (!drainList.empty() || isBusRequested()) {
 
-        if (success && cache->doMasterRequest())
-        {
-            DPRINTF(CachePort, "%s has more requests\n", name());
-            //Still more to issue, rerequest in 1 cycle
-            new BaseCache::RequestEvent(this, curTick + 1);
+            DPRINTF(CachePort, "%s has more responses/requests\n", name());
+            return false;
         }
+    } else {
+        waitingOnRetry = true;
+        DPRINTF(CachePort, "%s now waiting on a retry\n", name());
     }
-    else
-    {
-        assert(cache->doSlaveRequest());
-        //pkt = cache->getCoherencePacket();
-        //We save the packet, no reordering on CSHRS
-        pkt = cache->getCoherencePacket();
-        MSHR* cshr = (MSHR*)pkt->senderState;
-        bool success = sendTiming(pkt);
-        cache->sendCoherenceResult(pkt, cshr, success);
-        waitingOnRetry = !success;
-        if (success && cache->doSlaveRequest())
-        {
-            DPRINTF(CachePort, "%s has more requests\n", name());
-            //Still more to issue, rerequest in 1 cycle
-            new BaseCache::RequestEvent(this, curTick + 1);
+    return true;
+}
+
+
+bool
+BaseCache::CachePort::recvRetryCommon()
+{
+    assert(waitingOnRetry);
+    waitingOnRetry = false;
+    if (!drainList.empty()) {
+        if (!drainResponse()) {
+            // more responses to drain... re-request bus
+            scheduleRequestEvent(curTick + 1);
         }
+        // Check if we're done draining once this list is empty
+        if (drainList.empty()) {
+            cache->checkDrain();
+        }
+        return true;
     }
-    if (waitingOnRetry) DPRINTF(CachePort, "%s STILL Waiting on retry\n", name());
-    else DPRINTF(CachePort, "%s no longer waiting on retry\n", name());
-    return;
+    return false;
 }
+
+
 void
 BaseCache::CachePort::setBlocked()
 {
@@ -225,143 +241,6 @@ BaseCache::CachePort::clearBlocked()
     }
 }
 
-BaseCache::RequestEvent::RequestEvent(CachePort *_cachePort, Tick when)
-    : Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort)
-{
-    this->setFlags(AutoDelete);
-    schedule(when);
-}
-
-void
-BaseCache::RequestEvent::process()
-{
-    if (cachePort->waitingOnRetry) return;
-    //We have some responses to drain first
-    if (!cachePort->drainList.empty()) {
-        DPRINTF(CachePort, "%s trying to drain a response\n", cachePort->name());
-        if (cachePort->sendTiming(cachePort->drainList.front())) {
-            DPRINTF(CachePort, "%s drains a response succesfully\n", cachePort->name());
-            cachePort->drainList.pop_front();
-            if (!cachePort->drainList.empty() ||
-                !cachePort->isCpuSide && cachePort->cache->doMasterRequest() ||
-                cachePort->isCpuSide && cachePort->cache->doSlaveRequest()) {
-
-                DPRINTF(CachePort, "%s still has outstanding bus reqs\n", cachePort->name());
-                this->schedule(curTick + 1);
-            }
-        }
-        else {
-            cachePort->waitingOnRetry = true;
-            DPRINTF(CachePort, "%s now waiting on a retry\n", cachePort->name());
-        }
-    }
-    else if (!cachePort->isCpuSide)
-    {            //MSHR
-        DPRINTF(CachePort, "%s trying to send a MSHR request\n", cachePort->name());
-        if (!cachePort->cache->doMasterRequest()) {
-            //This can happen if I am the owner of a block and see an upgrade
-            //while the block was in my WB Buffers.  I just remove the
-            //wb and de-assert the masterRequest
-            return;
-        }
-
-        PacketPtr pkt = cachePort->cache->getPacket();
-        MSHR* mshr = (MSHR*) pkt->senderState;
-        //Copy the packet, it may be modified/destroyed elsewhere
-        PacketPtr copyPkt = new Packet(*pkt);
-        copyPkt->dataStatic<uint8_t>(pkt->getPtr<uint8_t>());
-        mshr->pkt = copyPkt;
-
-        bool success = cachePort->sendTiming(pkt);
-        DPRINTF(Cache, "Address %x was %s in sending the timing request\n",
-                pkt->getAddr(), success ? "succesful" : "unsuccesful");
-
-        cachePort->waitingOnRetry = !success;
-        if (cachePort->waitingOnRetry) {
-            DPRINTF(CachePort, "%s now waiting on a retry\n", cachePort->name());
-        }
-
-        cachePort->cache->sendResult(pkt, mshr, success);
-        if (success && cachePort->cache->doMasterRequest())
-        {
-            DPRINTF(CachePort, "%s still more MSHR requests to send\n",
-                    cachePort->name());
-            //Still more to issue, rerequest in 1 cycle
-            this->schedule(curTick+1);
-        }
-    }
-    else
-    {
-        //CSHR
-        assert(cachePort->cache->doSlaveRequest());
-        PacketPtr pkt = cachePort->cache->getCoherencePacket();
-        MSHR* cshr = (MSHR*) pkt->senderState;
-        bool success = cachePort->sendTiming(pkt);
-        cachePort->cache->sendCoherenceResult(pkt, cshr, success);
-        cachePort->waitingOnRetry = !success;
-        if (cachePort->waitingOnRetry)
-            DPRINTF(CachePort, "%s now waiting on a retry\n", cachePort->name());
-        if (success && cachePort->cache->doSlaveRequest())
-        {
-            DPRINTF(CachePort, "%s still more CSHR requests to send\n",
-                    cachePort->name());
-            //Still more to issue, rerequest in 1 cycle
-            this->schedule(curTick+1);
-        }
-    }
-}
-
-const char *
-BaseCache::RequestEvent::description()
-{
-    return "Cache request event";
-}
-
-BaseCache::ResponseEvent::ResponseEvent(CachePort *_cachePort)
-    : Event(&mainEventQueue, CPU_Tick_Pri), cachePort(_cachePort)
-{
-}
-
-void
-BaseCache::ResponseEvent::process()
-{
-    assert(cachePort->transmitList.size());
-    assert(cachePort->transmitList.front().first <= curTick);
-    PacketPtr pkt = cachePort->transmitList.front().second;
-    cachePort->transmitList.pop_front();
-    if (!cachePort->transmitList.empty()) {
-        Tick time = cachePort->transmitList.front().first;
-        schedule(time <= curTick ? curTick+1 : time);
-    }
-
-    if (pkt->flags & NACKED_LINE)
-        pkt->result = Packet::Nacked;
-    else
-        pkt->result = Packet::Success;
-    pkt->makeTimingResponse();
-    DPRINTF(CachePort, "%s attempting to send a response\n", cachePort->name());
-    if (!cachePort->drainList.empty() || cachePort->waitingOnRetry) {
-        //Already have a list, just append
-        cachePort->drainList.push_back(pkt);
-        DPRINTF(CachePort, "%s appending response onto drain list\n", cachePort->name());
-    }
-    else if (!cachePort->sendTiming(pkt)) {
-        //It failed, save it to list of drain events
-        DPRINTF(CachePort, "%s now waiting for a retry\n", cachePort->name());
-        cachePort->drainList.push_back(pkt);
-        cachePort->waitingOnRetry = true;
-    }
-
-    // Check if we're done draining once this list is empty
-    if (cachePort->drainList.empty() && cachePort->transmitList.empty())
-        cachePort->cache->checkDrain();
-}
-
-const char *
-BaseCache::ResponseEvent::description()
-{
-    return "Cache response event";
-}
 
 void
 BaseCache::init()
index e45e36fa0ee001466a81d8f17a1c124f23e58630..2d63945d9ac3b7479649246b3824d3176da8aba2 100644 (file)
@@ -26,6 +26,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Erik Hallnor
+ *          Steve Reinhardt
+ *          Ron Dreslinski
  */
 
 /**
@@ -83,7 +85,10 @@ class BaseCache : public MemObject
         BaseCache *cache;
 
       protected:
-        CachePort(const std::string &_name, BaseCache *_cache, bool _isCpuSide);
+        Event *responseEvent;
+
+        CachePort(const std::string &_name, BaseCache *_cache);
+
         virtual void recvStatusChange(Status status);
 
         virtual void getDeviceAddressRanges(AddrRangeList &resp,
@@ -91,9 +96,11 @@ class BaseCache : public MemObject
 
         virtual int deviceBlockSize();
 
-        virtual void recvRetry();
+        bool recvRetryCommon();
 
       public:
+        void setOtherPort(CachePort *_otherPort) { otherPort = _otherPort; }
+
         void setBlocked();
 
         void clearBlocked();
@@ -104,65 +111,52 @@ class BaseCache : public MemObject
 
         bool canDrain() { return drainList.empty() && transmitList.empty(); }
 
+        bool drainResponse();
+
+        CachePort *otherPort;
+
         bool blocked;
 
         bool mustSendRetry;
 
-        bool isCpuSide;
-
         bool waitingOnRetry;
 
+        /**
+         * Bit vector for the outstanding requests for the master interface.
+         */
+        uint8_t requestCauses;
+
         std::list<PacketPtr> drainList;
 
         std::list<std::pair<Tick,PacketPtr> > transmitList;
-    };
 
-    struct RequestEvent : public Event
-    {
-        CachePort *cachePort;
+        bool isBusRequested() { return requestCauses != 0; }
 
-        RequestEvent(CachePort *_cachePort, Tick when);
-        void process();
-        const char *description();
-    };
+        // These need to be virtual since the Event objects depend on
+        // cache template parameters.
+        virtual void scheduleRequestEvent(Tick t) = 0;
 
-    struct ResponseEvent : public Event
-    {
-        CachePort *cachePort;
+        void requestBus(RequestCause cause, Tick time)
+        {
+            if (!isBusRequested() && !waitingOnRetry) {
+                scheduleRequestEvent(time);
+            }
+            requestCauses |= (1 << cause);
+        }
+
+        void deassertBusRequest(RequestCause cause)
+        {
+            requestCauses &= ~(1 << cause);
+        }
 
-        ResponseEvent(CachePort *_cachePort);
-        void process();
-        const char *description();
+        void respond(PacketPtr pkt, Tick time);
     };
 
   public: //Made public so coherence can get at it.
     CachePort *cpuSidePort;
     CachePort *memSidePort;
 
-    ResponseEvent *sendEvent;
-    ResponseEvent *memSendEvent;
-
   private:
-    void recvStatusChange(Port::Status status, bool isCpuSide)
-    {
-        if (status == Port::RangeChange){
-            if (!isCpuSide) {
-                cpuSidePort->sendStatusChange(Port::RangeChange);
-            }
-            else {
-                memSidePort->sendStatusChange(Port::RangeChange);
-            }
-        }
-    }
-
-    virtual PacketPtr getPacket() = 0;
-
-    virtual PacketPtr getCoherencePacket() = 0;
-
-    virtual void sendResult(PacketPtr &pkt, MSHR* mshr, bool success) = 0;
-
-    virtual void sendCoherenceResult(PacketPtr &pkt, MSHR* mshr, bool success) = 0;
-
     /**
      * Bit vector of the blocking reasons for the access path.
      * @sa #BlockedCause
@@ -175,16 +169,6 @@ class BaseCache : public MemObject
      */
     uint8_t blockedSnoop;
 
-    /**
-     * Bit vector for the outstanding requests for the master interface.
-     */
-    uint8_t masterRequests;
-
-    /**
-     * Bit vector for the outstanding requests for the slave interface.
-     */
-    uint8_t slaveRequests;
-
   protected:
 
     /** Stores time the cache blocked for statistics. */
@@ -309,20 +293,10 @@ class BaseCache : public MemObject
      * of this cache.
      * @param params The parameter object for this BaseCache.
      */
-    BaseCache(const std::string &name, Params &params)
-        : MemObject(name), blocked(0), blockedSnoop(0), masterRequests(0),
-          slaveRequests(0), blkSize(params.blkSize),
-          missCount(params.maxMisses), drainEvent(NULL)
-    {
-        //Start ports at null if more than one is created we should panic
-        cpuSidePort = NULL;
-        memSidePort = NULL;
-    }
+    BaseCache(const std::string &name, Params &params);
 
     ~BaseCache()
     {
-        delete sendEvent;
-        delete memSendEvent;
     }
 
     virtual void init();
@@ -422,12 +396,12 @@ class BaseCache : public MemObject
     }
 
     /**
-     * True if the master bus should be requested.
+     * True if the memory-side bus should be requested.
      * @return True if there are outstanding requests for the master bus.
      */
-    bool doMasterRequest()
+    bool isMemSideBusRequested()
     {
-        return masterRequests != 0;
+        return memSidePort->isBusRequested();
     }
 
     /**
@@ -435,59 +409,18 @@ class BaseCache : public MemObject
      * @param cause The reason for the request.
      * @param time The time to make the request.
      */
-    void setMasterRequest(RequestCause cause, Tick time)
+    void requestMemSideBus(RequestCause cause, Tick time)
     {
-        if (!doMasterRequest() && !memSidePort->waitingOnRetry)
-        {
-            new RequestEvent(memSidePort, time);
-        }
-        uint8_t flag = 1<<cause;
-        masterRequests |= flag;
+        memSidePort->requestBus(cause, time);
     }
 
     /**
      * Clear the master bus request for the given cause.
      * @param cause The request reason to clear.
      */
-    void clearMasterRequest(RequestCause cause)
+    void deassertMemSideBusRequest(RequestCause cause)
     {
-        uint8_t flag = 1<<cause;
-        masterRequests &= ~flag;
-        checkDrain();
-    }
-
-    /**
-     * Return true if the slave bus should be requested.
-     * @return True if there are outstanding requests for the slave bus.
-     */
-    bool doSlaveRequest()
-    {
-        return slaveRequests != 0;
-    }
-
-    /**
-     * Request the slave bus for the given reason and time.
-     * @param cause The reason for the request.
-     * @param time The time to make the request.
-     */
-    void setSlaveRequest(RequestCause cause, Tick time)
-    {
-        if (!doSlaveRequest() && !cpuSidePort->waitingOnRetry)
-        {
-            new RequestEvent(cpuSidePort, time);
-        }
-        uint8_t flag = 1<<cause;
-        slaveRequests |= flag;
-    }
-
-    /**
-     * Clear the slave bus request for the given reason.
-     * @param cause The request reason to clear.
-     */
-    void clearSlaveRequest(RequestCause cause)
-    {
-        uint8_t flag = 1<<cause;
-        slaveRequests &= ~flag;
+        memSidePort->deassertBusRequest(cause);
         checkDrain();
     }
 
@@ -498,111 +431,7 @@ class BaseCache : public MemObject
      */
     void respond(PacketPtr pkt, Tick time)
     {
-        assert(time >= curTick);
-        if (pkt->needsResponse()) {
-/*            CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
-            reqCpu->schedule(time);
-*/
-            if (cpuSidePort->transmitList.empty()) {
-                assert(!sendEvent->scheduled());
-                sendEvent->schedule(time);
-                cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
-                                                    (time,pkt));
-                return;
-            }
-
-            // something is on the list and this belongs at the end
-            if (time >= cpuSidePort->transmitList.back().first) {
-                cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
-                                                    (time,pkt));
-                return;
-            }
-            // Something is on the list and this belongs somewhere else
-            std::list<std::pair<Tick,PacketPtr> >::iterator i =
-                cpuSidePort->transmitList.begin();
-            std::list<std::pair<Tick,PacketPtr> >::iterator end =
-                cpuSidePort->transmitList.end();
-            bool done = false;
-
-            while (i != end && !done) {
-                if (time < i->first) {
-                    if (i == cpuSidePort->transmitList.begin()) {
-                        //Inserting at begining, reschedule
-                        sendEvent->reschedule(time);
-                    }
-                    cpuSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr>
-                                                     (time,pkt));
-                    done = true;
-                }
-                i++;
-            }
-        }
-        else {
-            if (pkt->cmd != MemCmd::UpgradeReq)
-            {
-                delete pkt->req;
-                delete pkt;
-            }
-        }
-    }
-
-    /**
-     * Send a reponse to the slave interface and calculate miss latency.
-     * @param pkt The request to respond to.
-     * @param time The time the response is ready.
-     */
-    void respondToMiss(PacketPtr pkt, Tick time)
-    {
-        assert(time >= curTick);
-        if (!pkt->req->isUncacheable()) {
-            missLatency[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/] +=
-                time - pkt->time;
-        }
-        if (pkt->needsResponse()) {
-/*            CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
-            reqCpu->schedule(time);
-*/
-            if (cpuSidePort->transmitList.empty()) {
-                assert(!sendEvent->scheduled());
-                sendEvent->schedule(time);
-                cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
-                                                    (time,pkt));
-                return;
-            }
-
-            // something is on the list and this belongs at the end
-            if (time >= cpuSidePort->transmitList.back().first) {
-                cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
-                                                    (time,pkt));
-                return;
-            }
-            // Something is on the list and this belongs somewhere else
-            std::list<std::pair<Tick,PacketPtr> >::iterator i =
-                cpuSidePort->transmitList.begin();
-            std::list<std::pair<Tick,PacketPtr> >::iterator end =
-                cpuSidePort->transmitList.end();
-            bool done = false;
-
-            while (i != end && !done) {
-                if (time < i->first) {
-                    if (i == cpuSidePort->transmitList.begin()) {
-                        //Inserting at begining, reschedule
-                        sendEvent->reschedule(time);
-                    }
-                    cpuSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr>
-                                                     (time,pkt));
-                    done = true;
-                }
-                i++;
-            }
-        }
-        else {
-            if (pkt->cmd != MemCmd::UpgradeReq)
-            {
-                delete pkt->req;
-                delete pkt;
-            }
-        }
+        cpuSidePort->respond(pkt, time);
     }
 
     /**
@@ -611,65 +440,7 @@ class BaseCache : public MemObject
      */
     void respondToSnoop(PacketPtr pkt, Tick time)
     {
-        assert(time >= curTick);
-        assert (pkt->needsResponse());
-/*        CacheEvent *reqMem = new CacheEvent(memSidePort, pkt);
-        reqMem->schedule(time);
-*/
-        if (memSidePort->transmitList.empty()) {
-            assert(!memSendEvent->scheduled());
-            memSendEvent->schedule(time);
-            memSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
-                                                (time,pkt));
-            return;
-        }
-
-        // something is on the list and this belongs at the end
-        if (time >= memSidePort->transmitList.back().first) {
-            memSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
-                                                (time,pkt));
-            return;
-        }
-        // Something is on the list and this belongs somewhere else
-        std::list<std::pair<Tick,PacketPtr> >::iterator i =
-            memSidePort->transmitList.begin();
-        std::list<std::pair<Tick,PacketPtr> >::iterator end =
-            memSidePort->transmitList.end();
-        bool done = false;
-
-        while (i != end && !done) {
-            if (time < i->first) {
-                if (i == memSidePort->transmitList.begin()) {
-                    //Inserting at begining, reschedule
-                    memSendEvent->reschedule(time);
-                }
-                memSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr>(time,pkt));
-                done = true;
-            }
-            i++;
-        }
-    }
-
-    /**
-     * Notification from master interface that a address range changed. Nothing
-     * to do for a cache.
-     */
-    void rangeChange() {}
-
-    void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop, bool isCpuSide)
-    {
-        if (isCpuSide)
-        {
-            AddrRangeList dummy;
-            memSidePort->getPeerAddressRanges(resp, dummy);
-        }
-        else
-        {
-            //This is where snoops get updated
-            AddrRangeList dummy;
-            cpuSidePort->getPeerAddressRanges(dummy, snoop);
-            return;
-        }
+        memSidePort->respond(pkt, time);
     }
 
     virtual unsigned int drain(Event *de);
@@ -686,7 +457,7 @@ class BaseCache : public MemObject
 
     bool canDrain()
     {
-        if (doMasterRequest() || doSlaveRequest()) {
+        if (isMemSideBusRequested()) {
             return false;
         } else if (memSidePort && !memSidePort->canDrain()) {
             return false;
index cb4e7f62e0c69de5e325bc37b1377f7c8ec2ebf3..2b4e7b9c8066e731729aacdebf936c6e6670fffe 100644 (file)
@@ -61,7 +61,6 @@
 #include "mem/cache/miss/miss_queue.hh"
 #include "mem/cache/miss/blocking_buffer.hh"
 
-#include "mem/cache/coherence/uni_coherence.hh"
 #include "mem/cache/coherence/simple_coherence.hh"
 
 #include "mem/cache/cache_impl.hh"
 
 #if defined(USE_CACHE_FALRU)
 template class Cache<FALRU, SimpleCoherence>;
-template class Cache<FALRU, UniCoherence>;
 #endif
 
 #if defined(USE_CACHE_IIC)
 template class Cache<IIC, SimpleCoherence>;
-template class Cache<IIC, UniCoherence>;
 #endif
 
 #if defined(USE_CACHE_LRU)
 template class Cache<LRU, SimpleCoherence>;
-template class Cache<LRU, UniCoherence>;
 #endif
 
 #if defined(USE_CACHE_SPLIT)
 template class Cache<Split, SimpleCoherence>;
-template class Cache<Split, UniCoherence>;
 #endif
 
 #if defined(USE_CACHE_SPLIT_LIFO)
 template class Cache<SplitLIFO, SimpleCoherence>;
-template class Cache<SplitLIFO, UniCoherence>;
 #endif
 
 #endif //DOXYGEN_SHOULD_SKIP_THIS
index 3e45c85d2fc3cd86f4109838220bb6971ca5b058..75fb50f4ea9bb51e8bf5d2e7e71282b252129da8 100644 (file)
@@ -28,6 +28,7 @@
  * Authors: Erik Hallnor
  *          Dave Greene
  *          Steve Reinhardt
+ *          Ron Dreslinski
  */
 
 /**
@@ -46,6 +47,8 @@
 #include "mem/cache/cache_blk.hh"
 #include "mem/cache/miss/miss_buffer.hh"
 
+#include "sim/eventq.hh"
+
 //Forward decleration
 class MSHR;
 class BasePrefetcher;
@@ -83,11 +86,26 @@ class Cache : public BaseCache
             return static_cast<Cache<TagStore,Coherence> *>(cache);
         }
 
+        void processRequestEvent();
+        void processResponseEvent();
+
         virtual bool recvTiming(PacketPtr pkt);
 
+        virtual void recvRetry();
+
         virtual Tick recvAtomic(PacketPtr pkt);
 
         virtual void recvFunctional(PacketPtr pkt);
+
+        typedef EventWrapper<CpuSidePort, &CpuSidePort::processResponseEvent>
+                ResponseEvent;
+
+        typedef EventWrapper<CpuSidePort, &CpuSidePort::processRequestEvent>
+                RequestEvent;
+
+        virtual void scheduleRequestEvent(Tick t) {
+            new RequestEvent(this, t);
+        }
     };
 
     class MemSidePort : public CachePort
@@ -103,11 +121,26 @@ class Cache : public BaseCache
             return static_cast<Cache<TagStore,Coherence> *>(cache);
         }
 
+        void processRequestEvent();
+        void processResponseEvent();
+
         virtual bool recvTiming(PacketPtr pkt);
 
+        virtual void recvRetry();
+
         virtual Tick recvAtomic(PacketPtr pkt);
 
         virtual void recvFunctional(PacketPtr pkt);
+
+        typedef EventWrapper<MemSidePort, &MemSidePort::processResponseEvent>
+                ResponseEvent;
+
+        typedef EventWrapper<MemSidePort, &MemSidePort::processRequestEvent>
+                RequestEvent;
+
+        virtual void scheduleRequestEvent(Tick t) {
+            new RequestEvent(this, t);
+        }
     };
 
     /** Tag and data Storage */
@@ -339,8 +372,6 @@ class Cache : public BaseCache
     virtual Port *getPort(const std::string &if_name, int idx = -1);
     virtual void deletePortRefs(Port *p);
 
-    virtual void recvStatusChange(Port::Status status, bool isCpuSide);
-
     void regStats();
 
     /**
@@ -354,21 +385,14 @@ class Cache : public BaseCache
      * Selects a request to send on the bus.
      * @return The memory request to service.
      */
-    virtual PacketPtr getPacket();
+    PacketPtr getPacket();
 
     /**
      * Was the request was sent successfully?
      * @param pkt The request.
      * @param success True if the request was sent successfully.
      */
-    virtual void sendResult(PacketPtr &pkt, MSHR* mshr, bool success);
-
-    /**
-     * Was the CSHR request was sent successfully?
-     * @param pkt The request.
-     * @param success True if the request was sent successfully.
-     */
-    virtual void sendCoherenceResult(PacketPtr &pkt, MSHR* cshr, bool success);
+    void sendResult(PacketPtr &pkt, MSHR* mshr, bool success);
 
     /**
      * Handles a response (cache line fill/write ack) from the bus.
@@ -376,12 +400,6 @@ class Cache : public BaseCache
      */
     void handleResponse(PacketPtr &pkt);
 
-    /**
-     * Selects a coherence message to forward to lower levels of the hierarchy.
-     * @return The coherence message to forward.
-     */
-    virtual PacketPtr getCoherencePacket();
-
     /**
      * Snoops bus transactions to maintain coherence.
      * @param pkt The current bus transaction.
index e887f711eba333437a968d4874e50a21bec8b7cd..bc1a8a775c2761c8a4ca16fe9db0f8663616f23d 100644 (file)
@@ -75,7 +75,6 @@
 #include "mem/cache/miss/blocking_buffer.hh"
 
 // Coherence Templates
-#include "mem/cache/coherence/uni_coherence.hh"
 #include "mem/cache/coherence/simple_coherence.hh"
 
 //Prefetcher Headers
@@ -302,13 +301,8 @@ END_INIT_SIM_OBJECT_PARAMS(BaseCache)
     } while (0)
 
 #define BUILD_COHERENCE(b) do {                                                \
-        if (protocol == NULL) {                                                \
-            UniCoherence *coh = new UniCoherence();                    \
-            BUILD_CACHES(UniCoherence);                                \
-        } else {                                                       \
-            SimpleCoherence *coh = new SimpleCoherence(protocol);      \
-            BUILD_CACHES(SimpleCoherence);                             \
-        }                                                              \
+        SimpleCoherence *coh = new SimpleCoherence(protocol);           \
+        BUILD_CACHES(SimpleCoherence);                                  \
     } while (0)
 
 #if defined(USE_TAGGED)
index 9b094c1e334f383ad250c76a6c00736a520cbb63..6b9eac865d94ef2166f1630ce3bc10aa85de537c 100644 (file)
@@ -28,6 +28,8 @@
  * Authors: Erik Hallnor
  *          Dave Greene
  *          Nathan Binkert
+ *          Steve Reinhardt
+ *          Ron Dreslinski
  */
 
 /**
 bool SIGNAL_NACK_HACK;
 
 template<class TagStore, class Coherence>
-void
-Cache<TagStore,Coherence>::
-recvStatusChange(Port::Status status, bool isCpuSide)
-{
-
-}
-
-
-template<class TagStore, class Coherence>
-Cache<TagStore,Coherence>::
-Cache(const std::string &_name,
-      Cache<TagStore,Coherence>::Params &params)
+Cache<TagStore,Coherence>::Cache(const std::string &_name,
+                                 Cache<TagStore,Coherence>::Params &params)
     : BaseCache(_name, params.baseParams),
       prefetchAccess(params.prefetchAccess),
       tags(params.tags), missQueue(params.missQueue),
@@ -84,6 +76,11 @@ Cache(const std::string &_name,
       adaptiveCompression(params.adaptiveCompression),
       writebackCompressed(params.writebackCompressed)
 {
+    cpuSidePort = new CpuSidePort(_name + "-cpu_side_port", this);
+    memSidePort = new MemSidePort(_name + "-mem_side_port", this);
+    cpuSidePort->setOtherPort(memSidePort);
+    memSidePort->setOtherPort(cpuSidePort);
+
     tags->setCache(this);
     missQueue->setCache(this);
     missQueue->setPrefetcher(prefetcher);
@@ -406,7 +403,11 @@ Cache<TagStore,Coherence>::handleFill(BlkType *blk, MSHR * mshr,
 //            mshr->pkt = pkt;
             break;
         }
-        respondToMiss(target, completion_time);
+        if (!target->req->isUncacheable()) {
+            missLatency[target->cmdToIndex()][0/*pkt->req->getThreadNum()*/] +=
+                completion_time - target->time;
+        }
+        respond(target, completion_time);
         mshr->popTarget();
     }
 
@@ -688,7 +689,7 @@ Cache<TagStore,Coherence>::getPacket()
         }
     }
 
-    assert(!doMasterRequest() || missQueue->havePending());
+    assert(!isMemSideBusRequested() || missQueue->havePending());
     assert(!pkt || pkt->time <= curTick);
     SIGNAL_NACK_HACK = false;
     return pkt;
@@ -727,7 +728,6 @@ Cache<TagStore,Coherence>::sendResult(PacketPtr &pkt, MSHR* mshr,
         pkt->flags &= ~NACKED_LINE;
         SIGNAL_NACK_HACK = false;
         pkt->flags &= ~SATISFIED;
-        pkt->flags &= ~SNOOP_COMMIT;
 
 //Rmove copy from mshr
         delete mshr->pkt;
@@ -783,22 +783,6 @@ Cache<TagStore,Coherence>::handleResponse(PacketPtr &pkt)
     }
 }
 
-template<class TagStore, class Coherence>
-PacketPtr
-Cache<TagStore,Coherence>::getCoherencePacket()
-{
-    return coherence->getPacket();
-}
-
-template<class TagStore, class Coherence>
-void
-Cache<TagStore,Coherence>::sendCoherenceResult(PacketPtr &pkt,
-                                                         MSHR *cshr,
-                                                         bool success)
-{
-    coherence->sendResult(pkt, cshr, success);
-}
-
 
 template<class TagStore, class Coherence>
 void
@@ -1146,27 +1130,15 @@ template<class TagStore, class Coherence>
 Port *
 Cache<TagStore,Coherence>::getPort(const std::string &if_name, int idx)
 {
-    if (if_name == "" || if_name == "cpu_side")
-    {
-        if (cpuSidePort == NULL) {
-            cpuSidePort = new CpuSidePort(name() + "-cpu_side_port", this);
-            sendEvent = new ResponseEvent(cpuSidePort);
-        }
+    if (if_name == "" || if_name == "cpu_side") {
         return cpuSidePort;
-    }
-    else if (if_name == "functional")
-    {
-        return new CpuSidePort(name() + "-cpu_side_funcport", this);
-    }
-    else if (if_name == "mem_side")
-    {
-        if (memSidePort != NULL)
-            panic("Already have a mem side for this cache\n");
-        memSidePort = new MemSidePort(name() + "-mem_side_port", this);
-        memSendEvent = new ResponseEvent(memSidePort);
+    } else if (if_name == "mem_side") {
         return memSidePort;
+    } else if (if_name == "functional") {
+        return new CpuSidePort(name() + "-cpu_side_funcport", this);
+    } else {
+        panic("Port name %s unrecognized\n", if_name);
     }
-    else panic("Port name %s unrecognized\n", if_name);
 }
 
 template<class TagStore, class Coherence>
@@ -1213,6 +1185,68 @@ Cache<TagStore,Coherence>::CpuSidePort::recvTiming(PacketPtr pkt)
     return true;
 }
 
+
+template<class TagStore, class Coherence>
+void
+Cache<TagStore,Coherence>::CpuSidePort::recvRetry()
+{
+    recvRetryCommon();
+}
+
+
+template<class TagStore, class Coherence>
+void
+Cache<TagStore,Coherence>::CpuSidePort::processRequestEvent()
+{
+    if (waitingOnRetry)
+        return;
+    //We have some responses to drain first
+    if (!drainList.empty()) {
+        if (!drainResponse()) {
+            // more responses to drain... re-request bus
+            scheduleRequestEvent(curTick + 1);
+        }
+    }
+}
+
+
+template<class TagStore, class Coherence>
+void
+Cache<TagStore,Coherence>::CpuSidePort::processResponseEvent()
+{
+    assert(transmitList.size());
+    assert(transmitList.front().first <= curTick);
+    PacketPtr pkt = transmitList.front().second;
+    transmitList.pop_front();
+    if (!transmitList.empty()) {
+        Tick time = transmitList.front().first;
+        responseEvent->schedule(time <= curTick ? curTick+1 : time);
+    }
+
+    if (pkt->flags & NACKED_LINE)
+        pkt->result = Packet::Nacked;
+    else
+        pkt->result = Packet::Success;
+    pkt->makeTimingResponse();
+    DPRINTF(CachePort, "%s attempting to send a response\n", name());
+    if (!drainList.empty() || waitingOnRetry) {
+        //Already have a list, just append
+        drainList.push_back(pkt);
+        DPRINTF(CachePort, "%s appending response onto drain list\n", name());
+    }
+    else if (!sendTiming(pkt)) {
+        //It failed, save it to list of drain events
+        DPRINTF(CachePort, "%s now waiting for a retry\n", name());
+        drainList.push_back(pkt);
+        waitingOnRetry = true;
+    }
+
+    // Check if we're done draining once this list is empty
+    if (drainList.empty() && transmitList.empty())
+        myCache()->checkDrain();
+}
+
+
 template<class TagStore, class Coherence>
 Tick
 Cache<TagStore,Coherence>::CpuSidePort::recvAtomic(PacketPtr pkt)
@@ -1249,23 +1283,149 @@ Cache<TagStore,Coherence>::MemSidePort::recvTiming(PacketPtr pkt)
     if (pkt->result == Packet::Nacked)
         panic("Need to implement cache resending nacked packets!\n");
 
-    if (pkt->isRequest() && blocked)
-    {
+    if (pkt->isRequest() && blocked) {
         DPRINTF(Cache,"Scheduling a retry while blocked\n");
         mustSendRetry = true;
         return false;
     }
 
-    if (pkt->isResponse())
+    if (pkt->isResponse()) {
         myCache()->handleResponse(pkt);
-    else {
-        //Check if we should do the snoop
-        if (pkt->flags & SNOOP_COMMIT)
-            myCache()->snoop(pkt);
+    } else {
+        myCache()->snoop(pkt);
     }
     return true;
 }
 
+template<class TagStore, class Coherence>
+void
+Cache<TagStore,Coherence>::MemSidePort::recvRetry()
+{
+    if (recvRetryCommon()) {
+        return;
+    }
+
+    DPRINTF(CachePort, "%s attempting to send a retry for MSHR\n", name());
+    if (!cache->isMemSideBusRequested()) {
+        //This can happen if I am the owner of a block and see an upgrade
+        //while the block was in my WB Buffers.  I just remove the
+        //wb and de-assert the masterRequest
+        waitingOnRetry = false;
+        return;
+    }
+    PacketPtr pkt = myCache()->getPacket();
+    MSHR* mshr = (MSHR*) pkt->senderState;
+    //Copy the packet, it may be modified/destroyed elsewhere
+    PacketPtr copyPkt = new Packet(*pkt);
+    copyPkt->dataStatic<uint8_t>(pkt->getPtr<uint8_t>());
+    mshr->pkt = copyPkt;
+
+    bool success = sendTiming(pkt);
+    DPRINTF(Cache, "Address %x was %s in sending the timing request\n",
+            pkt->getAddr(), success ? "succesful" : "unsuccesful");
+
+    waitingOnRetry = !success;
+    if (waitingOnRetry) {
+        DPRINTF(CachePort, "%s now waiting on a retry\n", name());
+    }
+
+    myCache()->sendResult(pkt, mshr, success);
+
+    if (success && cache->isMemSideBusRequested())
+    {
+        DPRINTF(CachePort, "%s has more requests\n", name());
+        //Still more to issue, rerequest in 1 cycle
+        new RequestEvent(this, curTick + 1);
+    }
+}
+
+
+template<class TagStore, class Coherence>
+void
+Cache<TagStore,Coherence>::MemSidePort::processRequestEvent()
+{
+    if (waitingOnRetry)
+        return;
+    //We have some responses to drain first
+    if (!drainList.empty()) {
+        if (!drainResponse()) {
+            // more responses to drain... re-request bus
+            scheduleRequestEvent(curTick + 1);
+        }
+        return;
+    }
+
+    DPRINTF(CachePort, "%s trying to send a MSHR request\n", name());
+    if (!isBusRequested()) {
+        //This can happen if I am the owner of a block and see an upgrade
+        //while the block was in my WB Buffers.  I just remove the
+        //wb and de-assert the masterRequest
+        return;
+    }
+
+    PacketPtr pkt = myCache()->getPacket();
+    MSHR* mshr = (MSHR*) pkt->senderState;
+    //Copy the packet, it may be modified/destroyed elsewhere
+    PacketPtr copyPkt = new Packet(*pkt);
+    copyPkt->dataStatic<uint8_t>(pkt->getPtr<uint8_t>());
+    mshr->pkt = copyPkt;
+
+    bool success = sendTiming(pkt);
+    DPRINTF(Cache, "Address %x was %s in sending the timing request\n",
+            pkt->getAddr(), success ? "succesful" : "unsuccesful");
+
+    waitingOnRetry = !success;
+    if (waitingOnRetry) {
+        DPRINTF(CachePort, "%s now waiting on a retry\n", name());
+    }
+
+    myCache()->sendResult(pkt, mshr, success);
+    if (success && isBusRequested())
+    {
+        DPRINTF(CachePort, "%s still more MSHR requests to send\n", name());
+        //Still more to issue, rerequest in 1 cycle
+        scheduleRequestEvent(curTick+1);
+    }
+}
+
+
+template<class TagStore, class Coherence>
+void
+Cache<TagStore,Coherence>::MemSidePort::processResponseEvent()
+{
+    assert(transmitList.size());
+    assert(transmitList.front().first <= curTick);
+    PacketPtr pkt = transmitList.front().second;
+    transmitList.pop_front();
+    if (!transmitList.empty()) {
+        Tick time = transmitList.front().first;
+        responseEvent->schedule(time <= curTick ? curTick+1 : time);
+    }
+
+    if (pkt->flags & NACKED_LINE)
+        pkt->result = Packet::Nacked;
+    else
+        pkt->result = Packet::Success;
+    pkt->makeTimingResponse();
+    DPRINTF(CachePort, "%s attempting to send a response\n", name());
+    if (!drainList.empty() || waitingOnRetry) {
+        //Already have a list, just append
+        drainList.push_back(pkt);
+        DPRINTF(CachePort, "%s appending response onto drain list\n", name());
+    }
+    else if (!sendTiming(pkt)) {
+        //It failed, save it to list of drain events
+        DPRINTF(CachePort, "%s now waiting for a retry\n", name());
+        drainList.push_back(pkt);
+        waitingOnRetry = true;
+    }
+
+    // Check if we're done draining once this list is empty
+    if (drainList.empty() && transmitList.empty())
+        myCache()->checkDrain();
+}
+
+
 template<class TagStore, class Coherence>
 Tick
 Cache<TagStore,Coherence>::MemSidePort::recvAtomic(PacketPtr pkt)
@@ -1292,15 +1452,17 @@ template<class TagStore, class Coherence>
 Cache<TagStore,Coherence>::
 CpuSidePort::CpuSidePort(const std::string &_name,
                          Cache<TagStore,Coherence> *_cache)
-    : BaseCache::CachePort(_name, _cache, true)
+    : BaseCache::CachePort(_name, _cache)
 {
+    responseEvent = new ResponseEvent(this);
 }
 
 template<class TagStore, class Coherence>
 Cache<TagStore,Coherence>::
 MemSidePort::MemSidePort(const std::string &_name,
                          Cache<TagStore,Coherence> *_cache)
-    : BaseCache::CachePort(_name, _cache, false)
+    : BaseCache::CachePort(_name, _cache)
 {
+    responseEvent = new ResponseEvent(this);
 }
 
index 03a2d85d7c857106f0600550d5347c408a025c47..7b94f73e15bc9176d5f080175b10b57bcaa295b0 100644 (file)
@@ -31,5 +31,4 @@
 Import('*')
 
 Source('coherence_protocol.cc')
-Source('uni_coherence.cc')
 
diff --git a/src/mem/cache/coherence/uni_coherence.cc b/src/mem/cache/coherence/uni_coherence.cc
deleted file mode 100644 (file)
index 6061c89..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Erik Hallnor
- */
-
-#include "mem/cache/coherence/uni_coherence.hh"
-#include "mem/cache/base_cache.hh"
-
-#include "base/trace.hh"
-
-using namespace std;
-
-UniCoherence::UniCoherence()
-    : cshrs(50)
-{
-}
-
-PacketPtr
-UniCoherence::getPacket()
-{
-    PacketPtr pkt = cshrs.getReq();
-    return pkt;
-}
-
-void
-UniCoherence::sendResult(PacketPtr &pkt, MSHR* cshr, bool success)
-{
-    if (success)
-    {
-        bool unblock = cshrs.isFull();
-//        cshrs.markInService(cshr);
-        delete pkt->req;
-        cshrs.deallocate(cshr);
-        if (!cshrs.havePending()) {
-            cache->clearSlaveRequest(Request_Coherence);
-        }
-        if (unblock) {
-            //since CSHRs are always used as buffers, should always get rid of one
-            assert(!cshrs.isFull());
-            cache->clearBlocked(Blocked_Coherence);
-        }
-    }
-}
-
-
-/**
- * @todo add support for returning slave requests, not doing them here.
- */
-bool
-UniCoherence::handleBusRequest(PacketPtr &pkt, CacheBlk *blk, MSHR *mshr,
-                               CacheBlk::State &new_state)
-{
-    new_state = 0;
-    if (pkt->isInvalidate()) {
-            DPRINTF(Cache, "snoop inval on blk %x (blk ptr %x)\n",
-                    pkt->getAddr(), blk);
-    }
-    else if (blk) {
-        new_state = blk->status;
-        if (pkt->isRead()) {
-            DPRINTF(Cache, "Uni-coherence snoops a read that hit in itself"
-                    ". Should satisfy the packet\n");
-            return true; //Satisfy Reads if we can
-        }
-    }
-    return false;
-}
-
-bool
-UniCoherence::propogateInvalidate(PacketPtr pkt, bool isTiming)
-{
-    if (pkt->isInvalidate()) {
-/*  Temp Fix for now, forward all invalidates up as functional accesses */
-        if (isTiming) {
-            // Forward to other caches
-            Request* req = new Request(pkt->req->getPaddr(), pkt->getSize(), 0);
-            PacketPtr tmp = new Packet(req, MemCmd::InvalidateReq, -1);
-            cshrs.allocate(tmp);
-            cache->setSlaveRequest(Request_Coherence, curTick);
-            if (cshrs.isFull())
-                cache->setBlockedForSnoop(Blocked_Coherence);
-        }
-        else {
-            PacketPtr tmp = new Packet(pkt->req, MemCmd::InvalidateReq, -1);
-            cache->cpuSidePort->sendAtomic(tmp);
-            delete tmp;
-        }
-/**/
-/*            PacketPtr tmp = new Packet(pkt->req, MemCmd::InvalidateReq, -1);
-            cache->cpuSidePort->sendFunctional(tmp);
-            delete tmp;
-*/
-    }
-    if (pkt->isRead()) {
-        /*For now we will see if someone above us has the data by
-          doing a functional access on reads.  Fix this later */
-            PacketPtr tmp = new Packet(pkt->req, MemCmd::ReadReq, -1);
-            tmp->allocate();
-            cache->cpuSidePort->sendFunctional(tmp);
-            bool hit = (tmp->result == Packet::Success);
-            if (hit) {
-                memcpy(pkt->getPtr<uint8_t>(), tmp->getPtr<uint8_t>(),
-                       pkt->getSize());
-                DPRINTF(Cache, "Uni-coherence snoops a read that hit in L1\n");
-            }
-            delete tmp;
-            return hit;
-    }
-    return false;
-}
diff --git a/src/mem/cache/coherence/uni_coherence.hh b/src/mem/cache/coherence/uni_coherence.hh
deleted file mode 100644 (file)
index 9efb4e1..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Erik Hallnor
- */
-
-#ifndef __UNI_COHERENCE_HH__
-#define __UNI_COHERENCE_HH__
-
-#include "base/trace.hh"
-#include "base/misc.hh"
-#include "mem/cache/cache_blk.hh"
-#include "mem/cache/miss/mshr_queue.hh"
-#include "mem/packet.hh"
-
-class BaseCache;
-
-class UniCoherence
-{
-  protected:
-    /** Buffers to hold forwarded invalidates. */
-    MSHRQueue cshrs;
-    /** Pointer to the parent cache. */
-    BaseCache *cache;
-
-  public:
-    /**
-     * Construct and initialize this coherence policy.
-     */
-    UniCoherence();
-
-    /**
-     * Set the pointer to the parent cache.
-     * @param _cache The parent cache.
-     */
-    void setCache(BaseCache *_cache)
-    {
-        cache = _cache;
-    }
-
-    /**
-     * Register statistics.
-     * @param name The name to prepend to stat descriptions.
-     */
-    void regStats(const std::string &name)
-    {
-    }
-
-    /**
-     * Return Read.
-     * @param cmd The request's command.
-     * @param state The current state of the cache block.
-     * @return The proper bus command, as determined by the protocol.
-     * @todo Make changes so writebacks don't get here.
-     */
-    MemCmd getBusCmd(MemCmd cmd, CacheBlk::State state)
-    {
-        if (cmd == MemCmd::HardPFReq && state)
-            warn("Trying to issue a prefetch to a block we already have\n");
-        if (cmd == MemCmd::Writeback)
-            return MemCmd::Writeback;
-        return MemCmd::ReadReq;
-    }
-
-    /**
-     * Just return readable and writeable.
-     * @param pkt The bus response.
-     * @param current The current block state.
-     * @return The new state.
-     */
-    CacheBlk::State getNewState(PacketPtr &pkt, CacheBlk::State current)
-    {
-        if (pkt->senderState) //Blocking Buffers don't get mshrs
-        {
-            if (((MSHR *)(pkt->senderState))->originalCmd == MemCmd::HardPFReq) {
-                DPRINTF(HWPrefetch, "Marking a hardware prefetch as such in the state\n");
-                return BlkHWPrefetched | BlkValid | BlkWritable;
-            }
-            else {
-                return BlkValid | BlkWritable;
-            }
-        }
-        //@todo What about prefetching with blocking buffers
-        else
-            return BlkValid | BlkWritable;
-    }
-
-    /**
-     * Return outstanding invalidate to forward.
-     * @return The next invalidate to forward to lower levels of cache.
-     */
-    PacketPtr getPacket();
-
-    /**
-     * Was the CSHR request was sent successfully?
-     * @param pkt The request.
-     * @param success True if the request was sent successfully.
-     */
-    void sendResult(PacketPtr &pkt, MSHR* cshr, bool success);
-
-    /**
-     * Handle snooped bus requests.
-     * @param pkt The snooped bus request.
-     * @param blk The cache block corresponding to the request, if any.
-     * @param mshr The MSHR corresponding to the request, if any.
-     * @param new_state The new coherence state of the block.
-     * @return True if the request should be satisfied locally.
-     */
-    bool handleBusRequest(PacketPtr &pkt, CacheBlk *blk, MSHR *mshr,
-                          CacheBlk::State &new_state);
-
-    /**
-     * Return true if this coherence policy can handle fast cache writes.
-     */
-    bool allowFastWrites() { return true; }
-
-    bool hasProtocol() { return false; }
-
-    bool propogateInvalidate(PacketPtr pkt, bool isTiming);
-};
-
-#endif //__UNI_COHERENCE_HH__
index e8ff268800b8261f42ea3c2701279e3dd4d5d56f..281328c2e97920234471c1da9fb9272fa6c56ff7 100644 (file)
@@ -64,7 +64,7 @@ BlockingBuffer::handleMiss(PacketPtr &pkt, int blk_size, Tick time)
         std::memcpy(wb.pkt->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), blk_size);
 
         cache->setBlocked(Blocked_NoWBBuffers);
-        cache->setMasterRequest(Request_WB, time);
+        cache->requestMemSideBus(Request_WB, time);
         return;
     }
 
@@ -77,7 +77,7 @@ BlockingBuffer::handleMiss(PacketPtr &pkt, int blk_size, Tick time)
         miss.pkt->flags |= CACHE_LINE_FILL;
     }
     cache->setBlocked(Blocked_NoMSHRs);
-    cache->setMasterRequest(Request_MSHR, time);
+    cache->requestMemSideBus(Request_MSHR, time);
 }
 
 PacketPtr
@@ -111,7 +111,7 @@ BlockingBuffer::markInService(PacketPtr &pkt, MSHR* mshr)
         // Forwarding a write/ writeback, don't need to change
         // the command
         assert(mshr == &wb);
-        cache->clearMasterRequest(Request_WB);
+        cache->deassertMemSideBusRequest(Request_WB);
         if (!pkt->needsResponse()) {
             assert(wb.getNumTargets() == 0);
             wb.deallocate();
@@ -121,7 +121,7 @@ BlockingBuffer::markInService(PacketPtr &pkt, MSHR* mshr)
         }
     } else {
         assert(mshr == &miss);
-        cache->clearMasterRequest(Request_MSHR);
+        cache->deassertMemSideBusRequest(Request_MSHR);
         if (!pkt->needsResponse()) {
             assert(miss.getNumTargets() == 0);
             miss.deallocate();
@@ -178,7 +178,7 @@ BlockingBuffer::squash(int threadNum)
         if (!miss.inService) {
             miss.deallocate();
             cache->clearBlocked(Blocked_NoMSHRs);
-            cache->clearMasterRequest(Request_MSHR);
+            cache->deassertMemSideBusRequest(Request_MSHR);
         }
     }
 }
@@ -203,7 +203,7 @@ BlockingBuffer::doWriteback(Addr addr,
     writebacks[0/*pkt->req->getThreadNum()*/]++;
 
     wb.allocateAsBuffer(pkt);
-    cache->setMasterRequest(Request_WB, curTick);
+    cache->requestMemSideBus(Request_WB, curTick);
     cache->setBlocked(Blocked_NoWBBuffers);
 }
 
@@ -221,7 +221,7 @@ BlockingBuffer::doWriteback(PacketPtr &pkt)
     std::memcpy(wb.pkt->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), pkt->getSize());
 
     cache->setBlocked(Blocked_NoWBBuffers);
-    cache->setMasterRequest(Request_WB, curTick);
+    cache->requestMemSideBus(Request_WB, curTick);
 }
 
 
index 24ca9cfa2e517e06c52ad2081a5d7c0ec64612e3..67036ed021533fb51a046c08257216d33ddd2f9a 100644 (file)
@@ -348,7 +348,7 @@ MissQueue::allocateMiss(PacketPtr &pkt, int size, Tick time)
     }
     if (pkt->cmd != MemCmd::HardPFReq) {
         //If we need to request the bus (not on HW prefetch), do so
-        cache->setMasterRequest(Request_MSHR, time);
+        cache->requestMemSideBus(Request_MSHR, time);
     }
     return mshr;
 }
@@ -376,7 +376,7 @@ MissQueue::allocateWrite(PacketPtr &pkt, int size, Tick time)
         cache->setBlocked(Blocked_NoWBBuffers);
     }
 
-    cache->setMasterRequest(Request_WB, time);
+    cache->requestMemSideBus(Request_WB, time);
 
     return mshr;
 }
@@ -450,7 +450,7 @@ MissQueue::fetchBlock(Addr addr, int blk_size, Tick time,
     if (mq.isFull()) {
         cache->setBlocked(Blocked_NoMSHRs);
     }
-    cache->setMasterRequest(Request_MSHR, time);
+    cache->requestMemSideBus(Request_MSHR, time);
     return mshr;
 }
 
@@ -534,7 +534,7 @@ MissQueue::markInService(PacketPtr &pkt, MSHR* mshr)
         unblock = wb.isFull();
         wb.markInService(mshr);
         if (!wb.havePending()){
-            cache->clearMasterRequest(Request_WB);
+            cache->deassertMemSideBusRequest(Request_WB);
         }
         if (unblock) {
             // Do we really unblock?
@@ -545,7 +545,7 @@ MissQueue::markInService(PacketPtr &pkt, MSHR* mshr)
         unblock = mq.isFull();
         mq.markInService(mshr);
         if (!mq.havePending()){
-            cache->clearMasterRequest(Request_MSHR);
+            cache->deassertMemSideBusRequest(Request_MSHR);
         }
         if (mshr->originalCmd == MemCmd::HardPFReq) {
             DPRINTF(HWPrefetch, "%s:Marking a HW_PF in service\n",
@@ -553,7 +553,7 @@ MissQueue::markInService(PacketPtr &pkt, MSHR* mshr)
             //Also clear pending if need be
             if (!prefetcher->havePending())
             {
-                cache->clearMasterRequest(Request_PF);
+                cache->deassertMemSideBusRequest(Request_PF);
             }
         }
         if (unblock) {
@@ -602,7 +602,7 @@ MissQueue::handleResponse(PacketPtr &pkt, Tick time)
             mshr->pkt->req = mshr->getTarget()->req;
             mq.markPending(mshr, cmd);
             mshr->order = order++;
-            cache->setMasterRequest(Request_MSHR, time);
+            cache->requestMemSideBus(Request_MSHR, time);
         }
         else {
             unblock = mq.isFull();
@@ -683,7 +683,7 @@ MissQueue::squash(int threadNum)
     }
     mq.squash(threadNum);
     if (!mq.havePending()) {
-        cache->clearMasterRequest(Request_MSHR);
+        cache->deassertMemSideBusRequest(Request_MSHR);
     }
     if (unblock && !mq.isFull()) {
         cache->clearBlocked(cause);
index 44daf75e1be4b35280c9efa886a0f1c066326851..966f7d005aa719815d976f88efc79f86b2398ddf 100644 (file)
@@ -141,7 +141,7 @@ BasePrefetcher::getPacket()
             keepTrying = cache->inCache(pkt->getAddr());
         }
         if (pf.empty()) {
-            cache->clearMasterRequest(Request_PF);
+            cache->deassertMemSideBusRequest(Request_PF);
             if (keepTrying) return NULL; //None left, all were in cache
         }
     } while (keepTrying);
@@ -165,7 +165,7 @@ BasePrefetcher::handleMiss(PacketPtr &pkt, Tick time)
             pfRemovedMSHR++;
             pf.erase(iter);
             if (pf.empty())
-                cache->clearMasterRequest(Request_PF);
+                cache->deassertMemSideBusRequest(Request_PF);
         }
 
         //Remove anything in queue with delay older than time
@@ -182,7 +182,7 @@ BasePrefetcher::handleMiss(PacketPtr &pkt, Tick time)
                 iter--;
             }
             if (pf.empty())
-                cache->clearMasterRequest(Request_PF);
+                cache->deassertMemSideBusRequest(Request_PF);
         }
 
 
@@ -244,7 +244,7 @@ BasePrefetcher::handleMiss(PacketPtr &pkt, Tick time)
             prefetch->flags |= CACHE_LINE_FILL;
 
             //Make sure to request the bus, with proper delay
-            cache->setMasterRequest(Request_PF, prefetch->time);
+            cache->requestMemSideBus(Request_PF, prefetch->time);
 
             //Increment through the list
             addr++;
index dc23e9f6da328ec53a40f24a0857d3ec7a858588..577f991160b7c5c1d8afe77443ddd1c83e3c0923 100644 (file)
@@ -61,8 +61,8 @@ typedef std::list<PacketPtr> PacketList;
 #define CACHE_LINE_FILL (1 << 3)
 #define COMPRESSED      (1 << 4)
 #define NO_ALLOCATE     (1 << 5)
-#define SNOOP_COMMIT    (1 << 6)
 
+#define EXPRESS_SNOOP   (1 << 7)
 
 class MemCmd
 {