cpu: Update DRAM traffic gen
[gem5.git] / src / cpu / inorder / resources / branch_predictor.cc
index 8ca5a9718679280b71fb530b122de60e122f355e..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,
+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(this, params)
+      branchPred(params->branchPred)
 {
     instSize = sizeof(MachInst);
 }
@@ -57,20 +61,31 @@ BranchPredictor::regStats()
         .desc("Number of Branches Predicted As Not Taken (False).");
 
     Resource::regStats();
-   
-    branchPred.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;
+    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;
+    }
+
+    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:
@@ -80,20 +95,17 @@ BranchPredictor::execute(int slot_num)
                 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 ISA_HAS_DELAY_SLOT
-                // By default set target to NNPC (e.g. PC + 8)
-                // so that a not-taken branch will update
-                // correctly
-                pred_PC.advance();
-#endif
 
                 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);
+                    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 "
@@ -108,9 +120,11 @@ BranchPredictor::execute(int slot_num)
                     inst->setBranchPred(predict_taken);
                 }
 
+                //@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]: Predicted PC is "
-                        "%s.\n", tid, seq_num, pred_PC);
+                DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: %s Predicted PC is "
+                        "%s.\n", tid, seq_num, inst->instName(), pred_PC);
             }
 
             bpred_req->done();
@@ -130,7 +144,7 @@ BranchPredictor::execute(int slot_num)
                         tid, seq_num);
 
 
-                branchPred.update(seq_num, tid);
+                branchPred->update(seq_num, tid);
             }
 
             bpred_req->done();
@@ -146,24 +160,22 @@ void
 BranchPredictor::squash(DynInstPtr inst, int squash_stage,
                         InstSeqNum squash_seq_num, ThreadID tid)
 {
-    DPRINTF(InOrderBPred, "[tid:%i][sn:%i] Squashing...\n", tid, inst->seqNum);
-
-#if ISA_HAS_DELAY_SLOT
-    // We need to squash the actual branch , NOT the delay slot
-    // in the branch predictor
-    squash_seq_num = squash_seq_num - 1;
-#endif
+    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) {
-        bool taken = inst->predTaken();
-        branchPred.squash(squash_seq_num, inst->readPredTarg(), taken, tid);
+        branchPred->squash(bpred_squash_num, inst->pcState(),
+                           inst->pcState().branching(), tid);
     } else {
-        branchPred.squash(squash_seq_num, tid);
+    // 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);
 }