1 #ifndef __INST_QUEUE_HH__
2 #define __INST_QUEUE_HH__
10 #include "base/statistics.hh"
11 #include "base/timebuf.hh"
12 #include "cpu/inst_seq.hh"
15 * A standard instruction queue class. It holds instructions in an
16 * array, holds the ordering of the instructions within a linked list,
17 * and tracks producer/consumer dependencies within a separate linked
18 * list. Similar to the rename map and the free list, it expects that
19 * floating point registers have their indices start after the integer
20 * registers (ie with 96 int and 96 fp registers, regs 0-95 are integer
21 * and 96-191 are fp). This remains true even for both logical and
22 * physical register indices.
25 class InstructionQueue
28 //Typedefs from the Impl.
29 typedef typename Impl::FullCPU FullCPU;
30 typedef typename Impl::DynInstPtr DynInstPtr;
31 typedef typename Impl::Params Params;
33 typedef typename Impl::CPUPol::MemDepUnit MemDepUnit;
34 typedef typename Impl::CPUPol::IssueStruct IssueStruct;
35 typedef typename Impl::CPUPol::TimeStruct TimeStruct;
37 // Typedef of iterator through the list of instructions. Might be
38 // better to untie this from the FullCPU or pass its information to
40 typedef typename std::list<DynInstPtr>::iterator ListIt;
43 * Struct for comparing entries to be added to the priority queue. This
44 * gives reverse ordering to the instructions in terms of sequence
45 * numbers: the instructions with smaller sequence numbers (and hence
46 * are older) will be at the top of the priority queue.
50 bool operator() (const DynInstPtr &lhs, const DynInstPtr &rhs) const
52 return lhs->seqNum > rhs->seqNum;
57 * Struct for comparing entries to be added to the set. This gives
58 * standard ordering in terms of sequence numbers.
62 bool operator() (const DynInstPtr &lhs, const DynInstPtr &rhs) const
64 return lhs->seqNum < rhs->seqNum;
68 typedef std::priority_queue<DynInstPtr, vector<DynInstPtr>, pqCompare>
71 InstructionQueue(Params ¶ms);
75 void setCPU(FullCPU *cpu);
77 void setIssueToExecuteQueue(TimeBuffer<IssueStruct> *i2eQueue);
79 void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
81 unsigned numFreeEntries();
85 void insert(DynInstPtr &new_inst);
87 void insertNonSpec(DynInstPtr &new_inst);
89 void advanceTail(DynInstPtr &inst);
91 void scheduleReadyInsts();
93 void scheduleNonSpec(const InstSeqNum &inst);
95 void wakeDependents(DynInstPtr &completed_inst);
97 void violation(DynInstPtr &store, DynInstPtr &faulting_load);
99 // Change this to take in the sequence number
106 /** Debugging function to dump all the list sizes, as well as print
107 * out the list of nonspeculative instructions. Should not be used
108 * in any other capacity, but it has no harmful sideaffects.
113 /** Debugging function to count how many entries are in the IQ. It does
114 * a linear walk through the instructions, so do not call this function
115 * during normal execution.
120 /** Pointer to the CPU. */
123 /** The memory dependence unit, which tracks/predicts memory dependences
124 * between instructions.
126 MemDepUnit memDepUnit;
128 /** The queue to the execute stage. Issued instructions will be written
131 TimeBuffer<IssueStruct> *issueToExecuteQueue;
133 /** The backwards time buffer. */
134 TimeBuffer<TimeStruct> *timeBuffer;
136 /** Wire to read information from timebuffer. */
137 typename TimeBuffer<TimeStruct>::wire fromCommit;
149 /** List of ready int instructions. Used to keep track of the order in
150 * which instructions should issue.
152 ReadyInstQueue readyIntInsts;
154 /** List of ready floating point instructions. */
155 ReadyInstQueue readyFloatInsts;
157 /** List of ready branch instructions. */
158 ReadyInstQueue readyBranchInsts;
160 /** List of ready memory instructions. */
161 // ReadyInstQueue readyMemInsts;
163 /** List of ready miscellaneous instructions. */
164 ReadyInstQueue readyMiscInsts;
166 /** List of squashed instructions (which are still valid and in IQ).
167 * Implemented using a priority queue; the entries must contain both
168 * the IQ index and sequence number of each instruction so that
169 * ordering based on sequence numbers can be used.
171 ReadyInstQueue squashedInsts;
173 /** List of non-speculative instructions that will be scheduled
174 * once the IQ gets a signal from commit. While it's redundant to
175 * have the key be a part of the value (the sequence number is stored
176 * inside of DynInst), when these instructions are woken up only
177 * the sequence number will be available. Thus it is necessary to be
178 * able to search by the sequence number alone.
180 std::map<InstSeqNum, DynInstPtr> nonSpecInsts;
182 typedef typename std::map<InstSeqNum, DynInstPtr>::iterator non_spec_it_t;
184 /** Number of free IQ entries left. */
185 unsigned freeEntries;
187 /** The number of entries in the instruction queue. */
190 /** The number of integer instructions that can be issued in one
195 /** The number of floating point instructions that can be issued
200 /** The number of branches that can be issued in one cycle. */
201 unsigned branchWidth;
203 /** The number of memory instructions that can be issued in one cycle. */
204 unsigned memoryWidth;
206 /** The total number of instructions that can be issued in one cycle. */
209 //The number of physical registers in the CPU.
210 unsigned numPhysRegs;
212 /** The number of physical integer registers in the CPU. */
213 unsigned numPhysIntRegs;
215 /** The number of floating point registers in the CPU. */
216 unsigned numPhysFloatRegs;
218 /** Delay between commit stage and the IQ.
219 * @todo: Make there be a distinction between the delays within IEW.
221 unsigned commitToIEWDelay;
223 //////////////////////////////////
224 // Variables needed for squashing
225 //////////////////////////////////
227 /** The sequence number of the squashed instruction. */
228 InstSeqNum squashedSeqNum;
230 /** Iterator that points to the youngest instruction in the IQ. */
233 /** Iterator that points to the last instruction that has been squashed.
234 * This will not be valid unless the IQ is in the process of squashing.
238 ///////////////////////////////////
239 // Dependency graph stuff
240 ///////////////////////////////////
242 class DependencyEntry
246 //Might want to include data about what arch. register the
247 //dependence is waiting on.
248 DependencyEntry *next;
250 //This function, and perhaps this whole class, stand out a little
251 //bit as they don't fit a classification well. I want access
252 //to the underlying structure of the linked list, yet at
253 //the same time it feels like this should be something abstracted
254 //away. So for now it will sit here, within the IQ, until
255 //a better implementation is decided upon.
256 // This function probably shouldn't be within the entry...
257 void insert(DynInstPtr &new_inst);
259 void remove(DynInstPtr &inst_to_remove);
261 // Debug variable, remove when done testing.
262 static unsigned mem_alloc_counter;
265 /** Array of linked lists. Each linked list is a list of all the
266 * instructions that depend upon a given register. The actual
267 * register's index is used to index into the graph; ie all
268 * instructions in flight that are dependent upon r34 will be
269 * in the linked list of dependGraph[34].
271 DependencyEntry *dependGraph;
273 /** A cache of the recently woken registers. It is 1 if the register
274 * has been woken up recently, and 0 if the register has been added
275 * to the dependency graph and has not yet received its value. It
276 * is basically a secondary scoreboard, and should pretty much mirror
277 * the scoreboard that exists in the rename map.
279 vector<bool> regScoreboard;
281 bool addToDependents(DynInstPtr &new_inst);
282 void insertDependency(DynInstPtr &new_inst);
283 void createDependency(DynInstPtr &new_inst);
284 void dumpDependGraph();
286 void addIfReady(DynInstPtr &inst);
288 Stats::Scalar<> iqInstsAdded;
289 Stats::Scalar<> iqNonSpecInstsAdded;
290 // Stats::Scalar<> iqIntInstsAdded;
291 Stats::Scalar<> iqIntInstsIssued;
292 // Stats::Scalar<> iqFloatInstsAdded;
293 Stats::Scalar<> iqFloatInstsIssued;
294 // Stats::Scalar<> iqBranchInstsAdded;
295 Stats::Scalar<> iqBranchInstsIssued;
296 // Stats::Scalar<> iqMemInstsAdded;
297 Stats::Scalar<> iqMemInstsIssued;
298 // Stats::Scalar<> iqMiscInstsAdded;
299 Stats::Scalar<> iqMiscInstsIssued;
300 Stats::Scalar<> iqSquashedInstsIssued;
301 Stats::Scalar<> iqLoopSquashStalls;
302 Stats::Scalar<> iqSquashedInstsExamined;
303 Stats::Scalar<> iqSquashedOperandsExamined;
304 Stats::Scalar<> iqSquashedNonSpecRemoved;
308 #endif //__INST_QUEUE_HH__