diff options
Diffstat (limited to 'cpu/ozone/back_end.hh')
-rw-r--r-- | cpu/ozone/back_end.hh | 516 |
1 files changed, 0 insertions, 516 deletions
diff --git a/cpu/ozone/back_end.hh b/cpu/ozone/back_end.hh deleted file mode 100644 index 14b011ab8..000000000 --- a/cpu/ozone/back_end.hh +++ /dev/null @@ -1,516 +0,0 @@ - -#ifndef __CPU_OZONE_BACK_END_HH__ -#define __CPU_OZONE_BACK_END_HH__ - -#include <list> -#include <queue> -#include <string> - -#include "arch/faults.hh" -#include "base/timebuf.hh" -#include "cpu/inst_seq.hh" -#include "cpu/ozone/rename_table.hh" -#include "cpu/ozone/thread_state.hh" -#include "mem/functional/functional.hh" -#include "mem/mem_interface.hh" -#include "mem/mem_req.hh" -#include "sim/eventq.hh" - -class ExecContext; - -template <class Impl> -class OzoneThreadState; - -template <class Impl> -class BackEnd -{ - public: - typedef OzoneThreadState<Impl> Thread; - - typedef typename Impl::Params Params; - typedef typename Impl::DynInst DynInst; - typedef typename Impl::DynInstPtr DynInstPtr; - typedef typename Impl::FullCPU FullCPU; - typedef typename Impl::FrontEnd FrontEnd; - typedef typename Impl::FullCPU::CommStruct CommStruct; - - struct SizeStruct { - int size; - }; - - typedef SizeStruct DispatchToIssue; - typedef SizeStruct IssueToExec; - typedef SizeStruct ExecToCommit; - typedef SizeStruct Writeback; - - TimeBuffer<DispatchToIssue> d2i; - typename TimeBuffer<DispatchToIssue>::wire instsToDispatch; - TimeBuffer<IssueToExec> i2e; - typename TimeBuffer<IssueToExec>::wire instsToExecute; - TimeBuffer<ExecToCommit> e2c; - TimeBuffer<Writeback> numInstsToWB; - - TimeBuffer<CommStruct> *comm; - typename TimeBuffer<CommStruct>::wire toIEW; - typename TimeBuffer<CommStruct>::wire fromCommit; - - class InstQueue { - enum queue { - NonSpec, - IQ, - ToBeScheduled, - ReadyList, - ReplayList - }; - struct pqCompare { - bool operator() (const DynInstPtr &lhs, const DynInstPtr &rhs) const - { - return lhs->seqNum > rhs->seqNum; - } - }; - public: - InstQueue(Params *params); - - std::string name() const; - - void regStats(); - - void setIssueExecQueue(TimeBuffer<IssueToExec> *i2e_queue); - - void setBE(BackEnd *_be) { be = _be; } - - void insert(DynInstPtr &inst); - - void scheduleReadyInsts(); - - void scheduleNonSpec(const InstSeqNum &sn); - - DynInstPtr getReadyInst(); - - void commit(const InstSeqNum &sn) {} - - void squash(const InstSeqNum &sn); - - int wakeDependents(DynInstPtr &inst); - - /** Tells memory dependence unit that a memory instruction needs to be - * rescheduled. It will re-execute once replayMemInst() is called. - */ - void rescheduleMemInst(DynInstPtr &inst); - - /** Re-executes all rescheduled memory instructions. */ - void replayMemInst(DynInstPtr &inst); - - /** Completes memory instruction. */ - void completeMemInst(DynInstPtr &inst); - - void violation(DynInstPtr &inst, DynInstPtr &violation) { } - - bool isFull() { return numInsts >= size; } - - void dumpInsts(); - - private: - bool find(queue q, typename std::list<DynInstPtr>::iterator it); - BackEnd *be; - TimeBuffer<IssueToExec> *i2e; - typename TimeBuffer<IssueToExec>::wire numIssued; - typedef typename std::list<DynInstPtr> InstList; - typedef typename std::list<DynInstPtr>::iterator InstListIt; - typedef typename std::priority_queue<DynInstPtr, std::vector<DynInstPtr>, pqCompare> ReadyInstQueue; - // Not sure I need the IQ list; it just needs to be a count. - InstList iq; - InstList toBeScheduled; - InstList readyList; - InstList nonSpec; - InstList replayList; - ReadyInstQueue readyQueue; - public: - int size; - int numInsts; - int width; - - Stats::VectorDistribution<> occ_dist; - - Stats::Vector<> inst_count; - Stats::Vector<> peak_inst_count; - Stats::Scalar<> empty_count; - Stats::Scalar<> current_count; - Stats::Scalar<> fullCount; - - Stats::Formula occ_rate; - Stats::Formula avg_residency; - Stats::Formula empty_rate; - Stats::Formula full_rate; - }; - - /** LdWriteback event for a load completion. */ - class LdWritebackEvent : public Event { - private: - /** Instruction that is writing back data to the register file. */ - DynInstPtr inst; - /** Pointer to IEW stage. */ - BackEnd *be; - - public: - /** Constructs a load writeback event. */ - LdWritebackEvent(DynInstPtr &_inst, BackEnd *be); - - /** Processes writeback event. */ - virtual void process(); - /** Returns the description of the writeback event. */ - virtual const char *description(); - }; - - BackEnd(Params *params); - - std::string name() const; - - void regStats(); - - void setCPU(FullCPU *cpu_ptr) - { cpu = cpu_ptr; } - - void setFrontEnd(FrontEnd *front_end_ptr) - { frontEnd = front_end_ptr; } - - void setXC(ExecContext *xc_ptr) - { xc = xc_ptr; } - - void setThreadState(Thread *thread_ptr) - { thread = thread_ptr; } - - void setCommBuffer(TimeBuffer<CommStruct> *_comm); - - void tick(); - void squash(); - void squashFromXC(); - bool xcSquash; - - template <class T> - Fault read(MemReqPtr &req, T &data, int load_idx); - - template <class T> - Fault write(MemReqPtr &req, T &data, int store_idx); - - Addr readCommitPC() { return commitPC; } - - Addr commitPC; - - bool robEmpty() { return instList.empty(); } - - bool isFull() { return numInsts >= numROBEntries; } - bool isBlocked() { return status == Blocked || dispatchStatus == Blocked; } - - /** Tells memory dependence unit that a memory instruction needs to be - * rescheduled. It will re-execute once replayMemInst() is called. - */ - void rescheduleMemInst(DynInstPtr &inst) - { IQ.rescheduleMemInst(inst); } - - /** Re-executes all rescheduled memory instructions. */ - void replayMemInst(DynInstPtr &inst) - { IQ.replayMemInst(inst); } - - /** Completes memory instruction. */ - void completeMemInst(DynInstPtr &inst) - { IQ.completeMemInst(inst); } - - void fetchFault(Fault &fault); - - private: - void updateStructures(); - void dispatchInsts(); - void dispatchStall(); - void checkDispatchStatus(); - void scheduleReadyInsts(); - void executeInsts(); - void commitInsts(); - void addToIQ(DynInstPtr &inst); - void addToLSQ(DynInstPtr &inst); - void instToCommit(DynInstPtr &inst); - void writebackInsts(); - bool commitInst(int inst_num); - void squash(const InstSeqNum &sn); - void squashDueToBranch(DynInstPtr &inst); - void squashDueToMemBlocked(DynInstPtr &inst); - void updateExeInstStats(DynInstPtr &inst); - void updateComInstStats(DynInstPtr &inst); - - public: - FullCPU *cpu; - - FrontEnd *frontEnd; - - ExecContext *xc; - - Thread *thread; - - enum Status { - Running, - Idle, - DcacheMissStall, - DcacheMissComplete, - Blocked - }; - - Status status; - - Status dispatchStatus; - - Counter funcExeInst; - - private: -// typedef typename Impl::InstQueue InstQueue; - - InstQueue IQ; - - typedef typename Impl::LdstQueue LdstQueue; - - LdstQueue LSQ; - public: - RenameTable<Impl> commitRenameTable; - - RenameTable<Impl> renameTable; - private: - class DCacheCompletionEvent : public Event - { - private: - BackEnd *be; - - public: - DCacheCompletionEvent(BackEnd *_be); - - virtual void process(); - virtual const char *description(); - }; - - friend class DCacheCompletionEvent; - - DCacheCompletionEvent cacheCompletionEvent; - - MemInterface *dcacheInterface; - - MemReqPtr memReq; - - // General back end width. Used if the more specific isn't given. - int width; - - // Dispatch width. - int dispatchWidth; - int numDispatchEntries; - int dispatchSize; - - int issueWidth; - - // Writeback width - int wbWidth; - - // Commit width - int commitWidth; - - /** 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; - - int numROBEntries; - int numInsts; - - bool squashPending; - InstSeqNum squashSeqNum; - Addr squashNextPC; - - Fault faultFromFetch; - - private: - typedef typename std::list<DynInstPtr>::iterator InstListIt; - - std::list<DynInstPtr> instList; - std::list<DynInstPtr> dispatch; - std::list<DynInstPtr> writeback; - - int latency; - - int squashLatency; - - bool exactFullStall; - - bool fetchRedirect[Impl::MaxThreads]; - - // number of cycles stalled for D-cache misses -/* Stats::Scalar<> dcacheStallCycles; - Counter lastDcacheStall; -*/ - Stats::Vector<> rob_cap_events; - Stats::Vector<> rob_cap_inst_count; - Stats::Vector<> iq_cap_events; - Stats::Vector<> iq_cap_inst_count; - // total number of instructions executed - Stats::Vector<> exe_inst; - Stats::Vector<> exe_swp; - Stats::Vector<> exe_nop; - Stats::Vector<> exe_refs; - Stats::Vector<> exe_loads; - Stats::Vector<> exe_branches; - - Stats::Vector<> issued_ops; - - // total number of loads forwaded from LSQ stores - Stats::Vector<> lsq_forw_loads; - - // total number of loads ignored due to invalid addresses - Stats::Vector<> inv_addr_loads; - - // total number of software prefetches ignored due to invalid addresses - Stats::Vector<> inv_addr_swpfs; - // ready loads blocked due to memory disambiguation - Stats::Vector<> lsq_blocked_loads; - - Stats::Scalar<> lsqInversion; - - Stats::Vector<> n_issued_dist; - Stats::VectorDistribution<> issue_delay_dist; - - Stats::VectorDistribution<> queue_res_dist; -/* - Stats::Vector<> stat_fu_busy; - Stats::Vector2d<> stat_fuBusy; - Stats::Vector<> dist_unissued; - Stats::Vector2d<> stat_issued_inst_type; - - Stats::Formula misspec_cnt; - Stats::Formula misspec_ipc; - Stats::Formula issue_rate; - Stats::Formula issue_stores; - Stats::Formula issue_op_rate; - Stats::Formula fu_busy_rate; - Stats::Formula commit_stores; - Stats::Formula commit_ipc; - Stats::Formula commit_ipb; - Stats::Formula lsq_inv_rate; -*/ - Stats::Vector<> writeback_count; - Stats::Vector<> producer_inst; - Stats::Vector<> consumer_inst; - Stats::Vector<> wb_penalized; - - Stats::Formula wb_rate; - Stats::Formula wb_fanout; - Stats::Formula wb_penalized_rate; - - // total number of instructions committed - Stats::Vector<> stat_com_inst; - Stats::Vector<> stat_com_swp; - Stats::Vector<> stat_com_refs; - Stats::Vector<> stat_com_loads; - Stats::Vector<> stat_com_membars; - Stats::Vector<> stat_com_branches; - - Stats::Distribution<> n_committed_dist; - - Stats::Scalar<> commit_eligible_samples; - Stats::Vector<> commit_eligible; - - Stats::Scalar<> ROB_fcount; - Stats::Formula ROB_full_rate; - - Stats::Vector<> ROB_count; // cumulative ROB occupancy - Stats::Formula ROB_occ_rate; - Stats::VectorDistribution<> ROB_occ_dist; - public: - void dumpInsts(); -}; - -template <class Impl> -template <class T> -Fault -BackEnd<Impl>::read(MemReqPtr &req, T &data, int load_idx) -{ -/* memReq->reset(addr, sizeof(T), flags); - - // translate to physical address - Fault fault = cpu->translateDataReadReq(memReq); - - // if we have a cache, do cache access too - if (fault == NoFault && dcacheInterface) { - memReq->cmd = Read; - memReq->completionEvent = NULL; - memReq->time = curTick; - memReq->flags &= ~INST_READ; - MemAccessResult result = dcacheInterface->access(memReq); - - // Ugly hack to get an event scheduled *only* if the access is - // a miss. We really should add first-class support for this - // at some point. - if (result != MA_HIT && dcacheInterface->doEvents()) { - // Fix this hack for keeping funcExeInst correct with loads that - // are executed twice. - --funcExeInst; - - memReq->completionEvent = &cacheCompletionEvent; - lastDcacheStall = curTick; -// unscheduleTickEvent(); -// status = DcacheMissStall; - DPRINTF(OzoneCPU, "Dcache miss stall!\n"); - } else { - // do functional access - fault = thread->mem->read(memReq, data); - - } - } -*/ -/* - if (!dcacheInterface && (memReq->flags & UNCACHEABLE)) - recordEvent("Uncached Read"); -*/ - return LSQ.read(req, data, load_idx); -} - -template <class Impl> -template <class T> -Fault -BackEnd<Impl>::write(MemReqPtr &req, T &data, int store_idx) -{ -/* - memReq->reset(addr, sizeof(T), flags); - - // translate to physical address - Fault fault = cpu->translateDataWriteReq(memReq); - - if (fault == NoFault && dcacheInterface) { - memReq->cmd = Write; - memcpy(memReq->data,(uint8_t *)&data,memReq->size); - memReq->completionEvent = NULL; - memReq->time = curTick; - memReq->flags &= ~INST_READ; - MemAccessResult result = dcacheInterface->access(memReq); - - // Ugly hack to get an event scheduled *only* if the access is - // a miss. We really should add first-class support for this - // at some point. - if (result != MA_HIT && dcacheInterface->doEvents()) { - memReq->completionEvent = &cacheCompletionEvent; - lastDcacheStall = curTick; -// unscheduleTickEvent(); -// status = DcacheMissStall; - DPRINTF(OzoneCPU, "Dcache miss stall!\n"); - } - } - - if (res && (fault == NoFault)) - *res = memReq->result; - */ -/* - if (!dcacheInterface && (memReq->flags & UNCACHEABLE)) - recordEvent("Uncached Write"); -*/ - return LSQ.write(req, data, store_idx); -} - -#endif // __CPU_OZONE_BACK_END_HH__ |