cpu: Update DRAM traffic gen
[gem5.git] / src / cpu / inorder / resources / execution_unit.cc
index 4292912315a83b0ef5a3110c0a30722b24382882..296d5126fa7a4bc981419d234ef3f18402b361cb 100644 (file)
  *
  */
 
-#include <vector>
 #include <list>
+#include <vector>
+
 #include "cpu/inorder/resources/execution_unit.hh"
-#include "cpu/inorder/resource_pool.hh"
 #include "cpu/inorder/cpu.hh"
+#include "cpu/inorder/resource_pool.hh"
+#include "debug/Fault.hh"
+#include "debug/InOrderExecute.hh"
+#include "debug/InOrderStall.hh"
+#include "sim/full_system.hh"
 
 using namespace std;
 using namespace ThePipeline;
 
 ExecutionUnit::ExecutionUnit(string res_name, int res_id, int res_width,
-                 int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params)
-    : Resource(res_name, res_id, res_width, res_latency, _cpu)
+                             Cycles res_latency, InOrderCPU *_cpu,
+                             ThePipeline::Params *params)
+    : Resource(res_name, res_id, res_width, res_latency, _cpu),
+      lastExecuteTick(0), lastControlTick(0)
 { }
 
 void
@@ -54,16 +61,25 @@ ExecutionUnit::regStats()
         .name(name() + ".predictedNotTakenIncorrect")
         .desc("Number of Branches Incorrectly Predicted As Not Taken).");
 
-    lastExecuteCycle = curTick;
+    executions
+        .name(name() + ".executions")
+        .desc("Number of Instructions Executed.");
 
-    cyclesExecuted
-        .name(name() + ".cyclesExecuted")
-        .desc("Number of Cycles Execution Unit was used.");
+    predictedIncorrect
+        .name(name() + ".mispredicted")
+        .desc("Number of Branches Incorrectly Predicted");
 
-    utilization
-        .name(name() + ".utilization")
-        .desc("Utilization of Execution Unit (cycles / totalCycles).");
-    utilization = cyclesExecuted / cpu->numCycles;
+    predictedCorrect
+        .name(name() + ".predicted")
+        .desc("Number of Branches Incorrectly Predicted");
+
+    mispredictPct
+        .name(name() + ".mispredictPct")
+        .desc("Percentage of Incorrect Branches Predicts")
+        .precision(6);
+    mispredictPct = (predictedIncorrect / 
+                     (predictedCorrect + predictedIncorrect)) * 100;
 
     Resource::regStats();
 }
@@ -71,138 +87,156 @@ ExecutionUnit::regStats()
 void
 ExecutionUnit::execute(int slot_num)
 {
-    ResourceRequest* exec_req = reqMap[slot_num];
-    DynInstPtr inst = reqMap[slot_num]->inst;
-    Fault fault = reqMap[slot_num]->fault;
-    ThreadID tid = inst->readTid();
-    int seq_num = inst->seqNum;
-
-    exec_req->fault = NoFault;
+    ResourceRequest* exec_req = reqs[slot_num];
+    DynInstPtr inst = reqs[slot_num]->inst;
+    if (inst->fault != NoFault) {
+        DPRINTF(InOrderExecute,
+                "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to "
+                "next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(),
+                inst->pcState());
+        exec_req->done();
+        return;
+    }
 
-    DPRINTF(InOrderExecute, "[tid:%i] Executing [sn:%i] [PC:%#x] %s.\n",
-            tid, seq_num, inst->readPC(), inst->instName());
+    Fault fault = NoFault;
+    Tick cur_tick = curTick();
+    unsigned stage_num = exec_req->getStageNum();
+    ThreadID tid = inst->readTid();
+#if TRACING_ON
+    InstSeqNum seq_num = inst->seqNum;
+#endif
 
     switch (exec_req->cmd)
     {
       case ExecuteInst:
         {
-            if (curTick != lastExecuteCycle) {
-                lastExecuteCycle = curTick;
-                cyclesExecuted++;
+            if (inst->isNop()) {
+                DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] [PC:%s] Ignoring execution"
+                        "of %s.\n", inst->readTid(), seq_num, inst->pcState(),
+                        inst->instName());
+                inst->setExecuted();
+                exec_req->done();
+                return;
+            } else {
+                DPRINTF(InOrderExecute, "[tid:%i] Executing [sn:%i] [PC:%s] %s.\n",
+                        inst->readTid(), seq_num, inst->pcState(), inst->instName());
             }
 
+            if (cur_tick != lastExecuteTick) {
+                lastExecuteTick = cur_tick;
+            }
+
+            //@todo: handle address generation here
+            assert(!inst->isMemRef());
+
+            if (inst->isControl()) {
+                if (lastControlTick == cur_tick) {
+                    DPRINTF(InOrderExecute, "Can not Execute More than One Control "
+                            "Inst Per Cycle. Blocking Request.\n");
+                    exec_req->done(false);
+                    return;
+                }
+                lastControlTick = curTick();
 
-            if (inst->isMemRef()) {
-                panic("%s not configured to handle memory ops.\n", resName);
-            } else if (inst->isControl()) {
                 // Evaluate Branch
                 fault = inst->execute();
 
-                inst->setExecuted();
+                // Should unconditional control , pc relative count as an
+                // execution??? Probably not.
+                executions++;
 
                 if (fault == NoFault) {
-                    // If branch is mispredicted, then signal squash
-                    // throughout all stages behind the pipeline stage
-                    // that got squashed.
-                    if (inst->mispredicted()) {
-                        int stage_num = exec_req->getStageNum();
-                        ThreadID tid = inst->readTid();
-
-                        // If it's a branch ...
-                        if (inst->isDirectCtrl()) {
-                            assert(!inst->isIndirectCtrl());
-
-                            if (inst->predTaken() && inst->isCondDelaySlot()) {
-                                inst->bdelaySeqNum = seq_num;
-                                inst->setPredTarg(inst->nextPC);
-
-                                DPRINTF(InOrderExecute, "[tid:%i]: Conditional branch inst"
-                                        "[sn:%i] PC %#x mispredicted as taken.\n", tid,
-                                        seq_num, inst->PC);
-                            } else if (!inst->predTaken() && inst->isCondDelaySlot()) {
-                                inst->bdelaySeqNum = seq_num;
-                                inst->setPredTarg(inst->nextPC);
-                                inst->procDelaySlotOnMispred = true;
-
-                                DPRINTF(InOrderExecute, "[tid:%i]: Conditional branch inst."
-                                        "[sn:%i] PC %#x mispredicted as not taken.\n", tid,
-                                        seq_num, inst->PC);
-                            } else {
-#if ISA_HAS_DELAY_SLOT
-                                inst->bdelaySeqNum = seq_num + 1;
-                                inst->setPredTarg(inst->nextNPC);
-#else
-                                inst->bdelaySeqNum = seq_num;
-                                inst->setPredTarg(inst->nextPC);
-#endif
-                                DPRINTF(InOrderExecute, "[tid:%i]: Misprediction detected at "
-                                        "[sn:%i] PC %#x,\n\t squashing after delay slot "
-                                        "instruction [sn:%i].\n",
-                                        tid, seq_num, inst->PC, inst->bdelaySeqNum);
-                                DPRINTF(InOrderStall, "STALL: [tid:%i]: Branch "
-                                        "misprediction at %#x\n", tid, inst->PC);
-                            }
-
-                            DPRINTF(InOrderExecute, "[tid:%i] Redirecting fetch to %#x.\n", tid,
-                                    inst->readPredTarg());
-
-                        } else if(inst->isIndirectCtrl()){
-#if ISA_HAS_DELAY_SLOT
-                            inst->setPredTarg(inst->nextNPC);
-                            inst->bdelaySeqNum = seq_num + 1;
-#else
-                            inst->setPredTarg(inst->nextPC);
-                            inst->bdelaySeqNum = seq_num;
-#endif
-
-                            DPRINTF(InOrderExecute, "[tid:%i] Redirecting fetch to %#x.\n", tid,
-                                    inst->readPredTarg());
-                        } else {
-                            panic("Non-control instruction (%s) mispredicting?!!",
-                                  inst->staticInst->getName());
-                        }
-
-                        DPRINTF(InOrderExecute, "[tid:%i] Squashing will start from stage %i.\n",
-                                tid, stage_num);
+                    inst->setExecuted();
 
-                        cpu->pipelineStage[stage_num]->squashDueToBranch(inst, tid);
+                    if (inst->mispredicted()) {
+                        assert(inst->isControl());
 
-                        inst->squashingStage = stage_num;
+                        // Set up Squash Generated By this Misprediction
+                        TheISA::PCState pc = inst->pcState();
+                        TheISA::advancePC(pc, inst->staticInst);
+                        inst->setPredTarg(pc);
+                        inst->setSquashInfo(stage_num);
+                        setupSquash(inst, stage_num, tid);
 
-                        // Squash throughout other resources
-                        cpu->resPool->scheduleEvent((InOrderCPU::CPUEventType)ResourcePool::SquashAll,
-                                                    inst, 0, 0, tid);
+                        DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i] Squashing from "
+                                "stage %i. Redirecting  fetch to %s.\n", tid,
+                                inst->seqNum, stage_num, pc);
+                        DPRINTF(InOrderStall, "STALL: [tid:%i]: Branch"
+                                " misprediction at %s\n", tid, inst->pcState());
 
                         if (inst->predTaken()) {
                             predictedTakenIncorrect++;
+                            DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ..."
+                                    "PC %s ... Mispredicts! "
+                                    "(Prediction: Taken)\n",
+                                    tid, inst->seqNum,
+                                    inst->staticInst->disassemble(
+                                        inst->instAddr()),
+                                    inst->pcState());
                         } else {
                             predictedNotTakenIncorrect++;
+                            DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ..."
+                                    "PC %s ... Mispredicts! "
+                                    "(Prediction: Not Taken)\n",
+                                    tid, inst->seqNum,
+                                    inst->staticInst->disassemble(
+                                        inst->instAddr()),
+                                    inst->pcState());
                         }
+                        predictedIncorrect++;
                     } else {
-                        DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: Prediction Correct.\n",
-                                inst->readTid(), seq_num);
+                        DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: Prediction"
+                                "Correct.\n", inst->readTid(), seq_num);
+                        predictedCorrect++;
                     }
 
                     exec_req->done();
                 } else {
-                    warn("inst [sn:%i] had a %s fault", seq_num, fault->name());
+                    DPRINTF(Fault, "[tid:%i]:[sn:%i]: Fault %s found\n",
+                            inst->readTid(), inst->seqNum, fault->name());
+                    inst->fault = fault;
+                    exec_req->done();
                 }
             } else {
                 // Regular ALU instruction
                 fault = inst->execute();
+                executions++;
 
                 if (fault == NoFault) {
                     inst->setExecuted();
 
-                    DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: The result of execution is 0x%x.\n",
-                            inst->readTid(), seq_num, (inst->resultType(0) == InOrderDynInst::Float) ?
-                            inst->readFloatResult(0) : inst->readIntResult(0));
+#if TRACING_ON
+                    for (int didx = 0; didx < inst->numDestRegs(); didx++)
+                        if (inst->resultType(didx) == InOrderDynInst::Float ||
+                            inst->resultType(didx) == InOrderDynInst::FloatBits ||
+                            inst->resultType(didx) == InOrderDynInst::Double)
+                            DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: Dest result %i "
+                                    "of FP execution is %08f (%x).\n", inst->readTid(),
+                                    seq_num, didx, inst->readFloatResult(didx),
+                                    inst->readFloatBitsResult(didx));
+                        else
+                            DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: Dest result %i "
+                                    "of Int execution is 0x%x.\n", inst->readTid(),
+                                    seq_num, didx, inst->readIntResult(didx));
+#endif
 
-                    exec_req->done();
+                    if (!FullSystem) {
+                        // The Syscall might change the PC, so conservatively
+                        // squash everything behing it
+                        if (inst->isSyscall()) {
+                            inst->setSquashInfo(stage_num);
+                            setupSquash(inst, stage_num, tid);
+                        }
+                    }
                 } else {
-                    warn("inst [sn:%i] had a %s fault", seq_num, fault->name());
-                    cpu->trap(fault, tid);
+                    DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: had a %s "
+                            "fault.\n", inst->readTid(), seq_num, fault->name());
+                    DPRINTF(Fault, "[tid:%i]:[sn:%i]: Fault %s found\n",
+                            inst->readTid(), inst->seqNum, fault->name());
+                    inst->fault = fault;
                 }
+
+                exec_req->done();
             }
         }
         break;