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