diff options
Diffstat (limited to 'src/cpu/minor/execute.hh')
-rw-r--r-- | src/cpu/minor/execute.hh | 128 |
1 files changed, 82 insertions, 46 deletions
diff --git a/src/cpu/minor/execute.hh b/src/cpu/minor/execute.hh index 8cd026534..165a5bae4 100644 --- a/src/cpu/minor/execute.hh +++ b/src/cpu/minor/execute.hh @@ -116,13 +116,13 @@ class Execute : public Named LSQ lsq; /** Scoreboard of instruction dependencies */ - Scoreboard scoreboard; + std::vector<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; + std::vector<InputBuffer<ForwardInstData>> inputBuffer; protected: /** Stage cycle-by-cycle state */ @@ -143,48 +143,75 @@ class Execute : public Named 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; + struct ExecuteThreadInfo { + /** Constructor */ + ExecuteThreadInfo(unsigned int insts_committed) : + inputIndex(0), + lastCommitWasEndOfMacroop(true), + instsBeingCommitted(insts_committed), + streamSeqNum(InstId::firstStreamSeqNum), + lastPredictionSeqNum(InstId::firstPredictionSeqNum), + drainState(NotDraining) + { } + + ExecuteThreadInfo(const ExecuteThreadInfo& other) : + inputIndex(other.inputIndex), + lastCommitWasEndOfMacroop(other.lastCommitWasEndOfMacroop), + instsBeingCommitted(other.instsBeingCommitted), + streamSeqNum(other.streamSeqNum), + lastPredictionSeqNum(other.lastPredictionSeqNum), + drainState(other.drainState) + { } + + /** 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. */ + 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; + }; - /** 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; + std::vector<ExecuteThreadInfo> executeInfo; - /** State progression for draining NotDraining -> ... -> DrainAllInsts */ - DrainState drainState; + ThreadID interruptPriority; + ThreadID issuePriority; + ThreadID commitPriority; 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(); + const ForwardInstData *getInput(ThreadID tid); /** Pop an element off the input buffer, if there are any */ - void popInput(); + void popInput(ThreadID tid); /** Generate Branch data based (into branch) on an observed (or not) * change in PC while executing an instruction. @@ -193,7 +220,7 @@ class Execute : public Named /** 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, + void updateBranchData(ThreadID tid, BranchData::Reason reason, MinorDynInstPtr inst, const TheISA::PCState &target, BranchData &branch); @@ -224,23 +251,32 @@ class Execute : public Named bool isInterrupted(ThreadID thread_id) const; /** Are we between instructions? Can we be interrupted? */ - bool isInbetweenInsts() const; + bool isInbetweenInsts(ThreadID thread_id) 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); + unsigned int issue(ThreadID thread_id); /** Try to act on PC-related events. Returns true if any were * executed */ - bool tryPCEvents(); + bool tryPCEvents(ThreadID thread_id); /** Do the stats handling and instruction count and PC event events * related to the new instruction/op counts */ void doInstCommitAccounting(MinorDynInstPtr inst); + /** Check all threads for possible interrupts. If interrupt is taken, + * returns the tid of the thread. interrupted is set if any thread + * has an interrupt, irrespective of if it is taken */ + ThreadID checkInterrupts(BranchData& branch, bool& interrupted); + + /** Checks if a specific thread has an interrupt. No action is taken. + * this is used for determining if a thread should only commit microops */ + bool hasInterrupt(ThreadID thread_id); + /** 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. @@ -266,10 +302,16 @@ class Execute : public Named * 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); + void commit(ThreadID thread_id, bool only_commit_microops, bool discard, + BranchData &branch); /** Set the drain state (with useful debugging messages) */ - void setDrainState(DrainState state); + void setDrainState(ThreadID thread_id, DrainState state); + + /** Use the current threading policy to determine the next thread to + * decode from. */ + ThreadID getCommittingThread(); + ThreadID getIssuingThread(); public: Execute(const std::string &name_, @@ -282,12 +324,6 @@ class Execute : public Named 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(); |