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 * Fetch1 is responsible for fetching "lines" from memory and passing 44 * them to Fetch2 45 */ 46 47#ifndef __CPU_MINOR_FETCH1_HH__ 48#define __CPU_MINOR_FETCH1_HH__ 49 50#include "cpu/minor/buffers.hh" 51#include "cpu/minor/cpu.hh" 52#include "cpu/minor/pipe_data.hh" 53#include "cpu/base.hh" 54#include "mem/packet.hh" 55 56namespace Minor 57{ 58 59/** A stage responsible for fetching "lines" from memory and passing 60 * them to Fetch2 */ 61class Fetch1 : public Named 62{ 63 protected: 64 /** Exposable fetch port */ 65 class IcachePort : public MinorCPU::MinorCPUPort 66 { 67 protected: 68 /** My owner */ 69 Fetch1 &fetch; 70 71 public: 72 IcachePort(std::string name, Fetch1 &fetch_, MinorCPU &cpu) : 73 MinorCPU::MinorCPUPort(name, cpu), fetch(fetch_) 74 { } 75 76 protected: 77 bool recvTimingResp(PacketPtr pkt) 78 { return fetch.recvTimingResp(pkt); } 79 80 void recvReqRetry() { fetch.recvReqRetry(); } 81 }; 82 83 /** Memory access queuing. 84 * 85 * A request can be submitted by pushing it onto the requests queue after 86 * issuing an ITLB lookup (state becomes InTranslation) with a 87 * FetchSenderState senderState containing the current lineSeqNum and 88 * stream/predictionSeqNum. 89 * 90 * Translated packets (state becomes Translation) are then passed to the 91 * memory system and the transfers queue (state becomes RequestIssuing). 92 * Retries are handled by leaving the packet on the requests queue and 93 * changing the state to IcacheNeedsRetry). 94 * 95 * Responses from the memory system alter the request object (state 96 * become Complete). Responses can be picked up from the head of the 97 * transfers queue to pass on to Fetch2. */ 98 99 /** Structure to hold SenderState info through 100 * translation and memory accesses. */ 101 class FetchRequest : 102 public BaseTLB::Translation, /* For TLB lookups */ 103 public Packet::SenderState /* For packing into a Packet */ 104 { 105 protected: 106 /** Owning fetch unit */ 107 Fetch1 &fetch; 108 109 public: 110 /** Progress of this request through address translation and 111 * memory */ 112 enum FetchRequestState 113 { 114 NotIssued, /* Just been made */ 115 InTranslation, /* Issued to ITLB, must wait for reqply */ 116 Translated, /* Translation complete */ 117 RequestIssuing, /* Issued to memory, must wait for response */ 118 Complete /* Complete. Either a fault, or a fetched line */ 119 }; 120 121 FetchRequestState state; 122 123 /** Identity of the line that this request will generate */ 124 InstId id; 125 126 /** FetchRequests carry packets while they're in the requests and 127 * transfers responses queues. When a Packet returns from the memory 128 * system, its request needs to have its packet updated as this may 129 * have changed in flight */ 130 PacketPtr packet; 131 132 /** The underlying request that this fetch represents */ 133 RequestPtr request; 134 135 /** PC to fixup with line address */ 136 TheISA::PCState pc; 137 138 /** Fill in a fault if one happens during fetch, check this by 139 * picking apart the response packet */ 140 Fault fault; 141 142 /** Make a packet to use with the memory transaction */ 143 void makePacket(); 144 145 /** Report interface */ 146 void reportData(std::ostream &os) const; 147 148 /** Is this line out of date with the current stream/prediction 149 * sequence and can it be discarded without orphaning in flight 150 * TLB lookups/memory accesses? */ 151 bool isDiscardable() const; 152 153 /** Is this a complete read line or fault */ 154 bool isComplete() const { return state == Complete; } 155 156 protected: 157 /** BaseTLB::Translation interface */ 158 159 /** Interface for ITLB responses. We can handle delay, so don't 160 * do anything */ 161 void markDelayed() { } 162 163 /** Interface for ITLB responses. Populates self and then passes 164 * the request on to the ports' handleTLBResponse member 165 * function */ 166 void finish(const Fault &fault_, const RequestPtr &request_, 167 ThreadContext *tc, BaseTLB::Mode mode); 168 169 public: 170 FetchRequest(Fetch1 &fetch_, InstId id_, TheISA::PCState pc_) : 171 SenderState(), 172 fetch(fetch_), 173 state(NotIssued), 174 id(id_), 175 packet(NULL), 176 request(), 177 pc(pc_), 178 fault(NoFault) 179 { 180 request = std::make_shared<Request>(); 181 } 182 183 ~FetchRequest(); 184 }; 185 186 typedef FetchRequest *FetchRequestPtr; 187 188 protected: 189 /** Construction-assigned data members */ 190 191 /** Pointer back to the containing CPU */ 192 MinorCPU &cpu; 193 194 /** Input port carrying branch requests from Execute */ 195 Latch<BranchData>::Output inp; 196 /** Output port carrying read lines to Fetch2 */ 197 Latch<ForwardLineData>::Input out; 198 /** Input port carrying branch predictions from Fetch2 */ 199 Latch<BranchData>::Output prediction; 200 201 /** Interface to reserve space in the next stage */ 202 std::vector<InputBuffer<ForwardLineData>> &nextStageReserve; 203 204 /** IcachePort to pass to the CPU. Fetch1 is the only module that uses 205 * it. */ 206 IcachePort icachePort; 207 208 /** Line snap size in bytes. All fetches clip to make their ends not 209 * extend beyond this limit. Setting this to the machine L1 cache line 210 * length will result in fetches never crossing line boundaries. */ 211 unsigned int lineSnap; 212 213 /** Maximum fetch width in bytes. Setting this (and lineSnap) to the 214 * machine L1 cache line length will result in fetches of whole cache 215 * lines. Setting this to sizeof(MachInst) will result it fetches of 216 * single instructions (except near the end of lineSnap lines) */ 217 unsigned int maxLineWidth; 218 219 /** Maximum number of fetches allowed in flight (in queues or memory) */ 220 unsigned int fetchLimit; 221 222 protected: 223 /** Cycle-by-cycle state */ 224 225 /** State of memory access for head instruction fetch */ 226 enum FetchState 227 { 228 FetchHalted, /* Not fetching, waiting to be woken by transition 229 to FetchWaitingForPC. The PC is not valid in this state */ 230 FetchWaitingForPC, /* Not fetching, waiting for stream change. 231 This doesn't stop issued fetches from being returned and 232 processed or for branches to change the state to Running. */ 233 FetchRunning /* Try to fetch, when possible */ 234 }; 235 236 /** Stage cycle-by-cycle state */ 237 238 struct Fetch1ThreadInfo { 239 240 /** Consturctor to initialize all fields. */ 241 Fetch1ThreadInfo() : 242 state(FetchWaitingForPC), 243 pc(TheISA::PCState(0)), 244 streamSeqNum(InstId::firstStreamSeqNum), 245 predictionSeqNum(InstId::firstPredictionSeqNum), 246 blocked(false), 247 wakeupGuard(false) 248 { } 249 250 Fetch1ThreadInfo(const Fetch1ThreadInfo& other) : 251 state(other.state), 252 pc(other.pc), 253 streamSeqNum(other.streamSeqNum), 254 predictionSeqNum(other.predictionSeqNum), 255 blocked(other.blocked) 256 { } 257 258 FetchState state; 259 260 /** Fetch PC value. This is updated by branches from Execute, branch 261 * prediction targets from Fetch2 and by incrementing it as we fetch 262 * lines subsequent to those two sources. */ 263 TheISA::PCState pc; 264 265 /** Stream sequence number. This changes on request from Execute and is 266 * used to tag instructions by the fetch stream to which they belong. 267 * Execute originates new prediction sequence numbers. */ 268 InstSeqNum streamSeqNum; 269 270 /** Prediction sequence number. This changes when requests from Execute 271 * or Fetch2 ask for a change of fetch address and is used to tag lines 272 * by the prediction to which they belong. Fetch2 originates 273 * prediction sequence numbers. */ 274 InstSeqNum predictionSeqNum; 275 276 /** Blocked indication for report */ 277 bool blocked; 278 279 /** Signal to guard against sleeping first cycle of wakeup */ 280 bool wakeupGuard; 281 }; 282 283 std::vector<Fetch1ThreadInfo> fetchInfo; 284 ThreadID threadPriority; 285 286 /** State of memory access for head instruction fetch */ 287 enum IcacheState 288 { 289 IcacheRunning, /* Default. Step icache queues when possible */ 290 IcacheNeedsRetry /* Request rejected, will be asked to retry */ 291 }; 292 293 typedef Queue<FetchRequestPtr, 294 ReportTraitsPtrAdaptor<FetchRequestPtr>, 295 NoBubbleTraits<FetchRequestPtr> > 296 FetchQueue; 297 298 /** Queue of address translated requests from Fetch1 */ 299 FetchQueue requests; 300 301 /** Queue of in-memory system requests and responses */ 302 FetchQueue transfers; 303 304 /** Retry state of icache_port */ 305 IcacheState icacheState; 306 307 /** Sequence number for line fetch used for ordering lines to flush */ 308 InstSeqNum lineSeqNum; 309 310 /** Count of the number fetches which have left the transfers queue 311 * and are in the 'wild' in the memory system. Try not to rely on 312 * this value, it's better to code without knowledge of the number 313 * of outstanding accesses */ 314 unsigned int numFetchesInMemorySystem; 315 /** Number of requests inside the ITLB rather than in the queues. 316 * All requests so located *must* have reserved space in the 317 * transfers queue */ 318 unsigned int numFetchesInITLB; 319 320 protected: 321 friend std::ostream &operator <<(std::ostream &os, 322 Fetch1::FetchState state); 323 324 /** Start fetching from a new address. */ 325 void changeStream(const BranchData &branch); 326 327 /** Update streamSeqNum and predictionSeqNum from the given branch (and 328 * assume these have changed and discard (on delivery) all lines in 329 * flight) */ 330 void updateExpectedSeqNums(const BranchData &branch); 331 332 /** Convert a response to a ForwardLineData */ 333 void processResponse(FetchRequestPtr response, 334 ForwardLineData &line); 335 336 friend std::ostream &operator <<(std::ostream &os, 337 IcacheState state); 338 339 340 /** Use the current threading policy to determine the next thread to 341 * fetch from. */ 342 ThreadID getScheduledThread(); 343 344 /** Insert a line fetch into the requests. This can be a partial 345 * line request where the given address has a non-0 offset into a 346 * line. */ 347 void fetchLine(ThreadID tid); 348 349 /** Try and issue a fetch for a translated request at the 350 * head of the requests queue. Also tries to move the request 351 * between queues */ 352 void tryToSendToTransfers(FetchRequestPtr request); 353 354 /** Try to send (or resend) a memory request's next/only packet to 355 * the memory system. Returns true if the fetch was successfully 356 * sent to memory */ 357 bool tryToSend(FetchRequestPtr request); 358 359 /** Move a request between queues */ 360 void moveFromRequestsToTransfers(FetchRequestPtr request); 361 362 /** Step requests along between requests and transfers queues */ 363 void stepQueues(); 364 365 /** Pop a request from the given queue and correctly deallocate and 366 * discard it. */ 367 void popAndDiscard(FetchQueue &queue); 368 369 /** Handle pushing a TLB response onto the right queue */ 370 void handleTLBResponse(FetchRequestPtr response); 371 372 /** Returns the total number of queue occupancy, in-ITLB and 373 * in-memory system fetches */ 374 unsigned int numInFlightFetches(); 375 376 /** Print the appropriate MinorLine line for a fetch response */ 377 void minorTraceResponseLine(const std::string &name, 378 FetchRequestPtr response) const; 379 380 /** Memory interface */ 381 virtual bool recvTimingResp(PacketPtr pkt); 382 virtual void recvReqRetry(); 383 384 public: 385 Fetch1(const std::string &name_, 386 MinorCPU &cpu_, 387 MinorCPUParams ¶ms, 388 Latch<BranchData>::Output inp_, 389 Latch<ForwardLineData>::Input out_, 390 Latch<BranchData>::Output prediction_, 391 std::vector<InputBuffer<ForwardLineData>> &next_stage_input_buffer); 392 393 public: 394 /** Returns the IcachePort owned by this Fetch1 */ 395 MinorCPU::MinorCPUPort &getIcachePort() { return icachePort; } 396 397 /** Pass on input/buffer data to the output if you can */ 398 void evaluate(); 399 400 /** Initiate fetch1 fetching */ 401 void wakeupFetch(ThreadID tid); 402 403 void minorTrace() const; 404 405 /** Is this stage drained? For Fetch1, draining is initiated by 406 * Execute signalling a branch with the reason HaltFetch */ 407 bool isDrained(); 408}; 409 410} 411 412#endif /* __CPU_MINOR_FETCH1_HH__ */ 413