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