inst_queue.hh revision 1060
1#ifndef __INST_QUEUE_HH__
2#define __INST_QUEUE_HH__
3
4#include <list>
5#include <queue>
6#include <stdint.h>
7
8#include "base/timebuf.hh"
9
10using namespace std;
11
12//Perhaps have a better separation between the data structure underlying
13//and the actual algorithm.
14//somewhat nasty to try to have a nice ordering.
15// Consider moving to STL list or slist for the LL stuff.
16
17/**
18 * A standard instruction queue class.  It holds instructions in an
19 * array, holds the ordering of the instructions within a linked list,
20 * and tracks producer/consumer dependencies within a separate linked
21 * list.  Similar to the rename map and the free list, it expects that
22 * floating point registers have their indices start after the integer
23 * registers (ie with 96 int and 96 fp registers, regs 0-95 are integer
24 * and 96-191 are fp).  This remains true even for both logical and
25 * physical register indices.
26 */
27template<class Impl>
28class InstructionQueue
29{
30  public:
31    //Typedefs from the Impl.
32    typedef typename Impl::FullCPU FullCPU;
33    typedef typename Impl::DynInst DynInst;
34    typedef typename Impl::Params Params;
35
36    typedef typename Impl::IssueStruct IssueStruct;
37    typedef typename Impl::TimeStruct TimeStruct;
38
39    // Typedef of iterator through the list of instructions.  Might be
40    // better to untie this from the FullCPU or pass its information to
41    // the stages.
42    typedef typename list<DynInst *>::iterator ListIt;
43
44    /**
45     * Class for priority queue entries.  Mainly made so that the < operator
46     * is defined.
47     */
48    struct ReadyEntry {
49        DynInst *inst;
50
51        ReadyEntry(DynInst *_inst)
52            : inst(_inst)
53        { }
54
55        /** Compare(lhs,rhs) checks if rhs is "bigger" than lhs.  If so, rhs
56         *  goes higher on the priority queue.  The oldest instruction should
57         *  be on the top of the instruction queue, so in this case "bigger"
58         *  has the reverse meaning; the instruction with the lowest
59         *  sequence number is on the top.
60         */
61        bool operator <(const ReadyEntry &rhs) const
62        {
63            if (this->inst->seqNum > rhs.inst->seqNum)
64                return true;
65            return false;
66        }
67    };
68
69    InstructionQueue(Params &params);
70
71    void setCPU(FullCPU *cpu);
72
73    void setIssueToExecuteQueue(TimeBuffer<IssueStruct> *i2eQueue);
74
75    void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
76
77    unsigned numFreeEntries();
78
79    bool isFull();
80
81    void insert(DynInst *new_inst);
82
83    void advanceTail(DynInst *inst);
84
85    void scheduleReadyInsts();
86
87    void wakeDependents(DynInst *completed_inst);
88
89    void doSquash();
90
91    void squash();
92
93    void stopSquash();
94
95  private:
96    /** Debugging function to count how many entries are in the IQ.  It does
97     *  a linear walk through the instructions, so do not call this function
98     *  during normal execution.
99     */
100    int countInsts();
101
102  private:
103    /** Pointer to the CPU. */
104    FullCPU *cpu;
105
106    /** The queue to the execute stage.  Issued instructions will be written
107     *  into it.
108     */
109    TimeBuffer<IssueStruct> *issueToExecuteQueue;
110
111    /** The backwards time buffer. */
112    TimeBuffer<TimeStruct> *timeBuffer;
113
114    /** Wire to read information from timebuffer. */
115    typename TimeBuffer<TimeStruct>::wire fromCommit;
116
117    enum InstList {
118        Int,
119        Float,
120        Branch,
121        Squashed,
122        None
123    };
124
125    /** List of ready int instructions.  Used to keep track of the order in
126     *  which */
127    priority_queue<ReadyEntry> readyIntInsts;
128
129    /** List of ready floating point instructions. */
130    priority_queue<ReadyEntry> readyFloatInsts;
131
132    /** List of ready branch instructions. */
133    priority_queue<ReadyEntry> readyBranchInsts;
134
135    /** List of squashed instructions (which are still valid and in IQ).
136     *  Implemented using a priority queue; the entries must contain both
137     *  the IQ index and sequence number of each instruction so that
138     *  ordering based on sequence numbers can be used.
139     */
140    priority_queue<ReadyEntry> squashedInsts;
141
142    /** Number of free IQ entries left. */
143    unsigned freeEntries;
144
145    /** The number of entries in the instruction queue. */
146    unsigned numEntries;
147
148    /** The number of integer instructions that can be issued in one
149     *  cycle.
150     */
151    unsigned intWidth;
152
153    /** The number of floating point instructions that can be issued
154     *  in one cycle.
155     */
156    unsigned floatWidth;
157
158    /** The number of branches that can be issued in one cycle. */
159    unsigned branchWidth;
160
161    /** The total number of instructions that can be issued in one cycle. */
162    unsigned totalWidth;
163
164    //The number of physical registers in the CPU.
165    unsigned numPhysRegs;
166
167    /** The number of physical integer registers in the CPU. */
168    unsigned numPhysIntRegs;
169
170    /** The number of floating point registers in the CPU. */
171    unsigned numPhysFloatRegs;
172
173    /** Delay between commit stage and the IQ.
174     *  @todo: Make there be a distinction between the delays within IEW.
175     */
176    unsigned commitToIEWDelay;
177
178    //////////////////////////////////
179    // Variables needed for squashing
180    //////////////////////////////////
181
182    /** The sequence number of the squashed instruction. */
183    InstSeqNum squashedSeqNum;
184
185    /** Iterator that points to the oldest instruction in the IQ. */
186    ListIt head;
187
188    /** Iterator that points to the youngest instruction in the IQ. */
189    ListIt tail;
190
191    /** Iterator that points to the last instruction that has been squashed.
192     *  This will not be valid unless the IQ is in the process of squashing.
193     */
194    ListIt squashIt;
195
196    ///////////////////////////////////
197    // Dependency graph stuff
198    ///////////////////////////////////
199
200    class DependencyEntry
201    {
202      public:
203        DynInst *inst;
204        //Might want to include data about what arch. register the
205        //dependence is waiting on.
206        DependencyEntry *next;
207
208        //This function, and perhaps this whole class, stand out a little
209        //bit as they don't fit a classification well.  I want access
210        //to the underlying structure of the linked list, yet at
211        //the same time it feels like this should be something abstracted
212        //away.  So for now it will sit here, within the IQ, until
213        //a better implementation is decided upon.
214        // This function probably shouldn't be within the entry...
215        void insert(DynInst *new_inst);
216
217        void remove(DynInst *inst_to_remove);
218    };
219
220    /** Array of linked lists.  Each linked list is a list of all the
221     *  instructions that depend upon a given register.  The actual
222     *  register's index is used to index into the graph; ie all
223     *  instructions in flight that are dependent upon r34 will be
224     *  in the linked list of dependGraph[34].
225     */
226    DependencyEntry *dependGraph;
227
228    /** A cache of the recently woken registers.  It is 1 if the register
229     *  has been woken up recently, and 0 if the register has been added
230     *  to the dependency graph and has not yet received its value.  It
231     *  is basically a secondary scoreboard, and should pretty much mirror
232     *  the scoreboard that exists in the rename map.
233     */
234    vector<bool> regScoreboard;
235
236    bool addToDependents(DynInst *new_inst);
237    void insertDependency(DynInst *new_inst);
238    void createDependency(DynInst *new_inst);
239
240    void addIfReady(DynInst *inst);
241};
242
243#endif //__INST_QUEUE_HH__
244