lsq.hh revision 10713
110259SAndrew.Bardsley@arm.com/* 210259SAndrew.Bardsley@arm.com * Copyright (c) 2013-2014 ARM Limited 310259SAndrew.Bardsley@arm.com * All rights reserved 410259SAndrew.Bardsley@arm.com * 510259SAndrew.Bardsley@arm.com * The license below extends only to copyright in the software and shall 610259SAndrew.Bardsley@arm.com * not be construed as granting a license to any other intellectual 710259SAndrew.Bardsley@arm.com * property including but not limited to intellectual property relating 810259SAndrew.Bardsley@arm.com * to a hardware implementation of the functionality of the software 910259SAndrew.Bardsley@arm.com * licensed hereunder. You may use the software subject to the license 1010259SAndrew.Bardsley@arm.com * terms below provided that you ensure that this notice is replicated 1110259SAndrew.Bardsley@arm.com * unmodified and in its entirety in all distributions of the software, 1210259SAndrew.Bardsley@arm.com * modified or unmodified, in source code or in binary form. 1310259SAndrew.Bardsley@arm.com * 1410259SAndrew.Bardsley@arm.com * Redistribution and use in source and binary forms, with or without 1510259SAndrew.Bardsley@arm.com * modification, are permitted provided that the following conditions are 1610259SAndrew.Bardsley@arm.com * met: redistributions of source code must retain the above copyright 1710259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer; 1810259SAndrew.Bardsley@arm.com * redistributions in binary form must reproduce the above copyright 1910259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer in the 2010259SAndrew.Bardsley@arm.com * documentation and/or other materials provided with the distribution; 2110259SAndrew.Bardsley@arm.com * neither the name of the copyright holders nor the names of its 2210259SAndrew.Bardsley@arm.com * contributors may be used to endorse or promote products derived from 2310259SAndrew.Bardsley@arm.com * this software without specific prior written permission. 2410259SAndrew.Bardsley@arm.com * 2510259SAndrew.Bardsley@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2610259SAndrew.Bardsley@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2710259SAndrew.Bardsley@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2810259SAndrew.Bardsley@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2910259SAndrew.Bardsley@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3010259SAndrew.Bardsley@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3110259SAndrew.Bardsley@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3210259SAndrew.Bardsley@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3310259SAndrew.Bardsley@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3410259SAndrew.Bardsley@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3510259SAndrew.Bardsley@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3610259SAndrew.Bardsley@arm.com * 3710259SAndrew.Bardsley@arm.com * Authors: Andrew Bardsley 3810259SAndrew.Bardsley@arm.com */ 3910259SAndrew.Bardsley@arm.com 4010259SAndrew.Bardsley@arm.com/** 4110259SAndrew.Bardsley@arm.com * @file 4210259SAndrew.Bardsley@arm.com * 4310259SAndrew.Bardsley@arm.com * A load/store queue that allows outstanding reads and writes. 4410259SAndrew.Bardsley@arm.com * 4510259SAndrew.Bardsley@arm.com */ 4610259SAndrew.Bardsley@arm.com 4710259SAndrew.Bardsley@arm.com#ifndef __CPU_MINOR_NEW_LSQ_HH__ 4810259SAndrew.Bardsley@arm.com#define __CPU_MINOR_NEW_LSQ_HH__ 4910259SAndrew.Bardsley@arm.com 5010259SAndrew.Bardsley@arm.com#include "cpu/minor/buffers.hh" 5110259SAndrew.Bardsley@arm.com#include "cpu/minor/cpu.hh" 5210259SAndrew.Bardsley@arm.com#include "cpu/minor/pipe_data.hh" 5310259SAndrew.Bardsley@arm.com#include "cpu/minor/trace.hh" 5410259SAndrew.Bardsley@arm.com 5510259SAndrew.Bardsley@arm.comnamespace Minor 5610259SAndrew.Bardsley@arm.com{ 5710259SAndrew.Bardsley@arm.com 5810259SAndrew.Bardsley@arm.com/* Forward declaration */ 5910259SAndrew.Bardsley@arm.comclass Execute; 6010259SAndrew.Bardsley@arm.com 6110259SAndrew.Bardsley@arm.comclass LSQ : public Named 6210259SAndrew.Bardsley@arm.com{ 6310259SAndrew.Bardsley@arm.com protected: 6410259SAndrew.Bardsley@arm.com /** My owner(s) */ 6510259SAndrew.Bardsley@arm.com MinorCPU &cpu; 6610259SAndrew.Bardsley@arm.com Execute &execute; 6710259SAndrew.Bardsley@arm.com 6810259SAndrew.Bardsley@arm.com protected: 6910259SAndrew.Bardsley@arm.com /** State of memory access for head access. */ 7010259SAndrew.Bardsley@arm.com enum MemoryState 7110259SAndrew.Bardsley@arm.com { 7210259SAndrew.Bardsley@arm.com MemoryRunning, /* Default. Step dcache queues when possible. */ 7310259SAndrew.Bardsley@arm.com MemoryNeedsRetry /* Request rejected, will be asked to retry */ 7410259SAndrew.Bardsley@arm.com }; 7510259SAndrew.Bardsley@arm.com 7610259SAndrew.Bardsley@arm.com /** Print MemoryState values as shown in the enum definition */ 7710259SAndrew.Bardsley@arm.com friend std::ostream &operator <<(std::ostream &os, 7810259SAndrew.Bardsley@arm.com MemoryState state); 7910259SAndrew.Bardsley@arm.com 8010259SAndrew.Bardsley@arm.com /** Coverage of one address range with another */ 8110259SAndrew.Bardsley@arm.com enum AddrRangeCoverage 8210259SAndrew.Bardsley@arm.com { 8310259SAndrew.Bardsley@arm.com PartialAddrRangeCoverage, /* Two ranges partly overlap */ 8410259SAndrew.Bardsley@arm.com FullAddrRangeCoverage, /* One range fully covers another */ 8510259SAndrew.Bardsley@arm.com NoAddrRangeCoverage /* Two ranges are disjoint */ 8610259SAndrew.Bardsley@arm.com }; 8710259SAndrew.Bardsley@arm.com 8810259SAndrew.Bardsley@arm.com /** Exposable data port */ 8910259SAndrew.Bardsley@arm.com class DcachePort : public MinorCPU::MinorCPUPort 9010259SAndrew.Bardsley@arm.com { 9110259SAndrew.Bardsley@arm.com protected: 9210259SAndrew.Bardsley@arm.com /** My owner */ 9310259SAndrew.Bardsley@arm.com LSQ &lsq; 9410259SAndrew.Bardsley@arm.com 9510259SAndrew.Bardsley@arm.com public: 9610259SAndrew.Bardsley@arm.com DcachePort(std::string name, LSQ &lsq_, MinorCPU &cpu) : 9710259SAndrew.Bardsley@arm.com MinorCPU::MinorCPUPort(name, cpu), lsq(lsq_) 9810259SAndrew.Bardsley@arm.com { } 9910259SAndrew.Bardsley@arm.com 10010259SAndrew.Bardsley@arm.com protected: 10110259SAndrew.Bardsley@arm.com bool recvTimingResp(PacketPtr pkt) 10210259SAndrew.Bardsley@arm.com { return lsq.recvTimingResp(pkt); } 10310259SAndrew.Bardsley@arm.com 10410259SAndrew.Bardsley@arm.com void recvReqRetry() { lsq.recvReqRetry(); } 10510259SAndrew.Bardsley@arm.com 10610259SAndrew.Bardsley@arm.com void recvTimingSnoopReq(PacketPtr pkt) 10710259SAndrew.Bardsley@arm.com { return lsq.recvTimingSnoopReq(pkt); } 10810259SAndrew.Bardsley@arm.com }; 10910259SAndrew.Bardsley@arm.com 11010259SAndrew.Bardsley@arm.com DcachePort dcachePort; 11110259SAndrew.Bardsley@arm.com 11210259SAndrew.Bardsley@arm.com public: 11311567Smitch.hayenga@arm.com /** Derived SenderState to carry data access info. through address 11411567Smitch.hayenga@arm.com * translation, the queues in this port and back from the memory 11511567Smitch.hayenga@arm.com * system. */ 11610259SAndrew.Bardsley@arm.com class LSQRequest : 11710259SAndrew.Bardsley@arm.com public BaseTLB::Translation, /* For TLB lookups */ 11810259SAndrew.Bardsley@arm.com public Packet::SenderState /* For packing into a Packet */ 11910259SAndrew.Bardsley@arm.com { 12010259SAndrew.Bardsley@arm.com public: 12110259SAndrew.Bardsley@arm.com /** Owning port */ 12210259SAndrew.Bardsley@arm.com LSQ &port; 12310259SAndrew.Bardsley@arm.com 12410259SAndrew.Bardsley@arm.com /** Instruction which made this request */ 12510259SAndrew.Bardsley@arm.com MinorDynInstPtr inst; 12610259SAndrew.Bardsley@arm.com 12710259SAndrew.Bardsley@arm.com /** Load/store indication used for building packet. This isn't 12811567Smitch.hayenga@arm.com * carried by Request so we need to keep it here */ 12910259SAndrew.Bardsley@arm.com bool isLoad; 13010259SAndrew.Bardsley@arm.com 13110259SAndrew.Bardsley@arm.com /** Dynamically allocated and populated data carried for 13210259SAndrew.Bardsley@arm.com * building write packets */ 13310259SAndrew.Bardsley@arm.com PacketDataPtr data; 13410259SAndrew.Bardsley@arm.com 13511567Smitch.hayenga@arm.com /* Requests carry packets on their way to the memory system. 13610259SAndrew.Bardsley@arm.com * When a Packet returns from the memory system, its 13710259SAndrew.Bardsley@arm.com * request needs to have its packet updated as this 13810259SAndrew.Bardsley@arm.com * may have changed in flight */ 13910259SAndrew.Bardsley@arm.com PacketPtr packet; 14010259SAndrew.Bardsley@arm.com 14111567Smitch.hayenga@arm.com /** The underlying request of this LSQRequest */ 14210259SAndrew.Bardsley@arm.com Request request; 14310259SAndrew.Bardsley@arm.com 14410259SAndrew.Bardsley@arm.com /** Fault generated performing this request */ 14510259SAndrew.Bardsley@arm.com Fault fault; 14610259SAndrew.Bardsley@arm.com 14710259SAndrew.Bardsley@arm.com /** Res from pushRequest */ 14810259SAndrew.Bardsley@arm.com uint64_t *res; 14910259SAndrew.Bardsley@arm.com 15010259SAndrew.Bardsley@arm.com /** Was skipped. Set to indicate any reason (faulted, bad 15110259SAndrew.Bardsley@arm.com * stream sequence number, in a fault shadow) that this 15210259SAndrew.Bardsley@arm.com * request did not perform a memory transfer */ 15310259SAndrew.Bardsley@arm.com bool skipped; 15410259SAndrew.Bardsley@arm.com 15510259SAndrew.Bardsley@arm.com /** This in an access other than a normal cacheable load 15610259SAndrew.Bardsley@arm.com * that's visited the memory system */ 15710259SAndrew.Bardsley@arm.com bool issuedToMemory; 15810259SAndrew.Bardsley@arm.com 15910259SAndrew.Bardsley@arm.com enum LSQRequestState 16010259SAndrew.Bardsley@arm.com { 16110259SAndrew.Bardsley@arm.com NotIssued, /* Newly created */ 16210259SAndrew.Bardsley@arm.com InTranslation, /* TLB accessed, no reply yet */ 16310259SAndrew.Bardsley@arm.com Translated, /* Finished address translation */ 16410259SAndrew.Bardsley@arm.com Failed, /* The starting start of FailedDataRequests */ 16510259SAndrew.Bardsley@arm.com RequestIssuing, /* Load/store issued to memory in the requests 16610259SAndrew.Bardsley@arm.com queue */ 16710259SAndrew.Bardsley@arm.com StoreToStoreBuffer, /* Store in transfers on its way to the 16810259SAndrew.Bardsley@arm.com store buffer */ 16910259SAndrew.Bardsley@arm.com RequestNeedsRetry, /* Retry needed for load */ 17010259SAndrew.Bardsley@arm.com StoreInStoreBuffer, /* Store in the store buffer, before issuing 17110259SAndrew.Bardsley@arm.com a memory transfer */ 17210259SAndrew.Bardsley@arm.com StoreBufferIssuing, /* Store in store buffer and has been 17310259SAndrew.Bardsley@arm.com issued */ 17410259SAndrew.Bardsley@arm.com StoreBufferNeedsRetry, /* Retry needed for store */ 17510259SAndrew.Bardsley@arm.com /* All completed states. Includes 17610259SAndrew.Bardsley@arm.com completed loads, TLB faults and skipped requests whose 17710259SAndrew.Bardsley@arm.com seqNum's no longer match */ 17810259SAndrew.Bardsley@arm.com Complete 17910259SAndrew.Bardsley@arm.com }; 18010259SAndrew.Bardsley@arm.com 18110259SAndrew.Bardsley@arm.com LSQRequestState state; 18210259SAndrew.Bardsley@arm.com 18310259SAndrew.Bardsley@arm.com protected: 18410259SAndrew.Bardsley@arm.com /** BaseTLB::Translation interface */ 18510259SAndrew.Bardsley@arm.com void markDelayed() { } 18610259SAndrew.Bardsley@arm.com 18710259SAndrew.Bardsley@arm.com public: 18810259SAndrew.Bardsley@arm.com LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_, 18910259SAndrew.Bardsley@arm.com PacketDataPtr data_ = NULL, uint64_t *res_ = NULL); 19010259SAndrew.Bardsley@arm.com 19110259SAndrew.Bardsley@arm.com virtual ~LSQRequest(); 19210259SAndrew.Bardsley@arm.com 19310259SAndrew.Bardsley@arm.com public: 19410259SAndrew.Bardsley@arm.com /** Make a packet to use with the memory transaction */ 19510259SAndrew.Bardsley@arm.com void makePacket(); 19610259SAndrew.Bardsley@arm.com 19710259SAndrew.Bardsley@arm.com /** Was no memory access attempted for this request? */ 19810259SAndrew.Bardsley@arm.com bool skippedMemAccess() { return skipped; } 19910259SAndrew.Bardsley@arm.com 20010259SAndrew.Bardsley@arm.com /** Set this request as having been skipped before a memory 20110259SAndrew.Bardsley@arm.com * transfer was attempt */ 20210259SAndrew.Bardsley@arm.com void setSkipped() { skipped = true; } 20310259SAndrew.Bardsley@arm.com 20410259SAndrew.Bardsley@arm.com /** Does address range req1 (req1_addr to req1_addr + req1_size - 1) 20510259SAndrew.Bardsley@arm.com * fully cover, partially cover or not cover at all the range req2 */ 20610259SAndrew.Bardsley@arm.com static AddrRangeCoverage containsAddrRangeOf( 20710259SAndrew.Bardsley@arm.com Addr req1_addr, unsigned int req1_size, 20810259SAndrew.Bardsley@arm.com Addr req2_addr, unsigned int req2_size); 20910259SAndrew.Bardsley@arm.com 21010259SAndrew.Bardsley@arm.com /** Does this request's address range fully cover the range 21110259SAndrew.Bardsley@arm.com * of other_request? */ 21210259SAndrew.Bardsley@arm.com AddrRangeCoverage containsAddrRangeOf(LSQRequest *other_request); 21310259SAndrew.Bardsley@arm.com 21410259SAndrew.Bardsley@arm.com /** Start the address translation process for this request. This 21510259SAndrew.Bardsley@arm.com * will issue a translation request to the TLB. */ 21610259SAndrew.Bardsley@arm.com virtual void startAddrTranslation() = 0; 21710259SAndrew.Bardsley@arm.com 21810259SAndrew.Bardsley@arm.com /** Get the next packet to issue for this request. For split 21910259SAndrew.Bardsley@arm.com * transfers, it will be necessary to step through the available 22010259SAndrew.Bardsley@arm.com * packets by calling do { getHeadPacket ; stepToNextPacket } while 22110259SAndrew.Bardsley@arm.com * (!sentAllPackets) and by retiring response using retireResponse */ 22210259SAndrew.Bardsley@arm.com virtual PacketPtr getHeadPacket() = 0; 22310259SAndrew.Bardsley@arm.com 22410259SAndrew.Bardsley@arm.com /** Step to the next packet for the next call to getHeadPacket */ 22510259SAndrew.Bardsley@arm.com virtual void stepToNextPacket() = 0; 22610259SAndrew.Bardsley@arm.com 22710259SAndrew.Bardsley@arm.com /** Have all packets been sent? */ 22810259SAndrew.Bardsley@arm.com virtual bool sentAllPackets() = 0; 22910259SAndrew.Bardsley@arm.com 23010259SAndrew.Bardsley@arm.com /** True if this request has any issued packets in the memory 23110259SAndrew.Bardsley@arm.com * system and so can't be interrupted until it gets responses */ 23210259SAndrew.Bardsley@arm.com virtual bool hasPacketsInMemSystem() = 0; 23310259SAndrew.Bardsley@arm.com 23410259SAndrew.Bardsley@arm.com /** Retire a response packet into the LSQRequest packet possibly 23510259SAndrew.Bardsley@arm.com * completing this transfer */ 23610259SAndrew.Bardsley@arm.com virtual void retireResponse(PacketPtr packet_) = 0; 23710259SAndrew.Bardsley@arm.com 23810259SAndrew.Bardsley@arm.com /** Is this a request a barrier? */ 23910259SAndrew.Bardsley@arm.com virtual bool isBarrier(); 24010259SAndrew.Bardsley@arm.com 24110259SAndrew.Bardsley@arm.com /** This request, once processed by the requests/transfers 24210259SAndrew.Bardsley@arm.com * queues, will need to go to the store buffer */ 24310259SAndrew.Bardsley@arm.com bool needsToBeSentToStoreBuffer(); 24410259SAndrew.Bardsley@arm.com 24510259SAndrew.Bardsley@arm.com /** Set state and output trace output */ 24610259SAndrew.Bardsley@arm.com void setState(LSQRequestState new_state); 24710259SAndrew.Bardsley@arm.com 24810259SAndrew.Bardsley@arm.com /** Has this request been completed. This includes *all* reasons 24910259SAndrew.Bardsley@arm.com * for completion: successful transfers, faults, skipped because 25010259SAndrew.Bardsley@arm.com * of preceding faults */ 25110259SAndrew.Bardsley@arm.com bool isComplete() const; 25210259SAndrew.Bardsley@arm.com 25310259SAndrew.Bardsley@arm.com /** MinorTrace report interface */ 25410259SAndrew.Bardsley@arm.com void reportData(std::ostream &os) const; 25510259SAndrew.Bardsley@arm.com }; 25610259SAndrew.Bardsley@arm.com 25710259SAndrew.Bardsley@arm.com typedef LSQRequest *LSQRequestPtr; 25810259SAndrew.Bardsley@arm.com 25910259SAndrew.Bardsley@arm.com friend std::ostream & operator <<(std::ostream &os, 26010259SAndrew.Bardsley@arm.com AddrRangeCoverage state); 26110259SAndrew.Bardsley@arm.com 26210259SAndrew.Bardsley@arm.com friend std::ostream & operator <<(std::ostream &os, 26310259SAndrew.Bardsley@arm.com LSQRequest::LSQRequestState state); 26411567Smitch.hayenga@arm.com 26511567Smitch.hayenga@arm.com protected: 26611567Smitch.hayenga@arm.com /** Special request types that don't actually issue memory requests */ 26710259SAndrew.Bardsley@arm.com class SpecialDataRequest : public LSQRequest 26811567Smitch.hayenga@arm.com { 26911567Smitch.hayenga@arm.com protected: 27010259SAndrew.Bardsley@arm.com /** TLB interace */ 27110259SAndrew.Bardsley@arm.com void finish(const Fault &fault_, RequestPtr request_, 27210259SAndrew.Bardsley@arm.com ThreadContext *tc, BaseTLB::Mode mode) 27310259SAndrew.Bardsley@arm.com { } 27410259SAndrew.Bardsley@arm.com 27510259SAndrew.Bardsley@arm.com public: 27610259SAndrew.Bardsley@arm.com /** Send single translation request */ 27710259SAndrew.Bardsley@arm.com void startAddrTranslation() { } 27810259SAndrew.Bardsley@arm.com 27910259SAndrew.Bardsley@arm.com /** Get the head packet as counted by numIssuedFragments */ 28010259SAndrew.Bardsley@arm.com PacketPtr getHeadPacket() 28110259SAndrew.Bardsley@arm.com { fatal("No packets in a SpecialDataRequest"); } 28210259SAndrew.Bardsley@arm.com 28310259SAndrew.Bardsley@arm.com /** Step on numIssuedFragments */ 28410259SAndrew.Bardsley@arm.com void stepToNextPacket() { } 28510259SAndrew.Bardsley@arm.com 28610259SAndrew.Bardsley@arm.com /** Has no packets to send */ 28710259SAndrew.Bardsley@arm.com bool sentAllPackets() { return true; } 28810259SAndrew.Bardsley@arm.com 28910259SAndrew.Bardsley@arm.com /** Never sends any requests */ 29010259SAndrew.Bardsley@arm.com bool hasPacketsInMemSystem() { return false; } 29110259SAndrew.Bardsley@arm.com 29210259SAndrew.Bardsley@arm.com /** Keep the given packet as the response packet 29310259SAndrew.Bardsley@arm.com * LSQRequest::packet */ 29410259SAndrew.Bardsley@arm.com void retireResponse(PacketPtr packet_) { } 29510259SAndrew.Bardsley@arm.com 296 public: 297 SpecialDataRequest(LSQ &port_, MinorDynInstPtr inst_) : 298 /* Say this is a load, not actually relevant */ 299 LSQRequest(port_, inst_, true, NULL, 0) 300 { } 301 }; 302 303 /** FailedDataRequest represents requests from instructions that 304 * failed their predicates but need to ride the requests/transfers 305 * queues to maintain trace ordering */ 306 class FailedDataRequest : public SpecialDataRequest 307 { 308 public: 309 FailedDataRequest(LSQ &port_, MinorDynInstPtr inst_) : 310 SpecialDataRequest(port_, inst_) 311 { state = Failed; } 312 }; 313 314 /** Request for doing barrier accounting in the store buffer. Not 315 * for use outside that unit */ 316 class BarrierDataRequest : public SpecialDataRequest 317 { 318 public: 319 bool isBarrier() { return true; } 320 321 public: 322 BarrierDataRequest(LSQ &port_, MinorDynInstPtr inst_) : 323 SpecialDataRequest(port_, inst_) 324 { state = Complete; } 325 }; 326 327 /** SingleDataRequest is used for requests that don't fragment */ 328 class SingleDataRequest : public LSQRequest 329 { 330 protected: 331 /** TLB interace */ 332 void finish(const Fault &fault_, RequestPtr request_, 333 ThreadContext *tc, BaseTLB::Mode mode); 334 335 /** Has my only packet been sent to the memory system but has not 336 * yet been responded to */ 337 bool packetInFlight; 338 339 /** Has the packet been at least sent to the memory system? */ 340 bool packetSent; 341 342 public: 343 /** Send single translation request */ 344 void startAddrTranslation(); 345 346 /** Get the head packet as counted by numIssuedFragments */ 347 PacketPtr getHeadPacket() { return packet; } 348 349 /** Remember that the packet has been sent */ 350 void stepToNextPacket() { packetInFlight = true; packetSent = true; } 351 352 /** Has packet been sent */ 353 bool hasPacketsInMemSystem() { return packetInFlight; } 354 355 /** packetInFlight can become false again, so need to check 356 * packetSent */ 357 bool sentAllPackets() { return packetSent; } 358 359 /** Keep the given packet as the response packet 360 * LSQRequest::packet */ 361 void retireResponse(PacketPtr packet_); 362 363 public: 364 SingleDataRequest(LSQ &port_, MinorDynInstPtr inst_, 365 bool isLoad_, PacketDataPtr data_ = NULL, uint64_t *res_ = NULL) : 366 LSQRequest(port_, inst_, isLoad_, data_, res_), 367 packetInFlight(false), 368 packetSent(false) 369 { } 370 }; 371 372 class SplitDataRequest : public LSQRequest 373 { 374 protected: 375 /** Event to step between translations */ 376 class TranslationEvent : public Event 377 { 378 protected: 379 SplitDataRequest &owner; 380 381 public: 382 TranslationEvent(SplitDataRequest &owner_) 383 : owner(owner_) { } 384 385 void process() 386 { owner.sendNextFragmentToTranslation(); } 387 }; 388 389 TranslationEvent translationEvent; 390 protected: 391 /** Number of fragments this request is split into */ 392 unsigned int numFragments; 393 394 /** Number of fragments in the address translation mechanism */ 395 unsigned int numInTranslationFragments; 396 397 /** Number of fragments that have completed address translation, 398 * (numTranslatedFragments + numInTranslationFragments) <= 399 * numFragments. When numTranslatedFramgents == numFragments, 400 * translation is complete */ 401 unsigned int numTranslatedFragments; 402 403 /** Number of fragments already issued (<= numFragments) */ 404 unsigned int numIssuedFragments; 405 406 /** Number of fragments retired back to this request */ 407 unsigned int numRetiredFragments; 408 409 /** Fragment Requests corresponding to the address ranges of 410 * each fragment */ 411 std::vector<Request *> fragmentRequests; 412 413 /** Packets matching fragmentRequests to issue fragments to memory */ 414 std::vector<Packet *> fragmentPackets; 415 416 protected: 417 /** TLB response interface */ 418 void finish(const Fault &fault_, RequestPtr request_, 419 ThreadContext *tc, BaseTLB::Mode mode); 420 421 public: 422 SplitDataRequest(LSQ &port_, MinorDynInstPtr inst_, 423 bool isLoad_, PacketDataPtr data_ = NULL, 424 uint64_t *res_ = NULL); 425 426 ~SplitDataRequest(); 427 428 public: 429 /** Make all the Requests for this transfer's fragments so that those 430 * requests can be sent for address translation */ 431 void makeFragmentRequests(); 432 433 /** Make the packets to go with the requests so they can be sent to 434 * the memory system */ 435 void makeFragmentPackets(); 436 437 /** Start a loop of do { sendNextFragmentToTranslation ; 438 * translateTiming ; finish } while (numTranslatedFragments != 439 * numFragments) to complete all this requests' fragments' address 440 * translations */ 441 void startAddrTranslation(); 442 443 /** Get the head packet as counted by numIssuedFragments */ 444 PacketPtr getHeadPacket(); 445 446 /** Step on numIssuedFragments */ 447 void stepToNextPacket(); 448 449 bool hasPacketsInMemSystem() 450 { return numIssuedFragments != numRetiredFragments; } 451 452 /** Have we stepped past the end of fragmentPackets? */ 453 bool sentAllPackets() { return numIssuedFragments == numFragments; } 454 455 /** For loads, paste the response data into the main 456 * response packet */ 457 void retireResponse(PacketPtr packet_); 458 459 /** Part of the address translation loop, see startAddTranslation */ 460 void sendNextFragmentToTranslation(); 461 }; 462 463 /** Store buffer. This contains stores which have been committed 464 * but whose memory transfers have not yet been issued. Load data 465 * can be forwarded out of the store buffer */ 466 class StoreBuffer : public Named 467 { 468 public: 469 /** My owner */ 470 LSQ &lsq; 471 472 /** Number of slots, this is a bound on the size of slots */ 473 const unsigned int numSlots; 474 475 /** Maximum number of stores that can be issued per cycle */ 476 const unsigned int storeLimitPerCycle; 477 478 public: 479 /** Queue of store requests on their way to memory */ 480 std::deque<LSQRequestPtr> slots; 481 482 /** Number of occupied slots which have not yet issued a 483 * memory access */ 484 unsigned int numUnissuedAccesses; 485 486 public: 487 StoreBuffer(std::string name_, LSQ &lsq_, 488 unsigned int store_buffer_size, 489 unsigned int store_limit_per_cycle); 490 491 public: 492 /** Can a new request be inserted into the queue? */ 493 bool canInsert() const; 494 495 /** Delete the given request and free the slot it occupied */ 496 void deleteRequest(LSQRequestPtr request); 497 498 /** Insert a request at the back of the queue */ 499 void insert(LSQRequestPtr request); 500 501 /** Look for a store which satisfies the given load. Returns an 502 * indication whether the forwarding request can be wholly, 503 * partly or not all all satisfied. If the request can be 504 * wholly satisfied, the store buffer slot number which can be used 505 * is returned in found_slot */ 506 AddrRangeCoverage canForwardDataToLoad(LSQRequestPtr request, 507 unsigned int &found_slot); 508 509 /** Fill the given packet with appropriate date from slot 510 * slot_number */ 511 void forwardStoreData(LSQRequestPtr load, unsigned int slot_number); 512 513 /** Number of stores in the store buffer which have not been 514 * completely issued to the memory system */ 515 unsigned int numUnissuedStores() { return numUnissuedAccesses; } 516 517 /** Count a store being issued to memory by decrementing 518 * numUnissuedAccesses. Does not count barrier requests as they 519 * will be handles as barriers are cleared from the buffer */ 520 void countIssuedStore(LSQRequestPtr request); 521 522 /** Drained if there is absolutely nothing left in the buffer */ 523 bool isDrained() const { return slots.empty(); } 524 525 /** Try to issue more stores to memory */ 526 void step(); 527 528 /** Report queue contents for MinorTrace */ 529 void minorTrace() const; 530 }; 531 532 protected: 533 /** Most recent execSeqNum of a memory barrier instruction or 534 * 0 if there are no in-flight barriers. Useful as a 535 * dependency for early-issued memory operations */ 536 InstSeqNum lastMemBarrier; 537 538 public: 539 /** Retry state of last issued memory transfer */ 540 MemoryState state; 541 542 /** Maximum number of in-flight accesses issued to the memory system */ 543 const unsigned int inMemorySystemLimit; 544 545 /** Memory system access width (and snap) in bytes */ 546 const unsigned int lineWidth; 547 548 public: 549 /** The LSQ consists of three queues: requests, transfers and the 550 * store buffer storeBuffer. */ 551 552 typedef Queue<LSQRequestPtr, 553 ReportTraitsPtrAdaptor<LSQRequestPtr>, 554 NoBubbleTraits<LSQRequestPtr> > 555 LSQQueue; 556 557 /** requests contains LSQRequests which have been issued to the TLB by 558 * calling ExecContext::readMem/writeMem (which in turn calls 559 * LSQ::pushRequest and LSQRequest::startAddrTranslation). Once they 560 * have a physical address, requests at the head of requests can be 561 * issued to the memory system. At this stage, it cannot be clear that 562 * memory accesses *must* happen (that there are no preceding faults or 563 * changes of flow of control) and so only cacheable reads are issued 564 * to memory. 565 * Cacheable stores are not issued at all (and just pass through 566 * 'transfers' in order) and all other transfers are stalled in requests 567 * until their corresponding instructions are at the head of the 568 * inMemInsts instruction queue and have the right streamSeqNum. */ 569 LSQQueue requests; 570 571 /** Once issued to memory (or, for stores, just had their 572 * state changed to StoreToStoreBuffer) LSQRequests pass through 573 * transfers waiting for memory responses. At the head of transfers, 574 * Execute::commitInst can pick up the memory response for a request 575 * using LSQ::findResponse. Responses to be committed can then 576 * have ExecContext::completeAcc on them. Stores can then be pushed 577 * into the store buffer. All other transfers will then be complete. */ 578 LSQQueue transfers; 579 580 /* The store buffer contains committed cacheable stores on 581 * their way to memory decoupled from subsequence instruction execution. 582 * Before trying to issue a cacheable read from 'requests' to memory, 583 * the store buffer is checked to see if a previous store contains the 584 * needed data (StoreBuffer::canForwardDataToLoad) which can be 585 * forwarded in lieu of a memory access. If there are outstanding 586 * stores in the transfers queue, they must be promoted to the store 587 * buffer (and so be commited) before they can be correctly checked 588 * for forwarding. */ 589 StoreBuffer storeBuffer; 590 591 protected: 592 /** Count of the number of mem. accesses which have left the 593 * requests queue and are in the 'wild' in the memory system and who 594 * *must not* be interrupted as they are not normal cacheable 595 * accesses. This is a count of the number of in-flight requests 596 * with issuedToMemory set who have visited tryToSendRequest at least 597 * once */ 598 unsigned int numAccessesInMemorySystem; 599 600 /** Number of requests in the DTLB in the requests queue */ 601 unsigned int numAccessesInDTLB; 602 603 /** The number of stores in the transfers queue. Useful when 604 * testing if the store buffer contains all the forwardable stores */ 605 unsigned int numStoresInTransfers; 606 607 /** The number of accesses which have been issued to the memory 608 * system but have not been committed/discarded *excluding* 609 * cacheable normal loads which don't need to be tracked */ 610 unsigned int numAccessesIssuedToMemory; 611 612 /** The request (from either requests or the store buffer) which is 613 * currently waiting have its memory access retried */ 614 LSQRequestPtr retryRequest; 615 616 /** Address Mask for a cache block (e.g. ~(cache_block_size-1)) */ 617 Addr cacheBlockMask; 618 619 protected: 620 /** Try and issue a memory access for a translated request at the 621 * head of the requests queue. Also tries to move the request 622 * between queues */ 623 void tryToSendToTransfers(LSQRequestPtr request); 624 625 /** Try to send (or resend) a memory request's next/only packet to 626 * the memory system. Returns true if the request was successfully 627 * sent to memory (and was also the last packet in a transfer) */ 628 bool tryToSend(LSQRequestPtr request); 629 630 /** Clear a barrier (if it's the last one marked up in lastMemBarrier) */ 631 void clearMemBarrier(MinorDynInstPtr inst); 632 633 /** Move a request between queues */ 634 void moveFromRequestsToTransfers(LSQRequestPtr request); 635 636 /** Can a request be sent to the memory system */ 637 bool canSendToMemorySystem(); 638 639 public: 640 LSQ(std::string name_, std::string dcache_port_name_, 641 MinorCPU &cpu_, Execute &execute_, 642 unsigned int max_accesses_in_memory_system, unsigned int line_width, 643 unsigned int requests_queue_size, unsigned int transfers_queue_size, 644 unsigned int store_buffer_size, 645 unsigned int store_buffer_cycle_store_limit); 646 647 virtual ~LSQ(); 648 649 public: 650 /** Step checks the queues to see if their are issuable transfers 651 * which were not otherwise picked up by tests at the end of other 652 * events. 653 * 654 * Steppable actions include deferred actions which couldn't be 655 * cascaded on the end of a memory response/TLB response event 656 * because of resource congestion. */ 657 void step(); 658 659 /** Is their space in the request queue to be able to push a request by 660 * issuing an isMemRef instruction */ 661 bool canRequest() { return requests.unreservedRemainingSpace() != 0; } 662 663 /** Returns a response if it's at the head of the transfers queue and 664 * it's either complete or can be sent on to the store buffer. After 665 * calling, the request still remains on the transfer queue until 666 * popResponse is called */ 667 LSQRequestPtr findResponse(MinorDynInstPtr inst); 668 669 /** Sanity check and pop the head response */ 670 void popResponse(LSQRequestPtr response); 671 672 /** Must check this before trying to insert into the store buffer */ 673 bool canPushIntoStoreBuffer() const { return storeBuffer.canInsert(); } 674 675 /** A store has been committed, please move it to the store buffer */ 676 void sendStoreToStoreBuffer(LSQRequestPtr request); 677 678 /** Are there any accesses other than normal cached loads in the 679 * memory system or having received responses which need to be 680 * handled for their instruction's to be completed */ 681 bool accessesInFlight() const 682 { return numAccessesIssuedToMemory != 0; } 683 684 /** A memory barrier instruction has been issued, remember its 685 * execSeqNum that we can avoid issuing memory ops until it is 686 * committed */ 687 void issuedMemBarrierInst(MinorDynInstPtr inst); 688 689 /** Get the execSeqNum of the last issued memory barrier */ 690 InstSeqNum getLastMemBarrier() const { return lastMemBarrier; } 691 692 /** Is there nothing left in the LSQ */ 693 bool isDrained(); 694 695 /** May need to be ticked next cycle as one of the queues contains 696 * an actionable transfers or address translation */ 697 bool needsToTick(); 698 699 /** Complete a barrier instruction. Where committed, makes a 700 * BarrierDataRequest and pushed it into the store buffer */ 701 void completeMemBarrierInst(MinorDynInstPtr inst, 702 bool committed); 703 704 /** Single interface for readMem/writeMem to issue requests into 705 * the LSQ */ 706 void pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data, 707 unsigned int size, Addr addr, unsigned int flags, uint64_t *res); 708 709 /** Push a predicate failed-representing request into the queues just 710 * to maintain commit order */ 711 void pushFailedRequest(MinorDynInstPtr inst); 712 713 /** Memory interface */ 714 bool recvTimingResp(PacketPtr pkt); 715 void recvReqRetry(); 716 void recvTimingSnoopReq(PacketPtr pkt); 717 718 /** Return the raw-bindable port */ 719 MinorCPU::MinorCPUPort &getDcachePort() { return dcachePort; } 720 721 void minorTrace() const; 722}; 723 724/** Make a suitable packet for the given request. If the request is a store, 725 * data will be the payload data. If sender_state is NULL, it won't be 726 * pushed into the packet as senderState */ 727PacketPtr makePacketForRequest(Request &request, bool isLoad, 728 Packet::SenderState *sender_state = NULL, PacketDataPtr data = NULL); 729} 730 731#endif /* __CPU_MINOR_NEW_LSQ_HH__ */ 732