O3: Remove some asserts that no longer seem to be valid.
[gem5.git] / src / cpu / o3 / decode_impl.hh
index 71637883bc1e9d25b3cb884045531958545e2f31..a523a8b45129801f2c3455e03c463e7b47d247db 100644 (file)
  * Authors: Kevin Lim
  */
 
+#include "arch/types.hh"
+#include "base/trace.hh"
+#include "config/full_system.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 "params/DerivO3CPU.hh"
 
 using namespace std;
 
 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)
 {
     _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;
+        stalls[tid].iew = false;
+        stalls[tid].commit = false;
     }
 
     // @todo: Make into a parameter
@@ -68,61 +77,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 +138,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 +148,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,18 +156,18 @@ 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>
-void
+bool
 DefaultDecode<Impl>::drain()
 {
     // Decode is done draining at any time.
     cpu->signalDrained();
+    return true;
 }
 
 template <class Impl>
@@ -179,24 +177,24 @@ DefaultDecode<Impl>::takeOverFrom()
     _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) {
+        decodeStatus[tid] = Idle;
+
+        stalls[tid].rename = false;
+        stalls[tid].iew = false;
+        stalls[tid].commit = false;
+        while (!insts[tid].empty())
+            insts[tid].pop();
+        while (!skidBuffer[tid].empty())
+            skidBuffer[tid].pop();
+        branchCount[tid] = 0;
     }
     wroteToTimeBuffer = false;
 }
 
 template<class Impl>
 bool
-DefaultDecode<Impl>::checkStall(unsigned tid) const
+DefaultDecode<Impl>::checkStall(ThreadID tid) const
 {
     bool ret_val = false;
 
@@ -223,7 +221,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);
 
@@ -251,7 +249,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()) {
@@ -270,19 +268,21 @@ DefaultDecode<Impl>::unblock(unsigned tid)
 
 template<class Impl>
 void
-DefaultDecode<Impl>::squash(DynInstPtr &inst, unsigned tid)
+DefaultDecode<Impl>::squash(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].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;
+
+    InstSeqNum squash_seq_num = inst->seqNum;
 
     // Might have to tell fetch to unblock.
     if (decodeStatus[tid] == Blocked ||
@@ -295,7 +295,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();
         }
     }
@@ -311,12 +311,12 @@ 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);
 
@@ -365,7 +365,7 @@ DefaultDecode<Impl>::squash(unsigned tid)
 
 template<class Impl>
 void
-DefaultDecode<Impl>::skidInsert(unsigned tid)
+DefaultDecode<Impl>::skidInsert(ThreadID tid)
 {
     DynInstPtr inst = NULL;
 
@@ -376,8 +376,8 @@ 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);
+        DPRINTF(Decode,"Inserting [sn:%lli] PC: %s into decode skidBuffer %i\n",
+                inst->seqNum, inst->pcState(), inst->threadNumber);
 
         skidBuffer[tid].push(inst);
     }
@@ -391,10 +391,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;
     }
 
@@ -407,12 +409,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;
@@ -446,10 +447,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]);
     }
@@ -457,7 +454,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;
@@ -489,7 +486,7 @@ DefaultDecode<Impl>::readStallSignals(unsigned tid)
 
 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.
@@ -564,13 +561,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;
@@ -591,7 +589,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()
@@ -610,7 +608,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);
@@ -636,7 +634,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.
@@ -673,13 +671,12 @@ DefaultDecode<Impl>::decodeInsts(unsigned tid)
         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;
 
@@ -706,9 +703,13 @@ DefaultDecode<Impl>::decodeInsts(unsigned tid)
         ++decodeDecodedInsts;
         --insts_available;
 
+#if TRACING_ON
+        inst->decodeTick = curTick();
+#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;
@@ -724,14 +725,18 @@ DefaultDecode<Impl>::decodeInsts(unsigned tid)
         if (inst->isDirectCtrl() && inst->isUncondCtrl()) {
             ++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;
             }
         }