diff options
Diffstat (limited to 'cpu/o3/commit.hh')
-rw-r--r-- | cpu/o3/commit.hh | 283 |
1 files changed, 250 insertions, 33 deletions
diff --git a/cpu/o3/commit.hh b/cpu/o3/commit.hh index 580c1a316..93b74ebb0 100644 --- a/cpu/o3/commit.hh +++ b/cpu/o3/commit.hh @@ -26,29 +26,42 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// Todo: Maybe have a special method for handling interrupts/traps. -// -// Traps: Have IEW send a signal to commit saying that there's a trap to -// be handled. Have commit send the PC back to the fetch stage, along -// with the current commit PC. Fetch will directly access the IPR and save -// off all the proper stuff. Commit can send out a squash, or something -// close to it. -// Do the same for hwrei(). However, requires that commit be specifically -// built to support that kind of stuff. Probably not horrible to have -// commit support having the CPU tell it to squash the other stages and -// restart at a given address. The IPR register does become an issue. -// Probably not a big deal if the IPR stuff isn't cycle accurate. Can just -// have the original function handle writing to the IPR register. - -#ifndef __CPU_O3_CPU_SIMPLE_COMMIT_HH__ -#define __CPU_O3_CPU_SIMPLE_COMMIT_HH__ +#ifndef __CPU_O3_COMMIT_HH__ +#define __CPU_O3_COMMIT_HH__ +#include "arch/faults.hh" +#include "cpu/inst_seq.hh" #include "base/statistics.hh" #include "base/timebuf.hh" +#include "cpu/exetrace.hh" #include "mem/memory_interface.hh" +template <class> +class O3ThreadState; + +/** + * DefaultCommit handles single threaded and SMT commit. Its width is specified + * by the parameters; each cycle it tries to commit that many instructions. The + * SMT policy decides which thread it tries to commit instructions from. Non- + * speculative instructions must reach the head of the ROB before they are + * ready to execute; once they reach the head, commit will broadcast the + * instruction's sequence number to the previous stages so that they can issue/ + * execute the instruction. Only one non-speculative instruction is handled per + * cycle. Commit is responsible for handling all back-end initiated redirects. + * It receives the redirect, and then broadcasts it to all stages, indicating + * the sequence number they should squash until, and any necessary branch mis- + * prediction information as well. It priortizes redirects by instruction's age, + * only broadcasting a redirect if it corresponds to an instruction that should + * currently be in the ROB. This is done by tracking the sequence number of the + * youngest instruction in the ROB, which gets updated to any squashing + * instruction's sequence number, and only broadcasting a redirect if it + * corresponds to an older instruction. Commit also supports multiple cycle + * squashing, to model a ROB that can only remove a certain number of + * instructions per cycle. Eventually traps and interrupts will most likely + * be handled here as well. + */ template<class Impl> -class SimpleCommit +class DefaultCommit { public: // Typedefs from the Impl. @@ -57,62 +70,191 @@ class SimpleCommit typedef typename Impl::Params Params; typedef typename Impl::CPUPol CPUPol; + typedef typename CPUPol::RenameMap RenameMap; typedef typename CPUPol::ROB ROB; typedef typename CPUPol::TimeStruct TimeStruct; + typedef typename CPUPol::FetchStruct FetchStruct; typedef typename CPUPol::IEWStruct IEWStruct; typedef typename CPUPol::RenameStruct RenameStruct; - public: - // I don't believe commit can block, so it will only have two - // statuses for now. - // Actually if there's a cache access that needs to block (ie - // uncachable load or just a mem access in commit) then the stage - // may have to wait. - enum Status { + typedef typename CPUPol::IEW IEW; + + typedef O3ThreadState<Impl> Thread; + + class TrapEvent : public Event { + private: + DefaultCommit<Impl> *commit; + unsigned tid; + + public: + TrapEvent(DefaultCommit<Impl> *_commit, unsigned _tid); + + void process(); + const char *description(); + }; + + /** Overall commit status. Used to determine if the CPU can deschedule + * itself due to a lack of activity. + */ + enum CommitStatus{ + Active, + Inactive + }; + + /** Individual thread status. */ + enum ThreadStatus { Running, Idle, ROBSquashing, - DcacheMissStall, - DcacheMissComplete + TrapPending, + FetchTrapPending + }; + + /** Commit policy for SMT mode. */ + enum CommitPolicy { + Aggressive, + RoundRobin, + OldestReady }; private: - Status _status; + /** Overall commit status. */ + CommitStatus _status; + /** Next commit status, to be set at the end of the cycle. */ + CommitStatus _nextStatus; + /** Per-thread status. */ + ThreadStatus commitStatus[Impl::MaxThreads]; + /** Commit policy used in SMT mode. */ + CommitPolicy commitPolicy; public: - SimpleCommit(Params ¶ms); + /** Construct a DefaultCommit with the given parameters. */ + DefaultCommit(Params *params); + + /** Returns the name of the DefaultCommit. */ + std::string name() const; + /** Registers statistics. */ void regStats(); + /** Sets the CPU pointer. */ void setCPU(FullCPU *cpu_ptr); + /** Sets the list of threads. */ + void setThreads(std::vector<Thread *> &threads); + + /** Sets the main time buffer pointer, used for backwards communication. */ void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr); + void setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr); + + /** Sets the pointer to the queue coming from rename. */ void setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr); + /** Sets the pointer to the queue coming from IEW. */ void setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr); + /** Sets the poitner to the IEW stage. */ + void setIEWStage(IEW *iew_stage); + + /** The pointer to the IEW stage. Used solely to ensure that syscalls do + * not execute until all stores have written back. + */ + IEW *iewStage; + + /** Sets pointer to list of active threads. */ + void setActiveThreads(std::list<unsigned> *at_ptr); + + /** Sets pointer to the commited state rename map. */ + void setRenameMap(RenameMap rm_ptr[Impl::MaxThreads]); + + /** Sets pointer to the ROB. */ void setROB(ROB *rob_ptr); + /** Initializes stage by sending back the number of free entries. */ + void initStage(); + + /** Ticks the commit stage, which tries to commit instructions. */ void tick(); + /** Handles any squashes that are sent from IEW, and adds instructions + * to the ROB and tries to commit instructions. + */ void commit(); + /** Returns the number of free ROB entries for a specific thread. */ + unsigned numROBFreeEntries(unsigned tid); + + void generateXCEvent(unsigned tid); + private: + /** Updates the overall status of commit with the nextStatus, and + * tell the CPU if commit is active/inactive. */ + void updateStatus(); + + /** Sets the next status based on threads' statuses, which becomes the + * current status at the end of the cycle. + */ + void setNextStatus(); + /** Checks if the ROB is completed with squashing. This is for the case + * where the ROB can take multiple cycles to complete squashing. + */ + bool robDoneSquashing(); + + /** Returns if any of the threads have the number of ROB entries changed + * on this cycle. Used to determine if the number of free ROB entries needs + * to be sent back to previous stages. + */ + bool changedROBEntries(); + + void squashFromTrap(unsigned tid); + + void squashFromXC(unsigned tid); + + void squashInFlightInsts(unsigned tid); + + private: + /** Commits as many instructions as possible. */ void commitInsts(); + /** Tries to commit the head ROB instruction passed in. + * @param head_inst The instruction to be committed. + */ bool commitHead(DynInstPtr &head_inst, unsigned inst_num); + void generateTrapEvent(unsigned tid); + + /** Gets instructions from rename and inserts them into the ROB. */ void getInsts(); + /** Marks completed instructions using information sent from IEW. */ void markCompletedInsts(); + /** Gets the thread to commit, based on the SMT policy. */ + int getCommittingThread(); + + /** Returns the thread ID to use based on a round robin policy. */ + int roundRobin(); + + /** Returns the thread ID to use based on an oldest instruction policy. */ + int oldestReady(); + public: - uint64_t readCommitPC(); + /** Returns the PC of the head instruction of the ROB. */ + uint64_t readPC(); + + uint64_t readPC(unsigned tid) { return PC[tid]; } - void setSquashing() { _status = ROBSquashing; } + void setPC(uint64_t val, unsigned tid) { PC[tid] = val; } + + uint64_t readNextPC(unsigned tid) { return nextPC[tid]; } + + void setNextPC(uint64_t val, unsigned tid) { nextPC[tid] = val; } + + /** Sets that the ROB is currently squashing. */ + void setSquashing(unsigned tid); private: /** Time buffer interface. */ @@ -124,6 +266,10 @@ class SimpleCommit /** Wire to read information from IEW (for ROB). */ typename TimeBuffer<TimeStruct>::wire robInfoFromIEW; + TimeBuffer<FetchStruct> *fetchQueue; + + typename TimeBuffer<FetchStruct>::wire fromFetch; + /** IEW instruction queue interface. */ TimeBuffer<IEWStruct> *iewQueue; @@ -136,22 +282,56 @@ class SimpleCommit /** Wire to read information from rename queue. */ typename TimeBuffer<RenameStruct>::wire fromRename; + public: /** ROB interface. */ ROB *rob; + private: /** Pointer to FullCPU. */ FullCPU *cpu; /** Memory interface. Used for d-cache accesses. */ MemInterface *dcacheInterface; + std::vector<Thread *> thread; + private: + Fault fetchFault; + InstSeqNum fetchFaultSN; + int fetchTrapWait; + /** Records that commit has written to the time buffer this cycle. Used for + * the CPU to determine if it can deschedule itself if there is no activity. + */ + bool wroteToTimeBuffer; + + /** Records if the number of ROB entries has changed this cycle. If it has, + * then the number of free entries must be re-broadcast. + */ + bool changedROBNumEntries[Impl::MaxThreads]; + + /** A counter of how many threads are currently squashing. */ + int squashCounter; + + /** Records if a thread has to squash this cycle due to a trap. */ + bool trapSquash[Impl::MaxThreads]; + + /** Records if a thread has to squash this cycle due to an XC write. */ + bool xcSquash[Impl::MaxThreads]; + + /** Priority List used for Commit Policy */ + std::list<unsigned> priority_list; + /** IEW to Commit delay, in ticks. */ unsigned iewToCommitDelay; + /** Commit to IEW delay, in ticks. */ + unsigned commitToIEWDelay; + /** Rename to ROB delay, in ticks. */ unsigned renameToROBDelay; + unsigned fetchToCommitDelay; + /** Rename width, in instructions. Used so ROB knows how many * instructions to get from the rename instruction queue. */ @@ -165,16 +345,53 @@ class SimpleCommit /** Commit width, in instructions. */ unsigned commitWidth; + /** Number of Reorder Buffers */ + unsigned numRobs; + + /** Number of Active Threads */ + unsigned numThreads; + + Tick trapLatency; + + Tick fetchTrapLatency; + Tick fetchFaultTick; + + Addr PC[Impl::MaxThreads]; + + Addr nextPC[Impl::MaxThreads]; + + /** The sequence number of the youngest valid instruction in the ROB. */ + InstSeqNum youngestSeqNum[Impl::MaxThreads]; + + /** Pointer to the list of active threads. */ + std::list<unsigned> *activeThreads; + + /** Rename map interface. */ + RenameMap *renameMap[Impl::MaxThreads]; + + /** Stat for the total number of committed instructions. */ Stats::Scalar<> commitCommittedInsts; + /** Stat for the total number of squashed instructions discarded by commit. + */ Stats::Scalar<> commitSquashedInsts; + /** Stat for the total number of times commit is told to squash. + * @todo: Actually increment this stat. + */ Stats::Scalar<> commitSquashEvents; + /** Stat for the total number of times commit has had to stall due to a non- + * speculative instruction reaching the head of the ROB. + */ Stats::Scalar<> commitNonSpecStalls; + /** Stat for the total number of committed branches. */ Stats::Scalar<> commitCommittedBranches; + /** Stat for the total number of committed loads. */ Stats::Scalar<> commitCommittedLoads; + /** Stat for the total number of committed memory references. */ Stats::Scalar<> commitCommittedMemRefs; + /** Stat for the total number of branch mispredicts that caused a squash. */ Stats::Scalar<> branchMispredicts; - - Stats::Distribution<> n_committed_dist; + /** Distribution of the number of committed instructions each cycle. */ + Stats::Distribution<> numCommittedDist; }; -#endif // __CPU_O3_CPU_SIMPLE_COMMIT_HH__ +#endif // __CPU_O3_COMMIT_HH__ |