dep_graph.hh

来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· HH 代码 · 共 273 行

HH
273
字号
/* * Copyright (c) 2006 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator. * * Permission is granted to use, copy, create derivative works and * redistribute this software and such derivative works for any * purpose, so long as the copyright notice above, this grant of * permission, and the disclaimer below appear in all copies made; and * so long as the name of The University of Michigan is not used in * any advertising or publicity pertaining to the use or distribution * of this software without specific, written prior authorization. * * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. * * Authors: Kevin T. Lim */#ifndef __CPU_O3_DEP_GRAPH_HH__#define __CPU_O3_DEP_GRAPH_HH__#include "cpu/o3/comm.hh"/** Node in a linked list. */template <class DynInstPtr>class DependencyEntry{  public:    DependencyEntry()        : inst(NULL), next(NULL)    { }    DynInstPtr inst;    //Might want to include data about what arch. register the    //dependence is waiting on.    DependencyEntry<DynInstPtr> *next;};/** Array of linked list that maintains the dependencies between * producing instructions and consuming instructions.  Each linked * list represents a single physical register, having the future * producer of the register's value, and all consumers waiting on that * value on the list.  The head node of each linked list represents * the producing instruction of that register.  Instructions are put * on the list upon reaching the IQ, and are removed from the list * either when the producer completes, or the instruction is squashed.*/template <class DynInstPtr>class DependencyGraph{  public:    typedef DependencyEntry<DynInstPtr> DepEntry;    /** Default construction.  Must call resize() prior to use. */    DependencyGraph()        : numEntries(0), memAllocCounter(0), nodesTraversed(0), nodesRemoved(0)    { }    ~DependencyGraph();    /** Resize the dependency graph to have num_entries registers. */    void resize(int num_entries);    /** Clears all of the linked lists. */    void reset();    /** Inserts an instruction to be dependent on the given index. */    void insert(PhysRegIndex idx, DynInstPtr &new_inst);    /** Sets the producing instruction of a given register. */    void setInst(PhysRegIndex idx, DynInstPtr &new_inst)    { dependGraph[idx].inst = new_inst; }    /** Clears the producing instruction. */    void clearInst(PhysRegIndex idx)    { dependGraph[idx].inst = NULL; }    /** Removes an instruction from a single linked list. */    void remove(PhysRegIndex idx, DynInstPtr &inst_to_remove);    /** Removes and returns the newest dependent of a specific register. */    DynInstPtr pop(PhysRegIndex idx);    /** Checks if there are any dependents on a specific register. */    bool empty(PhysRegIndex idx) { return !dependGraph[idx].next; }    /** Debugging function to dump out the dependency graph.     */    void dump();  private:    /** Array of linked lists.  Each linked list is a list of all the     *  instructions that depend upon a given register.  The actual     *  register's index is used to index into the graph; ie all     *  instructions in flight that are dependent upon r34 will be     *  in the linked list of dependGraph[34].     */    DepEntry *dependGraph;    /** Number of linked lists; identical to the number of registers. */    int numEntries;    // Debug variable, remove when done testing.    unsigned memAllocCounter;  public:    // Debug variable, remove when done testing.    uint64_t nodesTraversed;    // Debug variable, remove when done testing.    uint64_t nodesRemoved;};template <class DynInstPtr>DependencyGraph<DynInstPtr>::~DependencyGraph(){    delete [] dependGraph;}template <class DynInstPtr>voidDependencyGraph<DynInstPtr>::resize(int num_entries){    numEntries = num_entries;    dependGraph = new DepEntry[numEntries];}template <class DynInstPtr>voidDependencyGraph<DynInstPtr>::reset(){    // Clear the dependency graph    DepEntry *curr;    DepEntry *prev;    for (int i = 0; i < numEntries; ++i) {        curr = dependGraph[i].next;        while (curr) {            memAllocCounter--;            prev = curr;            curr = prev->next;            prev->inst = NULL;            delete prev;        }        if (dependGraph[i].inst) {            dependGraph[i].inst = NULL;        }        dependGraph[i].next = NULL;    }}template <class DynInstPtr>voidDependencyGraph<DynInstPtr>::insert(PhysRegIndex idx, DynInstPtr &new_inst){    //Add this new, dependent instruction at the head of the dependency    //chain.    // First create the entry that will be added to the head of the    // dependency chain.    DepEntry *new_entry = new DepEntry;    new_entry->next = dependGraph[idx].next;    new_entry->inst = new_inst;    // Then actually add it to the chain.    dependGraph[idx].next = new_entry;    ++memAllocCounter;}template <class DynInstPtr>voidDependencyGraph<DynInstPtr>::remove(PhysRegIndex idx,                                    DynInstPtr &inst_to_remove){    DepEntry *prev = &dependGraph[idx];    DepEntry *curr = dependGraph[idx].next;    // Make sure curr isn't NULL.  Because this instruction is being    // removed from a dependency list, it must have been placed there at    // an earlier time.  The dependency chain should not be empty,    // unless the instruction dependent upon it is already ready.    if (curr == NULL) {        return;    }    nodesRemoved++;    // Find the instruction to remove within the dependency linked list.    while (curr->inst != inst_to_remove) {        prev = curr;        curr = curr->next;        nodesTraversed++;        assert(curr != NULL);    }    // Now remove this instruction from the list.    prev->next = curr->next;    --memAllocCounter;    // Could push this off to the destructor of DependencyEntry    curr->inst = NULL;    delete curr;}template <class DynInstPtr>DynInstPtrDependencyGraph<DynInstPtr>::pop(PhysRegIndex idx){    DepEntry *node;    node = dependGraph[idx].next;    DynInstPtr inst = NULL;    if (node) {        inst = node->inst;        dependGraph[idx].next = node->next;        node->inst = NULL;        memAllocCounter--;        delete node;    }    return inst;}template <class DynInstPtr>voidDependencyGraph<DynInstPtr>::dump(){    DepEntry *curr;    for (int i = 0; i < numEntries; ++i)    {        curr = &dependGraph[i];        if (curr->inst) {            cprintf("dependGraph[%i]: producer: %#x [sn:%lli] consumer: ",                    i, curr->inst->readPC(), curr->inst->seqNum);        } else {            cprintf("dependGraph[%i]: No producer. consumer: ", i);        }        while (curr->next != NULL) {            curr = curr->next;            cprintf("%#x [sn:%lli] ",                    curr->inst->readPC(), curr->inst->seqNum);        }        cprintf("\n");    }    cprintf("memAllocCounter: %i\n", memAllocCounter);}#endif // __CPU_O3_DEP_GRAPH_HH__

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?