Deleted Added
sdiff udiff text old ( 13597:6b0f8e9cdeb5 ) new ( 13610:5d5404ac6288 )
full compact
1/*
2 * Copyright (c) 2013-2014, 2016 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(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 {
59 switch (reg.classValue())
60 {
61 case IntRegClass:
62 scoreboard_index = reg.index();
63 ret = true;
64 break;
65 case FloatRegClass:
66 scoreboard_index = TheISA::NumIntRegs + TheISA::NumCCRegs +
67 reg.index();
68 ret = true;
69 break;
70 case VecRegClass:
71 scoreboard_index = TheISA::NumIntRegs + TheISA::NumCCRegs +
72 TheISA::NumFloatRegs + reg.index();
73 ret = true;
74 break;
75 case VecElemClass:
76 scoreboard_index = TheISA::NumIntRegs + TheISA::NumCCRegs +
77 TheISA::NumFloatRegs + reg.flatIndex();
78 ret = true;
79 break;
80 case CCRegClass:
81 scoreboard_index = TheISA::NumIntRegs + reg.index();
82 ret = true;
83 break;
84 case MiscRegClass:
85 /* Don't bother with Misc registers */
86 ret = false;
87 break;
88 default:
89 panic("Unknown register class: %d",
90 static_cast<int>(reg.classValue()));
91 }
92 }
93
94 return ret;
95}
96
97/** Flatten a RegId, irrespective of what reg type it's pointing to */
98static RegId
99flattenRegIndex(const RegId& reg, ThreadContext *thread_context)
100{
101 return thread_context->flattenRegId(reg);
102}
103
104void
105Scoreboard::markupInstDests(MinorDynInstPtr inst, Cycles retire_time,
106 ThreadContext *thread_context, bool mark_unpredictable)
107{
108 if (inst->isFault())
109 return;
110
111 StaticInstPtr staticInst = inst->staticInst;
112 unsigned int num_dests = staticInst->numDestRegs();
113
114 /** Mark each destination register */
115 for (unsigned int dest_index = 0; dest_index < num_dests;
116 dest_index++)
117 {
118 RegId reg = flattenRegIndex(
119 staticInst->destRegIdx(dest_index), thread_context);
120 Index index;
121
122 if (findIndex(reg, index)) {
123 if (mark_unpredictable)
124 numUnpredictableResults[index]++;
125
126 inst->flatDestRegIdx[dest_index] = reg;
127
128 numResults[index]++;
129 returnCycle[index] = retire_time;
130 /* We should be able to rely on only being given accending
131 * execSeqNums, but sanity check */
132 if (inst->id.execSeqNum > writingInst[index]) {
133 writingInst[index] = inst->id.execSeqNum;
134 fuIndices[index] = inst->fuIndex;
135 }
136
137 DPRINTF(MinorScoreboard, "Marking up inst: %s"
138 " regIndex: %d final numResults: %d returnCycle: %d\n",
139 *inst, index, numResults[index], returnCycle[index]);
140 } else {
141 /* Use ZeroReg to mark invalid/untracked dests */
142 inst->flatDestRegIdx[dest_index] = RegId(IntRegClass,
143 TheISA::ZeroReg);
144 }
145 }
146}
147
148InstSeqNum
149Scoreboard::execSeqNumToWaitFor(MinorDynInstPtr inst,
150 ThreadContext *thread_context)
151{
152 InstSeqNum ret = 0;
153
154 if (inst->isFault())
155 return ret;
156
157 StaticInstPtr staticInst = inst->staticInst;
158 unsigned int num_srcs = staticInst->numSrcRegs();
159
160 for (unsigned int src_index = 0; src_index < num_srcs; src_index++) {
161 RegId reg = flattenRegIndex(staticInst->srcRegIdx(src_index),
162 thread_context);
163 unsigned short int index;
164
165 if (findIndex(reg, index)) {
166 if (writingInst[index] > ret)
167 ret = writingInst[index];
168 }
169 }
170
171 DPRINTF(MinorScoreboard, "Inst: %s depends on execSeqNum: %d\n",
172 *inst, ret);
173
174 return ret;
175}
176
177void
178Scoreboard::clearInstDests(MinorDynInstPtr inst, bool clear_unpredictable)
179{
180 if (inst->isFault())
181 return;
182
183 StaticInstPtr staticInst = inst->staticInst;
184 unsigned int num_dests = staticInst->numDestRegs();
185
186 /** Mark each destination register */
187 for (unsigned int dest_index = 0; dest_index < num_dests;
188 dest_index++)
189 {
190 const RegId& reg = inst->flatDestRegIdx[dest_index];
191 Index index;
192
193 if (findIndex(reg, index)) {
194 if (clear_unpredictable && numUnpredictableResults[index] != 0)
195 numUnpredictableResults[index] --;
196
197 numResults[index] --;
198
199 if (numResults[index] == 0) {
200 returnCycle[index] = Cycles(0);
201 writingInst[index] = 0;
202 fuIndices[index] = -1;
203 }
204
205 DPRINTF(MinorScoreboard, "Clearing inst: %s"
206 " regIndex: %d final numResults: %d\n",
207 *inst, index, numResults[index]);
208 }
209 }
210}
211
212bool
213Scoreboard::canInstIssue(MinorDynInstPtr inst,
214 const std::vector<Cycles> *src_reg_relative_latencies,
215 const std::vector<bool> *cant_forward_from_fu_indices,
216 Cycles now, ThreadContext *thread_context)
217{
218 /* Always allow fault to be issued */
219 if (inst->isFault())
220 return true;
221
222 StaticInstPtr staticInst = inst->staticInst;
223 unsigned int num_srcs = staticInst->numSrcRegs();
224
225 /* Default to saying you can issue */
226 bool ret = true;
227
228 unsigned int num_relative_latencies = 0;
229 Cycles default_relative_latency = Cycles(0);
230
231 /* Where relative latencies are given, the default is the last
232 * one as that allows the rel. lat. list to be shorted than the
233 * number of src. regs */
234 if (src_reg_relative_latencies &&
235 src_reg_relative_latencies->size() != 0)
236 {
237 num_relative_latencies = src_reg_relative_latencies->size();
238 default_relative_latency = (*src_reg_relative_latencies)
239 [num_relative_latencies-1];
240 }
241
242 /* For each source register, find the latest result */
243 unsigned int src_index = 0;
244 while (src_index < num_srcs && /* More registers */
245 ret /* Still possible */)
246 {
247 RegId reg = flattenRegIndex(staticInst->srcRegIdx(src_index),
248 thread_context);
249 unsigned short int index;
250
251 if (findIndex(reg, index)) {
252 bool cant_forward = fuIndices[index] != 1 &&
253 cant_forward_from_fu_indices &&
254 index < cant_forward_from_fu_indices->size() &&
255 (*cant_forward_from_fu_indices)[index];
256
257 Cycles relative_latency = (cant_forward ? Cycles(0) :
258 (src_index >= num_relative_latencies ?
259 default_relative_latency :
260 (*src_reg_relative_latencies)[src_index]));
261
262 if (returnCycle[index] > (now + relative_latency) ||
263 numUnpredictableResults[index] != 0)
264 {
265 ret = false;
266 }
267 }
268 src_index++;
269 }
270
271 if (DTRACE(MinorTiming)) {
272 if (ret && num_srcs > num_relative_latencies &&
273 num_relative_latencies != 0)
274 {
275 DPRINTF(MinorTiming, "Warning, inst: %s timing extra decode has"
276 " more src. regs: %d than relative latencies: %d\n",
277 staticInst->disassemble(0), num_srcs, num_relative_latencies);
278 }
279 }
280
281 return ret;
282}
283
284void
285Scoreboard::minorTrace() const
286{
287 std::ostringstream result_stream;
288
289 bool printed_element = false;
290
291 unsigned int i = 0;
292 while (i < numRegs) {
293 unsigned short int num_results = numResults[i];
294 unsigned short int num_unpredictable_results =
295 numUnpredictableResults[i];
296
297 if (!(num_results == 0 && num_unpredictable_results == Cycles(0))) {
298 if (printed_element)
299 result_stream << ',';
300
301 result_stream << '(' << i << ','
302 << num_results << '/'
303 << num_unpredictable_results << '/'
304 << returnCycle[i] << '/'
305 << writingInst[i] << ')';
306
307 printed_element = true;
308 }
309
310 i++;
311 }
312
313 MINORTRACE("busy=%s\n", result_stream.str());
314}
315
316}