Matthew Poremba has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/28387 )

Change subject: mem: Remove infinite queue between Ruby and memory
......................................................................

mem: Remove infinite queue between Ruby and memory

AbstractController sends requests using a QueuedMasterPort which has an
implicit buffer which is unbounded. Remove this by using the tryTiming
interface to query if the memory controller has space available before
sending the memory request. If space is available the request is sent
normally. Otherwise, the request remains in the Ruby MessageBuffer and
the controller wakes periodically to check for space.

This adds tryTiming interface to all of the memory controllers. It is
also added to the NoncoherentXbar because Ruby may place a crossbar
between the AbstractController and memories if there are more memories
than directories.

Change-Id: I8c592af92a1a499a418f34cfee16dd69d84803ad
---
M src/mem/dram_ctrl.cc
M src/mem/dram_ctrl.hh
M src/mem/noncoherent_xbar.hh
M src/mem/ruby/slicc_interface/AbstractController.cc
M src/mem/simple_mem.cc
M src/mem/simple_mem.hh
M src/mem/xbar.cc
M src/mem/xbar.hh
8 files changed, 70 insertions(+), 3 deletions(-)



diff --git a/src/mem/dram_ctrl.cc b/src/mem/dram_ctrl.cc
index 0a8479e..cf608ec 100644
--- a/src/mem/dram_ctrl.cc
+++ b/src/mem/dram_ctrl.cc
@@ -261,6 +261,23 @@
     }
 }

+bool
+DRAMCtrl::tryTiming(PacketPtr pkt)
+{
+    unsigned size = pkt->getSize();
+    unsigned offset = pkt->getAddr() & (burstSize - 1);
+    unsigned int dram_pkt_count = divCeil(offset + size, burstSize);
+
+    assert(pkt->isRead() || pkt->isWrite());
+    if (pkt->isRead() && readQueueFull(dram_pkt_count)) {
+        return false;
+    } else if (pkt->isWrite() && writeQueueFull(dram_pkt_count)) {
+        return false;
+    }
+
+    return true;
+}
+
 Tick
 DRAMCtrl::recvAtomic(PacketPtr pkt)
 {
@@ -2970,6 +2987,12 @@
     return ranges;
 }

+bool
+DRAMCtrl::MemoryPort::tryTiming(PacketPtr pkt)
+{
+    return memory.tryTiming(pkt);
+}
+
 void
 DRAMCtrl::MemoryPort::recvFunctional(PacketPtr pkt)
 {
diff --git a/src/mem/dram_ctrl.hh b/src/mem/dram_ctrl.hh
index 0fe78da..e156185 100644
--- a/src/mem/dram_ctrl.hh
+++ b/src/mem/dram_ctrl.hh
@@ -106,6 +106,8 @@

       protected:

+        bool tryTiming(PacketPtr pkt);
+
         Tick recvAtomic(PacketPtr pkt);

         void recvFunctional(PacketPtr pkt);
@@ -1258,6 +1260,7 @@

   protected:

+    bool tryTiming(PacketPtr pkt);
     Tick recvAtomic(PacketPtr pkt);
     void recvFunctional(PacketPtr pkt);
     bool recvTimingReq(PacketPtr pkt);
diff --git a/src/mem/noncoherent_xbar.hh b/src/mem/noncoherent_xbar.hh
index 86658d0..26b7b57 100644
--- a/src/mem/noncoherent_xbar.hh
+++ b/src/mem/noncoherent_xbar.hh
@@ -128,6 +128,19 @@
         {
             return xbar.getAddrRanges();
         }
+
+        bool
+        tryTiming(PacketPtr pkt)
+        {
+ AddrRange addr_range = RangeSize(pkt->getAddr(), pkt->getSize());
+            PortID master_port_id = xbar.findPort(addr_range);
+            if (xbar.reqLayers[master_port_id]->layerBusy()) {
+                return false;
+            }
+
+            // Forward the attempt to the master port
+            return xbar.masterPorts[master_port_id]->tryTiming(pkt);
+        }
     };

     /**
diff --git a/src/mem/ruby/slicc_interface/AbstractController.cc b/src/mem/ruby/slicc_interface/AbstractController.cc
index 59611ae..b70745a 100644
--- a/src/mem/ruby/slicc_interface/AbstractController.cc
+++ b/src/mem/ruby/slicc_interface/AbstractController.cc
@@ -250,12 +250,16 @@
         // to make more progress. Make sure it wakes up
         scheduleEvent(Cycles(1));
         recvTimingResp(pkt);
-    } else {
+    } else if (memoryPort.tryTiming(pkt)) {
         mem_queue->dequeue(clockEdge());
-        memoryPort.schedTimingReq(pkt, clockEdge());
+        memoryPort.sendTimingReq(pkt);
         // Since the queue was popped the controller may be able
         // to make more progress. Make sure it wakes up
         scheduleEvent(Cycles(1));
+    } else {
+        delete pkt;
+        delete s;
+        scheduleEvent(Cycles(1));
     }

     return true;
diff --git a/src/mem/simple_mem.cc b/src/mem/simple_mem.cc
index 4161e87..1030a0e 100644
--- a/src/mem/simple_mem.cc
+++ b/src/mem/simple_mem.cc
@@ -66,6 +66,12 @@
     }
 }

+bool
+SimpleMemory::tryTiming(PacketPtr pkt)
+{
+    return !isBusy;
+}
+
 Tick
 SimpleMemory::recvAtomic(PacketPtr pkt)
 {
@@ -271,6 +277,12 @@
     return ranges;
 }

+bool
+SimpleMemory::MemoryPort::tryTiming(PacketPtr pkt)
+{
+    return memory.tryTiming(pkt);
+}
+
 Tick
 SimpleMemory::MemoryPort::recvAtomic(PacketPtr pkt)
 {
diff --git a/src/mem/simple_mem.hh b/src/mem/simple_mem.hh
index 0bcb15c..3488d74 100644
--- a/src/mem/simple_mem.hh
+++ b/src/mem/simple_mem.hh
@@ -88,6 +88,7 @@
         MemoryPort(const std::string& _name, SimpleMemory& _memory);

       protected:
+        bool tryTiming(PacketPtr pkt) override;
         Tick recvAtomic(PacketPtr pkt) override;
         Tick recvAtomicBackdoor(
                 PacketPtr pkt, MemBackdoorPtr &_backdoor) override;
@@ -182,6 +183,7 @@
     void init() override;

   protected:
+    bool tryTiming(PacketPtr pkt);
     Tick recvAtomic(PacketPtr pkt);
     Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &_backdoor);
     void recvFunctional(PacketPtr pkt);
diff --git a/src/mem/xbar.cc b/src/mem/xbar.cc
index 9920216..2d300e5 100644
--- a/src/mem/xbar.cc
+++ b/src/mem/xbar.cc
@@ -174,6 +174,13 @@

 template <typename SrcType, typename DstType>
 bool
+BaseXBar::Layer<SrcType, DstType>::layerBusy() const
+{
+    return (state == BUSY || waitingForPeer != NULL);
+}
+
+template <typename SrcType, typename DstType>
+bool
 BaseXBar::Layer<SrcType, DstType>::tryTiming(SrcType* src_port)
 {
     // if we are in the retry state, we will not see anything but the
@@ -185,7 +192,7 @@
     // first we see if the layer is busy, next we check if the
     // destination port is already engaged in a transaction waiting
     // for a retry from the peer
-    if (state == BUSY || waitingForPeer != NULL) {
+    if (layerBusy()) {
         // the port should not be waiting already
         assert(std::find(waitingForLayer.begin(), waitingForLayer.end(),
                          src_port) == waitingForLayer.end());
diff --git a/src/mem/xbar.hh b/src/mem/xbar.hh
index 4488f74..05fa7c9 100644
--- a/src/mem/xbar.hh
+++ b/src/mem/xbar.hh
@@ -148,6 +148,9 @@

         void occupyLayer(Tick until);

+        /** Check if layer is busy */
+        bool layerBusy() const;
+
         /**
          * Send a retry to the port at the head of waitingForLayer. The
          * caller must ensure that the list is not empty.

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/28387
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I8c592af92a1a499a418f34cfee16dd69d84803ad
Gerrit-Change-Number: 28387
Gerrit-PatchSet: 1
Gerrit-Owner: Matthew Poremba <matthew.pore...@amd.com>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to