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/**
41 * @file
42 *
43 *  Contains class definitions for data flowing between pipeline stages in
44 *  the top-level structure portion of this model.  Latch types are also
45 *  defined which pair forward/backward flowing data specific to each stage
46 *  pair.
47 *
48 *  No post-configuration inter-stage communication should *ever* take place
49 *  outside these classes (except for reservation!)
50 */
51
52#ifndef __CPU_MINOR_PIPE_DATA_HH__
53#define __CPU_MINOR_PIPE_DATA_HH__
54
55#include "cpu/minor/buffers.hh"
56#include "cpu/minor/dyn_inst.hh"
57#include "cpu/base.hh"
58
59namespace Minor
60{
61
62/** Forward data betwen Execute and Fetch1 carrying change-of-address/stream
63 *  information. */
64class BranchData /* : public ReportIF, public BubbleIF */
65{
66  public:
67    enum Reason
68    {
69        /* *** No change of stream (information to branch prediction) */
70
71        /* Don't branch at all (bubble) */
72        NoBranch,
73        /* Don't branch, but here's the details of a correct prediction
74         * that was executed */
75        CorrectlyPredictedBranch,
76
77        /* *** Change of stream */
78
79        /* Take an unpredicted branch */
80        UnpredictedBranch,
81        /* Take a branch on branch prediction data (from Fetch2) */
82        BranchPrediction,
83        /* Prediction of wrong target PC */
84        BadlyPredictedBranchTarget,
85        /* Bad branch prediction (didn't actually branch).  Need to branch
86         *  back to correct stream.  If the target is wrong, use
87         *  BadlyPredictedBranchTarget */
88        BadlyPredictedBranch,
89        /* Suspend fetching for this thread (inst->id.threadId).
90         * This will be woken up by another stream changing branch so
91         * count it as stream changing itself and expect pc to be the PC
92         * of the next instruction */
93        SuspendThread,
94        /* Branch from an interrupt (no instruction) */
95        Interrupt,
96        /* Stop fetching in anticipation of of draining */
97        HaltFetch
98    };
99
100    /** Is a request with this reason actually a request to change the
101     *  PC rather than a bubble or branch prediction information */
102    static bool isStreamChange(const BranchData::Reason reason);
103
104    /** Is a request with this reason actually a 'real' branch, that is,
105     *  a stream change that's not just an instruction to Fetch1 to halt
106     *  or wake up */
107    static bool isBranch(const BranchData::Reason reason);
108
109  public:
110    /** Explanation for this branch */
111    Reason reason;
112
113    /** ThreadID associated with branch */
114    ThreadID threadId;
115
116    /** Sequence number of new stream/prediction to be adopted */
117    InstSeqNum newStreamSeqNum;
118    InstSeqNum newPredictionSeqNum;
119
120    /** Starting PC of that stream */
121    TheISA::PCState target;
122
123    /** Instruction which caused this branch */
124    MinorDynInstPtr inst;
125
126  public:
127    BranchData() :
128        reason(NoBranch), threadId(InvalidThreadID), newStreamSeqNum(0),
129        newPredictionSeqNum(0), target(TheISA::PCState(0)),
130        inst(MinorDynInst::bubble())
131    { }
132
133    BranchData(
134        Reason reason_,
135        ThreadID thread_id,
136        InstSeqNum new_stream_seq_num,
137        InstSeqNum new_prediction_seq_num,
138        TheISA::PCState target,
139        MinorDynInstPtr inst_) :
140        reason(reason_),
141        threadId(thread_id),
142        newStreamSeqNum(new_stream_seq_num),
143        newPredictionSeqNum(new_prediction_seq_num),
144        target(target),
145        inst(inst_)
146    { }
147
148    /** BubbleIF interface */
149    static BranchData bubble() { return BranchData(); }
150    bool isBubble() const { return reason == NoBranch; }
151
152    /** As static isStreamChange but on this branch data */
153    bool isStreamChange() const { return isStreamChange(reason); }
154
155    /** As static isBranch but on this branch data */
156    bool isBranch() const { return isBranch(reason); }
157
158    /** ReportIF interface */
159    void reportData(std::ostream &os) const;
160};
161
162/** Print a branch reason enum */
163std::ostream &operator <<(std::ostream &os, BranchData::Reason reason);
164
165/** Print BranchData contents in a format suitable for DPRINTF comments, not
166 *  for MinorTrace */
167std::ostream &operator <<(std::ostream &os, const BranchData &branch);
168
169/** Line fetch data in the forward direction.  Contains a single cache line
170 *  (or fragment of a line), its address, a sequence number assigned when
171 *  that line was fetched and a bubbleFlag that can allow ForwardLineData to
172 *  be used to represent the absence of line data in a pipeline. */
173class ForwardLineData /* : public ReportIF, public BubbleIF */
174{
175  private:
176    /** This line is a bubble.  No other data member is required to be valid
177     *  if this is true */
178    bool bubbleFlag;
179
180  public:
181    /** First byte address in the line.  This is allowed to be
182     *  <= pc.instAddr() */
183    Addr lineBaseAddr;
184
185    /** PC of the first requested inst within this line */
186    TheISA::PCState pc;
187
188    /** Explicit line width, don't rely on data.size */
189    unsigned int lineWidth;
190
191  public:
192    /** This line has a fault.  The bubble flag will be false and seqNums
193     *  will be valid but no data will */
194    Fault fault;
195
196    /** Thread, stream, prediction ... id of this line */
197    InstId id;
198
199    /** Line data.  line[0] is the byte at address pc.instAddr().  Data is
200     *  only valid upto lineWidth - 1. */
201    uint8_t *line;
202
203    /** Packet from which the line is taken */
204    Packet *packet;
205
206  public:
207    ForwardLineData() :
208        bubbleFlag(true),
209        lineBaseAddr(0),
210        lineWidth(0),
211        fault(NoFault),
212        line(NULL),
213        packet(NULL)
214    {
215        /* Make lines bubbles by default */
216    }
217
218    ~ForwardLineData() { line = NULL; }
219
220  public:
221    /** This is a fault, not a line */
222    bool isFault() const { return fault != NoFault; }
223
224    /** Set fault and possible clear the bubble flag */
225    void setFault(Fault fault_);
226
227    /** In-place initialise a ForwardLineData, freeing and overridding the
228     *  line */
229    void allocateLine(unsigned int width_);
230
231    /** Use the data from a packet as line instead of allocating new
232     *  space.  On destruction of this object, the packet will be destroyed */
233    void adoptPacketData(Packet *packet);
234
235    /** Free this ForwardLineData line.  Note that these are shared between
236     *  line objects and so you must be careful when deallocating them.
237     *  Copying of ForwardLineData can, therefore, be done by default copy
238     *  constructors/assignment */
239    void freeLine();
240
241    /** BubbleIF interface */
242    static ForwardLineData bubble() { return ForwardLineData(); }
243    bool isBubble() const { return bubbleFlag; }
244
245    /** ReportIF interface */
246    void reportData(std::ostream &os) const;
247};
248
249/** Maximum number of instructions that can be carried by the pipeline. */
250const unsigned int MAX_FORWARD_INSTS = 16;
251
252/** Forward flowing data between Fetch2,Decode,Execute carrying a packet of
253 *  instructions of a width appropriate to the configured stage widths.
254 *  Also carries exception information where instructions are not valid */
255class ForwardInstData /* : public ReportIF, public BubbleIF */
256{
257  public:
258    /** Array of carried insts, ref counted */
259    MinorDynInstPtr insts[MAX_FORWARD_INSTS];
260
261    /** The number of insts slots that can be expected to be valid insts */
262    unsigned int numInsts;
263
264    /** Thread associated with these instructions */
265    ThreadID threadId;
266
267  public:
268    explicit ForwardInstData(unsigned int width = 0,
269                             ThreadID tid = InvalidThreadID);
270
271    ForwardInstData(const ForwardInstData &src);
272
273  public:
274    /** Number of instructions carried by this object */
275    unsigned int width() const { return numInsts; }
276
277    /** Copy the inst array only as far as numInsts */
278    ForwardInstData &operator =(const ForwardInstData &src);
279
280    /** Resize a bubble/empty ForwardInstData and fill with bubbles */
281    void resize(unsigned int width);
282
283    /** Fill with bubbles from 0 to width() - 1 */
284    void bubbleFill();
285
286    /** BubbleIF interface */
287    bool isBubble() const;
288
289    /** ReportIF interface */
290    void reportData(std::ostream &os) const;
291};
292
293}
294
295#endif /* __CPU_MINOR_PIPE_DATA_HH__ */
296