| /* |
| * Copyright (c) 2012 ARM Limited |
| * All rights reserved |
| * |
| * The license below extends only to copyright in the software and shall |
| * not be construed as granting a license to any other intellectual |
| * property including but not limited to intellectual property relating |
| * to a hardware implementation of the functionality of the software |
| * licensed hereunder. You may use the software subject to the license |
| * terms below provided that you ensure that this notice is replicated |
| * unmodified and in its entirety in all distributions of the software, |
| * modified or unmodified, in source code or in binary form. |
| * |
| * Copyright (c) 2004-2006 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. |
| */ |
| |
| #ifndef __CPU_O3_DECODE_HH__ |
| #define __CPU_O3_DECODE_HH__ |
| |
| #include <queue> |
| |
| #include "base/statistics.hh" |
| #include "cpu/o3/comm.hh" |
| #include "cpu/o3/dyn_inst_ptr.hh" |
| #include "cpu/o3/limits.hh" |
| #include "cpu/timebuf.hh" |
| |
| namespace gem5 |
| { |
| |
| struct BaseO3CPUParams; |
| |
| namespace o3 |
| { |
| |
| class CPU; |
| |
| /** |
| * Decode class handles both single threaded and SMT |
| * decode. Its width is specified by the parameters; each cycles it |
| * tries to decode that many instructions. Because instructions are |
| * actually decoded when the StaticInst is created, this stage does |
| * not do much other than check any PC-relative branches. |
| */ |
| class Decode |
| { |
| public: |
| /** Overall decode stage status. Used to determine if the CPU can |
| * deschedule itself due to a lack of activity. |
| */ |
| enum DecodeStatus |
| { |
| Active, |
| Inactive |
| }; |
| |
| /** Individual thread status. */ |
| enum ThreadStatus |
| { |
| Running, |
| Idle, |
| StartSquash, |
| Squashing, |
| Blocked, |
| Unblocking |
| }; |
| |
| private: |
| /** Decode status. */ |
| DecodeStatus _status; |
| |
| /** Per-thread status. */ |
| ThreadStatus decodeStatus[MaxThreads]; |
| |
| public: |
| /** Decode constructor. */ |
| Decode(CPU *_cpu, const BaseO3CPUParams ¶ms); |
| |
| void startupStage(); |
| |
| /** Clear all thread-specific states */ |
| void clearStates(ThreadID tid); |
| |
| void resetStage(); |
| |
| /** Returns the name of decode. */ |
| std::string name() const; |
| |
| /** Sets the main backwards communication time buffer pointer. */ |
| void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr); |
| |
| /** Sets pointer to time buffer used to communicate to the next stage. */ |
| void setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr); |
| |
| /** Sets pointer to time buffer coming from fetch. */ |
| void setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr); |
| |
| /** Sets pointer to list of active threads. */ |
| void setActiveThreads(std::list<ThreadID> *at_ptr); |
| |
| /** Perform sanity checks after a drain. */ |
| void drainSanityCheck() const; |
| |
| /** Has the stage drained? */ |
| bool isDrained() const; |
| |
| /** Takes over from another CPU's thread. */ |
| void takeOverFrom() { resetStage(); } |
| |
| /** Ticks decode, processing all input signals and decoding as many |
| * instructions as possible. |
| */ |
| void tick(); |
| |
| /** Determines what to do based on decode's current status. |
| * @param status_change decode() sets this variable if there was a status |
| * change (ie switching from from blocking to unblocking). |
| * @param tid Thread id to decode instructions from. |
| */ |
| void decode(bool &status_change, ThreadID tid); |
| |
| /** Processes instructions from fetch and passes them on to rename. |
| * Decoding of instructions actually happens when they are created in |
| * fetch, so this function mostly checks if PC-relative branches are |
| * correct. |
| */ |
| void decodeInsts(ThreadID tid); |
| |
| private: |
| /** Inserts a thread's instructions into the skid buffer, to be decoded |
| * once decode unblocks. |
| */ |
| void skidInsert(ThreadID tid); |
| |
| /** Returns if all of the skid buffers are empty. */ |
| bool skidsEmpty(); |
| |
| /** Updates overall decode status based on all of the threads' statuses. */ |
| void updateStatus(); |
| |
| /** Separates instructions from fetch into individual lists of instructions |
| * sorted by thread. |
| */ |
| void sortInsts(); |
| |
| /** Reads all stall signals from the backwards communication timebuffer. */ |
| void readStallSignals(ThreadID tid); |
| |
| /** Checks all input signals and updates decode's status appropriately. */ |
| bool checkSignalsAndUpdate(ThreadID tid); |
| |
| /** Checks all stall signals, and returns if any are true. */ |
| bool checkStall(ThreadID tid) const; |
| |
| /** Returns if there any instructions from fetch on this cycle. */ |
| bool fetchInstsValid(); |
| |
| /** Switches decode to blocking, and signals back that decode has |
| * become blocked. |
| * @return Returns true if there is a status change. |
| */ |
| bool block(ThreadID tid); |
| |
| /** Switches decode to unblocking if the skid buffer is empty, and |
| * signals back that decode has unblocked. |
| * @return Returns true if there is a status change. |
| */ |
| bool unblock(ThreadID tid); |
| |
| /** Squashes if there is a PC-relative branch that was predicted |
| * incorrectly. Sends squash information back to fetch. |
| */ |
| void squash(const DynInstPtr &inst, ThreadID tid); |
| |
| public: |
| /** Squashes due to commit signalling a squash. Changes status to |
| * squashing and clears block/unblock signals as needed. |
| */ |
| unsigned squash(ThreadID tid); |
| |
| private: |
| // Interfaces to objects outside of decode. |
| /** CPU interface. */ |
| CPU *cpu; |
| |
| /** Time buffer interface. */ |
| TimeBuffer<TimeStruct> *timeBuffer; |
| |
| /** Wire to get rename's output from backwards time buffer. */ |
| TimeBuffer<TimeStruct>::wire fromRename; |
| |
| /** Wire to get iew's information from backwards time buffer. */ |
| TimeBuffer<TimeStruct>::wire fromIEW; |
| |
| /** Wire to get commit's information from backwards time buffer. */ |
| TimeBuffer<TimeStruct>::wire fromCommit; |
| |
| /** Wire to write information heading to previous stages. */ |
| // Might not be the best name as not only fetch will read it. |
| TimeBuffer<TimeStruct>::wire toFetch; |
| |
| /** Decode instruction queue. */ |
| TimeBuffer<DecodeStruct> *decodeQueue; |
| |
| /** Wire used to write any information heading to rename. */ |
| TimeBuffer<DecodeStruct>::wire toRename; |
| |
| /** Fetch instruction queue interface. */ |
| TimeBuffer<FetchStruct> *fetchQueue; |
| |
| /** Wire to get fetch's output from fetch queue. */ |
| TimeBuffer<FetchStruct>::wire fromFetch; |
| |
| /** Queue of all instructions coming from fetch this cycle. */ |
| std::queue<DynInstPtr> insts[MaxThreads]; |
| |
| /** Skid buffer between fetch and decode. */ |
| std::queue<DynInstPtr> skidBuffer[MaxThreads]; |
| |
| /** Variable that tracks if decode has written to the time buffer this |
| * cycle. Used to tell CPU if there is activity this cycle. |
| */ |
| bool wroteToTimeBuffer; |
| |
| /** Source of possible stalls. */ |
| struct Stalls |
| { |
| bool rename; |
| }; |
| |
| /** Tracks which stages are telling decode to stall. */ |
| Stalls stalls[MaxThreads]; |
| |
| /** Rename to decode delay. */ |
| Cycles renameToDecodeDelay; |
| |
| /** IEW to decode delay. */ |
| Cycles iewToDecodeDelay; |
| |
| /** Commit to decode delay. */ |
| Cycles commitToDecodeDelay; |
| |
| /** Fetch to decode delay. */ |
| Cycles fetchToDecodeDelay; |
| |
| /** The width of decode, in instructions. */ |
| unsigned decodeWidth; |
| |
| /** Index of instructions being sent to rename. */ |
| unsigned toRenameIndex; |
| |
| /** number of Active Threads*/ |
| ThreadID numThreads; |
| |
| /** List of active thread ids */ |
| std::list<ThreadID> *activeThreads; |
| |
| /** Maximum size of the skid buffer. */ |
| unsigned skidBufferMax; |
| |
| /** SeqNum of Squashing Branch Delay Instruction (used for MIPS)*/ |
| Addr bdelayDoneSeqNum[MaxThreads]; |
| |
| /** Instruction used for squashing branch (used for MIPS)*/ |
| DynInstPtr squashInst[MaxThreads]; |
| |
| /** Tells when their is a pending delay slot inst. to send |
| * to rename. If there is, then wait squash after the next |
| * instruction (used for MIPS). |
| */ |
| bool squashAfterDelaySlot[MaxThreads]; |
| |
| struct DecodeStats : public statistics::Group |
| { |
| DecodeStats(CPU *cpu); |
| |
| /** Stat for total number of idle cycles. */ |
| statistics::Scalar idleCycles; |
| /** Stat for total number of blocked cycles. */ |
| statistics::Scalar blockedCycles; |
| /** Stat for total number of normal running cycles. */ |
| statistics::Scalar runCycles; |
| /** Stat for total number of unblocking cycles. */ |
| statistics::Scalar unblockCycles; |
| /** Stat for total number of squashing cycles. */ |
| statistics::Scalar squashCycles; |
| /** Stat for number of times a branch is resolved at decode. */ |
| statistics::Scalar branchResolved; |
| /** Stat for number of times a branch mispredict is detected. */ |
| statistics::Scalar branchMispred; |
| /** Stat for number of times decode detected a non-control instruction |
| * incorrectly predicted as a branch. |
| */ |
| statistics::Scalar controlMispred; |
| /** Stat for total number of decoded instructions. */ |
| statistics::Scalar decodedInsts; |
| /** Stat for total number of squashed instructions. */ |
| statistics::Scalar squashedInsts; |
| } stats; |
| }; |
| |
| } // namespace o3 |
| } // namespace gem5 |
| |
| #endif // __CPU_O3_DECODE_HH__ |