dep_graph.hh revision 7720
12651Ssaidi@eecs.umich.edu/* 22651Ssaidi@eecs.umich.edu * Copyright (c) 2006 The Regents of The University of Michigan 32651Ssaidi@eecs.umich.edu * All rights reserved. 42651Ssaidi@eecs.umich.edu * 52651Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 62651Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are 72651Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright 82651Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 92651Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 102651Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 112651Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution; 122651Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its 132651Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from 142651Ssaidi@eecs.umich.edu * this software without specific prior written permission. 152651Ssaidi@eecs.umich.edu * 162651Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172651Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182651Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192651Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202651Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212651Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222651Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232651Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242651Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252651Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262651Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272651Ssaidi@eecs.umich.edu * 282651Ssaidi@eecs.umich.edu * Authors: Kevin Lim 292651Ssaidi@eecs.umich.edu */ 302651Ssaidi@eecs.umich.edu 312651Ssaidi@eecs.umich.edu#ifndef __CPU_O3_DEP_GRAPH_HH__ 322651Ssaidi@eecs.umich.edu#define __CPU_O3_DEP_GRAPH_HH__ 332651Ssaidi@eecs.umich.edu 342651Ssaidi@eecs.umich.edu#include "cpu/o3/comm.hh" 352651Ssaidi@eecs.umich.edu 362651Ssaidi@eecs.umich.edu/** Node in a linked list. */ 372651Ssaidi@eecs.umich.edutemplate <class DynInstPtr> 382651Ssaidi@eecs.umich.educlass DependencyEntry 392651Ssaidi@eecs.umich.edu{ 402651Ssaidi@eecs.umich.edu public: 412651Ssaidi@eecs.umich.edu DependencyEntry() 422651Ssaidi@eecs.umich.edu : inst(NULL), next(NULL) 432651Ssaidi@eecs.umich.edu { } 442651Ssaidi@eecs.umich.edu 452651Ssaidi@eecs.umich.edu DynInstPtr inst; 462651Ssaidi@eecs.umich.edu //Might want to include data about what arch. register the 472651Ssaidi@eecs.umich.edu //dependence is waiting on. 482651Ssaidi@eecs.umich.edu DependencyEntry<DynInstPtr> *next; 492651Ssaidi@eecs.umich.edu}; 502651Ssaidi@eecs.umich.edu 512651Ssaidi@eecs.umich.edu/** Array of linked list that maintains the dependencies between 522651Ssaidi@eecs.umich.edu * producing instructions and consuming instructions. Each linked 532651Ssaidi@eecs.umich.edu * list represents a single physical register, having the future 542651Ssaidi@eecs.umich.edu * producer of the register's value, and all consumers waiting on that 552651Ssaidi@eecs.umich.edu * value on the list. The head node of each linked list represents 562651Ssaidi@eecs.umich.edu * the producing instruction of that register. Instructions are put 572651Ssaidi@eecs.umich.edu * on the list upon reaching the IQ, and are removed from the list 582651Ssaidi@eecs.umich.edu * either when the producer completes, or the instruction is squashed. 592651Ssaidi@eecs.umich.edu*/ 602651Ssaidi@eecs.umich.edutemplate <class DynInstPtr> 612651Ssaidi@eecs.umich.educlass DependencyGraph 622651Ssaidi@eecs.umich.edu{ 632651Ssaidi@eecs.umich.edu public: 642651Ssaidi@eecs.umich.edu typedef DependencyEntry<DynInstPtr> DepEntry; 652651Ssaidi@eecs.umich.edu 662651Ssaidi@eecs.umich.edu /** Default construction. Must call resize() prior to use. */ 672651Ssaidi@eecs.umich.edu DependencyGraph() 682651Ssaidi@eecs.umich.edu : numEntries(0), memAllocCounter(0), nodesTraversed(0), nodesRemoved(0) 692651Ssaidi@eecs.umich.edu { } 702651Ssaidi@eecs.umich.edu 712651Ssaidi@eecs.umich.edu ~DependencyGraph(); 722651Ssaidi@eecs.umich.edu 732651Ssaidi@eecs.umich.edu /** Resize the dependency graph to have num_entries registers. */ 742651Ssaidi@eecs.umich.edu void resize(int num_entries); 752651Ssaidi@eecs.umich.edu 762651Ssaidi@eecs.umich.edu /** Clears all of the linked lists. */ 772651Ssaidi@eecs.umich.edu void reset(); 782651Ssaidi@eecs.umich.edu 792651Ssaidi@eecs.umich.edu /** Inserts an instruction to be dependent on the given index. */ 802651Ssaidi@eecs.umich.edu void insert(PhysRegIndex idx, DynInstPtr &new_inst); 812651Ssaidi@eecs.umich.edu 822651Ssaidi@eecs.umich.edu /** Sets the producing instruction of a given register. */ 832651Ssaidi@eecs.umich.edu void setInst(PhysRegIndex idx, DynInstPtr &new_inst) 842651Ssaidi@eecs.umich.edu { dependGraph[idx].inst = new_inst; } 852651Ssaidi@eecs.umich.edu 862651Ssaidi@eecs.umich.edu /** Clears the producing instruction. */ 872651Ssaidi@eecs.umich.edu void clearInst(PhysRegIndex idx) 882651Ssaidi@eecs.umich.edu { dependGraph[idx].inst = NULL; } 89 90 /** Removes an instruction from a single linked list. */ 91 void remove(PhysRegIndex idx, DynInstPtr &inst_to_remove); 92 93 /** Removes and returns the newest dependent of a specific register. */ 94 DynInstPtr pop(PhysRegIndex idx); 95 96 /** Checks if there are any dependents on a specific register. */ 97 bool empty(PhysRegIndex idx) { return !dependGraph[idx].next; } 98 99 /** Debugging function to dump out the dependency graph. 100 */ 101 void dump(); 102 103 private: 104 /** Array of linked lists. Each linked list is a list of all the 105 * instructions that depend upon a given register. The actual 106 * register's index is used to index into the graph; ie all 107 * instructions in flight that are dependent upon r34 will be 108 * in the linked list of dependGraph[34]. 109 */ 110 DepEntry *dependGraph; 111 112 /** Number of linked lists; identical to the number of registers. */ 113 int numEntries; 114 115 // Debug variable, remove when done testing. 116 unsigned memAllocCounter; 117 118 public: 119 // Debug variable, remove when done testing. 120 uint64_t nodesTraversed; 121 // Debug variable, remove when done testing. 122 uint64_t nodesRemoved; 123}; 124 125template <class DynInstPtr> 126DependencyGraph<DynInstPtr>::~DependencyGraph() 127{ 128 delete [] dependGraph; 129} 130 131template <class DynInstPtr> 132void 133DependencyGraph<DynInstPtr>::resize(int num_entries) 134{ 135 numEntries = num_entries; 136 dependGraph = new DepEntry[numEntries]; 137} 138 139template <class DynInstPtr> 140void 141DependencyGraph<DynInstPtr>::reset() 142{ 143 // Clear the dependency graph 144 DepEntry *curr; 145 DepEntry *prev; 146 147 for (int i = 0; i < numEntries; ++i) { 148 curr = dependGraph[i].next; 149 150 while (curr) { 151 memAllocCounter--; 152 153 prev = curr; 154 curr = prev->next; 155 prev->inst = NULL; 156 157 delete prev; 158 } 159 160 if (dependGraph[i].inst) { 161 dependGraph[i].inst = NULL; 162 } 163 164 dependGraph[i].next = NULL; 165 } 166} 167 168template <class DynInstPtr> 169void 170DependencyGraph<DynInstPtr>::insert(PhysRegIndex idx, DynInstPtr &new_inst) 171{ 172 //Add this new, dependent instruction at the head of the dependency 173 //chain. 174 175 // First create the entry that will be added to the head of the 176 // dependency chain. 177 DepEntry *new_entry = new DepEntry; 178 new_entry->next = dependGraph[idx].next; 179 new_entry->inst = new_inst; 180 181 // Then actually add it to the chain. 182 dependGraph[idx].next = new_entry; 183 184 ++memAllocCounter; 185} 186 187 188template <class DynInstPtr> 189void 190DependencyGraph<DynInstPtr>::remove(PhysRegIndex idx, 191 DynInstPtr &inst_to_remove) 192{ 193 DepEntry *prev = &dependGraph[idx]; 194 DepEntry *curr = dependGraph[idx].next; 195 196 // Make sure curr isn't NULL. Because this instruction is being 197 // removed from a dependency list, it must have been placed there at 198 // an earlier time. The dependency chain should not be empty, 199 // unless the instruction dependent upon it is already ready. 200 if (curr == NULL) { 201 return; 202 } 203 204 nodesRemoved++; 205 206 // Find the instruction to remove within the dependency linked list. 207 while (curr->inst != inst_to_remove) { 208 prev = curr; 209 curr = curr->next; 210 nodesTraversed++; 211 212 assert(curr != NULL); 213 } 214 215 // Now remove this instruction from the list. 216 prev->next = curr->next; 217 218 --memAllocCounter; 219 220 // Could push this off to the destructor of DependencyEntry 221 curr->inst = NULL; 222 223 delete curr; 224} 225 226template <class DynInstPtr> 227DynInstPtr 228DependencyGraph<DynInstPtr>::pop(PhysRegIndex idx) 229{ 230 DepEntry *node; 231 node = dependGraph[idx].next; 232 DynInstPtr inst = NULL; 233 if (node) { 234 inst = node->inst; 235 dependGraph[idx].next = node->next; 236 node->inst = NULL; 237 memAllocCounter--; 238 delete node; 239 } 240 return inst; 241} 242 243template <class DynInstPtr> 244void 245DependencyGraph<DynInstPtr>::dump() 246{ 247 DepEntry *curr; 248 249 for (int i = 0; i < numEntries; ++i) 250 { 251 curr = &dependGraph[i]; 252 253 if (curr->inst) { 254 cprintf("dependGraph[%i]: producer: %s [sn:%lli] consumer: ", 255 i, curr->inst->pcState(), curr->inst->seqNum); 256 } else { 257 cprintf("dependGraph[%i]: No producer. consumer: ", i); 258 } 259 260 while (curr->next != NULL) { 261 curr = curr->next; 262 263 cprintf("%s [sn:%lli] ", 264 curr->inst->pcState(), curr->inst->seqNum); 265 } 266 267 cprintf("\n"); 268 } 269 cprintf("memAllocCounter: %i\n", memAllocCounter); 270} 271 272#endif // __CPU_O3_DEP_GRAPH_HH__ 273