summaryrefslogtreecommitdiff
path: root/src/cpu/minor/pipe_data.hh
blob: e514be2f949f1d695907328be855cb75afaca86e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
/*
 * Copyright (c) 2013-2014 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Andrew Bardsley
 */

/**
 * @file
 *
 *  Contains class definitions for data flowing between pipeline stages in
 *  the top-level structure portion of this model.  Latch types are also
 *  defined which pair forward/backward flowing data specific to each stage
 *  pair.
 *
 *  No post-configuration inter-stage communication should *ever* take place
 *  outside these classes (except for reservation!)
 */

#ifndef __CPU_MINOR_PIPE_DATA_HH__
#define __CPU_MINOR_PIPE_DATA_HH__

#include "cpu/minor/buffers.hh"
#include "cpu/minor/dyn_inst.hh"
#include "cpu/base.hh"

namespace Minor
{

/** Forward data betwen Execute and Fetch1 carrying change-of-address/stream
 *  information. */
class BranchData /* : public ReportIF, public BubbleIF */
{
  public:
    enum Reason
    {
        /* *** No change of stream (information to branch prediction) */

        /* Don't branch at all (bubble) */
        NoBranch,
        /* Don't branch, but here's the details of a correct prediction
         * that was executed */
        CorrectlyPredictedBranch,

        /* *** Change of stream */

        /* Take an unpredicted branch */
        UnpredictedBranch,
        /* Take a branch on branch prediction data (from Fetch2) */
        BranchPrediction,
        /* Prediction of wrong target PC */
        BadlyPredictedBranchTarget,
        /* Bad branch prediction (didn't actually branch).  Need to branch
         *  back to correct stream.  If the target is wrong, use
         *  BadlyPredictedBranchTarget */
        BadlyPredictedBranch,
        /* Suspend fetching for this thread (inst->id.threadId).
         * This will be woken up by another stream changing branch so
         * count it as stream changing itself and expect pc to be the PC
         * of the next instruction */
        SuspendThread,
        /* Branch from an interrupt (no instruction) */
        Interrupt,
        /* Stop fetching in anticipation of of draining */
        HaltFetch
    };

    /** Is a request with this reason actually a request to change the
     *  PC rather than a bubble or branch prediction information */
    static bool isStreamChange(const BranchData::Reason reason);

    /** Is a request with this reason actually a 'real' branch, that is,
     *  a stream change that's not just an instruction to Fetch1 to halt
     *  or wake up */
    static bool isBranch(const BranchData::Reason reason);

  public:
    /** Explanation for this branch */
    Reason reason;

    /** ThreadID associated with branch */
    ThreadID threadId;

    /** Sequence number of new stream/prediction to be adopted */
    InstSeqNum newStreamSeqNum;
    InstSeqNum newPredictionSeqNum;

    /** Starting PC of that stream */
    TheISA::PCState target;

    /** Instruction which caused this branch */
    MinorDynInstPtr inst;

  public:
    BranchData() :
        reason(NoBranch), threadId(InvalidThreadID), newStreamSeqNum(0),
        newPredictionSeqNum(0), target(TheISA::PCState(0)),
        inst(MinorDynInst::bubble())
    { }

    BranchData(
        Reason reason_,
        ThreadID thread_id,
        InstSeqNum new_stream_seq_num,
        InstSeqNum new_prediction_seq_num,
        TheISA::PCState target,
        MinorDynInstPtr inst_) :
        reason(reason_),
        threadId(thread_id),
        newStreamSeqNum(new_stream_seq_num),
        newPredictionSeqNum(new_prediction_seq_num),
        target(target),
        inst(inst_)
    { }

    /** BubbleIF interface */
    static BranchData bubble() { return BranchData(); }
    bool isBubble() const { return reason == NoBranch; }

    /** As static isStreamChange but on this branch data */
    bool isStreamChange() const { return isStreamChange(reason); }

    /** As static isBranch but on this branch data */
    bool isBranch() const { return isBranch(reason); }

    /** ReportIF interface */
    void reportData(std::ostream &os) const;
};

/** Print a branch reason enum */
std::ostream &operator <<(std::ostream &os, BranchData::Reason reason);

/** Print BranchData contents in a format suitable for DPRINTF comments, not
 *  for MinorTrace */
std::ostream &operator <<(std::ostream &os, const BranchData &branch);

/** Line fetch data in the forward direction.  Contains a single cache line
 *  (or fragment of a line), its address, a sequence number assigned when
 *  that line was fetched and a bubbleFlag that can allow ForwardLineData to
 *  be used to represent the absence of line data in a pipeline. */
class ForwardLineData /* : public ReportIF, public BubbleIF */
{
  private:
    /** This line is a bubble.  No other data member is required to be valid
     *  if this is true */
    bool bubbleFlag;

  public:
    /** First byte address in the line.  This is allowed to be
     *  <= pc.instAddr() */
    Addr lineBaseAddr;

    /** PC of the first requested inst within this line */
    TheISA::PCState pc;

    /** Explicit line width, don't rely on data.size */
    unsigned int lineWidth;

  public:
    /** This line has a fault.  The bubble flag will be false and seqNums
     *  will be valid but no data will */
    Fault fault;

    /** Thread, stream, prediction ... id of this line */
    InstId id;

    /** Line data.  line[0] is the byte at address pc.instAddr().  Data is
     *  only valid upto lineWidth - 1. */
    uint8_t *line;

    /** Packet from which the line is taken */
    Packet *packet;

  public:
    ForwardLineData() :
        bubbleFlag(true),
        lineBaseAddr(0),
        lineWidth(0),
        fault(NoFault),
        line(NULL),
        packet(NULL)
    {
        /* Make lines bubbles by default */
    }

    ~ForwardLineData() { line = NULL; }

  public:
    /** This is a fault, not a line */
    bool isFault() const { return fault != NoFault; }

    /** Set fault and possible clear the bubble flag */
    void setFault(Fault fault_);

    /** In-place initialise a ForwardLineData, freeing and overridding the
     *  line */
    void allocateLine(unsigned int width_);

    /** Use the data from a packet as line instead of allocating new
     *  space.  On destruction of this object, the packet will be destroyed */
    void adoptPacketData(Packet *packet);

    /** Free this ForwardLineData line.  Note that these are shared between
     *  line objects and so you must be careful when deallocating them.
     *  Copying of ForwardLineData can, therefore, be done by default copy
     *  constructors/assignment */
    void freeLine();

    /** BubbleIF interface */
    static ForwardLineData bubble() { return ForwardLineData(); }
    bool isBubble() const { return bubbleFlag; }

    /** ReportIF interface */
    void reportData(std::ostream &os) const;
};

/** Maximum number of instructions that can be carried by the pipeline. */
const unsigned int MAX_FORWARD_INSTS = 16;

/** Forward flowing data between Fetch2,Decode,Execute carrying a packet of
 *  instructions of a width appropriate to the configured stage widths.
 *  Also carries exception information where instructions are not valid */
class ForwardInstData /* : public ReportIF, public BubbleIF */
{
  public:
    /** Array of carried insts, ref counted */
    MinorDynInstPtr insts[MAX_FORWARD_INSTS];

    /** The number of insts slots that can be expected to be valid insts */
    unsigned int numInsts;

    /** Thread associated with these instructions */
    ThreadID threadId;

  public:
    explicit ForwardInstData(unsigned int width = 0,
                             ThreadID tid = InvalidThreadID);

    ForwardInstData(const ForwardInstData &src);

  public:
    /** Number of instructions carried by this object */
    unsigned int width() const { return numInsts; }

    /** Copy the inst array only as far as numInsts */
    ForwardInstData &operator =(const ForwardInstData &src);

    /** Resize a bubble/empty ForwardInstData and fill with bubbles */
    void resize(unsigned int width);

    /** Fill with bubbles from 0 to width() - 1 */
    void bubbleFill();

    /** BubbleIF interface */
    bool isBubble() const;

    /** ReportIF interface */
    void reportData(std::ostream &os) const;
};

}

#endif /* __CPU_MINOR_PIPE_DATA_HH__ */