execute.hh revision 10259:ebb376f73dd2
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 *  All the fun of executing instructions from Decode and sending branch/new
44 *  instruction stream info. to Fetch1.
45 */
46
47#ifndef __CPU_MINOR_EXECUTE_HH__
48#define __CPU_MINOR_EXECUTE_HH__
49
50#include "cpu/minor/buffers.hh"
51#include "cpu/minor/cpu.hh"
52#include "cpu/minor/func_unit.hh"
53#include "cpu/minor/lsq.hh"
54#include "cpu/minor/pipe_data.hh"
55#include "cpu/minor/scoreboard.hh"
56
57namespace Minor
58{
59
60/** Execute stage.  Everything apart from fetching and decoding instructions.
61 *  The LSQ lives here too. */
62class Execute : public Named
63{
64  protected:
65    /** Input port carrying instructions from Decode */
66    Latch<ForwardInstData>::Output inp;
67
68    /** Input port carrying stream changes to Fetch1 */
69    Latch<BranchData>::Input out;
70
71    /** Pointer back to the containing CPU */
72    MinorCPU &cpu;
73
74    /** Number of instructions that can be issued per cycle */
75    unsigned int issueLimit;
76
77    /** Number of memory ops that can be issued per cycle */
78    unsigned int memoryIssueLimit;
79
80    /** Number of instructions that can be committed per cycle */
81    unsigned int commitLimit;
82
83    /** Number of memory instructions that can be committed per cycle */
84    unsigned int memoryCommitLimit;
85
86    /** If true, more than one input line can be processed each cycle if
87     *  there is room to execute more instructions than taken from the first
88     *  line */
89    bool processMoreThanOneInput;
90
91    /** Descriptions of the functional units we want to generate */
92    MinorFUPool &fuDescriptions;
93
94    /** Number of functional units to produce */
95    unsigned int numFuncUnits;
96
97    /** Longest latency of any FU, useful for setting up the activity
98     *  recoder */
99    Cycles longestFuLatency;
100
101    /** Modify instruction trace times on commit */
102    bool setTraceTimeOnCommit;
103
104    /** Modify instruction trace times on issue */
105    bool setTraceTimeOnIssue;
106
107    /** Allow mem refs to leave their FUs before reaching the head
108     *  of the in flight insts queue if their dependencies are met */
109    bool allowEarlyMemIssue;
110
111    /** The FU index of the non-existent costless FU for instructions
112     *  which pass the MinorDynInst::isNoCostInst test */
113    unsigned int noCostFUIndex;
114
115    /** Dcache port to pass on to the CPU.  Execute owns this */
116    LSQ lsq;
117
118    /** Scoreboard of instruction dependencies */
119    Scoreboard scoreboard;
120
121    /** The execution functional units */
122    std::vector<FUPipeline *> funcUnits;
123
124  public: /* Public for Pipeline to be able to pass it to Decode */
125    InputBuffer<ForwardInstData> inputBuffer;
126
127  protected:
128    /** Stage cycle-by-cycle state */
129
130    /** State that drain passes through (in order).  On a drain request,
131     *  Execute transitions into either DrainCurrentInst (if between
132     *  microops) or DrainHaltFetch.
133     *
134     *  Note that Execute doesn't actually have *  a 'Drained' state, only
135     *  an indication that it's currently draining and isDrained that can't
136     *  tell if there are insts still in the pipeline leading up to
137     *  Execute */
138    enum DrainState
139    {
140        NotDraining, /* Not draining, possibly running */
141        DrainCurrentInst, /* Draining to end of inst/macroop */
142        DrainHaltFetch, /* Halting Fetch after completing current inst */
143        DrainAllInsts /* Discarding all remaining insts */
144    };
145
146    /** In-order instructions either in FUs or the LSQ */
147    Queue<QueuedInst, ReportTraitsAdaptor<QueuedInst> > *inFlightInsts;
148
149    /** Memory ref instructions still in the FUs */
150    Queue<QueuedInst, ReportTraitsAdaptor<QueuedInst> > *inFUMemInsts;
151
152    /** Index that we've completed upto in getInput data.  We can say we're
153     *  popInput when this equals getInput()->width() */
154    unsigned int inputIndex;
155
156    /** The last commit was the end of a full instruction so an interrupt
157     *  can safely happen */
158    bool lastCommitWasEndOfMacroop;
159
160    /** Structure for reporting insts currently being processed/retired
161     *  for MinorTrace */
162    ForwardInstData instsBeingCommitted;
163
164    /** Source of sequence number for instuction streams.  Increment this and
165     *  pass to fetch whenever an instruction stream needs to be changed.
166     *  For any more complicated behaviour (e.g. speculation) there'll need
167     *  to be another plan. THREAD, need one for each thread */
168    InstSeqNum streamSeqNum;
169
170    /** A prediction number for use where one isn't available from an
171     *  instruction.  This is harvested from committed instructions.
172     *  This isn't really needed as the streamSeqNum will change on
173     *  a branch, but it minimises disruption in stream identification */
174    InstSeqNum lastPredictionSeqNum;
175
176    /** State progression for draining NotDraining -> ... -> DrainAllInsts */
177    DrainState drainState;
178
179  protected:
180    friend std::ostream &operator <<(std::ostream &os, DrainState state);
181
182    /** Get a piece of data to work on from the inputBuffer, or 0 if there
183     *  is no data. */
184    const ForwardInstData *getInput();
185
186    /** Pop an element off the input buffer, if there are any */
187    void popInput();
188
189    /** Generate Branch data based (into branch) on an observed (or not)
190     *  change in PC while executing an instruction.
191     *  Also handles branch prediction information within the inst. */
192    void tryToBranch(MinorDynInstPtr inst, Fault fault, BranchData &branch);
193
194    /** Actually create a branch to communicate to Fetch1/Fetch2 and,
195     *  if that is a stream-changing branch update the streamSeqNum */
196    void updateBranchData(BranchData::Reason reason,
197        MinorDynInstPtr inst, const TheISA::PCState &target,
198        BranchData &branch);
199
200    /** Handle extracting mem ref responses from the memory queues and
201     *  completing the associated instructions.
202     *  Fault is an output and will contain any fault caused (and already
203     *  invoked by the function)
204     *  Sets branch to any branch generated by the instruction. */
205    void handleMemResponse(MinorDynInstPtr inst,
206        LSQ::LSQRequestPtr response, BranchData &branch,
207        Fault &fault);
208
209    /** Execute a memory reference instruction.  This calls initiateAcc on
210     *  the instruction which will then call writeMem or readMem to issue a
211     *  memory access to the LSQ.
212     *  Returns true if the instruction was executed rather than stalled
213     *  because of a lack of LSQ resources and false otherwise.
214     *  branch is set to any branch raised by the instruction.
215     *  failed_predicate is set to false if the instruction passed its
216     *  predicate and so will access memory or true if the instruction
217     *  *failed* its predicate and is now complete.
218     *  fault is set if any non-NoFault fault is raised.
219     *  Any faults raised are actually invoke-d by this function. */
220    bool executeMemRefInst(MinorDynInstPtr inst, BranchData &branch,
221        bool &failed_predicate, Fault &fault);
222
223    /** Has an interrupt been raised */
224    bool isInterrupted(ThreadID thread_id) const;
225
226    /** Are we between instructions?  Can we be interrupted? */
227    bool isInbetweenInsts() const;
228
229    /** Act on an interrupt.  Returns true if an interrupt was actually
230     *  signalled and invoked */
231    bool takeInterrupt(ThreadID thread_id, BranchData &branch);
232
233    /** Try and issue instructions from the inputBuffer */
234    unsigned int issue(bool only_issue_microops);
235
236    /** Try to act on PC-related events.  Returns true if any were
237     *  executed */
238    bool tryPCEvents();
239
240    /** Do the stats handling and instruction count and PC event events
241     *  related to the new instruction/op counts */
242    void doInstCommitAccounting(MinorDynInstPtr inst);
243
244    /** Commit a single instruction.  Returns true if the instruction being
245     *  examined was completed (fully executed, discarded, or initiated a
246     *  memory access), false if there is still some processing to do.
247     *  fu_index is the index of the functional unit this instruction is
248     *  being executed in into for funcUnits
249     *  If early_memory_issue is true then this is an early execution
250     *  of a mem ref and so faults will not be processed.
251     *  If the return value is true:
252     *      fault is set if a fault happened,
253     *      branch is set to indicate any branch that occurs
254     *      committed is set to true if this instruction is committed
255     *          (and so needs to be traced and accounted for)
256     *      completed_mem_issue is set if the instruction was a
257     *          memory access that was issued */
258    bool commitInst(MinorDynInstPtr inst, bool early_memory_issue,
259        BranchData &branch, Fault &fault, bool &committed,
260        bool &completed_mem_issue);
261
262    /** Try and commit instructions from the ends of the functional unit
263     *  pipelines.
264     *  If only_commit_microops is true then only commit upto the
265     *  end of the currect full instruction.
266     *  If discard is true then discard all instructions rather than
267     *  committing.
268     *  branch is set to any branch raised during commit. */
269    void commit(bool only_commit_microops, bool discard, BranchData &branch);
270
271    /** Set the drain state (with useful debugging messages) */
272    void setDrainState(DrainState state);
273
274  public:
275    Execute(const std::string &name_,
276        MinorCPU &cpu_,
277        MinorCPUParams &params,
278        Latch<ForwardInstData>::Output inp_,
279        Latch<BranchData>::Input out_);
280
281    ~Execute();
282
283  public:
284
285    /** Cause Execute to issue an UnpredictedBranch (or WakeupFetch if
286     *  that was passed as the reason) to Fetch1 to wake the
287     *  system up (using the PC from the thread context). */
288    void wakeupFetch(BranchData::Reason reason =
289        BranchData::UnpredictedBranch);
290
291    /** Returns the DcachePort owned by this Execute to pass upwards */
292    MinorCPU::MinorCPUPort &getDcachePort();
293
294    /** To allow ExecContext to find the LSQ */
295    LSQ &getLSQ() { return lsq; }
296
297    /** Does the given instruction have the right stream sequence number
298     *  to be committed? */
299    bool instIsRightStream(MinorDynInstPtr inst);
300
301    /** Returns true if the given instruction is at the head of the
302     *  inFlightInsts instruction queue */
303    bool instIsHeadInst(MinorDynInstPtr inst);
304
305    /** Pass on input/buffer data to the output if you can */
306    void evaluate();
307
308    void minorTrace() const;
309
310    /** After thread suspension, has Execute been drained of in-flight
311     *  instructions and memory accesses. */
312    bool isDrained();
313
314    /** Like the drain interface on SimObject */
315    unsigned int drain();
316    void drainResume();
317};
318
319}
320
321#endif /* __CPU_MINOR_EXECUTE_HH__ */
322