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 ¶ms, 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