2 * Copyright (c) 2013-2014, 2016 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 "cpu/minor/scoreboard.hh"
42 #include "arch/registers.hh"
43 #include "cpu/reg_class.hh"
44 #include "debug/MinorScoreboard.hh"
45 #include "debug/MinorTiming.hh"
51 Scoreboard::findIndex(const RegId
& reg
, Index
&scoreboard_index
)
55 if (reg
.isZeroReg()) {
56 /* Don't bother with the zero register */
59 switch (reg
.classValue())
62 scoreboard_index
= reg
.index();
66 scoreboard_index
= TheISA::NumIntRegs
+ TheISA::NumCCRegs
+
71 scoreboard_index
= TheISA::NumIntRegs
+ TheISA::NumCCRegs
+
72 TheISA::NumFloatRegs
+ reg
.index();
76 scoreboard_index
= TheISA::NumIntRegs
+ TheISA::NumCCRegs
+
77 TheISA::NumFloatRegs
+ TheISA::NumVecRegs
+ reg
.index();
81 scoreboard_index
= TheISA::NumIntRegs
+ reg
.index();
85 /* Don't bother with Misc registers */
89 panic("Unknown register class: %d",
90 static_cast<int>(reg
.classValue()));
97 /** Flatten a RegId, irrespective of what reg type it's pointing to */
99 flattenRegIndex(const RegId
& reg
, ThreadContext
*thread_context
)
101 return thread_context
->flattenRegId(reg
);
105 Scoreboard::markupInstDests(MinorDynInstPtr inst
, Cycles retire_time
,
106 ThreadContext
*thread_context
, bool mark_unpredictable
)
111 StaticInstPtr staticInst
= inst
->staticInst
;
112 unsigned int num_dests
= staticInst
->numDestRegs();
114 /** Mark each destination register */
115 for (unsigned int dest_index
= 0; dest_index
< num_dests
;
118 RegId reg
= flattenRegIndex(
119 staticInst
->destRegIdx(dest_index
), thread_context
);
122 if (findIndex(reg
, index
)) {
123 if (mark_unpredictable
)
124 numUnpredictableResults
[index
]++;
126 inst
->flatDestRegIdx
[dest_index
] = reg
;
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
;
137 DPRINTF(MinorScoreboard
, "Marking up inst: %s"
138 " regIndex: %d final numResults: %d returnCycle: %d\n",
139 *inst
, index
, numResults
[index
], returnCycle
[index
]);
141 /* Use ZeroReg to mark invalid/untracked dests */
142 inst
->flatDestRegIdx
[dest_index
] = RegId(IntRegClass
,
149 Scoreboard::execSeqNumToWaitFor(MinorDynInstPtr inst
,
150 ThreadContext
*thread_context
)
157 StaticInstPtr staticInst
= inst
->staticInst
;
158 unsigned int num_srcs
= staticInst
->numSrcRegs();
160 for (unsigned int src_index
= 0; src_index
< num_srcs
; src_index
++) {
161 RegId reg
= flattenRegIndex(staticInst
->srcRegIdx(src_index
),
163 unsigned short int index
;
165 if (findIndex(reg
, index
)) {
166 if (writingInst
[index
] > ret
)
167 ret
= writingInst
[index
];
171 DPRINTF(MinorScoreboard
, "Inst: %s depends on execSeqNum: %d\n",
178 Scoreboard::clearInstDests(MinorDynInstPtr inst
, bool clear_unpredictable
)
183 StaticInstPtr staticInst
= inst
->staticInst
;
184 unsigned int num_dests
= staticInst
->numDestRegs();
186 /** Mark each destination register */
187 for (unsigned int dest_index
= 0; dest_index
< num_dests
;
190 const RegId
& reg
= inst
->flatDestRegIdx
[dest_index
];
193 if (findIndex(reg
, index
)) {
194 if (clear_unpredictable
&& numUnpredictableResults
[index
] != 0)
195 numUnpredictableResults
[index
] --;
197 numResults
[index
] --;
199 if (numResults
[index
] == 0) {
200 returnCycle
[index
] = Cycles(0);
201 writingInst
[index
] = 0;
202 fuIndices
[index
] = -1;
205 DPRINTF(MinorScoreboard
, "Clearing inst: %s"
206 " regIndex: %d final numResults: %d\n",
207 *inst
, index
, numResults
[index
]);
213 Scoreboard::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
)
218 /* Always allow fault to be issued */
222 StaticInstPtr staticInst
= inst
->staticInst
;
223 unsigned int num_srcs
= staticInst
->numSrcRegs();
225 /* Default to saying you can issue */
228 unsigned int num_relative_latencies
= 0;
229 Cycles default_relative_latency
= Cycles(0);
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)
237 num_relative_latencies
= src_reg_relative_latencies
->size();
238 default_relative_latency
= (*src_reg_relative_latencies
)
239 [num_relative_latencies
-1];
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 */)
247 RegId reg
= flattenRegIndex(staticInst
->srcRegIdx(src_index
),
249 unsigned short int index
;
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
];
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
]));
262 if (returnCycle
[index
] > (now
+ relative_latency
) ||
263 numUnpredictableResults
[index
] != 0)
271 if (DTRACE(MinorTiming
)) {
272 if (ret
&& num_srcs
> num_relative_latencies
&&
273 num_relative_latencies
!= 0)
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
);
285 Scoreboard::minorTrace() const
287 std::ostringstream result_stream
;
289 bool printed_element
= false;
292 while (i
< numRegs
) {
293 unsigned short int num_results
= numResults
[i
];
294 unsigned short int num_unpredictable_results
=
295 numUnpredictableResults
[i
];
297 if (!(num_results
== 0 && num_unpredictable_results
== Cycles(0))) {
299 result_stream
<< ',';
301 result_stream
<< '(' << i
<< ','
302 << num_results
<< '/'
303 << num_unpredictable_results
<< '/'
304 << returnCycle
[i
] << '/'
305 << writingInst
[i
] << ')';
307 printed_element
= true;
313 MINORTRACE("busy=%s\n", result_stream
.str());