From 0290fdd6c9204f958da9d76158105922c4cee624 Mon Sep 17 00:00:00 2001
From: Virendra Kumar Pathak <vpathak@broadcom.com>
Date: Fri, 6 Nov 2015 20:51:18 +0530
Subject: [PATCH] adding decodeQueue between decode and rename

---
 src/cpu/o3/decode_impl.hh | 99 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 87 insertions(+), 12 deletions(-)

diff --git a/src/cpu/o3/decode_impl.hh b/src/cpu/o3/decode_impl.hh
index 93d04a8..aa20d25 100644
--- a/src/cpu/o3/decode_impl.hh
+++ b/src/cpu/o3/decode_impl.hh
@@ -45,6 +45,7 @@
 
 #include "arch/types.hh"
 #include "base/trace.hh"
+#include "base/random.hh"
 #include "config/the_isa.hh"
 #include "cpu/o3/decode.hh"
 #include "cpu/inst_seq.hh"
@@ -61,11 +62,13 @@ using std::list;
 template<class Impl>
 DefaultDecode<Impl>::DefaultDecode(O3CPU *_cpu, DerivO3CPUParams *params)
     : cpu(_cpu),
+      decodeQueueSize(params->decodeQueueSize),
       renameToDecodeDelay(params->renameToDecodeDelay),
       iewToDecodeDelay(params->iewToDecodeDelay),
       commitToDecodeDelay(params->commitToDecodeDelay),
       fetchToDecodeDelay(params->fetchToDecodeDelay),
       decodeWidth(params->decodeWidth),
+      renameWidth(params->renameWidth),
       numThreads(params->numThreads)
 {
     if (decodeWidth > Impl::MaxWidth)
@@ -95,6 +98,7 @@ DefaultDecode<Impl>::resetStage()
         decodeStatus[tid] = Idle;
 
         stalls[tid].rename = false;
+        decodeQueue[tid].clear();
     }
 }
 
@@ -167,14 +171,13 @@ DefaultDecode<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
     fromCommit = timeBuffer->getWire(-commitToDecodeDelay);
 }
 
+// Directly assigning the deque time buffer
 template<class Impl>
 void
-DefaultDecode<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
+DefaultDecode<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dtb_ptr)
 {
-    decodeQueue = dq_ptr;
-
     // Setup wire to write information to proper place in decode queue.
-    toRename = decodeQueue->getWire(0);
+    toRename = dtb_ptr->getWire(0);
 }
 
 template<class Impl>
@@ -211,6 +214,8 @@ DefaultDecode<Impl>::isDrained() const
     for (ThreadID tid = 0; tid < numThreads; ++tid) {
         if (!insts[tid].empty() || !skidBuffer[tid].empty())
             return false;
+        if (!decodeQueue[tid].empty())
+            return false;
     }
     return true;
 }
@@ -333,6 +338,9 @@ DefaultDecode<Impl>::squash(DynInstPtr &inst, ThreadID tid)
         skidBuffer[tid].pop();
     }
 
+    // Empty decode Queue
+    //decodeQueue[tid].clear();
+
     // Squash instructions up until this one
     cpu->removeInstsUntil(squash_seq_num, tid);
 }
@@ -514,7 +522,8 @@ DefaultDecode<Impl>::checkSignalsAndUpdate(ThreadID tid)
         return true;
     }
 
-    if (checkStall(tid)) {
+    //if (checkStall(tid)) {
+    if (decodeQueue[tid].size() > 25) {
         return block(tid);
     }
 
@@ -570,6 +579,64 @@ DefaultDecode<Impl>::tick()
         decode(status_change, tid);
     }
 
+    //if (status_change) {
+      //  updateStatus();
+    //}
+
+    // send instructions enqueued into the decode queue to rename
+    // Limit rate by decodeWidth (?). Stall if rename is stalled
+    unsigned insts_to_rename = 0;
+    unsigned available_insts = 0;
+
+    list<ThreadID>::iterator threads1 = activeThreads->begin();
+    list<ThreadID>::iterator end1 = activeThreads->end();
+    while (threads1 != end1) {
+        ThreadID tid1 = *threads1++;
+        DPRINTF(Decode, "Vir1 Tid1 %d\n", tid1);
+        available_insts += decodeQueue[tid1].size();
+    }
+    //for (auto tid : *activeThreads) {
+      //  available_insts += decodeQueue[tid].size();
+    //}
+
+    // Pick a random thread to start trying to grab instructions from
+    auto tid_itr = activeThreads->begin();
+    std::advance(tid_itr, random_mt.random<uint8_t>(0, activeThreads->size() - 1));
+
+    DPRINTF(Decode, "Vir1 toRename->size %d available_insts %d toRenameIndex %d\n",
+            toRename->size, available_insts, toRenameIndex);
+    DPRINTF(Decode, "Vir1 what is size %i rename-stall %d\n",
+            decodeQueue[0].size(), stalls[0].rename);
+
+    while (available_insts != 0 && insts_to_rename < renameWidth) {
+        ThreadID tid = *tid_itr;
+        if (!stalls[tid].rename && !decodeQueue[tid].empty()) {
+            auto inst = decodeQueue[tid].front();
+            toRename->insts[toRename->size++] = inst;
+            //++(toRename->size);
+            DPRINTF(Decode,
+                    "[tid:%i][sn:%i]: Sending instruction to rename from "
+                    "decode queue. decode queue size: %i.\n",
+                    tid, inst->seqNum, decodeQueue[tid].size());
+
+            decodeQueue[tid].pop_front();
+            insts_to_rename++;
+            available_insts--;
+        } else {
+            break;
+        }
+
+        tid_itr++;
+        // Wrap around if at end of active threads
+        // list
+        if (tid_itr == activeThreads->end())
+            tid_itr = activeThreads->begin();
+    }
+
+    if (insts_to_rename) {
+        wroteToTimeBuffer = true;
+    }
+
     if (status_change) {
         updateStatus();
     }
@@ -657,7 +724,8 @@ DefaultDecode<Impl>::decodeInsts(ThreadID tid)
 
     DPRINTF(Decode, "[tid:%u]: Sending instruction to rename.\n",tid);
 
-    while (insts_available > 0 && toRenameIndex < decodeWidth) {
+    while (insts_available > 0 && toRenameIndex < decodeWidth &&
+            decodeQueue[tid].size() < decodeQueueSize) {
         assert(!insts_to_decode.empty());
 
         inst = insts_to_decode.front();
@@ -690,9 +758,14 @@ DefaultDecode<Impl>::decodeInsts(ThreadID tid)
         // This current instruction is valid, so add it into the decode
         // queue.  The next instruction may not be valid, so check to
         // see if branches were predicted correctly.
-        toRename->insts[toRenameIndex] = inst;
-
-        ++(toRename->size);
+        decodeQueue[tid].push_back(inst);
+        assert(decodeQueue[tid].size() <= decodeQueueSize);
+        DPRINTF(Decode, "[tid:%i]: Decode queue entry created (%i/%i).\n",
+                            tid, decodeQueue[tid].size(), decodeQueueSize);
+        //DPRINTF(Decode, "toRenameIndex %d\n", toRenameIndex);
+        //toRename->insts[toRenameIndex] = inst;
+
+        //++(toRename->size);
         ++toRenameIndex;
         ++decodeDecodedInsts;
         --insts_available;
@@ -740,15 +813,17 @@ DefaultDecode<Impl>::decodeInsts(ThreadID tid)
 
     // If we didn't process all instructions, then we will need to block
     // and put all those instructions into the skid buffer.
+    DPRINTF(Decode, "Vir, check for block %d \n", insts_to_decode.size());
     if (!insts_to_decode.empty()) {
+        DPRINTF(Decode, "Vir, are we still blocking dude ?\n");
         block(tid);
     }
 
     // Record that decode has written to the time buffer for activity
     // tracking.
-    if (toRenameIndex) {
-        wroteToTimeBuffer = true;
-    }
+    //if (toRenameIndex) {
+      //  wroteToTimeBuffer = true;
+    //}
 }
 
 #endif//__CPU_O3_DECODE_IMPL_HH__
-- 
1.9.1

