cpu-o3: Add cache read ports limit to LSQ
authorGabor Dozsa <gabor.dozsa@arm.com>
Mon, 25 Jun 2018 15:59:26 +0000 (16:59 +0100)
committerGabor Dozsa <gabor.dozsa@arm.com>
Fri, 22 Feb 2019 12:16:20 +0000 (12:16 +0000)
This change introduces cache read ports to limit the number of
per-cycle loads. Previously only the number of per-cycle stores
could be limited.

Change-Id: I39bbd984056c5a696725ee2db462a55b2079e2d4
Signed-off-by: Gabor Dozsa <gabor.dozsa@arm.com>
Reviewed-by: Giacomo Gabrielli <giacomo.gabrielli@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/13517
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>

src/cpu/o3/O3CPU.py
src/cpu/o3/lsq.hh
src/cpu/o3/lsq_impl.hh
src/cpu/o3/lsq_unit_impl.hh

index 8e17d9a3fa79b5d3c8e8f65046760fd3be0cd64b..4a994f07f7d5ef0c03462b0e10b05c109c33e997 100644 (file)
@@ -77,7 +77,9 @@ class DerivO3CPU(BaseCPU):
     activity = Param.Unsigned(0, "Initial count")
 
     cacheStorePorts = Param.Unsigned(200, "Cache Ports. "
-          "Constrains stores only. Loads are constrained by load FUs.")
+          "Constrains stores only.")
+    cacheLoadPorts = Param.Unsigned(200, "Cache Ports. "
+          "Constrains loads only.")
 
     decodeToFetchDelay = Param.Cycles(1, "Decode to fetch delay")
     renameToFetchDelay = Param.Cycles(1 ,"Rename to fetch delay")
index f576dd3f4e9294f940d01b394bc2a035bf582130..a6037b7f4b734f748bef67bbbbd2f1da4c2d7aac 100644 (file)
@@ -755,7 +755,7 @@ class LSQ
     int entryAmount(ThreadID num_threads);
 
     /** Ticks the LSQ. */
-    void tick() { usedStorePorts = 0; }
+    void tick();
 
     /** Inserts a load into the LSQ. */
     void insertLoad(const DynInstPtr &load_inst);
@@ -962,9 +962,9 @@ class LSQ
     /** Set D-cache blocked status */
     void cacheBlocked(bool v);
     /** Is any store port available to use? */
-    bool storePortAvailable() const;
+    bool cachePortAvailable(bool is_load) const;
     /** Another store port is in use */
-    void storePortBusy();
+    void cachePortBusy(bool is_load);
 
   protected:
     /** D-cache is blocked */
@@ -973,6 +973,10 @@ class LSQ
     int cacheStorePorts;
     /** The number of used cache ports in this cycle by stores. */
     int usedStorePorts;
+    /** The number of cache ports available each cycle (loads only). */
+    int cacheLoadPorts;
+    /** The number of used cache ports in this cycle by loads. */
+    int usedLoadPorts;
 
 
     /** The LSQ policy for SMT mode. */
index 5c64377b9f5402de639e3683fbb2e88980a0a52b..7327120297c960a6eb95b46288d30421c50a691b 100644 (file)
@@ -63,6 +63,7 @@ LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params)
     : cpu(cpu_ptr), iewStage(iew_ptr),
       _cacheBlocked(false),
       cacheStorePorts(params->cacheStorePorts), usedStorePorts(0),
+      cacheLoadPorts(params->cacheLoadPorts), usedLoadPorts(0),
       lsqPolicy(params->smtLSQPolicy),
       LQEntries(params->LQEntries),
       SQEntries(params->SQEntries),
@@ -173,6 +174,18 @@ LSQ<Impl>::takeOverFrom()
     }
 }
 
+template <class Impl>
+void
+LSQ<Impl>::tick()
+{
+    // Re-issue loads which got blocked on the per-cycle load ports limit.
+    if (usedLoadPorts == cacheLoadPorts && !_cacheBlocked)
+        iewStage->cacheUnblocked();
+
+    usedLoadPorts = 0;
+    usedStorePorts = 0;
+}
+
 template<class Impl>
 bool
 LSQ<Impl>::cacheBlocked() const
@@ -189,17 +202,27 @@ LSQ<Impl>::cacheBlocked(bool v)
 
 template<class Impl>
 bool
-LSQ<Impl>::storePortAvailable() const
+LSQ<Impl>::cachePortAvailable(bool is_load) const
 {
-    return usedStorePorts < cacheStorePorts;
+    bool ret;
+    if (is_load) {
+        ret  = usedLoadPorts < cacheLoadPorts;
+    } else {
+        ret  = usedStorePorts < cacheStorePorts;
+    }
+    return ret;
 }
 
 template<class Impl>
 void
-LSQ<Impl>::storePortBusy()
+LSQ<Impl>::cachePortBusy(bool is_load)
 {
-    usedStorePorts++;
-    assert(usedStorePorts <= cacheStorePorts);
+    assert(cachePortAvailable(is_load));
+    if (is_load) {
+        usedLoadPorts++;
+    } else {
+        usedStorePorts++;
+    }
 }
 
 template<class Impl>
index 48179ceb82119c5e25e42a09a55b912e1f139215..2c59d5a9e0d58d4d092dab3d4a6069d25181a6e7 100644 (file)
@@ -708,7 +708,7 @@ LSQUnit<Impl>::writebackStores()
            storeWBIt->valid() &&
            storeWBIt->canWB() &&
            ((!needsTSO) || (!storeInFlight)) &&
-           lsq->storePortAvailable()) {
+           lsq->cachePortAvailable(false)) {
 
         if (isStoreBlocked) {
             DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
@@ -1040,7 +1040,8 @@ LSQUnit<Impl>::trySendPacket(bool isLoad, PacketPtr data_pkt)
 
     auto state = dynamic_cast<LSQSenderState*>(data_pkt->senderState);
 
-    if (!lsq->cacheBlocked() && (isLoad || lsq->storePortAvailable())) {
+    if (!lsq->cacheBlocked() &&
+        lsq->cachePortAvailable(isLoad)) {
         if (!dcachePort->sendTimingReq(data_pkt)) {
             ret = false;
             cache_got_blocked = true;
@@ -1051,9 +1052,9 @@ LSQUnit<Impl>::trySendPacket(bool isLoad, PacketPtr data_pkt)
 
     if (ret) {
         if (!isLoad) {
-            lsq->storePortBusy();
             isStoreBlocked = false;
         }
+        lsq->cachePortBusy(isLoad);
         state->outstanding++;
         state->request()->packetSent();
     } else {
@@ -1067,7 +1068,6 @@ LSQUnit<Impl>::trySendPacket(bool isLoad, PacketPtr data_pkt)
         }
         state->request()->packetNotSent();
     }
-
     return ret;
 }