diff options
author | Korey Sewell <ksewell@umich.edu> | 2009-02-10 15:49:29 -0800 |
---|---|---|
committer | Korey Sewell <ksewell@umich.edu> | 2009-02-10 15:49:29 -0800 |
commit | 973d8b8b13b8e4ea178cafa95aaf6538699b8b15 (patch) | |
tree | 79321a7384b1fbd183a39e98e28dfa4e9e99d828 /src/cpu/inorder/resources/execution_unit.cc | |
parent | 36d9065f5f716f88c82a3f4e9a75fa040039aa0a (diff) | |
download | gem5-973d8b8b13b8e4ea178cafa95aaf6538699b8b15.tar.xz |
InOrder: Import new inorder CPU model from MIPS.
This model currently only works in MIPS_SE mode, so it will take some effort
to clean it up and make it generally useful. Hopefully people are willing to
help make that happen!
Diffstat (limited to 'src/cpu/inorder/resources/execution_unit.cc')
-rw-r--r-- | src/cpu/inorder/resources/execution_unit.cc | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/src/cpu/inorder/resources/execution_unit.cc b/src/cpu/inorder/resources/execution_unit.cc new file mode 100644 index 000000000..e41291103 --- /dev/null +++ b/src/cpu/inorder/resources/execution_unit.cc @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Korey Sewell + * + */ + +#include <vector> +#include <list> +#include "cpu/inorder/resources/execution_unit.hh" +#include "cpu/inorder/resource_pool.hh" +#include "cpu/inorder/cpu.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) +{ } + +void +ExecutionUnit::regStats() +{ + predictedTakenIncorrect + .name(name() + ".predictedTakenIncorrect") + .desc("Number of Branches Incorrectly Predicted As Taken."); + + predictedNotTakenIncorrect + .name(name() + ".predictedNotTakenIncorrect") + .desc("Number of Branches Incorrectly Predicted As Not Taken)."); + + 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; + + DPRINTF(Resource, "[tid:%i] Executing [sn:%i] [PC:%#x] .\n", + tid, seq_num, inst->readPC()); + + switch (exec_req->cmd) + { + case ExecuteInst: + { + if (inst->isMemRef()) { + fatal("%s not configured to handle memory ops.\n", resName); + } else if (inst->isControl()) { + // Evaluate Branch + fault = inst->execute(); + + inst->setExecuted(); + + 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(Resource, "[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(Resource, "[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(Resource, "[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(Resource, "[tid:%i] Redirecting fetch to %#x.\n", tid, + inst->readPredTarg()); + + } else if(inst->isIndirectCtrl()){ + inst->setPredTarg(inst->nextNPC); + inst->bdelaySeqNum = seq_num + 1; + DPRINTF(Resource, "[tid:%i] Redirecting fetch to %#x.\n", tid, + inst->readPredTarg()); + } else { + panic("Non-control instruction (%s) mispredicting?!!", + inst->staticInst->getName()); + } + + DPRINTF(Resource, "[tid:%i] Squashing will start from stage %i.\n", + tid, stage_num); + + cpu->pipelineStage[stage_num]->squashDueToBranch(inst, tid); + + inst->squashingStage = stage_num; + + // Squash throughout other resources + cpu->resPool->scheduleEvent((InOrderCPU::CPUEventType)ResourcePool::SquashAll, + inst, 0, 0, tid); + + if (inst->predTaken()) { + predictedTakenIncorrect++; + } else { + predictedNotTakenIncorrect++; + } + } + exec_req->done(); + } else { + warn("inst [sn:%i] had a %s fault", seq_num, fault->name()); + } + } else { + // Regular ALU instruction + fault = inst->execute(); + + if (fault == NoFault) { + inst->setExecuted(); + exec_req->done(); + + DPRINTF(Resource, "[tid:%i]: The result of execution is 0x%x.\n", + inst->readTid(), inst->readIntResult(0)); + } else { + warn("inst [sn:%i] had a %s fault", seq_num, fault->name()); + cpu->trap(fault, tid); + } + } + } + break; + + default: + fatal("Unrecognized command to %s", resName); + } +} + + |