mem: Unify request selection for read and write queues
authorNeha Agarwal <neha.agarwal@arm.com>
Fri, 1 Nov 2013 15:56:27 +0000 (11:56 -0400)
committerNeha Agarwal <neha.agarwal@arm.com>
Fri, 1 Nov 2013 15:56:27 +0000 (11:56 -0400)
This patch unifies the request selection across read and write queues
for FR-FCFS scheduling policy. It also fixes the request selection
code to prioritize the row hits present in the request queues over the
selection based on earliest bank availability.

src/mem/simple_dram.cc
src/mem/simple_dram.hh

index 69209fb8a183ecb435f48bdabf45d41f82ae8e70..46e81f56406f54ce0ba670dc39efe7038b880756 100644 (file)
@@ -791,34 +791,7 @@ SimpleDRAM::chooseNextWrite()
     if (memSchedPolicy == Enums::fcfs) {
         // Do nothing, since the correct request is already head
     } else if (memSchedPolicy == Enums::frfcfs) {
-        // Only determine bank availability when needed
-        uint64_t earliest_banks = 0;
-
-        auto i = writeQueue.begin();
-        bool foundRowHit = false;
-        while (!foundRowHit && i != writeQueue.end()) {
-            DRAMPacket* dram_pkt = *i;
-            const Bank& bank = dram_pkt->bankRef;
-            if (bank.openRow == dram_pkt->row) {
-                DPRINTF(DRAM, "Write row buffer hit\n");
-                writeQueue.erase(i);
-                writeQueue.push_front(dram_pkt);
-                foundRowHit = true;
-            } else {
-                // No row hit, go for first ready
-                if (earliest_banks == 0)
-                    earliest_banks = minBankFreeAt(writeQueue);
-
-                // Bank is ready or is one of the first available bank
-                if (bank.freeAt <= curTick() ||
-                    bits(earliest_banks, dram_pkt->bankId, dram_pkt->bankId)) {
-                    writeQueue.erase(i);
-                    writeQueue.push_front(dram_pkt);
-                    break;
-                }
-            }
-            ++i;
-        }
+        reorderQueue(writeQueue);
     } else
         panic("No scheduling policy chosen\n");
 
@@ -845,32 +818,7 @@ SimpleDRAM::chooseNextRead()
         // Do nothing, since the request to serve is already the first
         // one in the read queue
     } else if (memSchedPolicy == Enums::frfcfs) {
-        // Only determine this when needed
-        uint64_t earliest_banks = 0;
-
-        for (auto i = readQueue.begin(); i != readQueue.end() ; ++i) {
-            DRAMPacket* dram_pkt = *i;
-            const Bank& bank = dram_pkt->bankRef;
-            // Check if it is a row hit
-            if (bank.openRow == dram_pkt->row) {
-                DPRINTF(DRAM, "Row buffer hit\n");
-                readQueue.erase(i);
-                readQueue.push_front(dram_pkt);
-                break;
-            } else {
-                // No row hit, go for first ready
-                if (earliest_banks == 0)
-                    earliest_banks = minBankFreeAt(readQueue);
-
-                // Bank is ready or is the first available bank
-                if (bank.freeAt <= curTick() ||
-                    bits(earliest_banks, dram_pkt->bankId, dram_pkt->bankId)) {
-                    readQueue.erase(i);
-                    readQueue.push_front(dram_pkt);
-                    break;
-                }
-            }
-        }
+        reorderQueue(readQueue);
     } else
         panic("No scheduling policy chosen!\n");
 
@@ -878,6 +826,46 @@ SimpleDRAM::chooseNextRead()
     return true;
 }
 
+void
+SimpleDRAM::reorderQueue(std::deque<DRAMPacket*>& queue)
+{
+    // Only determine this when needed
+    uint64_t earliest_banks = 0;
+
+    // Search for row hits first, if no row hit is found then schedule the
+    // packet to one of the earliest banks available
+    bool found_earliest_pkt = false;
+    auto selected_pkt_it = queue.begin();
+
+    for (auto i = queue.begin(); i != queue.end() ; ++i) {
+        DRAMPacket* dram_pkt = *i;
+        const Bank& bank = dram_pkt->bankRef;
+        // Check if it is a row hit
+        if (bank.openRow == dram_pkt->row) {
+            DPRINTF(DRAM, "Row buffer hit\n");
+            selected_pkt_it = i;
+            break;
+        } else if (!found_earliest_pkt) {
+            // No row hit, go for first ready
+            if (earliest_banks == 0)
+                earliest_banks = minBankFreeAt(queue);
+
+            // Bank is ready or is the first available bank
+            if (bank.freeAt <= curTick() ||
+                bits(earliest_banks, dram_pkt->bankId, dram_pkt->bankId)) {
+                // Remember the packet to be scheduled to one of the earliest
+                // banks available
+                selected_pkt_it = i;
+                found_earliest_pkt = true;
+            }
+        }
+    }
+
+    DRAMPacket* selected_pkt = *selected_pkt_it;
+    queue.erase(selected_pkt_it);
+    queue.push_front(selected_pkt);
+}
+
 void
 SimpleDRAM::accessAndRespond(PacketPtr pkt, Tick static_latency)
 {
index a7a100d7c8596c595071f47da24ea4c88347c684..535e3a8c521ae0c11f827c45a440699f7af75e0f 100644 (file)
@@ -397,6 +397,12 @@ class SimpleDRAM : public AbstractMemory
      */
     void chooseNextWrite();
 
+    /**
+     * For FR-FCFS policy reorder the read/write queue depending on row buffer
+     * hits and earliest banks available in DRAM
+     */
+    void reorderQueue(std::deque<DRAMPacket*>& queue);
+
     /**
      * Looking at all banks, determine the moment in time when they
      * are all free.