inst_queue.hh
来自「linux下基于c++的处理器仿真平台。具有处理器流水线」· HH 代码 · 共 340 行
HH
340 行
/* * Copyright (c) 2004, 2005 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator, developed by Nathan Binkert, * Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions * from Ron Dreslinski, Dave Greene, Lisa Hsu, Kevin Lim, Ali Saidi, * and Andrew Schultz. * * Permission is granted to use, copy, create derivative works and * redistribute this software and such derivative works for any * purpose, so long as the copyright notice above, this grant of * permission, and the disclaimer below appear in all copies made; and * so long as the name of The University of Michigan is not used in * any advertising or publicity pertaining to the use or distribution * of this software without specific, written prior authorization. * * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. */#ifndef __CPU_O3_CPU_INST_QUEUE_HH__#define __CPU_O3_CPU_INST_QUEUE_HH__#include <list>#include <map>#include <queue>#include <vector>#include "base/statistics.hh"#include "base/timebuf.hh"#include "cpu/inst_seq.hh"#include "sim/host.hh"/** * A standard instruction queue class. It holds ready instructions, in * order, in seperate priority queues to facilitate the scheduling of * instructions. The IQ uses a separate linked list to track dependencies. * Similar to the rename map and the free list, it expects that * floating point registers have their indices start after the integer * registers (ie with 96 int and 96 fp registers, regs 0-95 are integer * and 96-191 are fp). This remains true even for both logical and * physical register indices. */template <class Impl>class InstructionQueue{ public: //Typedefs from the Impl. typedef typename Impl::FullCPU FullCPU; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::Params Params; typedef typename Impl::CPUPol::MemDepUnit MemDepUnit; typedef typename Impl::CPUPol::IssueStruct IssueStruct; typedef typename Impl::CPUPol::TimeStruct TimeStruct; // Typedef of iterator through the list of instructions. Might be // better to untie this from the FullCPU or pass its information to // the stages. typedef typename std::list<DynInstPtr>::iterator ListIt; /** * Struct for comparing entries to be added to the priority queue. This * gives reverse ordering to the instructions in terms of sequence * numbers: the instructions with smaller sequence numbers (and hence * are older) will be at the top of the priority queue. */ struct pqCompare { bool operator() (const DynInstPtr &lhs, const DynInstPtr &rhs) const { return lhs->seqNum > rhs->seqNum; } }; /** * Struct for comparing entries to be added to the set. This gives * standard ordering in terms of sequence numbers. */ struct setCompare { bool operator() (const DynInstPtr &lhs, const DynInstPtr &rhs) const { return lhs->seqNum < rhs->seqNum; } }; typedef std::priority_queue<DynInstPtr, vector<DynInstPtr>, pqCompare> ReadyInstQueue; InstructionQueue(Params ¶ms); void regStats(); void setCPU(FullCPU *cpu); void setIssueToExecuteQueue(TimeBuffer<IssueStruct> *i2eQueue); void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr); unsigned numFreeEntries(); bool isFull(); void insert(DynInstPtr &new_inst); void insertNonSpec(DynInstPtr &new_inst); void advanceTail(DynInstPtr &inst); void scheduleReadyInsts(); void scheduleNonSpec(const InstSeqNum &inst); void wakeDependents(DynInstPtr &completed_inst); void violation(DynInstPtr &store, DynInstPtr &faulting_load); // Change this to take in the sequence number void squash(); void doSquash(); void stopSquash(); private: /** Pointer to the CPU. */ FullCPU *cpu; /** The memory dependence unit, which tracks/predicts memory dependences * between instructions. */ MemDepUnit memDepUnit; /** The queue to the execute stage. Issued instructions will be written * into it. */ TimeBuffer<IssueStruct> *issueToExecuteQueue; /** The backwards time buffer. */ TimeBuffer<TimeStruct> *timeBuffer; /** Wire to read information from timebuffer. */ typename TimeBuffer<TimeStruct>::wire fromCommit; enum InstList { Int, Float, Branch, Memory, Misc, Squashed, None }; /** List of ready int instructions. Used to keep track of the order in * which instructions should issue. */ ReadyInstQueue readyIntInsts; /** List of ready floating point instructions. */ ReadyInstQueue readyFloatInsts; /** List of ready branch instructions. */ ReadyInstQueue readyBranchInsts; /** List of ready miscellaneous instructions. */ ReadyInstQueue readyMiscInsts; /** List of squashed instructions (which are still valid and in IQ). * Implemented using a priority queue; the entries must contain both * the IQ index and sequence number of each instruction so that * ordering based on sequence numbers can be used. */ ReadyInstQueue squashedInsts; /** List of non-speculative instructions that will be scheduled * once the IQ gets a signal from commit. While it's redundant to * have the key be a part of the value (the sequence number is stored * inside of DynInst), when these instructions are woken up only * the sequence number will be available. Thus it is most efficient to be * able to search by the sequence number alone. */ std::map<InstSeqNum, DynInstPtr> nonSpecInsts; typedef typename std::map<InstSeqNum, DynInstPtr>::iterator non_spec_it_t; /** Number of free IQ entries left. */ unsigned freeEntries; /** The number of entries in the instruction queue. */ unsigned numEntries; /** The number of integer instructions that can be issued in one * cycle. */ unsigned intWidth; /** The number of floating point instructions that can be issued * in one cycle. */ unsigned floatWidth; /** The number of branches that can be issued in one cycle. */ unsigned branchWidth; /** The number of memory instructions that can be issued in one cycle. */ unsigned memoryWidth; /** The total number of instructions that can be issued in one cycle. */ unsigned totalWidth; //The number of physical registers in the CPU. unsigned numPhysRegs; /** The number of physical integer registers in the CPU. */ unsigned numPhysIntRegs; /** The number of floating point registers in the CPU. */ unsigned numPhysFloatRegs; /** Delay between commit stage and the IQ. * @todo: Make there be a distinction between the delays within IEW. */ unsigned commitToIEWDelay; ////////////////////////////////// // Variables needed for squashing ////////////////////////////////// /** The sequence number of the squashed instruction. */ InstSeqNum squashedSeqNum; /** Iterator that points to the youngest instruction in the IQ. */ ListIt tail; /** Iterator that points to the last instruction that has been squashed. * This will not be valid unless the IQ is in the process of squashing. */ ListIt squashIt; /////////////////////////////////// // Dependency graph stuff /////////////////////////////////// class DependencyEntry { public: DynInstPtr inst; //Might want to include data about what arch. register the //dependence is waiting on. DependencyEntry *next; //This function, and perhaps this whole class, stand out a little //bit as they don't fit a classification well. I want access //to the underlying structure of the linked list, yet at //the same time it feels like this should be something abstracted //away. So for now it will sit here, within the IQ, until //a better implementation is decided upon. // This function probably shouldn't be within the entry... void insert(DynInstPtr &new_inst); void remove(DynInstPtr &inst_to_remove); // Debug variable, remove when done testing. static unsigned mem_alloc_counter; }; /** Array of linked lists. Each linked list is a list of all the * instructions that depend upon a given register. The actual * register's index is used to index into the graph; ie all * instructions in flight that are dependent upon r34 will be * in the linked list of dependGraph[34]. */ DependencyEntry *dependGraph; /** A cache of the recently woken registers. It is 1 if the register * has been woken up recently, and 0 if the register has been added * to the dependency graph and has not yet received its value. It * is basically a secondary scoreboard, and should pretty much mirror * the scoreboard that exists in the rename map. */ vector<bool> regScoreboard; bool addToDependents(DynInstPtr &new_inst); void insertDependency(DynInstPtr &new_inst); void createDependency(DynInstPtr &new_inst); void addIfReady(DynInstPtr &inst); private: /** Debugging function to count how many entries are in the IQ. It does * a linear walk through the instructions, so do not call this function * during normal execution. */ int countInsts(); /** Debugging function to dump out the dependency graph. */ void dumpDependGraph(); /** Debugging function to dump all the list sizes, as well as print * out the list of nonspeculative instructions. Should not be used * in any other capacity, but it has no harmful sideaffects. */ void dumpLists(); Stats::Scalar<> iqInstsAdded; Stats::Scalar<> iqNonSpecInstsAdded;// Stats::Scalar<> iqIntInstsAdded; Stats::Scalar<> iqIntInstsIssued;// Stats::Scalar<> iqFloatInstsAdded; Stats::Scalar<> iqFloatInstsIssued;// Stats::Scalar<> iqBranchInstsAdded; Stats::Scalar<> iqBranchInstsIssued;// Stats::Scalar<> iqMemInstsAdded; Stats::Scalar<> iqMemInstsIssued;// Stats::Scalar<> iqMiscInstsAdded; Stats::Scalar<> iqMiscInstsIssued; Stats::Scalar<> iqSquashedInstsIssued; Stats::Scalar<> iqLoopSquashStalls; Stats::Scalar<> iqSquashedInstsExamined; Stats::Scalar<> iqSquashedOperandsExamined; Stats::Scalar<> iqSquashedNonSpecRemoved;};#endif //__CPU_O3_CPU_INST_QUEUE_HH__
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?