1/*
2 * Copyright (c) 2013-2014,2018 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 *  The dynamic instruction and instruction/line id (sequence numbers)
44 *  definition for Minor.  A spirited attempt is made here to not carry too
45 *  much on this structure.
46 */
47
48#ifndef __CPU_MINOR_DYN_INST_HH__
49#define __CPU_MINOR_DYN_INST_HH__
50
51#include <iostream>
52
53#include "base/refcnt.hh"
54#include "cpu/minor/buffers.hh"
55#include "cpu/inst_seq.hh"
56#include "cpu/static_inst.hh"
57#include "cpu/timing_expr.hh"
58#include "sim/faults.hh"
59
60namespace Minor
61{
62
63class MinorDynInst;
64
65/** MinorDynInsts are currently reference counted. */
66typedef RefCountingPtr<MinorDynInst> MinorDynInstPtr;
67
68/** Id for lines and instructions.  This includes all the relevant sequence
69 *  numbers and thread ids for all stages of execution. */
70class InstId
71{
72  public:
73    /** First sequence numbers to use in initialisation of the pipeline and
74     *  to be expected on the first line/instruction issued */
75    static const InstSeqNum firstStreamSeqNum = 1;
76    static const InstSeqNum firstPredictionSeqNum = 1;
77    static const InstSeqNum firstLineSeqNum = 1;
78    static const InstSeqNum firstFetchSeqNum = 1;
79    static const InstSeqNum firstExecSeqNum = 1;
80
81  public:
82    /** The thread to which this line/instruction belongs */
83    ThreadID threadId;
84
85    /** The 'stream' this instruction belongs to.  Streams are interrupted
86     *  (and sequence numbers increased) when Execute finds it wants to
87     *  change the stream of instructions due to a branch. */
88    InstSeqNum streamSeqNum;
89
90    /** The predicted qualifier to stream, attached by Fetch2 as a
91     *  consequence of branch prediction */
92    InstSeqNum predictionSeqNum;
93
94    /** Line sequence number.  This is the sequence number of the fetched
95     *  line from which this instruction was fetched */
96    InstSeqNum lineSeqNum;
97
98    /** Fetch sequence number.  This is 0 for bubbles and an ascending
99     *  sequence for the stream of all fetched instructions */
100    InstSeqNum fetchSeqNum;
101
102    /** 'Execute' sequence number.  These are assigned after micro-op
103     *  decomposition and form an ascending sequence (starting with 1) for
104     *  post-micro-op decomposed instructions. */
105    InstSeqNum execSeqNum;
106
107  public:
108    /** Very boring default constructor */
109    InstId(
110        ThreadID thread_id = 0, InstSeqNum stream_seq_num = 0,
111        InstSeqNum prediction_seq_num = 0, InstSeqNum line_seq_num = 0,
112        InstSeqNum fetch_seq_num = 0, InstSeqNum exec_seq_num = 0) :
113        threadId(thread_id), streamSeqNum(stream_seq_num),
114        predictionSeqNum(prediction_seq_num), lineSeqNum(line_seq_num),
115        fetchSeqNum(fetch_seq_num), execSeqNum(exec_seq_num)
116    { }
117
118  public:
119    /* Equal if the thread and last set sequence number matches */
120    bool
121    operator== (const InstId &rhs)
122    {
123        /* If any of fetch and exec sequence number are not set
124         *  they need to be 0, so a straight comparison is still
125         *  fine */
126        bool ret = (threadId == rhs.threadId &&
127            lineSeqNum == rhs.lineSeqNum &&
128            fetchSeqNum == rhs.fetchSeqNum &&
129            execSeqNum == rhs.execSeqNum);
130
131        /* Stream and prediction *must* match if these are the same id */
132        if (ret) {
133            assert(streamSeqNum == rhs.streamSeqNum &&
134                predictionSeqNum == rhs.predictionSeqNum);
135        }
136
137        return ret;
138    }
139};
140
141/** Print this id in the usual slash-separated format expected by
142 *  MinorTrace */
143std::ostream &operator <<(std::ostream &os, const InstId &id);
144
145class MinorDynInst;
146
147/** Print a short reference to this instruction.  '-' for a bubble and a
148 *  series of '/' separated sequence numbers for other instructions.  The
149 *  sequence numbers will be in the order: stream, prediction, line, fetch,
150 *  exec with exec absent if it is 0.  This is used by MinorTrace. */
151std::ostream &operator <<(std::ostream &os, const MinorDynInst &inst);
152
153/** Dynamic instruction for Minor.
154 *  MinorDynInst implements the BubbleIF interface
155 *  Has two separate notions of sequence number for pre/post-micro-op
156 *  decomposition: fetchSeqNum and execSeqNum */
157class MinorDynInst : public RefCounted
158{
159  private:
160    /** A prototypical bubble instruction.  You must call MinorDynInst::init
161     *  to initialise this */
162    static MinorDynInstPtr bubbleInst;
163
164  public:
165    StaticInstPtr staticInst;
166
167    InstId id;
168
169    /** Trace information for this instruction's execution */
170    Trace::InstRecord *traceData;
171
172    /** The fetch address of this instruction */
173    TheISA::PCState pc;
174
175    /** This is actually a fault masquerading as an instruction */
176    Fault fault;
177
178    /** Tried to predict the destination of this inst (if a control
179     *  instruction or a sys call) */
180    bool triedToPredict;
181
182    /** This instruction was predicted to change control flow and
183     *  the following instructions will have a newer predictionSeqNum */
184    bool predictedTaken;
185
186    /** Predicted branch target */
187    TheISA::PCState predictedTarget;
188
189    /** Fields only set during execution */
190
191    /** FU this instruction is issued to */
192    unsigned int fuIndex;
193
194    /** This instruction is in the LSQ, not a functional unit */
195    bool inLSQ;
196
197    /** Translation fault in case of a mem ref */
198    Fault translationFault;
199
200    /** The instruction has been sent to the store buffer */
201    bool inStoreBuffer;
202
203    /** Can this instruction be executed out of order.  In this model,
204     *  this only happens with mem refs that need to be issued early
205     *  to allow other instructions to fill the fetch delay */
206    bool canEarlyIssue;
207
208    /** Flag controlling conditional execution of the instruction */
209    bool predicate;
210
211    /** Flag controlling conditional execution of the memory access associated
212     *  with the instruction (only meaningful for loads/stores) */
213    bool memAccPredicate;
214
215    /** execSeqNum of the latest inst on which this inst depends.
216     *  This can be used as a sanity check for dependency ordering
217     *  where slightly out of order execution is required (notably
218     *  initiateAcc for memory ops) */
219    InstSeqNum instToWaitFor;
220
221    /** Extra delay at the end of the pipeline */
222    Cycles extraCommitDelay;
223    TimingExpr *extraCommitDelayExpr;
224
225    /** Once issued, extraCommitDelay becomes minimumCommitCycle
226     *  to account for delay in absolute time */
227    Cycles minimumCommitCycle;
228
229    /** Flat register indices so that, when clearing the scoreboard, we
230     *  have the same register indices as when the instruction was marked
231     *  up */
232    RegId flatDestRegIdx[TheISA::MaxInstDestRegs];
233
234  public:
235    MinorDynInst(InstId id_ = InstId(), Fault fault_ = NoFault) :
236        staticInst(NULL), id(id_), traceData(NULL),
237        pc(TheISA::PCState(0)), fault(fault_),
238        triedToPredict(false), predictedTaken(false),
239        fuIndex(0), inLSQ(false), translationFault(NoFault),
240        inStoreBuffer(false), canEarlyIssue(false), predicate(true),
241        memAccPredicate(true), instToWaitFor(0), extraCommitDelay(Cycles(0)),
242        extraCommitDelayExpr(NULL), minimumCommitCycle(Cycles(0))
243    { }
244
245  public:
246    /** The BubbleIF interface. */
247    bool isBubble() const { return id.fetchSeqNum == 0; }
248
249    /** There is a single bubble inst */
250    static MinorDynInstPtr bubble() { return bubbleInst; }
251
252    /** Is this a fault rather than instruction */
253    bool isFault() const { return fault != NoFault; }
254
255    /** Is this a real instruction */
256    bool isInst() const { return !isBubble() && !isFault(); }
257
258    /** Is this a real mem ref instruction */
259    bool isMemRef() const { return isInst() && staticInst->isMemRef(); }
260
261    /** Is this an instruction that can be executed `for free' and
262     *  needn't spend time in an FU */
263    bool isNoCostInst() const;
264
265    /** Assuming this is not a fault, is this instruction either
266     *  a whole instruction or the last microop from a macroop */
267    bool isLastOpInInst() const;
268
269    /** Initialise the class */
270    static void init();
271
272    /** Print (possibly verbose) instruction information for
273     *  MinorTrace using the given Named object's name */
274    void minorTraceInst(const Named &named_object) const;
275
276    /** ReportIF interface */
277    void reportData(std::ostream &os) const;
278
279    bool readPredicate() const { return predicate; }
280
281    void setPredicate(bool val) { predicate = val; }
282
283    bool readMemAccPredicate() const { return memAccPredicate; }
284
285    void setMemAccPredicate(bool val) { memAccPredicate = val; }
286
287    ~MinorDynInst();
288};
289
290/** Print a summary of the instruction */
291std::ostream &operator <<(std::ostream &os, const MinorDynInst &inst);
292
293}
294
295#endif /* __CPU_MINOR_DYN_INST_HH__ */
296