diff options
Diffstat (limited to 'src/cpu/minor/execute.hh')
-rw-r--r-- | src/cpu/minor/execute.hh | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/src/cpu/minor/execute.hh b/src/cpu/minor/execute.hh new file mode 100644 index 000000000..8cd026534 --- /dev/null +++ b/src/cpu/minor/execute.hh @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2013-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. + * + * 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: Andrew Bardsley + */ + +/** + * @file + * + * All the fun of executing instructions from Decode and sending branch/new + * instruction stream info. to Fetch1. + */ + +#ifndef __CPU_MINOR_EXECUTE_HH__ +#define __CPU_MINOR_EXECUTE_HH__ + +#include "cpu/minor/buffers.hh" +#include "cpu/minor/cpu.hh" +#include "cpu/minor/func_unit.hh" +#include "cpu/minor/lsq.hh" +#include "cpu/minor/pipe_data.hh" +#include "cpu/minor/scoreboard.hh" + +namespace Minor +{ + +/** Execute stage. Everything apart from fetching and decoding instructions. + * The LSQ lives here too. */ +class Execute : public Named +{ + protected: + /** Input port carrying instructions from Decode */ + Latch<ForwardInstData>::Output inp; + + /** Input port carrying stream changes to Fetch1 */ + Latch<BranchData>::Input out; + + /** Pointer back to the containing CPU */ + MinorCPU &cpu; + + /** Number of instructions that can be issued per cycle */ + unsigned int issueLimit; + + /** Number of memory ops that can be issued per cycle */ + unsigned int memoryIssueLimit; + + /** Number of instructions that can be committed per cycle */ + unsigned int commitLimit; + + /** Number of memory instructions that can be committed per cycle */ + unsigned int memoryCommitLimit; + + /** If true, more than one input line can be processed each cycle if + * there is room to execute more instructions than taken from the first + * line */ + bool processMoreThanOneInput; + + /** Descriptions of the functional units we want to generate */ + MinorFUPool &fuDescriptions; + + /** Number of functional units to produce */ + unsigned int numFuncUnits; + + /** Longest latency of any FU, useful for setting up the activity + * recoder */ + Cycles longestFuLatency; + + /** Modify instruction trace times on commit */ + bool setTraceTimeOnCommit; + + /** Modify instruction trace times on issue */ + bool setTraceTimeOnIssue; + + /** Allow mem refs to leave their FUs before reaching the head + * of the in flight insts queue if their dependencies are met */ + bool allowEarlyMemIssue; + + /** The FU index of the non-existent costless FU for instructions + * which pass the MinorDynInst::isNoCostInst test */ + unsigned int noCostFUIndex; + + /** Dcache port to pass on to the CPU. Execute owns this */ + LSQ lsq; + + /** Scoreboard of instruction dependencies */ + Scoreboard scoreboard; + + /** The execution functional units */ + std::vector<FUPipeline *> funcUnits; + + public: /* Public for Pipeline to be able to pass it to Decode */ + InputBuffer<ForwardInstData> inputBuffer; + + protected: + /** Stage cycle-by-cycle state */ + + /** State that drain passes through (in order). On a drain request, + * Execute transitions into either DrainCurrentInst (if between + * microops) or DrainHaltFetch. + * + * Note that Execute doesn't actually have * a 'Drained' state, only + * an indication that it's currently draining and isDrained that can't + * tell if there are insts still in the pipeline leading up to + * Execute */ + enum DrainState + { + NotDraining, /* Not draining, possibly running */ + DrainCurrentInst, /* Draining to end of inst/macroop */ + DrainHaltFetch, /* Halting Fetch after completing current inst */ + DrainAllInsts /* Discarding all remaining insts */ + }; + + /** In-order instructions either in FUs or the LSQ */ + Queue<QueuedInst, ReportTraitsAdaptor<QueuedInst> > *inFlightInsts; + + /** Memory ref instructions still in the FUs */ + Queue<QueuedInst, ReportTraitsAdaptor<QueuedInst> > *inFUMemInsts; + + /** Index that we've completed upto in getInput data. We can say we're + * popInput when this equals getInput()->width() */ + unsigned int inputIndex; + + /** The last commit was the end of a full instruction so an interrupt + * can safely happen */ + bool lastCommitWasEndOfMacroop; + + /** Structure for reporting insts currently being processed/retired + * for MinorTrace */ + ForwardInstData instsBeingCommitted; + + /** Source of sequence number for instuction streams. Increment this and + * pass to fetch whenever an instruction stream needs to be changed. + * For any more complicated behaviour (e.g. speculation) there'll need + * to be another plan. THREAD, need one for each thread */ + InstSeqNum streamSeqNum; + + /** A prediction number for use where one isn't available from an + * instruction. This is harvested from committed instructions. + * This isn't really needed as the streamSeqNum will change on + * a branch, but it minimises disruption in stream identification */ + InstSeqNum lastPredictionSeqNum; + + /** State progression for draining NotDraining -> ... -> DrainAllInsts */ + DrainState drainState; + + protected: + friend std::ostream &operator <<(std::ostream &os, DrainState state); + + /** Get a piece of data to work on from the inputBuffer, or 0 if there + * is no data. */ + const ForwardInstData *getInput(); + + /** Pop an element off the input buffer, if there are any */ + void popInput(); + + /** Generate Branch data based (into branch) on an observed (or not) + * change in PC while executing an instruction. + * Also handles branch prediction information within the inst. */ + void tryToBranch(MinorDynInstPtr inst, Fault fault, BranchData &branch); + + /** Actually create a branch to communicate to Fetch1/Fetch2 and, + * if that is a stream-changing branch update the streamSeqNum */ + void updateBranchData(BranchData::Reason reason, + MinorDynInstPtr inst, const TheISA::PCState &target, + BranchData &branch); + + /** Handle extracting mem ref responses from the memory queues and + * completing the associated instructions. + * Fault is an output and will contain any fault caused (and already + * invoked by the function) + * Sets branch to any branch generated by the instruction. */ + void handleMemResponse(MinorDynInstPtr inst, + LSQ::LSQRequestPtr response, BranchData &branch, + Fault &fault); + + /** Execute a memory reference instruction. This calls initiateAcc on + * the instruction which will then call writeMem or readMem to issue a + * memory access to the LSQ. + * Returns true if the instruction was executed rather than stalled + * because of a lack of LSQ resources and false otherwise. + * branch is set to any branch raised by the instruction. + * failed_predicate is set to false if the instruction passed its + * predicate and so will access memory or true if the instruction + * *failed* its predicate and is now complete. + * fault is set if any non-NoFault fault is raised. + * Any faults raised are actually invoke-d by this function. */ + bool executeMemRefInst(MinorDynInstPtr inst, BranchData &branch, + bool &failed_predicate, Fault &fault); + + /** Has an interrupt been raised */ + bool isInterrupted(ThreadID thread_id) const; + + /** Are we between instructions? Can we be interrupted? */ + bool isInbetweenInsts() const; + + /** Act on an interrupt. Returns true if an interrupt was actually + * signalled and invoked */ + bool takeInterrupt(ThreadID thread_id, BranchData &branch); + + /** Try and issue instructions from the inputBuffer */ + unsigned int issue(bool only_issue_microops); + + /** Try to act on PC-related events. Returns true if any were + * executed */ + bool tryPCEvents(); + + /** Do the stats handling and instruction count and PC event events + * related to the new instruction/op counts */ + void doInstCommitAccounting(MinorDynInstPtr inst); + + /** Commit a single instruction. Returns true if the instruction being + * examined was completed (fully executed, discarded, or initiated a + * memory access), false if there is still some processing to do. + * fu_index is the index of the functional unit this instruction is + * being executed in into for funcUnits + * If early_memory_issue is true then this is an early execution + * of a mem ref and so faults will not be processed. + * If the return value is true: + * fault is set if a fault happened, + * branch is set to indicate any branch that occurs + * committed is set to true if this instruction is committed + * (and so needs to be traced and accounted for) + * completed_mem_issue is set if the instruction was a + * memory access that was issued */ + bool commitInst(MinorDynInstPtr inst, bool early_memory_issue, + BranchData &branch, Fault &fault, bool &committed, + bool &completed_mem_issue); + + /** Try and commit instructions from the ends of the functional unit + * pipelines. + * If only_commit_microops is true then only commit upto the + * end of the currect full instruction. + * If discard is true then discard all instructions rather than + * committing. + * branch is set to any branch raised during commit. */ + void commit(bool only_commit_microops, bool discard, BranchData &branch); + + /** Set the drain state (with useful debugging messages) */ + void setDrainState(DrainState state); + + public: + Execute(const std::string &name_, + MinorCPU &cpu_, + MinorCPUParams ¶ms, + Latch<ForwardInstData>::Output inp_, + Latch<BranchData>::Input out_); + + ~Execute(); + + public: + + /** Cause Execute to issue an UnpredictedBranch (or WakeupFetch if + * that was passed as the reason) to Fetch1 to wake the + * system up (using the PC from the thread context). */ + void wakeupFetch(BranchData::Reason reason = + BranchData::UnpredictedBranch); + + /** Returns the DcachePort owned by this Execute to pass upwards */ + MinorCPU::MinorCPUPort &getDcachePort(); + + /** To allow ExecContext to find the LSQ */ + LSQ &getLSQ() { return lsq; } + + /** Does the given instruction have the right stream sequence number + * to be committed? */ + bool instIsRightStream(MinorDynInstPtr inst); + + /** Returns true if the given instruction is at the head of the + * inFlightInsts instruction queue */ + bool instIsHeadInst(MinorDynInstPtr inst); + + /** Pass on input/buffer data to the output if you can */ + void evaluate(); + + void minorTrace() const; + + /** After thread suspension, has Execute been drained of in-flight + * instructions and memory accesses. */ + bool isDrained(); + + /** Like the drain interface on SimObject */ + unsigned int drain(); + void drainResume(); +}; + +} + +#endif /* __CPU_MINOR_EXECUTE_HH__ */ |