cpu: Fix the usage of const DynInstPtr
[gem5.git] / src / cpu / o3 / decode_impl.hh
index 8b851c032810327f4fb8f3f0aa0891dacb55f404..51c1b9de161e296625b43f1e19513ad9a0e56200 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2012, 2014 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2004-2006 The Regents of The University of Michigan
  * All rights reserved.
  *
  * Authors: Kevin Lim
  */
 
+#ifndef __CPU_O3_DECODE_IMPL_HH__
+#define __CPU_O3_DECODE_IMPL_HH__
+
+#include "arch/types.hh"
+#include "base/trace.hh"
+#include "config/the_isa.hh"
 #include "cpu/o3/decode.hh"
+#include "cpu/inst_seq.hh"
+#include "debug/Activity.hh"
+#include "debug/Decode.hh"
+#include "debug/O3PipeView.hh"
+#include "params/DerivO3CPU.hh"
+#include "sim/full_system.hh"
 
-using namespace std;
+// clang complains about std::set being overloaded with Packet::set if
+// we open up the entire namespace std
+using std::list;
 
 template<class Impl>
-DefaultDecode<Impl>::DefaultDecode(Params *params)
-    : renameToDecodeDelay(params->renameToDecodeDelay),
+DefaultDecode<Impl>::DefaultDecode(O3CPU *_cpu, DerivO3CPUParams *params)
+    : cpu(_cpu),
+      renameToDecodeDelay(params->renameToDecodeDelay),
       iewToDecodeDelay(params->iewToDecodeDelay),
       commitToDecodeDelay(params->commitToDecodeDelay),
       fetchToDecodeDelay(params->fetchToDecodeDelay),
       decodeWidth(params->decodeWidth),
-      numThreads(params->numberOfThreads)
+      numThreads(params->numThreads)
+{
+    if (decodeWidth > Impl::MaxWidth)
+        fatal("decodeWidth (%d) is larger than compiled limit (%d),\n"
+             "\tincrease MaxWidth in src/cpu/o3/impl.hh\n",
+             decodeWidth, static_cast<int>(Impl::MaxWidth));
+
+    // @todo: Make into a parameter
+    skidBufferMax = (fetchToDecodeDelay + 1) *  params->fetchWidth;
+}
+
+template<class Impl>
+void
+DefaultDecode<Impl>::startupStage()
+{
+    resetStage();
+}
+
+template<class Impl>
+void
+DefaultDecode<Impl>::resetStage()
 {
     _status = Inactive;
 
     // Setup status, make sure stall signals are clear.
-    for (int i = 0; i < numThreads; ++i) {
-        decodeStatus[i] = Idle;
+    for (ThreadID tid = 0; tid < numThreads; ++tid) {
+        decodeStatus[tid] = Idle;
 
-        stalls[i].rename = false;
-        stalls[i].iew = false;
-        stalls[i].commit = false;
+        stalls[tid].rename = false;
     }
-
-    // @todo: Make into a parameter
-    skidBufferMax = (fetchToDecodeDelay * params->fetchWidth) + decodeWidth;
 }
 
 template <class Impl>
@@ -68,61 +110,52 @@ void
 DefaultDecode<Impl>::regStats()
 {
     decodeIdleCycles
-        .name(name() + ".DECODE:IdleCycles")
+        .name(name() + ".IdleCycles")
         .desc("Number of cycles decode is idle")
         .prereq(decodeIdleCycles);
     decodeBlockedCycles
-        .name(name() + ".DECODE:BlockedCycles")
+        .name(name() + ".BlockedCycles")
         .desc("Number of cycles decode is blocked")
         .prereq(decodeBlockedCycles);
     decodeRunCycles
-        .name(name() + ".DECODE:RunCycles")
+        .name(name() + ".RunCycles")
         .desc("Number of cycles decode is running")
         .prereq(decodeRunCycles);
     decodeUnblockCycles
-        .name(name() + ".DECODE:UnblockCycles")
+        .name(name() + ".UnblockCycles")
         .desc("Number of cycles decode is unblocking")
         .prereq(decodeUnblockCycles);
     decodeSquashCycles
-        .name(name() + ".DECODE:SquashCycles")
+        .name(name() + ".SquashCycles")
         .desc("Number of cycles decode is squashing")
         .prereq(decodeSquashCycles);
     decodeBranchResolved
-        .name(name() + ".DECODE:BranchResolved")
+        .name(name() + ".BranchResolved")
         .desc("Number of times decode resolved a branch")
         .prereq(decodeBranchResolved);
     decodeBranchMispred
-        .name(name() + ".DECODE:BranchMispred")
+        .name(name() + ".BranchMispred")
         .desc("Number of times decode detected a branch misprediction")
         .prereq(decodeBranchMispred);
     decodeControlMispred
-        .name(name() + ".DECODE:ControlMispred")
+        .name(name() + ".ControlMispred")
         .desc("Number of times decode detected an instruction incorrectly"
               " predicted as a control")
         .prereq(decodeControlMispred);
     decodeDecodedInsts
-        .name(name() + ".DECODE:DecodedInsts")
+        .name(name() + ".DecodedInsts")
         .desc("Number of instructions handled by decode")
         .prereq(decodeDecodedInsts);
     decodeSquashedInsts
-        .name(name() + ".DECODE:SquashedInsts")
+        .name(name() + ".SquashedInsts")
         .desc("Number of squashed instructions handled by decode")
         .prereq(decodeSquashedInsts);
 }
 
-template<class Impl>
-void
-DefaultDecode<Impl>::setCPU(O3CPU *cpu_ptr)
-{
-    DPRINTF(Decode, "Setting CPU pointer.\n");
-    cpu = cpu_ptr;
-}
-
 template<class Impl>
 void
 DefaultDecode<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
 {
-    DPRINTF(Decode, "Setting time buffer pointer.\n");
     timeBuffer = tb_ptr;
 
     // Setup wire to write information back to fetch.
@@ -138,7 +171,6 @@ template<class Impl>
 void
 DefaultDecode<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
 {
-    DPRINTF(Decode, "Setting decode queue pointer.\n");
     decodeQueue = dq_ptr;
 
     // Setup wire to write information to proper place in decode queue.
@@ -149,7 +181,6 @@ template<class Impl>
 void
 DefaultDecode<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
 {
-    DPRINTF(Decode, "Setting fetch queue pointer.\n");
     fetchQueue = fq_ptr;
 
     // Setup wire to read information from fetch queue.
@@ -158,58 +189,42 @@ DefaultDecode<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
 
 template<class Impl>
 void
-DefaultDecode<Impl>::setActiveThreads(list<unsigned> *at_ptr)
+DefaultDecode<Impl>::setActiveThreads(std::list<ThreadID> *at_ptr)
 {
-    DPRINTF(Decode, "Setting active threads list pointer.\n");
     activeThreads = at_ptr;
 }
 
 template <class Impl>
-bool
-DefaultDecode<Impl>::drain()
+void
+DefaultDecode<Impl>::drainSanityCheck() const
 {
-    // Decode is done draining at any time.
-    cpu->signalDrained();
-    return true;
+    for (ThreadID tid = 0; tid < numThreads; ++tid) {
+        assert(insts[tid].empty());
+        assert(skidBuffer[tid].empty());
+    }
 }
 
 template <class Impl>
-void
-DefaultDecode<Impl>::takeOverFrom()
+bool
+DefaultDecode<Impl>::isDrained() const
 {
-    _status = Inactive;
-
-    // Be sure to reset state and clear out any old instructions.
-    for (int i = 0; i < numThreads; ++i) {
-        decodeStatus[i] = Idle;
-
-        stalls[i].rename = false;
-        stalls[i].iew = false;
-        stalls[i].commit = false;
-        while (!insts[i].empty())
-            insts[i].pop();
-        while (!skidBuffer[i].empty())
-            skidBuffer[i].pop();
-        branchCount[i] = 0;
+    for (ThreadID tid = 0; tid < numThreads; ++tid) {
+        if (!insts[tid].empty() || !skidBuffer[tid].empty() ||
+                (decodeStatus[tid] != Running && decodeStatus[tid] != Idle))
+            return false;
     }
-    wroteToTimeBuffer = false;
+    return true;
 }
 
 template<class Impl>
 bool
-DefaultDecode<Impl>::checkStall(unsigned tid) const
+DefaultDecode<Impl>::checkStall(ThreadID tid) const
 {
     bool ret_val = false;
 
     if (stalls[tid].rename) {
         DPRINTF(Decode,"[tid:%i]: Stall fom Rename stage detected.\n", tid);
         ret_val = true;
-    } else if (stalls[tid].iew) {
-        DPRINTF(Decode,"[tid:%i]: Stall fom IEW stage detected.\n", tid);
-        ret_val = true;
-    } else if (stalls[tid].commit) {
-        DPRINTF(Decode,"[tid:%i]: Stall fom Commit stage detected.\n", tid);
-        ret_val = true;
     }
 
     return ret_val;
@@ -224,7 +239,7 @@ DefaultDecode<Impl>::fetchInstsValid()
 
 template<class Impl>
 bool
-DefaultDecode<Impl>::block(unsigned tid)
+DefaultDecode<Impl>::block(ThreadID tid)
 {
     DPRINTF(Decode, "[tid:%u]: Blocking.\n", tid);
 
@@ -239,7 +254,9 @@ DefaultDecode<Impl>::block(unsigned tid)
         // Set the status to Blocked.
         decodeStatus[tid] = Blocked;
 
-        if (decodeStatus[tid] != Unblocking) {
+        if (toFetch->decodeUnblock[tid]) {
+            toFetch->decodeUnblock[tid] = false;
+        } else {
             toFetch->decodeBlock[tid] = true;
             wroteToTimeBuffer = true;
         }
@@ -252,7 +269,7 @@ DefaultDecode<Impl>::block(unsigned tid)
 
 template<class Impl>
 bool
-DefaultDecode<Impl>::unblock(unsigned tid)
+DefaultDecode<Impl>::unblock(ThreadID tid)
 {
     // Decode is done unblocking only if the skid buffer is empty.
     if (skidBuffer[tid].empty()) {
@@ -271,19 +288,25 @@ DefaultDecode<Impl>::unblock(unsigned tid)
 
 template<class Impl>
 void
-DefaultDecode<Impl>::squash(DynInstPtr &inst, unsigned tid)
+DefaultDecode<Impl>::squash(const DynInstPtr &inst, ThreadID tid)
 {
-    DPRINTF(Decode, "[tid:%i]: Squashing due to incorrect branch prediction "
-            "detected at decode.\n", tid);
+    DPRINTF(Decode, "[tid:%i]: [sn:%i] Squashing due to incorrect branch "
+            "prediction detected at decode.\n", tid, inst->seqNum);
 
     // Send back mispredict information.
     toFetch->decodeInfo[tid].branchMispredict = true;
-    toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum;
     toFetch->decodeInfo[tid].predIncorrect = true;
+    toFetch->decodeInfo[tid].mispredictInst = inst;
     toFetch->decodeInfo[tid].squash = true;
+    toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum;
     toFetch->decodeInfo[tid].nextPC = inst->branchTarget();
-    toFetch->decodeInfo[tid].branchTaken =
-        inst->readNextPC() != (inst->readPC() + sizeof(TheISA::MachInst));
+    toFetch->decodeInfo[tid].branchTaken = inst->pcState().branching();
+    toFetch->decodeInfo[tid].squashInst = inst;
+    if (toFetch->decodeInfo[tid].mispredictInst->isUncondCtrl()) {
+            toFetch->decodeInfo[tid].branchTaken = true;
+    }
+
+    InstSeqNum squash_seq_num = inst->seqNum;
 
     // Might have to tell fetch to unblock.
     if (decodeStatus[tid] == Blocked ||
@@ -296,7 +319,7 @@ DefaultDecode<Impl>::squash(DynInstPtr &inst, unsigned tid)
 
     for (int i=0; i<fromFetch->size; i++) {
         if (fromFetch->insts[i]->threadNumber == tid &&
-            fromFetch->insts[i]->seqNum > inst->seqNum) {
+            fromFetch->insts[i]->seqNum > squash_seq_num) {
             fromFetch->insts[i]->setSquashed();
         }
     }
@@ -312,30 +335,29 @@ DefaultDecode<Impl>::squash(DynInstPtr &inst, unsigned tid)
     }
 
     // Squash instructions up until this one
-    cpu->removeInstsUntil(inst->seqNum, tid);
+    cpu->removeInstsUntil(squash_seq_num, tid);
 }
 
 template<class Impl>
 unsigned
-DefaultDecode<Impl>::squash(unsigned tid)
+DefaultDecode<Impl>::squash(ThreadID tid)
 {
     DPRINTF(Decode, "[tid:%i]: Squashing.\n",tid);
 
     if (decodeStatus[tid] == Blocked ||
         decodeStatus[tid] == Unblocking) {
-#if !FULL_SYSTEM
-        // In syscall emulation, we can have both a block and a squash due
-        // to a syscall in the same cycle.  This would cause both signals to
-        // be high.  This shouldn't happen in full system.
-        // @todo: Determine if this still happens.
-        if (toFetch->decodeBlock[tid]) {
-            toFetch->decodeBlock[tid] = 0;
-        } else {
+        if (FullSystem) {
             toFetch->decodeUnblock[tid] = 1;
+        } else {
+            // In syscall emulation, we can have both a block and a squash due
+            // to a syscall in the same cycle.  This would cause both signals
+            // to be high.  This shouldn't happen in full system.
+            // @todo: Determine if this still happens.
+            if (toFetch->decodeBlock[tid])
+                toFetch->decodeBlock[tid] = 0;
+            else
+                toFetch->decodeUnblock[tid] = 1;
         }
-#else
-        toFetch->decodeUnblock[tid] = 1;
-#endif
     }
 
     // Set status to squashing.
@@ -366,7 +388,7 @@ DefaultDecode<Impl>::squash(unsigned tid)
 
 template<class Impl>
 void
-DefaultDecode<Impl>::skidInsert(unsigned tid)
+DefaultDecode<Impl>::skidInsert(ThreadID tid)
 {
     DynInstPtr inst = NULL;
 
@@ -377,10 +399,10 @@ DefaultDecode<Impl>::skidInsert(unsigned tid)
 
         assert(tid == inst->threadNumber);
 
-        DPRINTF(Decode,"Inserting [sn:%lli] PC:%#x into decode skidBuffer %i\n",
-                inst->seqNum, inst->readPC(), inst->threadNumber);
-
         skidBuffer[tid].push(inst);
+
+        DPRINTF(Decode,"Inserting [tid:%d][sn:%lli] PC: %s into decode skidBuffer %i\n",
+                inst->threadNumber, inst->seqNum, inst->pcState(), skidBuffer[tid].size());
     }
 
     // @todo: Eventually need to enforce this by not letting a thread
@@ -392,10 +414,12 @@ template<class Impl>
 bool
 DefaultDecode<Impl>::skidsEmpty()
 {
-    list<unsigned>::iterator threads = (*activeThreads).begin();
+    list<ThreadID>::iterator threads = activeThreads->begin();
+    list<ThreadID>::iterator end = activeThreads->end();
 
-    while (threads != (*activeThreads).end()) {
-        if (!skidBuffer[*threads++].empty())
+    while (threads != end) {
+        ThreadID tid = *threads++;
+        if (!skidBuffer[tid].empty())
             return false;
     }
 
@@ -408,12 +432,11 @@ DefaultDecode<Impl>::updateStatus()
 {
     bool any_unblocking = false;
 
-    list<unsigned>::iterator threads = (*activeThreads).begin();
-
-    threads = (*activeThreads).begin();
+    list<ThreadID>::iterator threads = activeThreads->begin();
+    list<ThreadID>::iterator end = activeThreads->end();
 
-    while (threads != (*activeThreads).end()) {
-        unsigned tid = *threads++;
+    while (threads != end) {
+        ThreadID tid = *threads++;
 
         if (decodeStatus[tid] == Unblocking) {
             any_unblocking = true;
@@ -447,10 +470,6 @@ void
 DefaultDecode<Impl>::sortInsts()
 {
     int insts_from_fetch = fromFetch->size;
-#ifdef DEBUG
-    for (int i=0; i < numThreads; i++)
-        assert(insts[i].empty());
-#endif
     for (int i = 0; i < insts_from_fetch; ++i) {
         insts[fromFetch->insts[i]->threadNumber].push(fromFetch->insts[i]);
     }
@@ -458,7 +477,7 @@ DefaultDecode<Impl>::sortInsts()
 
 template<class Impl>
 void
-DefaultDecode<Impl>::readStallSignals(unsigned tid)
+DefaultDecode<Impl>::readStallSignals(ThreadID tid)
 {
     if (fromRename->renameBlock[tid]) {
         stalls[tid].rename = true;
@@ -468,29 +487,11 @@ DefaultDecode<Impl>::readStallSignals(unsigned tid)
         assert(stalls[tid].rename);
         stalls[tid].rename = false;
     }
-
-    if (fromIEW->iewBlock[tid]) {
-        stalls[tid].iew = true;
-    }
-
-    if (fromIEW->iewUnblock[tid]) {
-        assert(stalls[tid].iew);
-        stalls[tid].iew = false;
-    }
-
-    if (fromCommit->commitBlock[tid]) {
-        stalls[tid].commit = true;
-    }
-
-    if (fromCommit->commitUnblock[tid]) {
-        assert(stalls[tid].commit);
-        stalls[tid].commit = false;
-    }
 }
 
 template <class Impl>
 bool
-DefaultDecode<Impl>::checkSignalsAndUpdate(unsigned tid)
+DefaultDecode<Impl>::checkSignalsAndUpdate(ThreadID tid)
 {
     // Check if there's a squash signal, squash if there is.
     // Check stall signals, block if necessary.
@@ -514,16 +515,6 @@ DefaultDecode<Impl>::checkSignalsAndUpdate(unsigned tid)
         return true;
     }
 
-    // Check ROB squash signals from commit.
-    if (fromCommit->commitInfo[tid].robSquashing) {
-        DPRINTF(Decode, "[tid:%u]: ROB is still squashing.\n", tid);
-
-        // Continue to squash.
-        decodeStatus[tid] = Squashing;
-
-        return true;
-    }
-
     if (checkStall(tid)) {
         return block(tid);
     }
@@ -565,13 +556,14 @@ DefaultDecode<Impl>::tick()
 
     toRenameIndex = 0;
 
-    list<unsigned>::iterator threads = (*activeThreads).begin();
+    list<ThreadID>::iterator threads = activeThreads->begin();
+    list<ThreadID>::iterator end = activeThreads->end();
 
     sortInsts();
 
     //Check stall and squash signals.
-    while (threads != (*activeThreads).end()) {
-    unsigned tid = *threads++;
+    while (threads != end) {
+        ThreadID tid = *threads++;
 
         DPRINTF(Decode,"Processing [tid:%i]\n",tid);
         status_change =  checkSignalsAndUpdate(tid) || status_change;
@@ -592,7 +584,7 @@ DefaultDecode<Impl>::tick()
 
 template<class Impl>
 void
-DefaultDecode<Impl>::decode(bool &status_change, unsigned tid)
+DefaultDecode<Impl>::decode(bool &status_change, ThreadID tid)
 {
     // If status is Running or idle,
     //     call decodeInsts()
@@ -611,7 +603,7 @@ DefaultDecode<Impl>::decode(bool &status_change, unsigned tid)
     // will allow, as long as it is not currently blocked.
     if (decodeStatus[tid] == Running ||
         decodeStatus[tid] == Idle) {
-        DPRINTF(Decode, "[tid:%u] Not blocked, so attempting to run "
+        DPRINTF(Decode, "[tid:%u]: Not blocked, so attempting to run "
                 "stage.\n",tid);
 
         decodeInsts(tid);
@@ -637,7 +629,7 @@ DefaultDecode<Impl>::decode(bool &status_change, unsigned tid)
 
 template <class Impl>
 void
-DefaultDecode<Impl>::decodeInsts(unsigned tid)
+DefaultDecode<Impl>::decodeInsts(ThreadID tid)
 {
     // Instructions can come either from the skid buffer or the list of
     // instructions coming from fetch, depending on decode's status.
@@ -658,8 +650,6 @@ DefaultDecode<Impl>::decodeInsts(unsigned tid)
         ++decodeRunCycles;
     }
 
-    DynInstPtr inst;
-
     std::queue<DynInstPtr>
         &insts_to_decode = decodeStatus[tid] == Unblocking ?
         skidBuffer[tid] : insts[tid];
@@ -669,18 +659,17 @@ DefaultDecode<Impl>::decodeInsts(unsigned tid)
     while (insts_available > 0 && toRenameIndex < decodeWidth) {
         assert(!insts_to_decode.empty());
 
-        inst = insts_to_decode.front();
+        DynInstPtr inst = std::move(insts_to_decode.front());
 
         insts_to_decode.pop();
 
         DPRINTF(Decode, "[tid:%u]: Processing instruction [sn:%lli] with "
-                "PC %#x\n",
-                tid, inst->seqNum, inst->readPC());
+                "PC %s\n", tid, inst->seqNum, inst->pcState());
 
         if (inst->isSquashed()) {
-            DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %#x is "
+            DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %s is "
                     "squashed, skipping.\n",
-                    tid, inst->seqNum, inst->readPC());
+                    tid, inst->seqNum, inst->pcState());
 
             ++decodeSquashedInsts;
 
@@ -707,9 +696,15 @@ DefaultDecode<Impl>::decodeInsts(unsigned tid)
         ++decodeDecodedInsts;
         --insts_available;
 
+#if TRACING_ON
+        if (DTRACE(O3PipeView)) {
+            inst->decodeTick = curTick() - inst->fetchTick;
+        }
+#endif
+
         // Ensure that if it was predicted as a branch, it really is a
         // branch.
-        if (inst->predTaken() && !inst->isControl()) {
+        if (inst->readPredTaken() && !inst->isControl()) {
             panic("Instruction predicted as a branch!");
 
             ++decodeControlMispred;
@@ -722,17 +717,25 @@ DefaultDecode<Impl>::decodeInsts(unsigned tid)
         }
 
         // Go ahead and compute any PC-relative branches.
-        if (inst->isDirectCtrl() && inst->isUncondCtrl()) {
+        // This includes direct unconditional control and
+        // direct conditional control that is predicted taken.
+        if (inst->isDirectCtrl() &&
+           (inst->isUncondCtrl() || inst->readPredTaken()))
+        {
             ++decodeBranchResolved;
 
-            if (inst->branchTarget() != inst->readPredTarg()) {
+            if (!(inst->branchTarget() == inst->readPredTarg())) {
                 ++decodeBranchMispred;
 
                 // Might want to set some sort of boolean and just do
                 // a check at the end
                 squash(inst, inst->threadNumber);
-                inst->setPredTarg(inst->branchTarget());
+                TheISA::PCState target = inst->branchTarget();
 
+                DPRINTF(Decode, "[sn:%i]: Updating predictions: PredPC: %s\n",
+                        inst->seqNum, target);
+                //The micro pc after an instruction level branch should be 0
+                inst->setPredTarg(target);
                 break;
             }
         }
@@ -750,3 +753,5 @@ DefaultDecode<Impl>::decodeInsts(unsigned tid)
         wroteToTimeBuffer = true;
     }
 }
+
+#endif//__CPU_O3_DECODE_IMPL_HH__