17ca3259586d23d84b6abe914fef1b29f6215e43
[gem5.git] / src / cpu / inorder / pipeline_stage.hh
1 /*
2 * Copyright (c) 2007 MIPS Technologies, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Korey Sewell
29 *
30 */
31
32 #ifndef __CPU_INORDER_PIPELINE_STAGE_HH__
33 #define __CPU_INORDER_PIPELINE_STAGE_HH__
34
35 #include <queue>
36 #include <vector>
37
38 #include "base/statistics.hh"
39 #include "base/timebuf.hh"
40 #include "cpu/inorder/inorder_dyn_inst.hh"
41 #include "cpu/inorder/comm.hh"
42 #include "params/InOrderCPU.hh"
43 #include "cpu/inorder/pipeline_traits.hh"
44
45 class InOrderCPU;
46
47 class PipelineStage
48 {
49 protected:
50 typedef ThePipeline::Params Params;
51 typedef ThePipeline::DynInstPtr DynInstPtr;
52
53 public:
54 /** Overall stage status. Used to determine if the CPU can
55 * deschedule itself due to a lack of activity.
56 */
57 enum StageStatus {
58 Active,
59 Inactive
60 };
61
62 /** Individual thread status. */
63 enum ThreadStatus {
64 Running,
65 Idle,
66 StartSquash,
67 Squashing,
68 Blocked,
69 Unblocking,
70 MemWaitResponse,
71 MemWaitRetry,
72 MemAccessComplete
73 };
74
75 protected:
76 /** The Number of This Pipeline Stage */
77 unsigned stageNum;
78
79 /** The width of stage, in instructions. */
80 unsigned stageWidth;
81
82 /** Number of Threads*/
83 unsigned numThreads;
84
85 /** Stage status. */
86 StageStatus _status;
87
88 /** Per-thread status. */
89 ThreadStatus stageStatus[ThePipeline::MaxThreads];
90
91 public:
92 PipelineStage(Params *params, unsigned stage_num);
93
94 /** MUST use init() function if this constructor is used. */
95 PipelineStage() { }
96
97 virtual ~PipelineStage() { }
98
99 /** PipelineStage initialization. */
100 void init(Params *params, unsigned stage_num);
101
102 /** Returns the name of stage. */
103 std::string name() const;
104
105 /** Registers statistics. */
106 void regStats();
107
108 /** Sets CPU pointer. */
109 virtual void setCPU(InOrderCPU *cpu_ptr);
110
111 virtual void scheduleStageStart(int delay, int tid) { }
112
113 /** Sets the main backwards communication time buffer pointer. */
114 void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
115
116 /** Sets pointer to time buffer coming from fetch. */
117 void setPrevStageQueue(TimeBuffer<InterStageStruct> *prev_stage_ptr);
118
119 /** Sets pointer to time buffer used to communicate to the next stage. */
120 void setNextStageQueue(TimeBuffer<InterStageStruct> *next_stage_ptr);
121
122 /** Sets pointer to list of active threads. */
123 void setActiveThreads(std::list<unsigned> *at_ptr);
124
125 bool nextStageQueueValid(int stage_num);
126
127 bool isBlocked(unsigned tid);
128
129 /** Changes the status of this stage to active, and indicates this
130 * to the CPU.
131 */
132 //inline void switchToActive();
133
134 /** Changes the status of this stage to inactive, and indicates
135 * this to the CPU.
136 */
137 //inline void switchToInactive();
138
139 /** Switches out the stage stage. */
140 void switchOut();
141
142 /** Takes over from another CPU's thread. */
143 void takeOverFrom();
144
145 /** Ticks stage, processing all input signals and executing as many
146 * instructions as possible.
147 */
148 virtual void tick();
149
150 /** Is out of order processing valid? */
151 bool outOfOrderValid();
152
153 /** Set a resource stall in the pipeline-stage */
154 void setResStall(ResReqPtr res_req, unsigned tid);
155
156 /** Unset a resource stall in the pipeline-stage */
157 void unsetResStall(ResReqPtr res_req, unsigned tid);
158
159 /** Remove all stall signals for a particular thread; */
160 virtual void removeStalls(unsigned tid);
161
162 /** Is there room in the stage buffer? */
163 int stageBufferAvail();
164
165 protected:
166 /** Evaluate Stage Conditions and then process stage */
167 virtual void processStage(bool &status_change);
168
169 /** Determines what to do based on stage's current status.
170 * @param status_change stage() sets this variable if there was a status
171 * change (ie switching from from blocking to unblocking).
172 * @param tid Thread id to stage instructions from.
173 */
174 virtual void processThread(bool &status_change, unsigned tid);
175
176 /** Processes instructions from fetch and passes them on to rename.
177 * Decoding of instructions actually happens when they are created in
178 * fetch, so this function mostly checks if PC-relative branches are
179 * correct.
180 */
181 virtual void processInsts(unsigned tid);
182
183 /** Process all resources on an instruction's resource schedule */
184 virtual bool processInstSchedule(DynInstPtr inst);
185
186 /** Is there room in the next stage buffer for this instruction? */
187 virtual bool canSendInstToStage(unsigned stage_num);
188
189 /** Send an instruction to the next stage buffer */
190 virtual bool sendInstToNextStage(DynInstPtr inst);
191
192 /** Inserts a thread's instructions into the skid buffer, to be staged
193 * once stage unblocks.
194 */
195 virtual void skidInsert(unsigned tid);
196
197 /** Total size of all skid buffers */
198 int skidSize();
199
200 /** Returns if all of the skid buffers are empty. */
201 bool skidsEmpty();
202
203 /** Updates overall stage status based on all of the threads' statuses. */
204 virtual void updateStatus();
205
206 /** Separates instructions from fetch into individual lists of instructions
207 * sorted by thread.
208 */
209 void sortInsts();
210
211 /** Reads all stall signals from the backwards communication timebuffer. */
212 virtual void readStallSignals(unsigned tid);
213
214 /** Checks all input signals and updates stage's status appropriately. */
215 virtual bool checkSignalsAndUpdate(unsigned tid);
216
217 /** Checks all stall signals, and returns if any are true. */
218 virtual bool checkStall(unsigned tid) const;
219
220 /** Returns if there any instructions from the previous stage
221 * on this cycle.
222 */
223 inline bool prevStageInstsValid();
224
225 /** Switches stage to blocking, and signals back that stage has
226 * become blocked.
227 * @return Returns true if there is a status change.
228 */
229 virtual bool block(unsigned tid);
230
231 void blockDueToBuffer(unsigned tid);
232
233 /** Switches stage to unblocking if the skid buffer is empty, and
234 * signals back that stage has unblocked.
235 * @return Returns true if there is a status change.
236 */
237 virtual bool unblock(unsigned tid);
238
239
240 public:
241 /** Squashes if there is a PC-relative branch that was predicted
242 * incorrectly. Sends squash information back to fetch.
243 */
244 virtual void squashDueToBranch(DynInstPtr &inst, unsigned tid);
245
246 /** Squash instructions from stage buffer */
247 virtual void squashPrevStageInsts(InstSeqNum squash_seq_num, unsigned tid);
248
249 /** Squashes due to commit signalling a squash. Changes status to
250 * squashing and clears block/unblock signals as needed.
251 */
252 virtual void squash(InstSeqNum squash_num, unsigned tid);
253
254 void dumpInsts();
255
256 protected:
257 /** CPU interface. */
258 InOrderCPU *cpu;
259
260 Trace::InOrderTrace *tracer;
261
262 /** List of active thread ids */
263 std::list<unsigned> *activeThreads;
264
265 /** Queue of all instructions coming from previous stage on this cycle. */
266 std::queue<DynInstPtr> insts[ThePipeline::MaxThreads];
267
268 /** Queue of instructions that are finished processing and ready to go next stage.
269 * This is used to prevent from processing an instrution more than once on any
270 * stage. NOTE: It is up to the PROGRAMMER must manage this as a queue
271 */
272 std::list<DynInstPtr> instsToNextStage;
273
274 /** Skid buffer between previous stage and this one. */
275 std::queue<DynInstPtr> skidBuffer[ThePipeline::MaxThreads];
276
277 /** Instruction used to signify that there is no *real* instruction in buffer slot */
278 DynInstPtr dummyBufferInst;
279
280 /** SeqNum of Squashing Branch Delay Instruction (used for MIPS) */
281 Addr bdelayDoneSeqNum[ThePipeline::MaxThreads];
282
283 /** Instruction used for squashing branch (used for MIPS) */
284 DynInstPtr squashInst[ThePipeline::MaxThreads];
285
286 /** Tells when their is a pending delay slot inst. to send
287 * to rename. If there is, then wait squash after the next
288 * instruction (used for MIPS).
289 */
290 bool squashAfterDelaySlot[ThePipeline::MaxThreads];
291
292 /** Maximum size of the inter-stage buffer connecting the previous stage to
293 * this stage (which we call a skid buffer) */
294 unsigned stageBufferMax;
295
296 /** Variable that tracks if stage has written to the time buffer this
297 * cycle. Used to tell CPU if there is activity this cycle.
298 */
299 bool wroteToTimeBuffer;
300
301 /** Index of instructions being sent to the next stage. */
302 unsigned toNextStageIndex;
303
304 /** The last stage that this particular stage should look for stalls */
305 int lastStallingStage[ThePipeline::MaxThreads];
306
307 /** Time buffer interface. */
308 TimeBuffer<TimeStruct> *timeBuffer;
309
310 public:
311 /** Wire to get rename's output from backwards time buffer. */
312 TimeBuffer<TimeStruct>::wire fromNextStages;
313
314 /** Wire to get iew's information from backwards time buffer. */
315 TimeBuffer<TimeStruct>::wire toPrevStages;
316
317 /** Instruction queue linking previous stage */
318 TimeBuffer<InterStageStruct> *prevStageQueue;
319
320 /** Wire to get the previous stage's. */
321 TimeBuffer<InterStageStruct>::wire prevStage;
322
323 /** Instruction queue linking next stage */
324 TimeBuffer<InterStageStruct> *nextStageQueue;
325
326 /** Wire to write to the next stage */
327 TimeBuffer<InterStageStruct>::wire nextStage;
328
329 /** Is Previous Stage Valid? */
330 bool prevStageValid;
331
332 /** Is Next Stage Valid? */
333 bool nextStageValid;
334
335 /** Source of possible stalls. */
336 struct Stalls {
337 bool stage[ThePipeline::NumStages];
338 std::vector<ResReqPtr> resources;
339 };
340
341 /** Tracks which stages are telling decode to stall. */
342 Stalls stalls[ThePipeline::MaxThreads];
343
344 //@TODO: Use Stats for the pipeline stages
345 /** Stat for total number of idle cycles. */
346 //Stats::Scalar<> stageIdleCycles;
347 /** Stat for total number of blocked cycles. */
348 //Stats::Scalar<> stageBlockedCycles;
349 /** Stat for total number of normal running cycles. */
350 //Stats::Scalar<> stageRunCycles;
351 /** Stat for total number of unblocking cycles. */
352 //Stats::Scalar<> stageUnblockCycles;
353 /** Stat for total number of squashing cycles. */
354 //Stats::Scalar<> stageSquashCycles;
355 /** Stat for total number of staged instructions. */
356 //Stats::Scalar<> stageProcessedInsts;
357 /** Stat for total number of squashed instructions. */
358 //Stats::Scalar<> stageSquashedInsts;
359 };
360
361 #endif