includes: sort all includes
[gem5.git] / src / cpu / inorder / resources / execution_unit.cc
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 #include <list>
33 #include <vector>
34
35 #include "cpu/inorder/resources/execution_unit.hh"
36 #include "cpu/inorder/cpu.hh"
37 #include "cpu/inorder/resource_pool.hh"
38
39 using namespace std;
40 using namespace ThePipeline;
41
42 ExecutionUnit::ExecutionUnit(string res_name, int res_id, int res_width,
43 int res_latency, InOrderCPU *_cpu,
44 ThePipeline::Params *params)
45 : Resource(res_name, res_id, res_width, res_latency, _cpu),
46 lastExecuteTick(0), lastControlTick(0), serializeTick(0)
47 { }
48
49 void
50 ExecutionUnit::regStats()
51 {
52 predictedTakenIncorrect
53 .name(name() + ".predictedTakenIncorrect")
54 .desc("Number of Branches Incorrectly Predicted As Taken.");
55
56 predictedNotTakenIncorrect
57 .name(name() + ".predictedNotTakenIncorrect")
58 .desc("Number of Branches Incorrectly Predicted As Not Taken).");
59
60 executions
61 .name(name() + ".executions")
62 .desc("Number of Instructions Executed.");
63
64
65 predictedIncorrect
66 .name(name() + ".mispredicted")
67 .desc("Number of Branches Incorrectly Predicted");
68
69 predictedCorrect
70 .name(name() + ".predicted")
71 .desc("Number of Branches Incorrectly Predicted");
72
73 mispredictPct
74 .name(name() + ".mispredictPct")
75 .desc("Percentage of Incorrect Branches Predicts")
76 .precision(6);
77 mispredictPct = (predictedIncorrect /
78 (predictedCorrect + predictedIncorrect)) * 100;
79
80 Resource::regStats();
81 }
82
83 void
84 ExecutionUnit::execute(int slot_num)
85 {
86 ResourceRequest* exec_req = reqs[slot_num];
87 DynInstPtr inst = reqs[slot_num]->inst;
88 Fault fault = NoFault;
89 InstSeqNum seq_num = inst->seqNum;
90 Tick cur_tick = curTick();
91
92 if (cur_tick == serializeTick) {
93 DPRINTF(InOrderExecute, "Can not execute [tid:%i][sn:%i][PC:%s] %s. "
94 "All instructions are being serialized this cycle\n",
95 inst->readTid(), seq_num, inst->pcState(), inst->instName());
96 exec_req->done(false);
97 return;
98 }
99
100
101 switch (exec_req->cmd)
102 {
103 case ExecuteInst:
104 {
105 if (inst->isNop()) {
106 DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] [PC:%s] Ignoring execution"
107 "of %s.\n", inst->readTid(), seq_num, inst->pcState(),
108 inst->instName());
109 inst->setExecuted();
110 exec_req->done();
111 return;
112 } else {
113 DPRINTF(InOrderExecute, "[tid:%i] Executing [sn:%i] [PC:%s] %s.\n",
114 inst->readTid(), seq_num, inst->pcState(), inst->instName());
115 }
116
117 if (cur_tick != lastExecuteTick) {
118 lastExecuteTick = cur_tick;
119 }
120
121 assert(!inst->isMemRef());
122
123 if (inst->isSerializeAfter()) {
124 serializeTick = cur_tick;
125 DPRINTF(InOrderExecute, "Serializing execution after [tid:%i] "
126 "[sn:%i] [PC:%s] %s.\n", inst->readTid(), seq_num,
127 inst->pcState(), inst->instName());
128 }
129
130 if (inst->isControl()) {
131 if (lastControlTick == cur_tick) {
132 DPRINTF(InOrderExecute, "Can not Execute More than One Control "
133 "Inst Per Cycle. Blocking Request.\n");
134 exec_req->done(false);
135 return;
136 }
137 lastControlTick = curTick();
138
139 // Evaluate Branch
140 fault = inst->execute();
141 executions++;
142
143 inst->setExecuted();
144
145 if (fault == NoFault) {
146 // If branch is mispredicted, then signal squash
147 // throughout all stages behind the pipeline stage
148 // that got squashed.
149 if (inst->mispredicted()) {
150 int stage_num = exec_req->getStageNum();
151 ThreadID tid = inst->readTid();
152 // If it's a branch ...
153 if (inst->isDirectCtrl()) {
154 assert(!inst->isIndirectCtrl());
155
156 TheISA::PCState pc = inst->pcState();
157 TheISA::advancePC(pc, inst->staticInst);
158 inst->setPredTarg(pc);
159
160 if (inst->predTaken() && inst->isCondDelaySlot()) {
161 inst->bdelaySeqNum = seq_num;
162
163 DPRINTF(InOrderExecute, "[tid:%i]: Conditional"
164 " branch inst [sn:%i] PC %s mis"
165 "predicted as taken.\n", tid,
166 seq_num, inst->pcState());
167 } else if (!inst->predTaken() &&
168 inst->isCondDelaySlot()) {
169 inst->bdelaySeqNum = seq_num;
170 inst->procDelaySlotOnMispred = true;
171
172 DPRINTF(InOrderExecute, "[tid:%i]: Conditional"
173 " branch inst [sn:%i] PC %s mis"
174 "predicted as not taken.\n", tid,
175 seq_num, inst->pcState());
176 } else {
177 #if ISA_HAS_DELAY_SLOT
178 inst->bdelaySeqNum = seq_num + 1;
179 #else
180 inst->bdelaySeqNum = seq_num;
181 #endif
182 DPRINTF(InOrderExecute, "[tid:%i]: "
183 "Misprediction detected at "
184 "[sn:%i] PC %s,\n\t squashing after "
185 "delay slot instruction [sn:%i].\n",
186 tid, seq_num, inst->pcState(),
187 inst->bdelaySeqNum);
188 DPRINTF(InOrderStall, "STALL: [tid:%i]: Branch"
189 " misprediction at %s\n",
190 tid, inst->pcState());
191 }
192
193 DPRINTF(InOrderExecute, "[tid:%i] Redirecting "
194 "fetch to %s.\n", tid,
195 inst->readPredTarg());
196
197 } else if (inst->isIndirectCtrl()){
198 TheISA::PCState pc = inst->pcState();
199 TheISA::advancePC(pc, inst->staticInst);
200 inst->seqNum = seq_num;
201 inst->setPredTarg(pc);
202
203 #if ISA_HAS_DELAY_SLOT
204 inst->bdelaySeqNum = seq_num + 1;
205 #else
206 inst->bdelaySeqNum = seq_num;
207 #endif
208
209 DPRINTF(InOrderExecute, "[tid:%i] Redirecting"
210 " fetch to %s.\n", tid,
211 inst->readPredTarg());
212 } else {
213 panic("Non-control instruction (%s) mispredict"
214 "ing?!!", inst->staticInst->getName());
215 }
216
217 DPRINTF(InOrderExecute, "[tid:%i] Squashing will "
218 "start from stage %i.\n", tid, stage_num);
219
220 cpu->pipelineStage[stage_num]->squashDueToBranch(inst,
221 tid);
222
223 inst->squashingStage = stage_num;
224
225 // Squash throughout other resources
226 cpu->resPool->scheduleEvent((InOrderCPU::CPUEventType)
227 ResourcePool::SquashAll,
228 inst, 0, 0, tid);
229
230 if (inst->predTaken()) {
231 predictedTakenIncorrect++;
232 DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ..."
233 "PC %s ... Mispredicts! (Taken)\n",
234 tid, inst->seqNum,
235 inst->staticInst->disassemble(
236 inst->instAddr()),
237 inst->pcState());
238 } else {
239 predictedNotTakenIncorrect++;
240 DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ..."
241 "PC %s ... Mispredicts! (Not Taken)\n",
242 tid, inst->seqNum,
243 inst->staticInst->disassemble(
244 inst->instAddr()),
245 inst->pcState());
246 }
247 predictedIncorrect++;
248 } else {
249 DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: Prediction"
250 "Correct.\n", inst->readTid(), seq_num);
251 predictedCorrect++;
252 }
253
254 exec_req->done();
255 } else {
256 warn("inst [sn:%i] had a %s fault",
257 seq_num, fault->name());
258 }
259 } else {
260 // Regular ALU instruction
261 fault = inst->execute();
262 executions++;
263
264 if (fault == NoFault) {
265 inst->setExecuted();
266
267 DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: The result "
268 "of execution is 0x%x.\n", inst->readTid(),
269 seq_num,
270 (inst->resultType(0) == InOrderDynInst::Float) ?
271 inst->readFloatResult(0) : inst->readIntResult(0));
272 } else {
273 DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: had a %s "
274 "fault.\n", inst->readTid(), seq_num, fault->name());
275 inst->fault = fault;
276 }
277
278 exec_req->done();
279 }
280 }
281 break;
282
283 default:
284 fatal("Unrecognized command to %s", resName);
285 }
286 }
287
288