summaryrefslogtreecommitdiff
path: root/src/cpu/inorder/resource_sked.hh
blob: c44c2d3fabb106e75d5afbc48fc11b13816bd893 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
/*
 * Copyright (c) 2010-2011 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Korey Sewell
 *
 */

#ifndef __CPU_INORDER_RESOURCE_SKED_HH__
#define __CPU_INORDER_RESOURCE_SKED_HH__

#include <cstdlib>
#include <list>
#include <vector>

/** ScheduleEntry class represents a single function that an instruction
    wants to do at any pipeline stage. For example, if an instruction
    needs to be decoded and do a branch prediction all in one stage
    then each of those tasks would need it's own ScheduleEntry.

    Each schedule entry corresponds to some resource that the instruction
    wants to interact with.

    The file pipeline_traits.cc shows how a typical instruction schedule is
    made up of these schedule entries.
*/
class ScheduleEntry {
  public:
    ScheduleEntry(int stage_num, int _priority, int res_num, int _cmd = 0,
                  int _idx = 0) :
        stageNum(stage_num), resNum(res_num), cmd(_cmd),
        idx(_idx), priority(_priority)
    { }

    /** Stage number to perform this service. */
    int stageNum;

    /** Resource ID to access */
    int resNum;

    /** See specific resource for meaning */
    unsigned cmd;

    /** See specific resource for meaning */
    unsigned idx;

    /** Some Resources May Need Priority */
    int priority;
};

/** The ResourceSked maintains the complete schedule
    for an instruction. That schedule includes what
    resources an instruction wants to acquire at each
    pipeline stage and is represented by a collection
    of ScheduleEntry objects (described above) that
    must be executed in-order.

    In every pipeline stage, the InOrder model will
    process all entries on the resource schedule for
    that stage and then send the instruction to the next
    stage if and only if the instruction successfully
    completed each ScheduleEntry.
*/
class ResourceSked {
  public:
    typedef std::list<ScheduleEntry*>::iterator SkedIt;
    typedef std::vector<std::list<ScheduleEntry*> > StageList;

    ResourceSked();

    /** Initializee the current entry pointer to
        pipeline stage 0 and the 1st schedule entry
    */
    void init();

    /** Goes through the remaining stages on the schedule
        and sums all the remaining entries left to be
        processed
    */
    int size();

    /** Is the schedule empty? */
    bool empty();

    /** Beginning Entry of this schedule */
    SkedIt begin();

    /** Ending Entry of this schedule */
    SkedIt end();

    /** Ending Entry of a specified stage */
    SkedIt end(int stage_num);

    /** Find a schedule entry based on stage and command */
    SkedIt find(int stage_num, int cmd);

    /** What is the next task for this instruction schedule? */
    ScheduleEntry* top();

    /** Top() Task is completed, remove it from schedule */
    void pop();

    /** Add To Schedule based on stage num and priority of
        Schedule Entry
    */
    void push(ScheduleEntry* sked_entry);

    /** Add Schedule Entry to be in front of another Entry */
    void pushBefore(ScheduleEntry* sked_entry, int sked_cmd, int sked_cmd_idx);

    /** Print what's left on the instruction schedule */
    void print();

    StageList *getStages()
    {
        return &stages;
    }

  private:
    /** Current Schedule Entry Pointer */
    SkedIt curSkedEntry;

    /** The Stage-by-Stage Resource Schedule:
        Resized to Number of Stages in the constructor
    */
    StageList stages;

    /** Find a place to insert the instruction using  the
        schedule entries priority
    */
    SkedIt findIterByPriority(ScheduleEntry *sked_entry, int stage_num);

    /** Find a place to insert the instruction using a particular command
        to look for.
    */
    SkedIt findIterByCommand(ScheduleEntry *sked_entry, int stage_num,
                             int sked_cmd, int sked_cmd_idx = -1);
};

/** Wrapper class around the SkedIt iterator in the Resource Sked so that
    we can use ++ operator to automatically go to the next available
    resource schedule entry but otherwise maintain same functionality
    as a normal iterator.
*/
class RSkedIt
{
  public:
    RSkedIt()
        : curStage(0), numStages(0)
    { }


    /** init() must be called before the use of any other member
        in the RSkedIt class.
    */
    void init(ResourceSked* rsked)
    {
        stages = rsked->getStages();
        numStages = stages->size();
    }

    /* Update the encapsulated "myIt" iterator, but only
       update curStage/curStage_end if the iterator is valid.
       The iterator could be invalid in the case where
       someone is saving the end of a list (i.e. std::list->end())
    */
    RSkedIt operator=(ResourceSked::SkedIt const &rhs)
    {
        myIt = rhs;
        if (myIt != (*stages)[numStages-1].end()) {
            curStage = (*myIt)->stageNum;
            curStage_end = (*stages)[curStage].end();
        }
        return *this;
    }

    /** Increment to the next entry in current stage.
        If no more entries then find the next stage that has
        resource schedule to complete.
        If no more stages, then return the end() iterator from
        the last stage to indicate we are done.
    */
    RSkedIt &operator++(int unused)
    {
        if (++myIt == curStage_end) {
            curStage++;
            while (curStage < numStages) {
                if ((*stages)[curStage].empty()) {
                    curStage++;
                } else {
                    myIt = (*stages)[curStage].begin();
                    curStage_end = (*stages)[curStage].end();
                    return *this;
                }
            }

            myIt = (*stages)[numStages - 1].end();
        }

        return *this;
    }

    /** The "pointer" operator can be used on a RSkedIt and it
        will use the encapsulated iterator
    */
    ScheduleEntry* operator->()
    {
        return *myIt;
    }

    /** Dereferencing a RSKedIt will access the encapsulated
        iterator
    */
    ScheduleEntry* operator*()
    {
        return *myIt;
    }

    /** Equality for RSkedIt only compares the "myIt" iterators,
        as the other members are just ancillary
    */
    bool operator==(RSkedIt const &rhs)
    {
        return this->myIt == rhs.myIt;
    }

    /** Inequality for RSkedIt only compares the "myIt" iterators,
        as the other members are just ancillary
    */
    bool operator!=(RSkedIt const &rhs)
    {
        return this->myIt != rhs.myIt;
    }

    /* The == and != operator overloads should be sufficient
       here if need otherwise direct access to the schedule
       iterator, then this can be used */
    ResourceSked::SkedIt getIt()
    {
        return myIt;
    }

  private:
    /** Schedule Iterator that this class is encapsulating */
    ResourceSked::SkedIt myIt;

    /** Ptr to resource schedule that the 'myIt' iterator
        belongs to
    */
    ResourceSked::StageList *stages;

    /**  The last iterator in the current stage. */
    ResourceSked::SkedIt curStage_end;

    /** Current Stage that "myIt" refers to. */
    int curStage;

    /** Number of stages in the "*stages" object. */
    int numStages;
};

#endif //__CPU_INORDER_RESOURCE_SKED_HH__