scoreboard.cc (12104:edd63f9c6184) scoreboard.cc (12106:7784fac1b159)
1/*
2 * Copyright (c) 2013-2014 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Andrew Bardsley
38 */
39
40#include "cpu/minor/scoreboard.hh"
41
42#include "arch/registers.hh"
43#include "cpu/reg_class.hh"
44#include "debug/MinorScoreboard.hh"
45#include "debug/MinorTiming.hh"
46
47namespace Minor
48{
49
50bool
1/*
2 * Copyright (c) 2013-2014 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Andrew Bardsley
38 */
39
40#include "cpu/minor/scoreboard.hh"
41
42#include "arch/registers.hh"
43#include "cpu/reg_class.hh"
44#include "debug/MinorScoreboard.hh"
45#include "debug/MinorTiming.hh"
46
47namespace Minor
48{
49
50bool
51Scoreboard::findIndex(RegId reg, Index &scoreboard_index)
51Scoreboard::findIndex(const RegId& reg, Index &scoreboard_index)
52{
53 bool ret = false;
54
55 if (reg.isZeroReg()) {
56 /* Don't bother with the zero register */
57 ret = false;
58 } else {
52{
53 bool ret = false;
54
55 if (reg.isZeroReg()) {
56 /* Don't bother with the zero register */
57 ret = false;
58 } else {
59 switch (reg.regClass)
59 switch (reg.classValue())
60 {
61 case IntRegClass:
60 {
61 case IntRegClass:
62 scoreboard_index = reg.regIdx;
62 scoreboard_index = reg.index();
63 ret = true;
64 break;
65 case FloatRegClass:
66 scoreboard_index = TheISA::NumIntRegs + TheISA::NumCCRegs +
63 ret = true;
64 break;
65 case FloatRegClass:
66 scoreboard_index = TheISA::NumIntRegs + TheISA::NumCCRegs +
67 reg.regIdx;
67 reg.index();
68 ret = true;
69 break;
70 case CCRegClass:
68 ret = true;
69 break;
70 case CCRegClass:
71 scoreboard_index = TheISA::NumIntRegs + reg.regIdx;
71 scoreboard_index = TheISA::NumIntRegs + reg.index();
72 ret = true;
73 break;
74 case MiscRegClass:
75 /* Don't bother with Misc registers */
76 ret = false;
77 break;
78 }
79 }
80
81 return ret;
82}
83
84/** Flatten a RegId, irrespective of what reg type it's pointing to */
85static RegId
72 ret = true;
73 break;
74 case MiscRegClass:
75 /* Don't bother with Misc registers */
76 ret = false;
77 break;
78 }
79 }
80
81 return ret;
82}
83
84/** Flatten a RegId, irrespective of what reg type it's pointing to */
85static RegId
86flattenRegIndex(RegId reg, ThreadContext *thread_context)
86flattenRegIndex(const RegId& reg, ThreadContext *thread_context)
87{
87{
88 switch (reg.regClass)
89 {
90 case IntRegClass:
91 reg.regIdx = thread_context->flattenIntIndex(reg.regIdx);
92 break;
93 case FloatRegClass:
94 reg.regIdx = thread_context->flattenFloatIndex(reg.regIdx);
95 break;
96 case CCRegClass:
97 reg.regIdx = thread_context->flattenCCIndex(reg.regIdx);
98 break;
99 case MiscRegClass:
100 /* Don't bother to flatten misc regs as we don't need them here */
101 /* return thread_context->flattenMiscIndex(reg); */
102 break;
103 }
104
105 return reg;
88 return thread_context->flattenRegId(reg);
106}
107
108void
109Scoreboard::markupInstDests(MinorDynInstPtr inst, Cycles retire_time,
110 ThreadContext *thread_context, bool mark_unpredictable)
111{
112 if (inst->isFault())
113 return;
114
115 StaticInstPtr staticInst = inst->staticInst;
116 unsigned int num_dests = staticInst->numDestRegs();
117
118 /** Mark each destination register */
119 for (unsigned int dest_index = 0; dest_index < num_dests;
120 dest_index++)
121 {
122 RegId reg = flattenRegIndex(
123 staticInst->destRegIdx(dest_index), thread_context);
124 Index index;
125
126 if (findIndex(reg, index)) {
127 if (mark_unpredictable)
128 numUnpredictableResults[index]++;
129
130 inst->flatDestRegIdx[dest_index] = reg;
131
132 numResults[index]++;
133 returnCycle[index] = retire_time;
134 /* We should be able to rely on only being given accending
135 * execSeqNums, but sanity check */
136 if (inst->id.execSeqNum > writingInst[index]) {
137 writingInst[index] = inst->id.execSeqNum;
138 fuIndices[index] = inst->fuIndex;
139 }
140
141 DPRINTF(MinorScoreboard, "Marking up inst: %s"
142 " regIndex: %d final numResults: %d returnCycle: %d\n",
143 *inst, index, numResults[index], returnCycle[index]);
144 } else {
145 /* Use ZeroReg to mark invalid/untracked dests */
89}
90
91void
92Scoreboard::markupInstDests(MinorDynInstPtr inst, Cycles retire_time,
93 ThreadContext *thread_context, bool mark_unpredictable)
94{
95 if (inst->isFault())
96 return;
97
98 StaticInstPtr staticInst = inst->staticInst;
99 unsigned int num_dests = staticInst->numDestRegs();
100
101 /** Mark each destination register */
102 for (unsigned int dest_index = 0; dest_index < num_dests;
103 dest_index++)
104 {
105 RegId reg = flattenRegIndex(
106 staticInst->destRegIdx(dest_index), thread_context);
107 Index index;
108
109 if (findIndex(reg, index)) {
110 if (mark_unpredictable)
111 numUnpredictableResults[index]++;
112
113 inst->flatDestRegIdx[dest_index] = reg;
114
115 numResults[index]++;
116 returnCycle[index] = retire_time;
117 /* We should be able to rely on only being given accending
118 * execSeqNums, but sanity check */
119 if (inst->id.execSeqNum > writingInst[index]) {
120 writingInst[index] = inst->id.execSeqNum;
121 fuIndices[index] = inst->fuIndex;
122 }
123
124 DPRINTF(MinorScoreboard, "Marking up inst: %s"
125 " regIndex: %d final numResults: %d returnCycle: %d\n",
126 *inst, index, numResults[index], returnCycle[index]);
127 } else {
128 /* Use ZeroReg to mark invalid/untracked dests */
146 inst->flatDestRegIdx[dest_index] = RegId::zeroReg;
129 inst->flatDestRegIdx[dest_index] = RegId(IntRegClass,
130 TheISA::ZeroReg);
147 }
148 }
149}
150
151InstSeqNum
152Scoreboard::execSeqNumToWaitFor(MinorDynInstPtr inst,
153 ThreadContext *thread_context)
154{
155 InstSeqNum ret = 0;
156
157 if (inst->isFault())
158 return ret;
159
160 StaticInstPtr staticInst = inst->staticInst;
161 unsigned int num_srcs = staticInst->numSrcRegs();
162
163 for (unsigned int src_index = 0; src_index < num_srcs; src_index++) {
164 RegId reg = flattenRegIndex(staticInst->srcRegIdx(src_index),
165 thread_context);
166 unsigned short int index;
167
168 if (findIndex(reg, index)) {
169 if (writingInst[index] > ret)
170 ret = writingInst[index];
171 }
172 }
173
174 DPRINTF(MinorScoreboard, "Inst: %s depends on execSeqNum: %d\n",
175 *inst, ret);
176
177 return ret;
178}
179
180void
181Scoreboard::clearInstDests(MinorDynInstPtr inst, bool clear_unpredictable)
182{
183 if (inst->isFault())
184 return;
185
186 StaticInstPtr staticInst = inst->staticInst;
187 unsigned int num_dests = staticInst->numDestRegs();
188
189 /** Mark each destination register */
190 for (unsigned int dest_index = 0; dest_index < num_dests;
191 dest_index++)
192 {
131 }
132 }
133}
134
135InstSeqNum
136Scoreboard::execSeqNumToWaitFor(MinorDynInstPtr inst,
137 ThreadContext *thread_context)
138{
139 InstSeqNum ret = 0;
140
141 if (inst->isFault())
142 return ret;
143
144 StaticInstPtr staticInst = inst->staticInst;
145 unsigned int num_srcs = staticInst->numSrcRegs();
146
147 for (unsigned int src_index = 0; src_index < num_srcs; src_index++) {
148 RegId reg = flattenRegIndex(staticInst->srcRegIdx(src_index),
149 thread_context);
150 unsigned short int index;
151
152 if (findIndex(reg, index)) {
153 if (writingInst[index] > ret)
154 ret = writingInst[index];
155 }
156 }
157
158 DPRINTF(MinorScoreboard, "Inst: %s depends on execSeqNum: %d\n",
159 *inst, ret);
160
161 return ret;
162}
163
164void
165Scoreboard::clearInstDests(MinorDynInstPtr inst, bool clear_unpredictable)
166{
167 if (inst->isFault())
168 return;
169
170 StaticInstPtr staticInst = inst->staticInst;
171 unsigned int num_dests = staticInst->numDestRegs();
172
173 /** Mark each destination register */
174 for (unsigned int dest_index = 0; dest_index < num_dests;
175 dest_index++)
176 {
193 RegId reg = inst->flatDestRegIdx[dest_index];
177 const RegId& reg = inst->flatDestRegIdx[dest_index];
194 Index index;
195
196 if (findIndex(reg, index)) {
197 if (clear_unpredictable && numUnpredictableResults[index] != 0)
198 numUnpredictableResults[index] --;
199
200 numResults[index] --;
201
202 if (numResults[index] == 0) {
203 returnCycle[index] = Cycles(0);
204 writingInst[index] = 0;
205 fuIndices[index] = -1;
206 }
207
208 DPRINTF(MinorScoreboard, "Clearing inst: %s"
209 " regIndex: %d final numResults: %d\n",
210 *inst, index, numResults[index]);
211 }
212 }
213}
214
215bool
216Scoreboard::canInstIssue(MinorDynInstPtr inst,
217 const std::vector<Cycles> *src_reg_relative_latencies,
218 const std::vector<bool> *cant_forward_from_fu_indices,
219 Cycles now, ThreadContext *thread_context)
220{
221 /* Always allow fault to be issued */
222 if (inst->isFault())
223 return true;
224
225 StaticInstPtr staticInst = inst->staticInst;
226 unsigned int num_srcs = staticInst->numSrcRegs();
227
228 /* Default to saying you can issue */
229 bool ret = true;
230
231 unsigned int num_relative_latencies = 0;
232 Cycles default_relative_latency = Cycles(0);
233
234 /* Where relative latencies are given, the default is the last
235 * one as that allows the rel. lat. list to be shorted than the
236 * number of src. regs */
237 if (src_reg_relative_latencies &&
238 src_reg_relative_latencies->size() != 0)
239 {
240 num_relative_latencies = src_reg_relative_latencies->size();
241 default_relative_latency = (*src_reg_relative_latencies)
242 [num_relative_latencies-1];
243 }
244
245 /* For each source register, find the latest result */
246 unsigned int src_index = 0;
247 while (src_index < num_srcs && /* More registers */
248 ret /* Still possible */)
249 {
250 RegId reg = flattenRegIndex(staticInst->srcRegIdx(src_index),
251 thread_context);
252 unsigned short int index;
253
254 if (findIndex(reg, index)) {
255 bool cant_forward = fuIndices[index] != 1 &&
256 cant_forward_from_fu_indices &&
257 index < cant_forward_from_fu_indices->size() &&
258 (*cant_forward_from_fu_indices)[index];
259
260 Cycles relative_latency = (cant_forward ? Cycles(0) :
261 (src_index >= num_relative_latencies ?
262 default_relative_latency :
263 (*src_reg_relative_latencies)[src_index]));
264
265 if (returnCycle[index] > (now + relative_latency) ||
266 numUnpredictableResults[index] != 0)
267 {
268 ret = false;
269 }
270 }
271 src_index++;
272 }
273
274 if (DTRACE(MinorTiming)) {
275 if (ret && num_srcs > num_relative_latencies &&
276 num_relative_latencies != 0)
277 {
278 DPRINTF(MinorTiming, "Warning, inst: %s timing extra decode has"
279 " more src. regs: %d than relative latencies: %d\n",
280 staticInst->disassemble(0), num_srcs, num_relative_latencies);
281 }
282 }
283
284 return ret;
285}
286
287void
288Scoreboard::minorTrace() const
289{
290 std::ostringstream result_stream;
291
292 bool printed_element = false;
293
294 unsigned int i = 0;
295 while (i < numRegs) {
296 unsigned short int num_results = numResults[i];
297 unsigned short int num_unpredictable_results =
298 numUnpredictableResults[i];
299
300 if (!(num_results == 0 && num_unpredictable_results == Cycles(0))) {
301 if (printed_element)
302 result_stream << ',';
303
304 result_stream << '(' << i << ','
305 << num_results << '/'
306 << num_unpredictable_results << '/'
307 << returnCycle[i] << '/'
308 << writingInst[i] << ')';
309
310 printed_element = true;
311 }
312
313 i++;
314 }
315
316 MINORTRACE("busy=%s\n", result_stream.str());
317}
318
319}
178 Index index;
179
180 if (findIndex(reg, index)) {
181 if (clear_unpredictable && numUnpredictableResults[index] != 0)
182 numUnpredictableResults[index] --;
183
184 numResults[index] --;
185
186 if (numResults[index] == 0) {
187 returnCycle[index] = Cycles(0);
188 writingInst[index] = 0;
189 fuIndices[index] = -1;
190 }
191
192 DPRINTF(MinorScoreboard, "Clearing inst: %s"
193 " regIndex: %d final numResults: %d\n",
194 *inst, index, numResults[index]);
195 }
196 }
197}
198
199bool
200Scoreboard::canInstIssue(MinorDynInstPtr inst,
201 const std::vector<Cycles> *src_reg_relative_latencies,
202 const std::vector<bool> *cant_forward_from_fu_indices,
203 Cycles now, ThreadContext *thread_context)
204{
205 /* Always allow fault to be issued */
206 if (inst->isFault())
207 return true;
208
209 StaticInstPtr staticInst = inst->staticInst;
210 unsigned int num_srcs = staticInst->numSrcRegs();
211
212 /* Default to saying you can issue */
213 bool ret = true;
214
215 unsigned int num_relative_latencies = 0;
216 Cycles default_relative_latency = Cycles(0);
217
218 /* Where relative latencies are given, the default is the last
219 * one as that allows the rel. lat. list to be shorted than the
220 * number of src. regs */
221 if (src_reg_relative_latencies &&
222 src_reg_relative_latencies->size() != 0)
223 {
224 num_relative_latencies = src_reg_relative_latencies->size();
225 default_relative_latency = (*src_reg_relative_latencies)
226 [num_relative_latencies-1];
227 }
228
229 /* For each source register, find the latest result */
230 unsigned int src_index = 0;
231 while (src_index < num_srcs && /* More registers */
232 ret /* Still possible */)
233 {
234 RegId reg = flattenRegIndex(staticInst->srcRegIdx(src_index),
235 thread_context);
236 unsigned short int index;
237
238 if (findIndex(reg, index)) {
239 bool cant_forward = fuIndices[index] != 1 &&
240 cant_forward_from_fu_indices &&
241 index < cant_forward_from_fu_indices->size() &&
242 (*cant_forward_from_fu_indices)[index];
243
244 Cycles relative_latency = (cant_forward ? Cycles(0) :
245 (src_index >= num_relative_latencies ?
246 default_relative_latency :
247 (*src_reg_relative_latencies)[src_index]));
248
249 if (returnCycle[index] > (now + relative_latency) ||
250 numUnpredictableResults[index] != 0)
251 {
252 ret = false;
253 }
254 }
255 src_index++;
256 }
257
258 if (DTRACE(MinorTiming)) {
259 if (ret && num_srcs > num_relative_latencies &&
260 num_relative_latencies != 0)
261 {
262 DPRINTF(MinorTiming, "Warning, inst: %s timing extra decode has"
263 " more src. regs: %d than relative latencies: %d\n",
264 staticInst->disassemble(0), num_srcs, num_relative_latencies);
265 }
266 }
267
268 return ret;
269}
270
271void
272Scoreboard::minorTrace() const
273{
274 std::ostringstream result_stream;
275
276 bool printed_element = false;
277
278 unsigned int i = 0;
279 while (i < numRegs) {
280 unsigned short int num_results = numResults[i];
281 unsigned short int num_unpredictable_results =
282 numUnpredictableResults[i];
283
284 if (!(num_results == 0 && num_unpredictable_results == Cycles(0))) {
285 if (printed_element)
286 result_stream << ',';
287
288 result_stream << '(' << i << ','
289 << num_results << '/'
290 << num_unpredictable_results << '/'
291 << returnCycle[i] << '/'
292 << writingInst[i] << ')';
293
294 printed_element = true;
295 }
296
297 i++;
298 }
299
300 MINORTRACE("busy=%s\n", result_stream.str());
301}
302
303}