dep_graph.hh revision 9444
15390SN/A/*
25446SN/A * Copyright (c) 2012 ARM Limited
35390SN/A * All rights reserved
45390SN/A *
55390SN/A * The license below extends only to copyright in the software and shall
65390SN/A * not be construed as granting a license to any other intellectual
75390SN/A * property including but not limited to intellectual property relating
85390SN/A * to a hardware implementation of the functionality of the software
95390SN/A * licensed hereunder.  You may use the software subject to the license
105390SN/A * terms below provided that you ensure that this notice is replicated
115390SN/A * unmodified and in its entirety in all distributions of the software,
125390SN/A * modified or unmodified, in source code or in binary form.
135390SN/A *
145390SN/A * Copyright (c) 2006 The Regents of The University of Michigan
155390SN/A * All rights reserved.
165390SN/A *
175390SN/A * Redistribution and use in source and binary forms, with or without
185390SN/A * modification, are permitted provided that the following conditions are
195390SN/A * met: redistributions of source code must retain the above copyright
205390SN/A * notice, this list of conditions and the following disclaimer;
215390SN/A * redistributions in binary form must reproduce the above copyright
225390SN/A * notice, this list of conditions and the following disclaimer in the
235390SN/A * documentation and/or other materials provided with the distribution;
245390SN/A * neither the name of the copyright holders nor the names of its
255390SN/A * contributors may be used to endorse or promote products derived from
265390SN/A * this software without specific prior written permission.
275390SN/A *
285390SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
295390SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
305390SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
315637Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
325637Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
335390SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
345636SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
355390SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
365390SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
375636SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
385636SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
395636SN/A *
405636SN/A * Authors: Kevin Lim
415636SN/A */
425636SN/A
435643Sgblack@eecs.umich.edu#ifndef __CPU_O3_DEP_GRAPH_HH__
445636SN/A#define __CPU_O3_DEP_GRAPH_HH__
455636SN/A
465636SN/A#include "cpu/o3/comm.hh"
475390SN/A
485390SN/A/** Node in a linked list. */
495636SN/Atemplate <class DynInstPtr>
505446SN/Aclass DependencyEntry
515446SN/A{
525636SN/A  public:
535636SN/A    DependencyEntry()
545636SN/A        : inst(NULL), next(NULL)
555636SN/A    { }
565636SN/A
575643Sgblack@eecs.umich.edu    DynInstPtr inst;
585390SN/A    //Might want to include data about what arch. register the
595446SN/A    //dependence is waiting on.
605390SN/A    DependencyEntry<DynInstPtr> *next;
615390SN/A};
625390SN/A
635390SN/A/** Array of linked list that maintains the dependencies between
645390SN/A * producing instructions and consuming instructions.  Each linked
655390SN/A * list represents a single physical register, having the future
665390SN/A * producer of the register's value, and all consumers waiting on that
675390SN/A * value on the list.  The head node of each linked list represents
685390SN/A * the producing instruction of that register.  Instructions are put
695390SN/A * on the list upon reaching the IQ, and are removed from the list
705637Sgblack@eecs.umich.edu * either when the producer completes, or the instruction is squashed.
71*/
72template <class DynInstPtr>
73class DependencyGraph
74{
75  public:
76    typedef DependencyEntry<DynInstPtr> DepEntry;
77
78    /** Default construction.  Must call resize() prior to use. */
79    DependencyGraph()
80        : numEntries(0), memAllocCounter(0), nodesTraversed(0), nodesRemoved(0)
81    { }
82
83    ~DependencyGraph();
84
85    /** Resize the dependency graph to have num_entries registers. */
86    void resize(int num_entries);
87
88    /** Clears all of the linked lists. */
89    void reset();
90
91    /** Inserts an instruction to be dependent on the given index. */
92    void insert(PhysRegIndex idx, DynInstPtr &new_inst);
93
94    /** Sets the producing instruction of a given register. */
95    void setInst(PhysRegIndex idx, DynInstPtr &new_inst)
96    { dependGraph[idx].inst = new_inst; }
97
98    /** Clears the producing instruction. */
99    void clearInst(PhysRegIndex idx)
100    { dependGraph[idx].inst = NULL; }
101
102    /** Removes an instruction from a single linked list. */
103    void remove(PhysRegIndex idx, DynInstPtr &inst_to_remove);
104
105    /** Removes and returns the newest dependent of a specific register. */
106    DynInstPtr pop(PhysRegIndex idx);
107
108    /** Checks if the entire dependency graph is empty. */
109    bool empty() const;
110
111    /** Checks if there are any dependents on a specific register. */
112    bool empty(PhysRegIndex idx) const { return !dependGraph[idx].next; }
113
114    /** Debugging function to dump out the dependency graph.
115     */
116    void dump();
117
118  private:
119    /** Array of linked lists.  Each linked list is a list of all the
120     *  instructions that depend upon a given register.  The actual
121     *  register's index is used to index into the graph; ie all
122     *  instructions in flight that are dependent upon r34 will be
123     *  in the linked list of dependGraph[34].
124     */
125    DepEntry *dependGraph;
126
127    /** Number of linked lists; identical to the number of registers. */
128    int numEntries;
129
130    // Debug variable, remove when done testing.
131    unsigned memAllocCounter;
132
133  public:
134    // Debug variable, remove when done testing.
135    uint64_t nodesTraversed;
136    // Debug variable, remove when done testing.
137    uint64_t nodesRemoved;
138};
139
140template <class DynInstPtr>
141DependencyGraph<DynInstPtr>::~DependencyGraph()
142{
143    delete [] dependGraph;
144}
145
146template <class DynInstPtr>
147void
148DependencyGraph<DynInstPtr>::resize(int num_entries)
149{
150    numEntries = num_entries;
151    dependGraph = new DepEntry[numEntries];
152}
153
154template <class DynInstPtr>
155void
156DependencyGraph<DynInstPtr>::reset()
157{
158    // Clear the dependency graph
159    DepEntry *curr;
160    DepEntry *prev;
161
162    for (int i = 0; i < numEntries; ++i) {
163        curr = dependGraph[i].next;
164
165        while (curr) {
166            memAllocCounter--;
167
168            prev = curr;
169            curr = prev->next;
170            prev->inst = NULL;
171
172            delete prev;
173        }
174
175        if (dependGraph[i].inst) {
176            dependGraph[i].inst = NULL;
177        }
178
179        dependGraph[i].next = NULL;
180    }
181}
182
183template <class DynInstPtr>
184void
185DependencyGraph<DynInstPtr>::insert(PhysRegIndex idx, DynInstPtr &new_inst)
186{
187    //Add this new, dependent instruction at the head of the dependency
188    //chain.
189
190    // First create the entry that will be added to the head of the
191    // dependency chain.
192    DepEntry *new_entry = new DepEntry;
193    new_entry->next = dependGraph[idx].next;
194    new_entry->inst = new_inst;
195
196    // Then actually add it to the chain.
197    dependGraph[idx].next = new_entry;
198
199    ++memAllocCounter;
200}
201
202
203template <class DynInstPtr>
204void
205DependencyGraph<DynInstPtr>::remove(PhysRegIndex idx,
206                                    DynInstPtr &inst_to_remove)
207{
208    DepEntry *prev = &dependGraph[idx];
209    DepEntry *curr = dependGraph[idx].next;
210
211    // Make sure curr isn't NULL.  Because this instruction is being
212    // removed from a dependency list, it must have been placed there at
213    // an earlier time.  The dependency chain should not be empty,
214    // unless the instruction dependent upon it is already ready.
215    if (curr == NULL) {
216        return;
217    }
218
219    nodesRemoved++;
220
221    // Find the instruction to remove within the dependency linked list.
222    while (curr->inst != inst_to_remove) {
223        prev = curr;
224        curr = curr->next;
225        nodesTraversed++;
226
227        assert(curr != NULL);
228    }
229
230    // Now remove this instruction from the list.
231    prev->next = curr->next;
232
233    --memAllocCounter;
234
235    // Could push this off to the destructor of DependencyEntry
236    curr->inst = NULL;
237
238    delete curr;
239}
240
241template <class DynInstPtr>
242DynInstPtr
243DependencyGraph<DynInstPtr>::pop(PhysRegIndex idx)
244{
245    DepEntry *node;
246    node = dependGraph[idx].next;
247    DynInstPtr inst = NULL;
248    if (node) {
249        inst = node->inst;
250        dependGraph[idx].next = node->next;
251        node->inst = NULL;
252        memAllocCounter--;
253        delete node;
254    }
255    return inst;
256}
257
258template <class DynInstPtr>
259bool
260DependencyGraph<DynInstPtr>::empty() const
261{
262    for (int i = 0; i < numEntries; ++i) {
263        if (!empty(i))
264            return false;
265    }
266    return true;
267}
268
269template <class DynInstPtr>
270void
271DependencyGraph<DynInstPtr>::dump()
272{
273    DepEntry *curr;
274
275    for (int i = 0; i < numEntries; ++i)
276    {
277        curr = &dependGraph[i];
278
279        if (curr->inst) {
280            cprintf("dependGraph[%i]: producer: %s [sn:%lli] consumer: ",
281                    i, curr->inst->pcState(), curr->inst->seqNum);
282        } else {
283            cprintf("dependGraph[%i]: No producer. consumer: ", i);
284        }
285
286        while (curr->next != NULL) {
287            curr = curr->next;
288
289            cprintf("%s [sn:%lli] ",
290                    curr->inst->pcState(), curr->inst->seqNum);
291        }
292
293        cprintf("\n");
294    }
295    cprintf("memAllocCounter: %i\n", memAllocCounter);
296}
297
298#endif // __CPU_O3_DEP_GRAPH_HH__
299