diff options
Diffstat (limited to 'cpu/o3/decode_impl.hh')
-rw-r--r-- | cpu/o3/decode_impl.hh | 425 |
1 files changed, 0 insertions, 425 deletions
diff --git a/cpu/o3/decode_impl.hh b/cpu/o3/decode_impl.hh deleted file mode 100644 index 463f0ddac..000000000 --- a/cpu/o3/decode_impl.hh +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright (c) 2004-2005 The Regents of The University of Michigan - * 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. - */ - -#include "cpu/o3/decode.hh" - -template<class Impl> -SimpleDecode<Impl>::SimpleDecode(Params ¶ms) - : renameToDecodeDelay(params.renameToDecodeDelay), - iewToDecodeDelay(params.iewToDecodeDelay), - commitToDecodeDelay(params.commitToDecodeDelay), - fetchToDecodeDelay(params.fetchToDecodeDelay), - decodeWidth(params.decodeWidth), - numInst(0) -{ - DPRINTF(Decode, "Decode: decodeWidth=%i.\n", decodeWidth); - _status = Idle; -} - -template <class Impl> -void -SimpleDecode<Impl>::regStats() -{ - decodeIdleCycles - .name(name() + ".decodeIdleCycles") - .desc("Number of cycles decode is idle") - .prereq(decodeIdleCycles); - decodeBlockedCycles - .name(name() + ".decodeBlockedCycles") - .desc("Number of cycles decode is blocked") - .prereq(decodeBlockedCycles); - decodeUnblockCycles - .name(name() + ".decodeUnblockCycles") - .desc("Number of cycles decode is unblocking") - .prereq(decodeUnblockCycles); - decodeSquashCycles - .name(name() + ".decodeSquashCycles") - .desc("Number of cycles decode is squashing") - .prereq(decodeSquashCycles); - decodeBranchMispred - .name(name() + ".decodeBranchMispred") - .desc("Number of times decode detected a branch misprediction") - .prereq(decodeBranchMispred); - decodeControlMispred - .name(name() + ".decodeControlMispred") - .desc("Number of times decode detected an instruction incorrectly" - " predicted as a control") - .prereq(decodeControlMispred); - decodeDecodedInsts - .name(name() + ".decodeDecodedInsts") - .desc("Number of instructions handled by decode") - .prereq(decodeDecodedInsts); - decodeSquashedInsts - .name(name() + ".decodeSquashedInsts") - .desc("Number of squashed instructions handled by decode") - .prereq(decodeSquashedInsts); -} - -template<class Impl> -void -SimpleDecode<Impl>::setCPU(FullCPU *cpu_ptr) -{ - DPRINTF(Decode, "Decode: Setting CPU pointer.\n"); - cpu = cpu_ptr; -} - -template<class Impl> -void -SimpleDecode<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) -{ - DPRINTF(Decode, "Decode: Setting time buffer pointer.\n"); - timeBuffer = tb_ptr; - - // Setup wire to write information back to fetch. - toFetch = timeBuffer->getWire(0); - - // Create wires to get information from proper places in time buffer. - fromRename = timeBuffer->getWire(-renameToDecodeDelay); - fromIEW = timeBuffer->getWire(-iewToDecodeDelay); - fromCommit = timeBuffer->getWire(-commitToDecodeDelay); -} - -template<class Impl> -void -SimpleDecode<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr) -{ - DPRINTF(Decode, "Decode: Setting decode queue pointer.\n"); - decodeQueue = dq_ptr; - - // Setup wire to write information to proper place in decode queue. - toRename = decodeQueue->getWire(0); -} - -template<class Impl> -void -SimpleDecode<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr) -{ - DPRINTF(Decode, "Decode: Setting fetch queue pointer.\n"); - fetchQueue = fq_ptr; - - // Setup wire to read information from fetch queue. - fromFetch = fetchQueue->getWire(-fetchToDecodeDelay); -} - -template<class Impl> -inline bool -SimpleDecode<Impl>::fetchInstsValid() -{ - return fromFetch->size > 0; -} - -template<class Impl> -void -SimpleDecode<Impl>::block() -{ - DPRINTF(Decode, "Decode: Blocking.\n"); - - // Set the status to Blocked. - _status = Blocked; - - // Add the current inputs to the skid buffer so they can be - // reprocessed when this stage unblocks. - skidBuffer.push(*fromFetch); - - // Note that this stage only signals previous stages to stall when - // it is the cause of the stall originates at this stage. Otherwise - // the previous stages are expected to check all possible stall signals. -} - -template<class Impl> -inline void -SimpleDecode<Impl>::unblock() -{ - DPRINTF(Decode, "Decode: Unblocking, going to remove " - "instructions from skid buffer.\n"); - // Remove the now processed instructions from the skid buffer. - skidBuffer.pop(); - - // If there's still information in the skid buffer, then - // continue to tell previous stages to stall. They will be - // able to restart once the skid buffer is empty. - if (!skidBuffer.empty()) { - toFetch->decodeInfo.stall = true; - } else { - DPRINTF(Decode, "Decode: Finished unblocking.\n"); - _status = Running; - } -} - -// This squash is specifically for when Decode detects a PC-relative branch -// was predicted incorrectly. -template<class Impl> -void -SimpleDecode<Impl>::squash(DynInstPtr &inst) -{ - DPRINTF(Decode, "Decode: Squashing due to incorrect branch prediction " - "detected at decode.\n"); - Addr new_PC = inst->readNextPC(); - - toFetch->decodeInfo.branchMispredict = true; - toFetch->decodeInfo.doneSeqNum = inst->seqNum; - toFetch->decodeInfo.predIncorrect = true; - toFetch->decodeInfo.squash = true; - toFetch->decodeInfo.nextPC = new_PC; - toFetch->decodeInfo.branchTaken = true; - - // Set status to squashing. - _status = Squashing; - - // Clear the skid buffer in case it has any data in it. - while (!skidBuffer.empty()) { - skidBuffer.pop(); - } - - // Squash instructions up until this one - // Slightly unrealistic! - cpu->removeInstsUntil(inst->seqNum); -} - -template<class Impl> -void -SimpleDecode<Impl>::squash() -{ - DPRINTF(Decode, "Decode: Squashing.\n"); - // Set status to squashing. - _status = Squashing; - - // Maybe advance the time buffer? Not sure what to do in the normal - // case. - - // Clear the skid buffer in case it has any data in it. - while (!skidBuffer.empty()) - { - skidBuffer.pop(); - } -} - -template<class Impl> -void -SimpleDecode<Impl>::tick() -{ - // Decode should try to execute as many instructions as its bandwidth - // will allow, as long as it is not currently blocked. - if (_status != Blocked && _status != Squashing) { - DPRINTF(Decode, "Decode: Not blocked, so attempting to run " - "stage.\n"); - // Make sure that the skid buffer has something in it if the - // status is unblocking. - assert(_status == Unblocking ? !skidBuffer.empty() : 1); - - decode(); - - // If the status was unblocking, then instructions from the skid - // buffer were used. Remove those instructions and handle - // the rest of unblocking. - if (_status == Unblocking) { - ++decodeUnblockCycles; - - if (fetchInstsValid()) { - // Add the current inputs to the skid buffer so they can be - // reprocessed when this stage unblocks. - skidBuffer.push(*fromFetch); - } - - unblock(); - } - } else if (_status == Blocked) { - ++decodeBlockedCycles; - - if (fetchInstsValid()) { - block(); - } - - if (!fromRename->renameInfo.stall && - !fromIEW->iewInfo.stall && - !fromCommit->commitInfo.stall) { - DPRINTF(Decode, "Decode: Stall signals cleared, going to " - "unblock.\n"); - _status = Unblocking; - - // Continue to tell previous stage to block until this - // stage is done unblocking. - toFetch->decodeInfo.stall = true; - } else { - DPRINTF(Decode, "Decode: Still blocked.\n"); - toFetch->decodeInfo.stall = true; - } - - if (fromCommit->commitInfo.squash || - fromCommit->commitInfo.robSquashing) { - squash(); - } - } else if (_status == Squashing) { - if (!fromCommit->commitInfo.squash && - !fromCommit->commitInfo.robSquashing) { - _status = Running; - } else if (fromCommit->commitInfo.squash) { - ++decodeSquashCycles; - - squash(); - } - } -} - -template<class Impl> -void -SimpleDecode<Impl>::decode() -{ - // Check time buffer if being told to squash. - if (fromCommit->commitInfo.squash) { - squash(); - return; - } - - // Check time buffer if being told to stall. - if (fromRename->renameInfo.stall || - fromIEW->iewInfo.stall || - fromCommit->commitInfo.stall) { - block(); - return; - } - - // Check fetch queue to see if instructions are available. - // If no available instructions, do nothing, unless this stage is - // currently unblocking. - if (!fetchInstsValid() && _status != Unblocking) { - DPRINTF(Decode, "Decode: Nothing to do, breaking out early.\n"); - // Should I change the status to idle? - ++decodeIdleCycles; - return; - } - - // Might be better to use a base DynInst * instead? - DynInstPtr inst; - - unsigned to_rename_index = 0; - - int insts_available = _status == Unblocking ? - skidBuffer.front().size - numInst : - fromFetch->size; - - // Debug block... -#if 0 - if (insts_available) { - DPRINTF(Decode, "Decode: Instructions available.\n"); - } else { - if (_status == Unblocking && skidBuffer.empty()) { - DPRINTF(Decode, "Decode: No instructions available, skid buffer " - "empty.\n"); - } else if (_status != Unblocking && - !fromFetch->insts[0]) { - DPRINTF(Decode, "Decode: No instructions available, fetch queue " - "empty.\n"); - } else { - panic("Decode: No instructions available, unexpected condition!" - "\n"); - } - } -#endif - - while (insts_available > 0) - { - DPRINTF(Decode, "Decode: Sending instruction to rename.\n"); - - inst = _status == Unblocking ? skidBuffer.front().insts[numInst] : - fromFetch->insts[numInst]; - - DPRINTF(Decode, "Decode: Processing instruction %i with PC %#x\n", - inst->seqNum, inst->readPC()); - - if (inst->isSquashed()) { - DPRINTF(Decode, "Decode: Instruction %i with PC %#x is " - "squashed, skipping.\n", - inst->seqNum, inst->readPC()); - - ++decodeSquashedInsts; - - ++numInst; - --insts_available; - - continue; - } - - - // Also check if instructions have no source registers. Mark - // them as ready to issue at any time. Not sure if this check - // should exist here or at a later stage; however it doesn't matter - // too much for function correctness. - // Isn't this handled by the inst queue? - if (inst->numSrcRegs() == 0) { - inst->setCanIssue(); - } - - // This current instruction is valid, so add it into the decode - // queue. The next instruction may not be valid, so check to - // see if branches were predicted correctly. - toRename->insts[to_rename_index] = inst; - - ++(toRename->size); - - // Ensure that if it was predicted as a branch, it really is a - // branch. - if (inst->predTaken() && !inst->isControl()) { - panic("Instruction predicted as a branch!"); - - ++decodeControlMispred; - // Might want to set some sort of boolean and just do - // a check at the end - squash(inst); - break; - } - - // Go ahead and compute any PC-relative branches. - - if (inst->isDirectCtrl() && inst->isUncondCtrl()) { - - inst->setNextPC(inst->branchTarget()); - - if (inst->mispredicted()) { - ++decodeBranchMispred; - // Might want to set some sort of boolean and just do - // a check at the end - squash(inst); - break; - } - } - - // Normally can check if a direct branch has the right target - // addr (either the immediate, or the branch PC + 4) and redirect - // fetch if it's incorrect. - - // Increment which instruction we're looking at. - ++numInst; - ++to_rename_index; - ++decodeDecodedInsts; - - --insts_available; - } - - numInst = 0; -} |