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