summaryrefslogtreecommitdiff
path: root/src/cpu/minor/execute.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/minor/execute.hh')
-rw-r--r--src/cpu/minor/execute.hh321
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 &params,
+ 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__ */