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