2 * Copyright (c) 2013-2014 ARM Limited
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.
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.
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.
37 * Authors: Andrew Bardsley
40 #include "arch/registers.hh"
41 #include "cpu/minor/scoreboard.hh"
42 #include "cpu/reg_class.hh"
43 #include "debug/MinorScoreboard.hh"
44 #include "debug/MinorTiming.hh"
50 Scoreboard::findIndex(RegIndex reg
, Index
&scoreboard_index
)
52 RegClass reg_class
= regIdxToClass(reg
);
55 if (reg
== TheISA::ZeroReg
) {
56 /* Don't bother with the zero register */
62 scoreboard_index
= reg
;
66 scoreboard_index
= TheISA::NumIntRegs
+ TheISA::NumCCRegs
+
67 reg
- TheISA::FP_Reg_Base
;
71 scoreboard_index
= TheISA::NumIntRegs
+ reg
- TheISA::FP_Reg_Base
;
75 /* Don't bother with Misc registers */
84 /** Flatten a RegIndex, irrespective of what reg type it's pointing to */
85 static TheISA::RegIndex
86 flattenRegIndex(TheISA::RegIndex reg
, ThreadContext
*thread_context
)
88 RegClass reg_class
= regIdxToClass(reg
);
89 TheISA::RegIndex ret
= reg
;
94 ret
= thread_context
->flattenIntIndex(reg
);
97 ret
= thread_context
->flattenFloatIndex(reg
);
100 ret
= thread_context
->flattenCCIndex(reg
);
103 /* Don't bother to flatten misc regs as we don't need them here */
104 /* return thread_context->flattenMiscIndex(reg); */
113 Scoreboard::markupInstDests(MinorDynInstPtr inst
, Cycles retire_time
,
114 ThreadContext
*thread_context
, bool mark_unpredictable
)
119 StaticInstPtr staticInst
= inst
->staticInst
;
120 unsigned int num_dests
= staticInst
->numDestRegs();
122 /** Mark each destination register */
123 for (unsigned int dest_index
= 0; dest_index
< num_dests
;
126 RegIndex reg
= flattenRegIndex(
127 staticInst
->destRegIdx(dest_index
), thread_context
);
130 if (findIndex(reg
, index
)) {
131 if (mark_unpredictable
)
132 numUnpredictableResults
[index
]++;
134 inst
->flatDestRegIdx
[dest_index
] = reg
;
137 returnCycle
[index
] = retire_time
;
138 /* We should be able to rely on only being given accending
139 * execSeqNums, but sanity check */
140 if (inst
->id
.execSeqNum
> writingInst
[index
]) {
141 writingInst
[index
] = inst
->id
.execSeqNum
;
142 fuIndices
[index
] = inst
->fuIndex
;
145 DPRINTF(MinorScoreboard
, "Marking up inst: %s"
146 " regIndex: %d final numResults: %d returnCycle: %d\n",
147 *inst
, index
, numResults
[index
], returnCycle
[index
]);
149 /* Use ZeroReg to mark invalid/untracked dests */
150 inst
->flatDestRegIdx
[dest_index
] = TheISA::ZeroReg
;
156 Scoreboard::execSeqNumToWaitFor(MinorDynInstPtr inst
,
157 ThreadContext
*thread_context
)
164 StaticInstPtr staticInst
= inst
->staticInst
;
165 unsigned int num_srcs
= staticInst
->numSrcRegs();
167 for (unsigned int src_index
= 0; src_index
< num_srcs
; src_index
++) {
168 RegIndex reg
= flattenRegIndex(staticInst
->srcRegIdx(src_index
),
170 unsigned short int index
;
172 if (findIndex(reg
, index
)) {
173 if (writingInst
[index
] > ret
)
174 ret
= writingInst
[index
];
178 DPRINTF(MinorScoreboard
, "Inst: %s depends on execSeqNum: %d\n",
185 Scoreboard::clearInstDests(MinorDynInstPtr inst
, bool clear_unpredictable
)
190 StaticInstPtr staticInst
= inst
->staticInst
;
191 unsigned int num_dests
= staticInst
->numDestRegs();
193 /** Mark each destination register */
194 for (unsigned int dest_index
= 0; dest_index
< num_dests
;
197 RegIndex reg
= inst
->flatDestRegIdx
[dest_index
];
200 if (findIndex(reg
, index
)) {
201 if (clear_unpredictable
&& numUnpredictableResults
[index
] != 0)
202 numUnpredictableResults
[index
] --;
204 numResults
[index
] --;
206 if (numResults
[index
] == 0) {
207 returnCycle
[index
] = Cycles(0);
208 writingInst
[index
] = 0;
209 fuIndices
[index
] = -1;
212 DPRINTF(MinorScoreboard
, "Clearing inst: %s"
213 " regIndex: %d final numResults: %d\n",
214 *inst
, index
, numResults
[index
]);
220 Scoreboard::canInstIssue(MinorDynInstPtr inst
,
221 const std::vector
<Cycles
> *src_reg_relative_latencies
,
222 const std::vector
<bool> *cant_forward_from_fu_indices
,
223 Cycles now
, ThreadContext
*thread_context
)
225 /* Always allow fault to be issued */
229 StaticInstPtr staticInst
= inst
->staticInst
;
230 unsigned int num_srcs
= staticInst
->numSrcRegs();
232 /* Default to saying you can issue */
235 unsigned int num_relative_latencies
= 0;
236 Cycles default_relative_latency
= Cycles(0);
238 /* Where relative latencies are given, the default is the last
239 * one as that allows the rel. lat. list to be shorted than the
240 * number of src. regs */
241 if (src_reg_relative_latencies
&&
242 src_reg_relative_latencies
->size() != 0)
244 num_relative_latencies
= src_reg_relative_latencies
->size();
245 default_relative_latency
= (*src_reg_relative_latencies
)
246 [num_relative_latencies
-1];
249 /* For each source register, find the latest result */
250 unsigned int src_index
= 0;
251 while (src_index
< num_srcs
&& /* More registers */
252 ret
/* Still possible */)
254 RegIndex reg
= flattenRegIndex(staticInst
->srcRegIdx(src_index
),
256 unsigned short int index
;
258 if (findIndex(reg
, index
)) {
259 bool cant_forward
= fuIndices
[index
] != 1 &&
260 cant_forward_from_fu_indices
&&
261 index
< cant_forward_from_fu_indices
->size() &&
262 (*cant_forward_from_fu_indices
)[index
];
264 Cycles relative_latency
= (cant_forward
? Cycles(0) :
265 (src_index
>= num_relative_latencies
?
266 default_relative_latency
:
267 (*src_reg_relative_latencies
)[src_index
]));
269 if (returnCycle
[index
] > (now
+ relative_latency
) ||
270 numUnpredictableResults
[index
] != 0)
278 if (DTRACE(MinorTiming
)) {
279 if (ret
&& num_srcs
> num_relative_latencies
&&
280 num_relative_latencies
!= 0)
282 DPRINTF(MinorTiming
, "Warning, inst: %s timing extra decode has"
283 " more src. regs: %d than relative latencies: %d\n",
284 staticInst
->disassemble(0), num_srcs
, num_relative_latencies
);
292 Scoreboard::minorTrace() const
294 std::ostringstream result_stream
;
296 bool printed_element
= false;
299 while (i
< numRegs
) {
300 unsigned short int num_results
= numResults
[i
];
301 unsigned short int num_unpredictable_results
=
302 numUnpredictableResults
[i
];
304 if (!(num_results
== 0 && num_unpredictable_results
== Cycles(0))) {
306 result_stream
<< ',';
308 result_stream
<< '(' << i
<< ','
309 << num_results
<< '/'
310 << num_unpredictable_results
<< '/'
311 << returnCycle
[i
] << '/'
312 << writingInst
[i
] << ')';
314 printed_element
= true;
320 MINORTRACE("busy=%s\n", result_stream
.str());