dep_graph.hh (2669:f2b336e89d2a) dep_graph.hh (2674:6d4afef73a20)
1
2#ifndef __CPU_O3_DEP_GRAPH_HH__
3#define __CPU_O3_DEP_GRAPH_HH__
4
5#include "cpu/o3/comm.hh"
6
1
2#ifndef __CPU_O3_DEP_GRAPH_HH__
3#define __CPU_O3_DEP_GRAPH_HH__
4
5#include "cpu/o3/comm.hh"
6
7/** Node in a linked list. */
7template <class DynInstPtr>
8class DependencyEntry
9{
10 public:
11 DependencyEntry()
12 : inst(NULL), next(NULL)
13 { }
14
15 DynInstPtr inst;
16 //Might want to include data about what arch. register the
17 //dependence is waiting on.
18 DependencyEntry<DynInstPtr> *next;
19};
20
8template <class DynInstPtr>
9class DependencyEntry
10{
11 public:
12 DependencyEntry()
13 : inst(NULL), next(NULL)
14 { }
15
16 DynInstPtr inst;
17 //Might want to include data about what arch. register the
18 //dependence is waiting on.
19 DependencyEntry<DynInstPtr> *next;
20};
21
22/** Array of linked list that maintains the dependencies between
23 * producing instructions and consuming instructions. Each linked
24 * list represents a single physical register, having the future
25 * producer of the register's value, and all consumers waiting on that
26 * value on the list. The head node of each linked list represents
27 * the producing instruction of that register. Instructions are put
28 * on the list upon reaching the IQ, and are removed from the list
29 * either when the producer completes, or the instruction is squashed.
30*/
21template <class DynInstPtr>
22class DependencyGraph
23{
24 public:
25 typedef DependencyEntry<DynInstPtr> DepEntry;
26
31template <class DynInstPtr>
32class DependencyGraph
33{
34 public:
35 typedef DependencyEntry<DynInstPtr> DepEntry;
36
37 /** Default construction. Must call resize() prior to use. */
27 DependencyGraph()
28 : numEntries(0), memAllocCounter(0), nodesTraversed(0), nodesRemoved(0)
29 { }
30
38 DependencyGraph()
39 : numEntries(0), memAllocCounter(0), nodesTraversed(0), nodesRemoved(0)
40 { }
41
42 /** Resize the dependency graph to have num_entries registers. */
31 void resize(int num_entries);
32
43 void resize(int num_entries);
44
45 /** Clears all of the linked lists. */
33 void reset();
34
46 void reset();
47
48 /** Inserts an instruction to be dependent on the given index. */
35 void insert(PhysRegIndex idx, DynInstPtr &new_inst);
36
49 void insert(PhysRegIndex idx, DynInstPtr &new_inst);
50
51 /** Sets the producing instruction of a given register. */
37 void setInst(PhysRegIndex idx, DynInstPtr &new_inst)
38 { dependGraph[idx].inst = new_inst; }
39
52 void setInst(PhysRegIndex idx, DynInstPtr &new_inst)
53 { dependGraph[idx].inst = new_inst; }
54
55 /** Clears the producing instruction. */
40 void clearInst(PhysRegIndex idx)
41 { dependGraph[idx].inst = NULL; }
42
56 void clearInst(PhysRegIndex idx)
57 { dependGraph[idx].inst = NULL; }
58
59 /** Removes an instruction from a single linked list. */
43 void remove(PhysRegIndex idx, DynInstPtr &inst_to_remove);
44
60 void remove(PhysRegIndex idx, DynInstPtr &inst_to_remove);
61
62 /** Removes and returns the newest dependent of a specific register. */
45 DynInstPtr pop(PhysRegIndex idx);
46
63 DynInstPtr pop(PhysRegIndex idx);
64
65 /** Checks if there are any dependents on a specific register. */
47 bool empty(PhysRegIndex idx) { return !dependGraph[idx].next; }
48
49 /** Debugging function to dump out the dependency graph.
50 */
51 void dump();
52
53 private:
54 /** Array of linked lists. Each linked list is a list of all the
55 * instructions that depend upon a given register. The actual
56 * register's index is used to index into the graph; ie all
57 * instructions in flight that are dependent upon r34 will be
58 * in the linked list of dependGraph[34].
59 */
60 DepEntry *dependGraph;
61
66 bool empty(PhysRegIndex idx) { return !dependGraph[idx].next; }
67
68 /** Debugging function to dump out the dependency graph.
69 */
70 void dump();
71
72 private:
73 /** Array of linked lists. Each linked list is a list of all the
74 * instructions that depend upon a given register. The actual
75 * register's index is used to index into the graph; ie all
76 * instructions in flight that are dependent upon r34 will be
77 * in the linked list of dependGraph[34].
78 */
79 DepEntry *dependGraph;
80
81 /** Number of linked lists; identical to the number of registers. */
62 int numEntries;
63
64 // Debug variable, remove when done testing.
65 unsigned memAllocCounter;
66
67 public:
82 int numEntries;
83
84 // Debug variable, remove when done testing.
85 unsigned memAllocCounter;
86
87 public:
88 // Debug variable, remove when done testing.
68 uint64_t nodesTraversed;
89 uint64_t nodesTraversed;
90 // Debug variable, remove when done testing.
69 uint64_t nodesRemoved;
70};
71
72template <class DynInstPtr>
73void
74DependencyGraph<DynInstPtr>::resize(int num_entries)
75{
76 numEntries = num_entries;
77 dependGraph = new DepEntry[numEntries];
78}
79
80template <class DynInstPtr>
81void
82DependencyGraph<DynInstPtr>::reset()
83{
84 // Clear the dependency graph
85 DepEntry *curr;
86 DepEntry *prev;
87
88 for (int i = 0; i < numEntries; ++i) {
89 curr = dependGraph[i].next;
90
91 while (curr) {
92 memAllocCounter--;
93
94 prev = curr;
95 curr = prev->next;
96 prev->inst = NULL;
97
98 delete prev;
99 }
100
101 if (dependGraph[i].inst) {
102 dependGraph[i].inst = NULL;
103 }
104
105 dependGraph[i].next = NULL;
106 }
107}
108
109template <class DynInstPtr>
110void
111DependencyGraph<DynInstPtr>::insert(PhysRegIndex idx, DynInstPtr &new_inst)
112{
113 //Add this new, dependent instruction at the head of the dependency
114 //chain.
115
116 // First create the entry that will be added to the head of the
117 // dependency chain.
118 DepEntry *new_entry = new DepEntry;
119 new_entry->next = dependGraph[idx].next;
120 new_entry->inst = new_inst;
121
122 // Then actually add it to the chain.
123 dependGraph[idx].next = new_entry;
124
125 ++memAllocCounter;
126}
127
128
129template <class DynInstPtr>
130void
131DependencyGraph<DynInstPtr>::remove(PhysRegIndex idx,
132 DynInstPtr &inst_to_remove)
133{
134 DepEntry *prev = &dependGraph[idx];
135 DepEntry *curr = dependGraph[idx].next;
136
137 // Make sure curr isn't NULL. Because this instruction is being
138 // removed from a dependency list, it must have been placed there at
139 // an earlier time. The dependency chain should not be empty,
140 // unless the instruction dependent upon it is already ready.
141 if (curr == NULL) {
142 return;
143 }
144
145 nodesRemoved++;
146
147 // Find the instruction to remove within the dependency linked list.
148 while (curr->inst != inst_to_remove) {
149 prev = curr;
150 curr = curr->next;
151 nodesTraversed++;
152
153 assert(curr != NULL);
154 }
155
156 // Now remove this instruction from the list.
157 prev->next = curr->next;
158
159 --memAllocCounter;
160
161 // Could push this off to the destructor of DependencyEntry
162 curr->inst = NULL;
163
164 delete curr;
165}
166
167template <class DynInstPtr>
168DynInstPtr
169DependencyGraph<DynInstPtr>::pop(PhysRegIndex idx)
170{
171 DepEntry *node;
172 node = dependGraph[idx].next;
173 DynInstPtr inst = NULL;
174 if (node) {
175 inst = node->inst;
176 dependGraph[idx].next = node->next;
177 node->inst = NULL;
178 memAllocCounter--;
179 delete node;
180 }
181 return inst;
182}
183
184template <class DynInstPtr>
185void
186DependencyGraph<DynInstPtr>::dump()
187{
188 DepEntry *curr;
189
190 for (int i = 0; i < numEntries; ++i)
191 {
192 curr = &dependGraph[i];
193
194 if (curr->inst) {
195 cprintf("dependGraph[%i]: producer: %#x [sn:%lli] consumer: ",
196 i, curr->inst->readPC(), curr->inst->seqNum);
197 } else {
198 cprintf("dependGraph[%i]: No producer. consumer: ", i);
199 }
200
201 while (curr->next != NULL) {
202 curr = curr->next;
203
204 cprintf("%#x [sn:%lli] ",
205 curr->inst->readPC(), curr->inst->seqNum);
206 }
207
208 cprintf("\n");
209 }
210 cprintf("memAllocCounter: %i\n", memAllocCounter);
211}
212
213#endif // __CPU_O3_DEP_GRAPH_HH__
91 uint64_t nodesRemoved;
92};
93
94template <class DynInstPtr>
95void
96DependencyGraph<DynInstPtr>::resize(int num_entries)
97{
98 numEntries = num_entries;
99 dependGraph = new DepEntry[numEntries];
100}
101
102template <class DynInstPtr>
103void
104DependencyGraph<DynInstPtr>::reset()
105{
106 // Clear the dependency graph
107 DepEntry *curr;
108 DepEntry *prev;
109
110 for (int i = 0; i < numEntries; ++i) {
111 curr = dependGraph[i].next;
112
113 while (curr) {
114 memAllocCounter--;
115
116 prev = curr;
117 curr = prev->next;
118 prev->inst = NULL;
119
120 delete prev;
121 }
122
123 if (dependGraph[i].inst) {
124 dependGraph[i].inst = NULL;
125 }
126
127 dependGraph[i].next = NULL;
128 }
129}
130
131template <class DynInstPtr>
132void
133DependencyGraph<DynInstPtr>::insert(PhysRegIndex idx, DynInstPtr &new_inst)
134{
135 //Add this new, dependent instruction at the head of the dependency
136 //chain.
137
138 // First create the entry that will be added to the head of the
139 // dependency chain.
140 DepEntry *new_entry = new DepEntry;
141 new_entry->next = dependGraph[idx].next;
142 new_entry->inst = new_inst;
143
144 // Then actually add it to the chain.
145 dependGraph[idx].next = new_entry;
146
147 ++memAllocCounter;
148}
149
150
151template <class DynInstPtr>
152void
153DependencyGraph<DynInstPtr>::remove(PhysRegIndex idx,
154 DynInstPtr &inst_to_remove)
155{
156 DepEntry *prev = &dependGraph[idx];
157 DepEntry *curr = dependGraph[idx].next;
158
159 // Make sure curr isn't NULL. Because this instruction is being
160 // removed from a dependency list, it must have been placed there at
161 // an earlier time. The dependency chain should not be empty,
162 // unless the instruction dependent upon it is already ready.
163 if (curr == NULL) {
164 return;
165 }
166
167 nodesRemoved++;
168
169 // Find the instruction to remove within the dependency linked list.
170 while (curr->inst != inst_to_remove) {
171 prev = curr;
172 curr = curr->next;
173 nodesTraversed++;
174
175 assert(curr != NULL);
176 }
177
178 // Now remove this instruction from the list.
179 prev->next = curr->next;
180
181 --memAllocCounter;
182
183 // Could push this off to the destructor of DependencyEntry
184 curr->inst = NULL;
185
186 delete curr;
187}
188
189template <class DynInstPtr>
190DynInstPtr
191DependencyGraph<DynInstPtr>::pop(PhysRegIndex idx)
192{
193 DepEntry *node;
194 node = dependGraph[idx].next;
195 DynInstPtr inst = NULL;
196 if (node) {
197 inst = node->inst;
198 dependGraph[idx].next = node->next;
199 node->inst = NULL;
200 memAllocCounter--;
201 delete node;
202 }
203 return inst;
204}
205
206template <class DynInstPtr>
207void
208DependencyGraph<DynInstPtr>::dump()
209{
210 DepEntry *curr;
211
212 for (int i = 0; i < numEntries; ++i)
213 {
214 curr = &dependGraph[i];
215
216 if (curr->inst) {
217 cprintf("dependGraph[%i]: producer: %#x [sn:%lli] consumer: ",
218 i, curr->inst->readPC(), curr->inst->seqNum);
219 } else {
220 cprintf("dependGraph[%i]: No producer. consumer: ", i);
221 }
222
223 while (curr->next != NULL) {
224 curr = curr->next;
225
226 cprintf("%#x [sn:%lli] ",
227 curr->inst->readPC(), curr->inst->seqNum);
228 }
229
230 cprintf("\n");
231 }
232 cprintf("memAllocCounter: %i\n", memAllocCounter);
233}
234
235#endif // __CPU_O3_DEP_GRAPH_HH__