inst_queue.hh revision 1684
12686Sksewell@umich.edu#ifndef __CPU_BETA_CPU_INST_QUEUE_HH__ 22686Sksewell@umich.edu#define __CPU_BETA_CPU_INST_QUEUE_HH__ 35268Sksewell@umich.edu 45268Sksewell@umich.edu#include <list> 55268Sksewell@umich.edu#include <map> 65268Sksewell@umich.edu#include <queue> 75268Sksewell@umich.edu#include <stdint.h> 85268Sksewell@umich.edu#include <vector> 95268Sksewell@umich.edu 105268Sksewell@umich.edu#include "base/statistics.hh" 115268Sksewell@umich.edu#include "base/timebuf.hh" 125268Sksewell@umich.edu#include "cpu/inst_seq.hh" 135268Sksewell@umich.edu 145268Sksewell@umich.edu/** 155268Sksewell@umich.edu * A standard instruction queue class. It holds instructions in an 165268Sksewell@umich.edu * array, holds the ordering of the instructions within a linked list, 175268Sksewell@umich.edu * and tracks producer/consumer dependencies within a separate linked 185268Sksewell@umich.edu * list. Similar to the rename map and the free list, it expects that 195268Sksewell@umich.edu * floating point registers have their indices start after the integer 205268Sksewell@umich.edu * registers (ie with 96 int and 96 fp registers, regs 0-95 are integer 215268Sksewell@umich.edu * and 96-191 are fp). This remains true even for both logical and 225268Sksewell@umich.edu * physical register indices. 235268Sksewell@umich.edu */ 245268Sksewell@umich.edutemplate <class Impl> 255268Sksewell@umich.educlass InstructionQueue 265268Sksewell@umich.edu{ 275268Sksewell@umich.edu public: 285268Sksewell@umich.edu //Typedefs from the Impl. 295268Sksewell@umich.edu typedef typename Impl::FullCPU FullCPU; 302706Sksewell@umich.edu typedef typename Impl::DynInstPtr DynInstPtr; 312022SN/A typedef typename Impl::Params Params; 322022SN/A 332022SN/A typedef typename Impl::CPUPol::MemDepUnit MemDepUnit; 342022SN/A typedef typename Impl::CPUPol::IssueStruct IssueStruct; 352022SN/A typedef typename Impl::CPUPol::TimeStruct TimeStruct; 362022SN/A 372022SN/A // Typedef of iterator through the list of instructions. Might be 382022SN/A // better to untie this from the FullCPU or pass its information to 392022SN/A // the stages. 402022SN/A typedef typename std::list<DynInstPtr>::iterator ListIt; 413349Sbinkertn@umich.edu 427720Sgblack@eecs.umich.edu /** 432022SN/A * Struct for comparing entries to be added to the priority queue. This 443349Sbinkertn@umich.edu * gives reverse ordering to the instructions in terms of sequence 452022SN/A * numbers: the instructions with smaller sequence numbers (and hence 462022SN/A * are older) will be at the top of the priority queue. 472022SN/A */ 484661Sksewell@umich.edu struct pqCompare 494661Sksewell@umich.edu { 504661Sksewell@umich.edu bool operator() (const DynInstPtr &lhs, const DynInstPtr &rhs) const 514661Sksewell@umich.edu { 524661Sksewell@umich.edu return lhs->seqNum > rhs->seqNum; 534661Sksewell@umich.edu } 544661Sksewell@umich.edu }; 554661Sksewell@umich.edu 564661Sksewell@umich.edu /** 574661Sksewell@umich.edu * Struct for comparing entries to be added to the set. This gives 584661Sksewell@umich.edu * standard ordering in terms of sequence numbers. 594661Sksewell@umich.edu */ 604661Sksewell@umich.edu struct setCompare 614661Sksewell@umich.edu { 623349Sbinkertn@umich.edu bool operator() (const DynInstPtr &lhs, const DynInstPtr &rhs) const 633349Sbinkertn@umich.edu { 643349Sbinkertn@umich.edu return lhs->seqNum < rhs->seqNum; 653349Sbinkertn@umich.edu } 662447SN/A }; 672022SN/A 682022SN/A typedef std::priority_queue<DynInstPtr, vector<DynInstPtr>, pqCompare> 692022SN/A ReadyInstQueue; 702523SN/A 712447SN/A InstructionQueue(Params ¶ms); 722686Sksewell@umich.edu 734661Sksewell@umich.edu void regStats(); 746334Sgblack@eecs.umich.edu 754661Sksewell@umich.edu void setCPU(FullCPU *cpu); 764661Sksewell@umich.edu 774661Sksewell@umich.edu void setIssueToExecuteQueue(TimeBuffer<IssueStruct> *i2eQueue); 782686Sksewell@umich.edu 792022SN/A void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr); 802022SN/A 812022SN/A unsigned numFreeEntries(); 822022SN/A 832022SN/A bool isFull(); 842022SN/A 852022SN/A void insert(DynInstPtr &new_inst); 864661Sksewell@umich.edu 873348Sbinkertn@umich.edu void insertNonSpec(DynInstPtr &new_inst); 883348Sbinkertn@umich.edu 894661Sksewell@umich.edu void advanceTail(DynInstPtr &inst); 902022SN/A 914661Sksewell@umich.edu void scheduleReadyInsts(); 924661Sksewell@umich.edu 932447SN/A void scheduleNonSpec(const InstSeqNum &inst); 942447SN/A 952022SN/A void wakeDependents(DynInstPtr &completed_inst); 962022SN/A 97 void violation(DynInstPtr &store, DynInstPtr &faulting_load); 98 99 // Change this to take in the sequence number 100 void squash(); 101 102 void doSquash(); 103 104 void stopSquash(); 105 106 private: 107 /** Pointer to the CPU. */ 108 FullCPU *cpu; 109 110 /** The memory dependence unit, which tracks/predicts memory dependences 111 * between instructions. 112 */ 113 MemDepUnit memDepUnit; 114 115 /** The queue to the execute stage. Issued instructions will be written 116 * into it. 117 */ 118 TimeBuffer<IssueStruct> *issueToExecuteQueue; 119 120 /** The backwards time buffer. */ 121 TimeBuffer<TimeStruct> *timeBuffer; 122 123 /** Wire to read information from timebuffer. */ 124 typename TimeBuffer<TimeStruct>::wire fromCommit; 125 126 enum InstList { 127 Int, 128 Float, 129 Branch, 130 Memory, 131 Misc, 132 Squashed, 133 None 134 }; 135 136 /** List of ready int instructions. Used to keep track of the order in 137 * which instructions should issue. 138 */ 139 ReadyInstQueue readyIntInsts; 140 141 /** List of ready floating point instructions. */ 142 ReadyInstQueue readyFloatInsts; 143 144 /** List of ready branch instructions. */ 145 ReadyInstQueue readyBranchInsts; 146 147 /** List of ready miscellaneous instructions. */ 148 ReadyInstQueue readyMiscInsts; 149 150 /** List of squashed instructions (which are still valid and in IQ). 151 * Implemented using a priority queue; the entries must contain both 152 * the IQ index and sequence number of each instruction so that 153 * ordering based on sequence numbers can be used. 154 */ 155 ReadyInstQueue squashedInsts; 156 157 /** List of non-speculative instructions that will be scheduled 158 * once the IQ gets a signal from commit. While it's redundant to 159 * have the key be a part of the value (the sequence number is stored 160 * inside of DynInst), when these instructions are woken up only 161 * the sequence number will be available. Thus it is most efficient to be 162 * able to search by the sequence number alone. 163 */ 164 std::map<InstSeqNum, DynInstPtr> nonSpecInsts; 165 166 typedef typename std::map<InstSeqNum, DynInstPtr>::iterator non_spec_it_t; 167 168 /** Number of free IQ entries left. */ 169 unsigned freeEntries; 170 171 /** The number of entries in the instruction queue. */ 172 unsigned numEntries; 173 174 /** The number of integer instructions that can be issued in one 175 * cycle. 176 */ 177 unsigned intWidth; 178 179 /** The number of floating point instructions that can be issued 180 * in one cycle. 181 */ 182 unsigned floatWidth; 183 184 /** The number of branches that can be issued in one cycle. */ 185 unsigned branchWidth; 186 187 /** The number of memory instructions that can be issued in one cycle. */ 188 unsigned memoryWidth; 189 190 /** The total number of instructions that can be issued in one cycle. */ 191 unsigned totalWidth; 192 193 //The number of physical registers in the CPU. 194 unsigned numPhysRegs; 195 196 /** The number of physical integer registers in the CPU. */ 197 unsigned numPhysIntRegs; 198 199 /** The number of floating point registers in the CPU. */ 200 unsigned numPhysFloatRegs; 201 202 /** Delay between commit stage and the IQ. 203 * @todo: Make there be a distinction between the delays within IEW. 204 */ 205 unsigned commitToIEWDelay; 206 207 ////////////////////////////////// 208 // Variables needed for squashing 209 ////////////////////////////////// 210 211 /** The sequence number of the squashed instruction. */ 212 InstSeqNum squashedSeqNum; 213 214 /** Iterator that points to the youngest instruction in the IQ. */ 215 ListIt tail; 216 217 /** Iterator that points to the last instruction that has been squashed. 218 * This will not be valid unless the IQ is in the process of squashing. 219 */ 220 ListIt squashIt; 221 222 /////////////////////////////////// 223 // Dependency graph stuff 224 /////////////////////////////////// 225 226 class DependencyEntry 227 { 228 public: 229 DynInstPtr inst; 230 //Might want to include data about what arch. register the 231 //dependence is waiting on. 232 DependencyEntry *next; 233 234 //This function, and perhaps this whole class, stand out a little 235 //bit as they don't fit a classification well. I want access 236 //to the underlying structure of the linked list, yet at 237 //the same time it feels like this should be something abstracted 238 //away. So for now it will sit here, within the IQ, until 239 //a better implementation is decided upon. 240 // This function probably shouldn't be within the entry... 241 void insert(DynInstPtr &new_inst); 242 243 void remove(DynInstPtr &inst_to_remove); 244 245 // Debug variable, remove when done testing. 246 static unsigned mem_alloc_counter; 247 }; 248 249 /** Array of linked lists. Each linked list is a list of all the 250 * instructions that depend upon a given register. The actual 251 * register's index is used to index into the graph; ie all 252 * instructions in flight that are dependent upon r34 will be 253 * in the linked list of dependGraph[34]. 254 */ 255 DependencyEntry *dependGraph; 256 257 /** A cache of the recently woken registers. It is 1 if the register 258 * has been woken up recently, and 0 if the register has been added 259 * to the dependency graph and has not yet received its value. It 260 * is basically a secondary scoreboard, and should pretty much mirror 261 * the scoreboard that exists in the rename map. 262 */ 263 vector<bool> regScoreboard; 264 265 bool addToDependents(DynInstPtr &new_inst); 266 void insertDependency(DynInstPtr &new_inst); 267 void createDependency(DynInstPtr &new_inst); 268 269 void addIfReady(DynInstPtr &inst); 270 271 private: 272 /** Debugging function to count how many entries are in the IQ. It does 273 * a linear walk through the instructions, so do not call this function 274 * during normal execution. 275 */ 276 int countInsts(); 277 278 /** Debugging function to dump out the dependency graph. 279 */ 280 void dumpDependGraph(); 281 282 /** Debugging function to dump all the list sizes, as well as print 283 * out the list of nonspeculative instructions. Should not be used 284 * in any other capacity, but it has no harmful sideaffects. 285 */ 286 void dumpLists(); 287 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; 305 306}; 307 308#endif //__CPU_BETA_CPU_INST_QUEUE_HH__ 309