cpu: Update DRAM traffic gen
[gem5.git] / src / cpu / inorder / resources / branch_predictor.cc
index 905de07943c89e5c750abbd4cdd413092de5b02c..50d3847baf040f71ee0fc6ec54d82c2cc47ec2e9 100644 (file)
  *
  */
 
+#include "config/the_isa.hh"
 #include "cpu/inorder/resources/branch_predictor.hh"
+#include "debug/InOrderBPred.hh"
+#include "debug/InOrderStage.hh"
+#include "debug/Resource.hh"
 
 using namespace std;
 using namespace TheISA;
 using namespace ThePipeline;
 
-BranchPredictor::BranchPredictor(std::string res_name, int res_id, int res_width,
-                       int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params)
+BranchPredictor::BranchPredictor(std::string res_name, int res_id,
+                                 int res_width, Cycles res_latency,
+                                 InOrderCPU *_cpu,
+                                 ThePipeline::Params *params)
     : Resource(res_name, res_id, res_width, res_latency, _cpu),
-      branchPred(params)
+      branchPred(params->branchPred)
 {
     instSize = sizeof(MachInst);
 }
@@ -60,57 +66,65 @@ BranchPredictor::regStats()
 void
 BranchPredictor::execute(int slot_num)
 {
-    // After this is working, change this to a reinterpret cast
-    // for performance considerations
-    ResourceRequest* bpred_req = reqMap[slot_num];
-
+    ResourceRequest* bpred_req = reqs[slot_num];
     DynInstPtr inst = bpred_req->inst;
-    ThreadID tid = inst->readTid();
-    int seq_num = inst->seqNum;
-    //int stage_num = bpred_req->getStageNum();
+    if (inst->fault != NoFault) {
+        DPRINTF(InOrderBPred,
+                "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to "
+                "next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(),
+                inst->pcState());
+        bpred_req->done();
+        return;
+    }
 
-    bpred_req->fault = NoFault;
+    if (!inst->isControl()) {
+        DPRINTF(Resource, "Ignoring %s, not a control inst.\n",
+                inst->instName());
+        bpred_req->done();
+        return;
+    }
 
+    ThreadID tid = inst->readTid();
+    InstSeqNum seq_num = inst->seqNum;
     switch (bpred_req->cmd)
     {
       case PredictBranch:
         {
-            Addr pred_PC = inst->readNextPC();
-
-            if (inst->isControl()) {
-                // If not, the pred_PC be updated to pc+8
-                // If predicted, the pred_PC will be updated to new target value
-                bool predict_taken = branchPred.predict(inst, pred_PC, tid);
-
-                if (predict_taken) {
-                    DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Branch predicted true.\n",
-                            tid, seq_num);
-
-                    inst->setPredTarg(pred_PC);
-
-                    predictedTaken++;
-                } else {
-                    DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Branch predicted false.\n",
-                            tid, seq_num);
-
-                    if (inst->isCondDelaySlot())
-                    {
-                        inst->setPredTarg(inst->readPC() + (2 * instSize));
+            if (inst->seqNum > cpu->squashSeqNum[tid] &&
+                curTick() == cpu->lastSquashCycle[tid]) {
+                DPRINTF(InOrderStage, "[tid:%u]: [sn:%i]: squashed, "
+                        "skipping prediction \n", tid, inst->seqNum);
+            } else {
+                TheISA::PCState instPC = inst->pcState();
+                TheISA::PCState pred_PC = inst->pcState();
+                TheISA::advancePC(pred_PC, inst->staticInst);
+
+                if (inst->isControl()) {
+                    // If not, the pred_PC be updated to pc+8
+                    // If predicted, the pred_PC will be updated to new target
+                    // value
+                    bool predict_taken = branchPred->predictInOrder(
+                                            inst->staticInst, inst->seqNum,
+                                            inst->asid, instPC, pred_PC, tid);
+
+                    if (predict_taken) {
+                        DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Branch "
+                                "predicted true.\n", tid, seq_num);
+                        predictedTaken++;
                     } else {
-                        inst->setPredTarg(pred_PC);
+                        DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Branch "
+                                "predicted false.\n", tid, seq_num);
+                        predictedNotTaken++;
                     }
 
-                    predictedNotTaken++;
+                    inst->setBranchPred(predict_taken);
                 }
 
-                inst->setBranchPred(predict_taken);
-
-                DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Predicted PC is %08p.\n",
-                            tid, seq_num, pred_PC);
-
-            } else {
-                DPRINTF(InOrderBPred, "[tid:%i]: Ignoring [sn:%i] because this isn't "
-                        "a control instruction.\n", tid, seq_num);
+                //@todo: Check to see how hw_rei is handled here...how does
+                //PC,NPC get updated to compare mispredict against???
+                inst->setPredTarg(pred_PC);
+                DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: %s Predicted PC is "
+                        "%s.\n", tid, seq_num, inst->instName(), pred_PC);
             }
 
             bpred_req->done();
@@ -119,11 +133,19 @@ BranchPredictor::execute(int slot_num)
 
       case UpdatePredictor:
         {
-            DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Updating Branch Predictor.\n",
-                    tid, seq_num);
+            if (inst->seqNum > cpu->squashSeqNum[tid] &&
+                curTick() == cpu->lastSquashCycle[tid]) {
+                DPRINTF(InOrderStage, "[tid:%u]: [sn:%i]: squashed, "
+                        "skipping branch predictor update \n",
+                        tid, inst->seqNum);
+            } else {
+                DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Updating "
+                        "Branch Predictor.\n",
+                        tid, seq_num);
 
 
-            branchPred.update(seq_num, tid);
+                branchPred->update(seq_num, tid);
+            }
 
             bpred_req->done();
         }
@@ -138,12 +160,22 @@ void
 BranchPredictor::squash(DynInstPtr inst, int squash_stage,
                         InstSeqNum squash_seq_num, ThreadID tid)
 {
-    DPRINTF(InOrderBPred, "Squashing...\n");
-    branchPred.squash(squash_seq_num, tid);
+    InstSeqNum bpred_squash_num = inst->seqNum;
+    DPRINTF(InOrderBPred, "[tid:%i][sn:%i] Squashing...\n", tid,
+            bpred_squash_num);
+
+    // update due to branch resolution
+    if (squash_stage >= ThePipeline::BackEndStartStage) {
+        branchPred->squash(bpred_squash_num, inst->pcState(),
+                           inst->pcState().branching(), tid);
+    } else {
+    // update due to predicted taken branch
+        branchPred->squash(bpred_squash_num, tid);
+    }
 }
 
 void
 BranchPredictor::instGraduated(InstSeqNum seq_num, ThreadID tid)
 {
-    branchPred.update(seq_num, tid);
+    branchPred->update(seq_num, tid);
 }