// Todo: // Add a couple of the branch fields to DynInst. Figure out where DynInst // should try to compute the target of a PC-relative branch. Try to avoid // having so many returns within the code. // Fix up squashing too, as it's too // dependent upon the iew stage continually telling it to squash. #ifndef __SIMPLE_DECODE_HH__ #define __SIMPLE_DECODE_HH__ #include #include "base/timebuf.hh" template class SimpleDecode { private: // Typedefs from the Impl. typedef typename Impl::ISA ISA; typedef typename Impl::FullCPU FullCPU; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::Params Params; typedef typename Impl::CPUPol CPUPol; // Typedefs from the CPU policy. typedef typename CPUPol::FetchStruct FetchStruct; typedef typename CPUPol::DecodeStruct DecodeStruct; typedef typename CPUPol::TimeStruct TimeStruct; // Typedefs from the ISA. typedef typename ISA::Addr Addr; public: // The only time decode will become blocked is if dispatch becomes // blocked, which means IQ or ROB is probably full. enum Status { Running, Idle, Squashing, Blocked, Unblocking }; private: // May eventually need statuses on a per thread basis. Status _status; public: SimpleDecode(Params ¶ms); void regStats(); void setCPU(FullCPU *cpu_ptr); void setTimeBuffer(TimeBuffer *tb_ptr); void setDecodeQueue(TimeBuffer *dq_ptr); void setFetchQueue(TimeBuffer *fq_ptr); void tick(); void decode(); // Might want to make squash a friend function. void squash(); private: void block(); inline void unblock(); void squash(DynInstPtr &inst); // Interfaces to objects outside of decode. /** CPU interface. */ FullCPU *cpu; /** Time buffer interface. */ TimeBuffer *timeBuffer; /** Wire to get rename's output from backwards time buffer. */ typename TimeBuffer::wire fromRename; /** Wire to get iew's information from backwards time buffer. */ typename TimeBuffer::wire fromIEW; /** Wire to get commit's information from backwards time buffer. */ typename TimeBuffer::wire fromCommit; /** Wire to write information heading to previous stages. */ // Might not be the best name as not only fetch will read it. typename TimeBuffer::wire toFetch; /** Decode instruction queue. */ TimeBuffer *decodeQueue; /** Wire used to write any information heading to rename. */ typename TimeBuffer::wire toRename; /** Fetch instruction queue interface. */ TimeBuffer *fetchQueue; /** Wire to get fetch's output from fetch queue. */ typename TimeBuffer::wire fromFetch; /** Skid buffer between fetch and decode. */ std::queue skidBuffer; private: //Consider making these unsigned to avoid any confusion. /** Rename to decode delay, in ticks. */ unsigned renameToDecodeDelay; /** IEW to decode delay, in ticks. */ unsigned iewToDecodeDelay; /** Commit to decode delay, in ticks. */ unsigned commitToDecodeDelay; /** Fetch to decode delay, in ticks. */ unsigned fetchToDecodeDelay; /** The width of decode, in instructions. */ unsigned decodeWidth; /** The instruction that decode is currently on. It needs to have * persistent state so that when a stall occurs in the middle of a * group of instructions, it can restart at the proper instruction. */ unsigned numInst; Stats::Scalar<> decodeIdleCycles; Stats::Scalar<> decodeBlockedCycles; Stats::Scalar<> decodeUnblockCycles; Stats::Scalar<> decodeSquashCycles; Stats::Scalar<> decodeBranchMispred; Stats::Scalar<> decodeControlMispred; Stats::Scalar<> decodeDecodedInsts; Stats::Scalar<> decodeSquashedInsts; }; #endif // __SIMPLE_DECODE_HH__