*
*/
-#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
.name(name() + ".predictedNotTakenIncorrect")
.desc("Number of Branches Incorrectly Predicted As Not Taken).");
+ executions
+ .name(name() + ".executions")
+ .desc("Number of Instructions Executed.");
+
+
+ predictedIncorrect
+ .name(name() + ".mispredicted")
+ .desc("Number of Branches Incorrectly Predicted");
+
+ 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();
}
void
ExecutionUnit::execute(int slot_num)
{
- ResourceRequest* exec_req = reqMap[slot_num];
- DynInstPtr inst = reqMap[slot_num]->inst;
- Fault fault = reqMap[slot_num]->fault;
- int 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] .\n",
- tid, seq_num, inst->readPC());
+ 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 (inst->isMemRef()) {
- fatal("%s not configured to handle memory ops.\n", resName);
- } else if (inst->isControl()) {
+ 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();
+
// 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();
- int 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 {
- inst->bdelaySeqNum = seq_num + 1;
-
- 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);
- inst->setPredTarg(inst->nextNPC);
- }
-
- DPRINTF(InOrderExecute, "[tid:%i] Redirecting fetch to %#x.\n", tid,
- inst->readPredTarg());
-
- } else if(inst->isIndirectCtrl()){
- inst->setPredTarg(inst->nextNPC);
- inst->bdelaySeqNum = seq_num + 1;
- 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);
+ 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();
- exec_req->done();
- DPRINTF(InOrderExecute, "[tid:%i]: The result of execution is 0x%x.\n",
- inst->readTid(), 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
+
+ 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;