merge whitespace changes
[gem5.git] / src / cpu / o3 / iew_impl.hh
index e9b24a6d43840f16f1c315fdc126b68a412bc754..399c449092d708403adc5d4e3bffcfa141e931d0 100644 (file)
 #include "cpu/o3/iew.hh"
 
 template<class Impl>
-DefaultIEW<Impl>::DefaultIEW(Params *params)
+DefaultIEW<Impl>::DefaultIEW(O3CPU *_cpu, Params *params)
     : issueToExecQueue(params->backComSize, params->forwardComSize),
-      instQueue(params),
-      ldstQueue(params),
+      cpu(_cpu),
+      instQueue(_cpu, this, params),
+      ldstQueue(_cpu, this, params),
       fuPool(params->fuPool),
       commitToIEWDelay(params->commitToIEWDelay),
       renameToIEWDelay(params->renameToIEWDelay),
@@ -64,14 +65,10 @@ DefaultIEW<Impl>::DefaultIEW(Params *params)
     // Instruction queue needs the queue between issue and execute.
     instQueue.setIssueToExecuteQueue(&issueToExecQueue);
 
-    instQueue.setIEW(this);
-    ldstQueue.setIEW(this);
-
     for (int i=0; i < numThreads; i++) {
         dispatchStatus[i] = Running;
         stalls[i].commit = false;
         fetchRedirect[i] = false;
-        bdelayDoneSeqNum[i] = 0;
     }
 
     wbMax = wbWidth * params->wbDepth;
@@ -162,17 +159,17 @@ DefaultIEW<Impl>::regStats()
     branchMispredicts = predictedTakenIncorrect + predictedNotTakenIncorrect;
 
     iewExecutedInsts
-        .name(name() + ".EXEC:insts")
+        .name(name() + ".iewExecutedInsts")
         .desc("Number of executed instructions");
 
     iewExecLoadInsts
         .init(cpu->number_of_threads)
-        .name(name() + ".EXEC:loads")
+        .name(name() + ".iewExecLoadInsts")
         .desc("Number of load instructions executed")
         .flags(total);
 
     iewExecSquashedInsts
-        .name(name() + ".EXEC:squashedInsts")
+        .name(name() + ".iewExecSquashedInsts")
         .desc("Number of squashed instructions skipped in execute");
 
     iewExecutedSwp
@@ -276,17 +273,6 @@ DefaultIEW<Impl>::initStage()
         toRename->iewInfo[tid].freeLSQEntries =
             ldstQueue.numFreeEntries(tid);
     }
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::setCPU(O3CPU *cpu_ptr)
-{
-    DPRINTF(IEW, "Setting CPU pointer.\n");
-    cpu = cpu_ptr;
-
-    instQueue.setCPU(cpu_ptr);
-    ldstQueue.setCPU(cpu_ptr);
 
     cpu->activateStage(O3CPU::IEWIdx);
 }
@@ -295,7 +281,6 @@ template<class Impl>
 void
 DefaultIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
 {
-    DPRINTF(IEW, "Setting time buffer pointer.\n");
     timeBuffer = tb_ptr;
 
     // Setup wire to read information from time buffer, from commit.
@@ -314,7 +299,6 @@ template<class Impl>
 void
 DefaultIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
 {
-    DPRINTF(IEW, "Setting rename queue pointer.\n");
     renameQueue = rq_ptr;
 
     // Setup wire to read information from rename queue.
@@ -325,7 +309,6 @@ template<class Impl>
 void
 DefaultIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
 {
-    DPRINTF(IEW, "Setting IEW queue pointer.\n");
     iewQueue = iq_ptr;
 
     // Setup wire to write instructions to commit.
@@ -336,7 +319,6 @@ template<class Impl>
 void
 DefaultIEW<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
 {
-    DPRINTF(IEW, "Setting active threads list pointer.\n");
     activeThreads = at_ptr;
 
     ldstQueue.setActiveThreads(at_ptr);
@@ -347,7 +329,6 @@ template<class Impl>
 void
 DefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr)
 {
-    DPRINTF(IEW, "Setting scoreboard pointer.\n");
     scoreboard = sb_ptr;
 }
 
@@ -372,6 +353,8 @@ DefaultIEW<Impl>::switchOut()
 {
     // Clear any state.
     switchedOut = true;
+    assert(insts[0].empty());
+    assert(skidBuffer[0].empty());
 
     instQueue.switchOut();
     ldstQueue.switchOut();
@@ -410,7 +393,6 @@ DefaultIEW<Impl>::takeOverFrom()
 
     updateLSQNextCycle = false;
 
-    // @todo: Fix hardcoded number
     for (int i = 0; i < issueToExecQueue.getSize(); ++i) {
         issueToExecQueue.advance();
     }
@@ -427,31 +409,14 @@ DefaultIEW<Impl>::squash(unsigned tid)
     instQueue.squash(tid);
 
     // Tell the LDSTQ to start squashing.
-#if ISA_HAS_DELAY_SLOT
-    ldstQueue.squash(fromCommit->commitInfo[tid].bdelayDoneSeqNum, tid);
-#else
     ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum, tid);
-#endif
     updatedQueues = true;
 
     // Clear the skid buffer in case it has any data in it.
     DPRINTF(IEW, "[tid:%i]: Removing skidbuffer instructions until [sn:%i].\n",
-            tid, fromCommit->commitInfo[tid].bdelayDoneSeqNum);
+            tid, fromCommit->commitInfo[tid].doneSeqNum);
 
     while (!skidBuffer[tid].empty()) {
-#if ISA_HAS_DELAY_SLOT
-        if (skidBuffer[tid].front()->seqNum <=
-            fromCommit->commitInfo[tid].bdelayDoneSeqNum) {
-            DPRINTF(IEW, "[tid:%i]: Cannot remove skidbuffer instructions "
-                    "that occur before delay slot [sn:%i].\n",
-                    fromCommit->commitInfo[tid].bdelayDoneSeqNum,
-                    tid);
-            break;
-        } else {
-            DPRINTF(IEW, "[tid:%i]: Removing instruction [sn:%i] from "
-                    "skidBuffer.\n", tid, skidBuffer[tid].front()->seqNum);
-        }
-#endif
         if (skidBuffer[tid].front()->isLoad() ||
             skidBuffer[tid].front()->isStore() ) {
             toRename->iewInfo[tid].dispatchedToLSQ++;
@@ -462,8 +427,6 @@ DefaultIEW<Impl>::squash(unsigned tid)
         skidBuffer[tid].pop();
     }
 
-    bdelayDoneSeqNum[tid] = fromCommit->commitInfo[tid].bdelayDoneSeqNum;
-
     emptyRenameInsts(tid);
 }
 
@@ -480,23 +443,18 @@ DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, unsigned tid)
     toCommit->branchMispredict[tid] = true;
 
 #if ISA_HAS_DELAY_SLOT
-    bool branch_taken = inst->readNextNPC() !=
-        (inst->readNextPC() + sizeof(TheISA::MachInst));
-
-    toCommit->branchTaken[tid] = branch_taken;
-
-    toCommit->condDelaySlotBranch[tid] = inst->isCondDelaySlot();
-
-    if (inst->isCondDelaySlot() && branch_taken) {
-        toCommit->nextPC[tid] = inst->readNextPC();
-    } else {
-        toCommit->nextPC[tid] = inst->readNextNPC();
-    }
+    int instSize = sizeof(TheISA::MachInst);
+    toCommit->branchTaken[tid] =
+        !(inst->readNextPC() + instSize == inst->readNextNPC() &&
+          (inst->readNextPC() == inst->readPC() + instSize ||
+           inst->readNextPC() == inst->readPC() + 2 * instSize));
 #else
     toCommit->branchTaken[tid] = inst->readNextPC() !=
         (inst->readPC() + sizeof(TheISA::MachInst));
-    toCommit->nextPC[tid] = inst->readNextPC();
 #endif
+    toCommit->nextPC[tid] = inst->readNextPC();
+    toCommit->nextNPC[tid] = inst->readNextNPC();
+    toCommit->nextMicroPC[tid] = inst->readNextMicroPC();
 
     toCommit->includeSquashInst[tid] = false;
 
@@ -513,6 +471,8 @@ DefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, unsigned tid)
     toCommit->squash[tid] = true;
     toCommit->squashedSeqNum[tid] = inst->seqNum;
     toCommit->nextPC[tid] = inst->readNextPC();
+    toCommit->nextNPC[tid] = inst->readNextNPC();
+    toCommit->branchMispredict[tid] = false;
 
     toCommit->includeSquashInst[tid] = false;
 
@@ -529,6 +489,8 @@ DefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, unsigned tid)
     toCommit->squash[tid] = true;
     toCommit->squashedSeqNum[tid] = inst->seqNum;
     toCommit->nextPC[tid] = inst->readPC();
+    toCommit->nextNPC[tid] = inst->readNextPC();
+    toCommit->branchMispredict[tid] = false;
 
     // Must include the broadcasted SN in the squash.
     toCommit->includeSquashInst[tid] = true;
@@ -599,6 +561,11 @@ template<class Impl>
 void
 DefaultIEW<Impl>::instToCommit(DynInstPtr &inst)
 {
+    // This function should not be called after writebackInsts in a
+    // single cycle.  That will cause problems with an instruction
+    // being added to the queue to commit without being processed by
+    // writebackInsts prior to being sent to commit.
+
     // First check the time slot that this instruction will write
     // to.  If there are free write ports at the time, then go ahead
     // and write the instruction to that time.  If there are not,
@@ -611,9 +578,11 @@ DefaultIEW<Impl>::instToCommit(DynInstPtr &inst)
             wbNumInst = 0;
         }
 
-        assert((wbCycle * wbWidth + wbNumInst) < wbMax);
+        assert((wbCycle * wbWidth + wbNumInst) <= wbMax);
     }
 
+    DPRINTF(IEW, "Current wb cycle: %i, width: %i, numInst: %i\nwbActual:%i\n",
+            wbCycle, wbWidth, wbNumInst, wbCycle * wbWidth + wbNumInst);
     // Add finished instruction to queue to commit.
     (*iewQueue)[wbCycle].insts[wbNumInst] = inst;
     (*iewQueue)[wbCycle].size++;
@@ -661,10 +630,12 @@ DefaultIEW<Impl>::skidCount()
 {
     int max=0;
 
-    std::list<unsigned>::iterator threads = (*activeThreads).begin();
+    std::list<unsigned>::iterator threads = activeThreads->begin();
+    std::list<unsigned>::iterator end = activeThreads->end();
 
-    while (threads != (*activeThreads).end()) {
-        unsigned thread_count = skidBuffer[*threads++].size();
+    while (threads != end) {
+        unsigned tid = *threads++;
+        unsigned thread_count = skidBuffer[tid].size();
         if (max < thread_count)
             max = thread_count;
     }
@@ -676,10 +647,13 @@ template<class Impl>
 bool
 DefaultIEW<Impl>::skidsEmpty()
 {
-    std::list<unsigned>::iterator threads = (*activeThreads).begin();
+    std::list<unsigned>::iterator threads = activeThreads->begin();
+    std::list<unsigned>::iterator end = activeThreads->end();
+
+    while (threads != end) {
+        unsigned tid = *threads++;
 
-    while (threads != (*activeThreads).end()) {
-        if (!skidBuffer[*threads++].empty())
+        if (!skidBuffer[tid].empty())
             return false;
     }
 
@@ -692,11 +666,10 @@ DefaultIEW<Impl>::updateStatus()
 {
     bool any_unblocking = false;
 
-    std::list<unsigned>::iterator threads = (*activeThreads).begin();
-
-    threads = (*activeThreads).begin();
+    std::list<unsigned>::iterator threads = activeThreads->begin();
+    std::list<unsigned>::iterator end = activeThreads->end();
 
-    while (threads != (*activeThreads).end()) {
+    while (threads != end) {
         unsigned tid = *threads++;
 
         if (dispatchStatus[tid] == Unblocking) {
@@ -860,10 +833,8 @@ DefaultIEW<Impl>::sortInsts()
 {
     int insts_from_rename = fromRename->size;
 #ifdef DEBUG
-#if !ISA_HAS_DELAY_SLOT
     for (int i = 0; i < numThreads; i++)
         assert(insts[i].empty());
-#endif
 #endif
     for (int i = 0; i < insts_from_rename; ++i) {
         insts[fromRename->insts[i]->threadNumber].push(fromRename->insts[i]);
@@ -874,21 +845,9 @@ template <class Impl>
 void
 DefaultIEW<Impl>::emptyRenameInsts(unsigned tid)
 {
-    DPRINTF(IEW, "[tid:%i]: Removing incoming rename instructions until "
-            "[sn:%i].\n", tid, bdelayDoneSeqNum[tid]);
+    DPRINTF(IEW, "[tid:%i]: Removing incoming rename instructions\n", tid);
 
     while (!insts[tid].empty()) {
-#if ISA_HAS_DELAY_SLOT
-        if (insts[tid].front()->seqNum <= bdelayDoneSeqNum[tid]) {
-            DPRINTF(IEW, "[tid:%i]: Done removing, cannot remove instruction"
-                    " that occurs at or before delay slot [sn:%i].\n",
-                    tid, bdelayDoneSeqNum[tid]);
-            break;
-        } else {
-            DPRINTF(IEW, "[tid:%i]: Removing incoming rename instruction "
-                    "[sn:%i].\n", tid, insts[tid].front()->seqNum);
-        }
-#endif
 
         if (insts[tid].front()->isLoad() ||
             insts[tid].front()->isStore() ) {
@@ -1110,25 +1069,10 @@ DefaultIEW<Impl>::dispatchInsts(unsigned tid)
             }
 
             toRename->iewInfo[tid].dispatchedToLSQ++;
-#if FULL_SYSTEM
         } else if (inst->isMemBarrier() || inst->isWriteBarrier()) {
             // Same as non-speculative stores.
             inst->setCanCommit();
             instQueue.insertBarrier(inst);
-            add_to_iq = false;
-#endif
-        } else if (inst->isNonSpeculative()) {
-            DPRINTF(IEW, "[tid:%i]: Issue: Nonspeculative instruction "
-                    "encountered, skipping.\n", tid);
-
-            // Same as non-speculative stores.
-            inst->setCanCommit();
-
-            // Specifically insert it as nonspeculative.
-            instQueue.insertNonSpec(inst);
-
-            ++iewDispNonSpecInsts;
-
             add_to_iq = false;
         } else if (inst->isNop()) {
             DPRINTF(IEW, "[tid:%i]: Issue: Nop instruction encountered, "
@@ -1157,6 +1101,20 @@ DefaultIEW<Impl>::dispatchInsts(unsigned tid)
         } else {
             add_to_iq = true;
         }
+        if (inst->isNonSpeculative()) {
+            DPRINTF(IEW, "[tid:%i]: Issue: Nonspeculative instruction "
+                    "encountered, skipping.\n", tid);
+
+            // Same as non-speculative stores.
+            inst->setCanCommit();
+
+            // Specifically insert it as nonspeculative.
+            instQueue.insertNonSpec(inst);
+
+            ++iewDispNonSpecInsts;
+
+            add_to_iq = false;
+        }
 
         // If the instruction queue is not full, then add the
         // instruction.
@@ -1216,9 +1174,10 @@ DefaultIEW<Impl>::executeInsts()
     wbNumInst = 0;
     wbCycle = 0;
 
-    std::list<unsigned>::iterator threads = (*activeThreads).begin();
+    std::list<unsigned>::iterator threads = activeThreads->begin();
+    std::list<unsigned>::iterator end = activeThreads->end();
 
-    while (threads != (*activeThreads).end()) {
+    while (threads != end) {
         unsigned tid = *threads++;
         fetchRedirect[tid] = false;
     }
@@ -1273,13 +1232,25 @@ DefaultIEW<Impl>::executeInsts()
                 // event adds the instruction to the queue to commit
                 fault = ldstQueue.executeLoad(inst);
             } else if (inst->isStore()) {
-                ldstQueue.executeStore(inst);
+                fault = ldstQueue.executeStore(inst);
 
                 // If the store had a fault then it may not have a mem req
-                if (inst->req && !(inst->req->getFlags() & LOCKED)) {
+                if (!inst->isStoreConditional() && fault == NoFault) {
                     inst->setExecuted();
 
                     instToCommit(inst);
+                } else if (fault != NoFault) {
+                    // If the instruction faulted, then we need to send it along to commit
+                    // without the instruction completing.
+                    DPRINTF(IEW, "Store has fault %s! [sn:%lli]\n",
+                            fault->name(), inst->seqNum);
+
+                    // Send this instruction to commit, also make sure iew stage
+                    // realizes there is activity.
+                    inst->setExecuted();
+
+                    instToCommit(inst);
+                    activityThisCycle();
                 }
 
                 // Store conditionals will mark themselves as
@@ -1309,30 +1280,28 @@ DefaultIEW<Impl>::executeInsts()
         // instruction first, so the branch resolution order will be correct.
         unsigned tid = inst->threadNumber;
 
-        if (!fetchRedirect[tid]) {
+        if (!fetchRedirect[tid] ||
+            toCommit->squashedSeqNum[tid] > inst->seqNum) {
 
             if (inst->mispredicted()) {
                 fetchRedirect[tid] = true;
 
                 DPRINTF(IEW, "Execute: Branch mispredict detected.\n");
-#if ISA_HAS_DELAY_SLOT
-                DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x.\n",
-                        inst->nextNPC);
-#else
-                DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x.\n",
-                        inst->nextPC);
-#endif
+                DPRINTF(IEW, "Predicted target was %#x, %#x.\n",
+                        inst->readPredPC(), inst->readPredNPC());
+                DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x,"
+                        " NPC: %#x.\n", inst->readNextPC(),
+                        inst->readNextNPC());
                 // If incorrect, then signal the ROB that it must be squashed.
                 squashDueToBranch(inst, tid);
 
-                if (inst->predTaken()) {
+                if (inst->readPredTaken()) {
                     predictedTakenIncorrect++;
                 } else {
                     predictedNotTakenIncorrect++;
                 }
             } else if (ldstQueue.violation(tid)) {
-                fetchRedirect[tid] = true;
-
+                assert(inst->isMemRef());
                 // If there was an ordering violation, then get the
                 // DynInst that caused the violation.  Note that this
                 // clears the violation signal.
@@ -1343,6 +1312,14 @@ DefaultIEW<Impl>::executeInsts()
                         "%#x, inst PC: %#x.  Addr is: %#x.\n",
                         violator->readPC(), inst->readPC(), inst->physEffAddr);
 
+                // Ensure the violating instruction is older than
+                // current squash
+/*                if (fetchRedirect[tid] &&
+                    violator->seqNum >= toCommit->squashedSeqNum[tid] + 1)
+                    continue;
+*/
+                fetchRedirect[tid] = true;
+
                 // Tell the instruction queue that a violation has occured.
                 instQueue.violation(inst, violator);
 
@@ -1360,6 +1337,33 @@ DefaultIEW<Impl>::executeInsts()
 
                 squashDueToMemBlocked(inst, tid);
             }
+        } else {
+            // Reset any state associated with redirects that will not
+            // be used.
+            if (ldstQueue.violation(tid)) {
+                assert(inst->isMemRef());
+
+                DynInstPtr violator = ldstQueue.getMemDepViolator(tid);
+
+                DPRINTF(IEW, "LDSTQ detected a violation.  Violator PC: "
+                        "%#x, inst PC: %#x.  Addr is: %#x.\n",
+                        violator->readPC(), inst->readPC(), inst->physEffAddr);
+                DPRINTF(IEW, "Violation will not be handled because "
+                        "already squashing\n");
+
+                ++memOrderViolationEvents;
+            }
+            if (ldstQueue.loadBlocked(tid) &&
+                !ldstQueue.isLoadBlockedHandled(tid)) {
+                DPRINTF(IEW, "Load operation couldn't execute because the "
+                        "memory system is blocked.  PC: %#x [sn:%lli]\n",
+                        inst->readPC(), inst->seqNum);
+                DPRINTF(IEW, "Blocked load will not be handled because "
+                        "already squashing\n");
+
+                ldstQueue.setLoadBlockedHandled(tid);
+            }
+
         }
     }
 
@@ -1389,7 +1393,7 @@ DefaultIEW<Impl>::writebackInsts()
     // mark scoreboard that this instruction is finally complete.
     // Either have IEW have direct access to scoreboard, or have this
     // as part of backwards communication.
-    for (int inst_num = 0; inst_num < issueWidth &&
+    for (int inst_num = 0; inst_num < wbWidth &&
              toCommit->insts[inst_num]; inst_num++) {
         DynInstPtr inst = toCommit->insts[inst_num];
         int tid = inst->threadNumber;
@@ -1404,7 +1408,7 @@ DefaultIEW<Impl>::writebackInsts()
         // E.g. Uncached loads have not actually executed when they
         // are first sent to commit.  Instead commit must tell the LSQ
         // when it's ready to execute the uncached load.
-        if (!inst->isSquashed() && inst->isExecuted()) {
+        if (!inst->isSquashed() && inst->isExecuted() && inst->getFault() == NoFault) {
             int dependents = instQueue.wakeDependents(inst);
 
             for (int i = 0; i < inst->numDestRegs(); i++) {
@@ -1440,11 +1444,12 @@ DefaultIEW<Impl>::tick()
     // Free function units marked as being freed this cycle.
     fuPool->processFreeUnits();
 
-    std::list<unsigned>::iterator threads = (*activeThreads).begin();
+    std::list<unsigned>::iterator threads = activeThreads->begin();
+    std::list<unsigned>::iterator end = activeThreads->end();
 
     // Check stall and squash signals, dispatch any instructions.
-    while (threads != (*activeThreads).end()) {
-           unsigned tid = *threads++;
+    while (threads != end) {
+        unsigned tid = *threads++;
 
         DPRINTF(IEW,"Issue: Processing [tid:%i]\n",tid);
 
@@ -1484,8 +1489,8 @@ DefaultIEW<Impl>::tick()
     // nonspeculative instruction.
     // This is pretty inefficient...
 
-    threads = (*activeThreads).begin();
-    while (threads != (*activeThreads).end()) {
+    threads = activeThreads->begin();
+    while (threads != end) {
         unsigned tid = (*threads++);
 
         DPRINTF(IEW,"Processing [tid:%i]\n",tid);
@@ -1508,6 +1513,7 @@ DefaultIEW<Impl>::tick()
             //DPRINTF(IEW,"NonspecInst from thread %i",tid);
             if (fromCommit->commitInfo[tid].uncached) {
                 instQueue.replayMemInst(fromCommit->commitInfo[tid].uncachedLoad);
+                fromCommit->commitInfo[tid].uncachedLoad->setAtCommit();
             } else {
                 instQueue.scheduleNonSpec(
                     fromCommit->commitInfo[tid].nonSpecSeqNum);