2c2
< * Copyright (c) 2004-2006 The Regents of The University of Michigan
---
> * Copyright (c) 2004-2005 The Regents of The University of Michigan
26a27,28
> *
> * Authors: Kevin Lim
29,30c31,32
< #ifndef __CPU_O3_INST_QUEUE_HH__
< #define __CPU_O3_INST_QUEUE_HH__
---
> #ifndef __CPU_O3_CPU_INST_QUEUE_HH__
> #define __CPU_O3_CPU_INST_QUEUE_HH__
40,41d41
< #include "cpu/o3/dep_graph.hh"
< #include "encumbered/cpu/full/op_class.hh"
44,46d43
< class FUPool;
< class MemInterface;
<
55,62c52
< * physical register indices. The IQ depends on the memory dependence unit to
< * track when memory operations are ready in terms of ordering; register
< * dependencies are tracked normally. Right now the IQ also handles the
< * execution timing; this is mainly to allow back-to-back scheduling without
< * requiring IEW to be able to peek into the IQ. At the end of the execution
< * latency, the instruction is put into the queue to execute, where it will
< * have the execute() function called on it.
< * @todo: Make IQ able to handle multiple FU pools.
---
> * physical register indices.
73d62
< typedef typename Impl::CPUPol::IEW IEW;
78c67,69
< // Typedef of iterator through the list of instructions.
---
> // Typedef of iterator through the list of instructions. Might be
> // better to untie this from the FullCPU or pass its information to
> // the stages.
81c72,84
< friend class Impl::FullCPU;
---
> /**
> * 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;
> }
> };
83,104c86,95
< /** FU completion event class. */
< class FUCompletion : public Event {
< private:
< /** Executing instruction. */
< DynInstPtr inst;
<
< /** Index of the FU used for executing. */
< int fuIdx;
<
< /** Pointer back to the instruction queue. */
< InstructionQueue<Impl> *iqPtr;
<
< bool freeFU;
<
< public:
< /** Construct a FU completion event. */
< FUCompletion(DynInstPtr &_inst, int fu_idx,
< InstructionQueue<Impl> *iq_ptr);
<
< virtual void process();
< virtual const char *description();
< void setFreeFU() { freeFU = true; }
---
> /**
> * 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;
> }
107,108c98,99
< /** Constructs an IQ. */
< InstructionQueue(Params *params);
---
> typedef std::priority_queue<DynInstPtr, vector<DynInstPtr>, pqCompare>
> ReadyInstQueue;
110,111c101
< /** Destructs the IQ. */
< ~InstructionQueue();
---
> InstructionQueue(Params &params);
113,116d102
< /** Returns the name of the IQ. */
< std::string name() const;
<
< /** Registers statistics. */
119c105
< void resetState();
---
> void setCPU(FullCPU *cpu);
121,130d106
< /** Sets CPU pointer. */
< void setCPU(FullCPU *_cpu) { cpu = _cpu; }
<
< /** Sets active threads list. */
< void setActiveThreads(std::list<unsigned> *at_ptr);
<
< /** Sets the IEW pointer. */
< void setIEW(IEW *iew_ptr) { iewStage = iew_ptr; }
<
< /** Sets the timer buffer between issue and execute. */
133d108
< /** Sets the global time buffer. */
136,148d110
< void switchOut();
<
< void takeOverFrom();
<
< bool isSwitchedOut() { return switchedOut; }
<
< /** Number of entries needed for given amount of threads. */
< int entryAmount(int num_threads);
<
< /** Resets max entries for all threads. */
< void resetEntries();
<
< /** Returns total number of free entries. */
151,154d112
< /** Returns number of free entries for a thread. */
< unsigned numFreeEntries(unsigned tid);
<
< /** Returns whether or not the IQ is full. */
157,163d114
< /** Returns whether or not the IQ is full for a specific thread. */
< bool isFull(unsigned tid);
<
< /** Returns if there are any ready instructions in the IQ. */
< bool hasReadyInsts();
<
< /** Inserts a new instruction into the IQ. */
166d116
< /** Inserts a new, non-speculative instruction into the IQ. */
169,172c119
< /** Inserts a memory or write barrier into the IQ to make sure
< * loads and stores are ordered properly.
< */
< void insertBarrier(DynInstPtr &barr_inst);
---
> void advanceTail(DynInstPtr &inst);
174,189d120
< DynInstPtr getInstToExecute();
<
< /**
< * Records the instruction as the producer of a register without
< * adding it to the rest of the IQ.
< */
< void recordProducer(DynInstPtr &inst)
< { addToProducers(inst); }
<
< /** Process FU completion event. */
< void processFUCompletion(DynInstPtr &inst, int fu_idx);
<
< /**
< * Schedules ready instructions, adding the ready ones (oldest first) to
< * the queue to execute.
< */
192d122
< /** Schedules a single specific non-speculative instruction. */
195,199c125
< /**
< * Commits all instructions up to and including the given sequence number,
< * for a specific thread.
< */
< void commit(const InstSeqNum &inst, unsigned tid = 0);
---
> void wakeDependents(DynInstPtr &completed_inst);
201,219d126
< /** Wakes all dependents of a completed instruction. */
< int wakeDependents(DynInstPtr &completed_inst);
<
< /** Adds a ready memory instruction to the ready list. */
< void addReadyMemInst(DynInstPtr &ready_inst);
<
< /**
< * Reschedules a memory instruction. It will be ready to issue once
< * replayMemInst() is called.
< */
< void rescheduleMemInst(DynInstPtr &resched_inst);
<
< /** Replays a memory instruction. It must be rescheduled first. */
< void replayMemInst(DynInstPtr &replay_inst);
<
< /** Completes a memory operation. */
< void completeMemInst(DynInstPtr &completed_inst);
<
< /** Indicates an ordering violation between a store and a load. */
222,226c129,130
< /**
< * Squashes instructions for a thread. Squashing information is obtained
< * from the time buffer.
< */
< void squash(unsigned tid);
---
> // Change this to take in the sequence number
> void squash();
228,229c132
< /** Returns the number of used entries for a thread. */
< unsigned getCount(unsigned tid) { return count[tid]; };
---
> void doSquash();
231,232c134
< /** Debug function to print all instructions. */
< void printInsts();
---
> void stopSquash();
235,241d136
< /** Does the actual squashing. */
< void doSquash(unsigned tid);
<
< /////////////////////////
< // Various pointers
< /////////////////////////
<
245,250d139
< /** Cache interface. */
< MemInterface *dcacheInterface;
<
< /** Pointer to IEW stage. */
< IEW *iewStage;
<
254c143
< MemDepUnit memDepUnit[Impl::MaxThreads];
---
> MemDepUnit memDepUnit;
267,268c156,164
< /** Function unit pool. */
< FUPool *fuPool;
---
> enum InstList {
> Int,
> Float,
> Branch,
> Memory,
> Misc,
> Squashed,
> None
> };
270,272c166,169
< //////////////////////////////////////
< // Instruction lists, ready queues, and ordering
< //////////////////////////////////////
---
> /** List of ready int instructions. Used to keep track of the order in
> * which instructions should issue.
> */
> ReadyInstQueue readyIntInsts;
274,275c171,172
< /** List of all the instructions in the IQ (some of which may be issued). */
< std::list<DynInstPtr> instList[Impl::MaxThreads];
---
> /** List of ready floating point instructions. */
> ReadyInstQueue readyFloatInsts;
277c174,175
< std::list<DynInstPtr> instsToExecute;
---
> /** List of ready branch instructions. */
> ReadyInstQueue readyBranchInsts;
279,290c177,178
< /**
< * 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;
< }
< };
---
> /** List of ready miscellaneous instructions. */
> ReadyInstQueue readyMiscInsts;
292,296c180,183
< typedef std::priority_queue<DynInstPtr, std::vector<DynInstPtr>, pqCompare>
< ReadyInstQueue;
<
< /** List of ready instructions, per op class. They are separated by op
< * class to allow for easy mapping to FUs.
---
> /** 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.
298c185
< ReadyInstQueue readyInsts[Num_OpClasses];
---
> ReadyInstQueue squashedInsts;
309c196
< typedef typename std::map<InstSeqNum, DynInstPtr>::iterator NonSpecMapIt;
---
> typedef typename std::map<InstSeqNum, DynInstPtr>::iterator non_spec_it_t;
311,315c198,199
< /** Entry for the list age ordering by op class. */
< struct ListOrderEntry {
< OpClass queueType;
< InstSeqNum oldestInst;
< };
---
> /** Number of free IQ entries left. */
> unsigned freeEntries;
317,324c201,202
< /** List that contains the age order of the oldest instruction of each
< * ready queue. Used to select the oldest instruction available
< * among op classes.
< * @todo: Might be better to just move these entries around instead
< * of creating new ones every time the position changes due to an
< * instruction issuing. Not sure std::list supports this.
< */
< std::list<ListOrderEntry> listOrder;
---
> /** The number of entries in the instruction queue. */
> unsigned numEntries;
326,332c204,205
< typedef typename std::list<ListOrderEntry>::iterator ListOrderIt;
<
< /** Tracks if each ready queue is on the age order list. */
< bool queueOnList[Num_OpClasses];
<
< /** Iterators of each ready queue. Points to their spot in the age order
< * list.
---
> /** The number of integer instructions that can be issued in one
> * cycle.
334c207
< ListOrderIt readyIt[Num_OpClasses];
---
> unsigned intWidth;
336,341c209,210
< /** Add an op class to the age order list. */
< void addToOrderList(OpClass op_class);
<
< /**
< * Called when the oldest instruction has been removed from a ready queue;
< * this places that ready queue into the proper spot in the age order list.
---
> /** The number of floating point instructions that can be issued
> * in one cycle.
343c212
< void moveToYoungerInst(ListOrderIt age_order_it);
---
> unsigned floatWidth;
345c214,215
< DependencyGraph<DynInstPtr> dependGraph;
---
> /** The number of branches that can be issued in one cycle. */
> unsigned branchWidth;
347,349c217,218
< //////////////////////////////////////
< // Various parameters
< //////////////////////////////////////
---
> /** The number of memory instructions that can be issued in one cycle. */
> unsigned memoryWidth;
351,378d219
< /** IQ Resource Sharing Policy */
< enum IQPolicy {
< Dynamic,
< Partitioned,
< Threshold
< };
<
< /** IQ sharing policy for SMT. */
< IQPolicy iqPolicy;
<
< /** Number of Total Threads*/
< unsigned numThreads;
<
< /** Pointer to list of active threads. */
< std::list<unsigned> *activeThreads;
<
< /** Per Thread IQ count */
< unsigned count[Impl::MaxThreads];
<
< /** Max IQ Entries Per Thread */
< unsigned maxEntries[Impl::MaxThreads];
<
< /** Number of free IQ entries left. */
< unsigned freeEntries;
<
< /** The number of entries in the instruction queue. */
< unsigned numEntries;
<
382c223
< /** The number of physical registers in the CPU. */
---
> //The number of physical registers in the CPU.
396c237,239
< bool switchedOut;
---
> //////////////////////////////////
> // Variables needed for squashing
> //////////////////////////////////
399c242
< InstSeqNum squashedSeqNum[Impl::MaxThreads];
---
> InstSeqNum squashedSeqNum;
400a244,286
> /** 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;
>
407c293
< std::vector<bool> regScoreboard;
---
> vector<bool> regScoreboard;
409d294
< /** Adds an instruction to the dependency graph, as a consumer. */
410a296,297
> void insertDependency(DynInstPtr &new_inst);
> void createDependency(DynInstPtr &new_inst);
412,415d298
< /** Adds an instruction to the dependency graph, as a producer. */
< void addToProducers(DynInstPtr &new_inst);
<
< /** Moves an instruction to the ready queue if it is ready. */
417a301
> private:
423a308,311
> /** Debugging function to dump out the dependency graph.
> */
> void dumpDependGraph();
>
430,435d317
< /** Debugging function to dump out all instructions that are in the
< * IQ.
< */
< void dumpInsts();
<
< /** Stat for number of instructions added. */
437d318
< /** Stat for number of non-speculative instructions added. */
439,441c320
<
< Stats::Scalar<> iqInstsIssued;
< /** Stat for number of integer instructions issued. */
---
> // Stats::Scalar<> iqIntInstsAdded;
443c322
< /** Stat for number of floating point instructions issued. */
---
> // Stats::Scalar<> iqFloatInstsAdded;
445c324
< /** Stat for number of branch instructions issued. */
---
> // Stats::Scalar<> iqBranchInstsAdded;
447c326
< /** Stat for number of memory instructions issued. */
---
> // Stats::Scalar<> iqMemInstsAdded;
449c328
< /** Stat for number of miscellaneous instructions issued. */
---
> // Stats::Scalar<> iqMiscInstsAdded;
451d329
< /** Stat for number of squashed instructions that were ready to issue. */
453c331
< /** Stat for number of squashed instructions examined when squashing. */
---
> Stats::Scalar<> iqLoopSquashStalls;
455,457d332
< /** Stat for number of squashed instruction operands examined when
< * squashing.
< */
459,460d333
< /** Stat for number of non-speculative instructions removed due to a squash.
< */
463,476d335
< Stats::VectorDistribution<> queueResDist;
< Stats::Distribution<> numIssuedDist;
< Stats::VectorDistribution<> issueDelayDist;
<
< Stats::Vector<> statFuBusy;
< // Stats::Vector<> dist_unissued;
< Stats::Vector2d<> statIssuedInstType;
<
< Stats::Formula issueRate;
< // Stats::Formula issue_stores;
< // Stats::Formula issue_op_rate;
< Stats::Vector<> fuBusy; //cumulative fu busy
<
< Stats::Formula fuBusyRate;
479c338
< #endif //__CPU_O3_INST_QUEUE_HH__
---
> #endif //__CPU_O3_CPU_INST_QUEUE_HH__