/* * Copyright (c) 2010-2012, 2014 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. * * Authors: Kevin Lim */ #ifndef __CPU_O3_IEW_HH__ #define __CPU_O3_IEW_HH__ #include #include #include "base/statistics.hh" #include "cpu/o3/comm.hh" #include "cpu/o3/lsq.hh" #include "cpu/o3/scoreboard.hh" #include "cpu/timebuf.hh" #include "debug/IEW.hh" #include "sim/probe/probe.hh" struct DerivO3CPUParams; class FUPool; /** * DefaultIEW handles both single threaded and SMT IEW * (issue/execute/writeback). It handles the dispatching of * instructions to the LSQ/IQ as part of the issue stage, and has the * IQ try to issue instructions each cycle. The execute latency is * actually tied into the issue latency to allow the IQ to be able to * do back-to-back scheduling without having to speculatively schedule * instructions. This happens by having the IQ have access to the * functional units, and the IQ gets the execution latencies from the * FUs when it issues instructions. Instructions reach the execute * stage on the last cycle of their execution, which is when the IQ * knows to wake up any dependent instructions, allowing back to back * scheduling. The execute portion of IEW separates memory * instructions from non-memory instructions, either telling the LSQ * to execute the instruction, or executing the instruction directly. * The writeback portion of IEW completes the instructions by waking * up any dependents, and marking the register ready on the * scoreboard. */ template class DefaultIEW { private: //Typedefs from Impl typedef typename Impl::CPUPol CPUPol; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::O3CPU O3CPU; typedef typename CPUPol::IQ IQ; typedef typename CPUPol::RenameMap RenameMap; typedef typename CPUPol::LSQ LSQ; typedef typename CPUPol::TimeStruct TimeStruct; typedef typename CPUPol::IEWStruct IEWStruct; typedef typename CPUPol::RenameStruct RenameStruct; typedef typename CPUPol::IssueStruct IssueStruct; public: /** Overall IEW stage status. Used to determine if the CPU can * deschedule itself due to a lack of activity. */ enum Status { Active, Inactive }; /** Status for Issue, Execute, and Writeback stages. */ enum StageStatus { Running, Blocked, Idle, StartSquash, Squashing, Unblocking }; private: /** Overall stage status. */ Status _status; /** Dispatch status. */ StageStatus dispatchStatus[Impl::MaxThreads]; /** Execute status. */ StageStatus exeStatus; /** Writeback status. */ StageStatus wbStatus; /** Probe points. */ ProbePointArg *ppMispredict; ProbePointArg *ppDispatch; /** To probe when instruction execution begins. */ ProbePointArg *ppExecute; /** To probe when instruction execution is complete. */ ProbePointArg *ppToCommit; public: /** Constructs a DefaultIEW with the given parameters. */ DefaultIEW(O3CPU *_cpu, DerivO3CPUParams *params); /** Returns the name of the DefaultIEW stage. */ std::string name() const; /** Registers statistics. */ void regStats(); /** Registers probes. */ void regProbePoints(); /** Initializes stage; sends back the number of free IQ and LSQ entries. */ void startupStage(); /** Sets main time buffer used for backwards communication. */ void setTimeBuffer(TimeBuffer *tb_ptr); /** Sets time buffer for getting instructions coming from rename. */ void setRenameQueue(TimeBuffer *rq_ptr); /** Sets time buffer to pass on instructions to commit. */ void setIEWQueue(TimeBuffer *iq_ptr); /** Sets pointer to list of active threads. */ void setActiveThreads(std::list *at_ptr); /** Sets pointer to the scoreboard. */ void setScoreboard(Scoreboard *sb_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(); /** Squashes instructions in IEW for a specific thread. */ void squash(ThreadID tid); /** Wakes all dependents of a completed instruction. */ void wakeDependents(const DynInstPtr &inst); /** Tells memory dependence unit that a memory instruction needs to be * rescheduled. It will re-execute once replayMemInst() is called. */ void rescheduleMemInst(const DynInstPtr &inst); /** Re-executes all rescheduled memory instructions. */ void replayMemInst(const DynInstPtr &inst); /** Moves memory instruction onto the list of cache blocked instructions */ void blockMemInst(const DynInstPtr &inst); /** Notifies that the cache has become unblocked */ void cacheUnblocked(); /** Sends an instruction to commit through the time buffer. */ void instToCommit(const DynInstPtr &inst); /** Inserts unused instructions of a thread into the skid buffer. */ void skidInsert(ThreadID tid); /** Returns the max of the number of entries in all of the skid buffers. */ int skidCount(); /** Returns if all of the skid buffers are empty. */ bool skidsEmpty(); /** Updates overall IEW status based on all of the stages' statuses. */ void updateStatus(); /** Resets entries of the IQ and the LSQ. */ void resetEntries(); /** Tells the CPU to wakeup if it has descheduled itself due to no * activity. Used mainly by the LdWritebackEvent. */ void wakeCPU(); /** Reports to the CPU that there is activity this cycle. */ void activityThisCycle(); /** Tells CPU that the IEW stage is active and running. */ inline void activateStage(); /** Tells CPU that the IEW stage is inactive and idle. */ inline void deactivateStage(); /** Returns if the LSQ has any stores to writeback. */ bool hasStoresToWB() { return ldstQueue.hasStoresToWB(); } /** Returns if the LSQ has any stores to writeback. */ bool hasStoresToWB(ThreadID tid) { return ldstQueue.hasStoresToWB(tid); } /** Check misprediction */ void checkMisprediction(const DynInstPtr &inst); private: /** Sends commit proper information for a squash due to a branch * mispredict. */ void squashDueToBranch(const DynInstPtr &inst, ThreadID tid); /** Sends commit proper information for a squash due to a memory order * violation. */ void squashDueToMemOrder(const DynInstPtr &inst, ThreadID tid); /** Sets Dispatch to blocked, and signals back to other stages to block. */ void block(ThreadID tid); /** Unblocks Dispatch if the skid buffer is empty, and signals back to * other stages to unblock. */ void unblock(ThreadID tid); /** Determines proper actions to take given Dispatch's status. */ void dispatch(ThreadID tid); /** Dispatches instructions to IQ and LSQ. */ void dispatchInsts(ThreadID tid); /** Executes instructions. In the case of memory operations, it informs the * LSQ to execute the instructions. Also handles any redirects that occur * due to the executed instructions. */ void executeInsts(); /** Writebacks instructions. In our model, the instruction's execute() * function atomically reads registers, executes, and writes registers. * Thus this writeback only wakes up dependent instructions, and informs * the scoreboard of registers becoming ready. */ void writebackInsts(); /** Returns the number of valid, non-squashed instructions coming from * rename to dispatch. */ unsigned validInstsFromRename(); /** Checks if any of the stall conditions are currently true. */ bool checkStall(ThreadID tid); /** Processes inputs and changes state accordingly. */ void checkSignalsAndUpdate(ThreadID tid); /** Removes instructions from rename from a thread's instruction list. */ void emptyRenameInsts(ThreadID tid); /** Sorts instructions coming from rename into lists separated by thread. */ void sortInsts(); public: /** Ticks IEW stage, causing Dispatch, the IQ, the LSQ, Execute, and * Writeback to run for one cycle. */ void tick(); private: /** Updates execution stats based on the instruction. */ void updateExeInstStats(const DynInstPtr &inst); /** Pointer to main time buffer used for backwards communication. */ TimeBuffer *timeBuffer; /** Wire to write information heading to previous stages. */ typename TimeBuffer::wire toFetch; /** Wire to get commit's output from backwards time buffer. */ typename TimeBuffer::wire fromCommit; /** Wire to write information heading to previous stages. */ typename TimeBuffer::wire toRename; /** Rename instruction queue interface. */ TimeBuffer *renameQueue; /** Wire to get rename's output from rename queue. */ typename TimeBuffer::wire fromRename; /** Issue stage queue. */ TimeBuffer issueToExecQueue; /** Wire to read information from the issue stage time queue. */ typename TimeBuffer::wire fromIssue; /** * IEW stage time buffer. Holds ROB indices of instructions that * can be marked as completed. */ TimeBuffer *iewQueue; /** Wire to write infromation heading to commit. */ typename TimeBuffer::wire toCommit; /** Queue of all instructions coming from rename this cycle. */ std::queue insts[Impl::MaxThreads]; /** Skid buffer between rename and IEW. */ std::queue skidBuffer[Impl::MaxThreads]; /** Scoreboard pointer. */ Scoreboard* scoreboard; private: /** CPU pointer. */ O3CPU *cpu; /** Records if IEW has written to the time buffer this cycle, so that the * CPU can deschedule itself if there is no activity. */ bool wroteToTimeBuffer; /** Debug function to print instructions that are issued this cycle. */ void printAvailableInsts(); public: /** Instruction queue. */ IQ instQueue; /** Load / store queue. */ LSQ ldstQueue; /** Pointer to the functional unit pool. */ FUPool *fuPool; /** Records if the LSQ needs to be updated on the next cycle, so that * IEW knows if there will be activity on the next cycle. */ bool updateLSQNextCycle; private: /** Records if there is a fetch redirect on this cycle for each thread. */ bool fetchRedirect[Impl::MaxThreads]; /** Records if the queues have been changed (inserted or issued insts), * so that IEW knows to broadcast the updated amount of free entries. */ bool updatedQueues; /** Commit to IEW delay. */ Cycles commitToIEWDelay; /** Rename to IEW delay. */ Cycles renameToIEWDelay; /** * Issue to execute delay. What this actually represents is * the amount of time it takes for an instruction to wake up, be * scheduled, and sent to a FU for execution. */ Cycles issueToExecuteDelay; /** Width of dispatch, in instructions. */ unsigned dispatchWidth; /** Width of issue, in instructions. */ unsigned issueWidth; /** Index into queue of instructions being written back. */ unsigned wbNumInst; /** Cycle number within the queue of instructions being written back. * Used in case there are too many instructions writing back at the current * cycle and writesbacks need to be scheduled for the future. See comments * in instToCommit(). */ unsigned wbCycle; /** Writeback width. */ unsigned wbWidth; /** Number of active threads. */ ThreadID numThreads; /** Pointer to list of active threads. */ std::list *activeThreads; /** Maximum size of the skid buffer. */ unsigned skidBufferMax; /** Stat for total number of idle cycles. */ Stats::Scalar iewIdleCycles; /** Stat for total number of squashing cycles. */ Stats::Scalar iewSquashCycles; /** Stat for total number of blocking cycles. */ Stats::Scalar iewBlockCycles; /** Stat for total number of unblocking cycles. */ Stats::Scalar iewUnblockCycles; /** Stat for total number of instructions dispatched. */ Stats::Scalar iewDispatchedInsts; /** Stat for total number of squashed instructions dispatch skips. */ Stats::Scalar iewDispSquashedInsts; /** Stat for total number of dispatched load instructions. */ Stats::Scalar iewDispLoadInsts; /** Stat for total number of dispatched store instructions. */ Stats::Scalar iewDispStoreInsts; /** Stat for total number of dispatched non speculative instructions. */ Stats::Scalar iewDispNonSpecInsts; /** Stat for number of times the IQ becomes full. */ Stats::Scalar iewIQFullEvents; /** Stat for number of times the LSQ becomes full. */ Stats::Scalar iewLSQFullEvents; /** Stat for total number of memory ordering violation events. */ Stats::Scalar memOrderViolationEvents; /** Stat for total number of incorrect predicted taken branches. */ Stats::Scalar predictedTakenIncorrect; /** Stat for total number of incorrect predicted not taken branches. */ Stats::Scalar predictedNotTakenIncorrect; /** Stat for total number of mispredicted branches detected at execute. */ Stats::Formula branchMispredicts; /** Stat for total number of executed instructions. */ Stats::Scalar iewExecutedInsts; /** Stat for total number of executed load instructions. */ Stats::Vector iewExecLoadInsts; /** Stat for total number of executed store instructions. */ // Stats::Scalar iewExecStoreInsts; /** Stat for total number of squashed instructions skipped at execute. */ Stats::Scalar iewExecSquashedInsts; /** Number of executed software prefetches. */ Stats::Vector iewExecutedSwp; /** Number of executed nops. */ Stats::Vector iewExecutedNop; /** Number of executed meomory references. */ Stats::Vector iewExecutedRefs; /** Number of executed branches. */ Stats::Vector iewExecutedBranches; /** Number of executed store instructions. */ Stats::Formula iewExecStoreInsts; /** Number of instructions executed per cycle. */ Stats::Formula iewExecRate; /** Number of instructions sent to commit. */ Stats::Vector iewInstsToCommit; /** Number of instructions that writeback. */ Stats::Vector writebackCount; /** Number of instructions that wake consumers. */ Stats::Vector producerInst; /** Number of instructions that wake up from producers. */ Stats::Vector consumerInst; /** Number of instructions per cycle written back. */ Stats::Formula wbRate; /** Average number of woken instructions per writeback. */ Stats::Formula wbFanout; }; #endif // __CPU_O3_IEW_HH__