lsq.hh revision 12127
15449Sgblack@eecs.umich.edu/* 24519Sgblack@eecs.umich.edu * Copyright (c) 2013-2014 ARM Limited 34519Sgblack@eecs.umich.edu * All rights reserved 47087Snate@binkert.org * 57087Snate@binkert.org * The license below extends only to copyright in the software and shall 67087Snate@binkert.org * not be construed as granting a license to any other intellectual 77087Snate@binkert.org * property including but not limited to intellectual property relating 87087Snate@binkert.org * to a hardware implementation of the functionality of the software 97087Snate@binkert.org * licensed hereunder. You may use the software subject to the license 107087Snate@binkert.org * terms below provided that you ensure that this notice is replicated 117087Snate@binkert.org * unmodified and in its entirety in all distributions of the software, 124519Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form. 137087Snate@binkert.org * 147087Snate@binkert.org * Redistribution and use in source and binary forms, with or without 157087Snate@binkert.org * modification, are permitted provided that the following conditions are 167087Snate@binkert.org * met: redistributions of source code must retain the above copyright 177087Snate@binkert.org * notice, this list of conditions and the following disclaimer; 187087Snate@binkert.org * redistributions in binary form must reproduce the above copyright 197087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 207087Snate@binkert.org * documentation and/or other materials provided with the distribution; 214519Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 227087Snate@binkert.org * contributors may be used to endorse or promote products derived from 234519Sgblack@eecs.umich.edu * this software without specific prior written permission. 244519Sgblack@eecs.umich.edu * 254519Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 264519Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 274519Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 284519Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 294519Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 304519Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 314519Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 324519Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 334519Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 344519Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 354519Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 364519Sgblack@eecs.umich.edu * 374519Sgblack@eecs.umich.edu * Authors: Andrew Bardsley 384519Sgblack@eecs.umich.edu */ 394519Sgblack@eecs.umich.edu 404519Sgblack@eecs.umich.edu/** 414519Sgblack@eecs.umich.edu * @file 424519Sgblack@eecs.umich.edu * 434519Sgblack@eecs.umich.edu * A load/store queue that allows outstanding reads and writes. 444590Sgblack@eecs.umich.edu * 455163Sgblack@eecs.umich.edu */ 464590Sgblack@eecs.umich.edu 474590Sgblack@eecs.umich.edu#ifndef __CPU_MINOR_NEW_LSQ_HH__ 484590Sgblack@eecs.umich.edu#define __CPU_MINOR_NEW_LSQ_HH__ 495163Sgblack@eecs.umich.edu 504590Sgblack@eecs.umich.edu#include "cpu/minor/buffers.hh" 514590Sgblack@eecs.umich.edu#include "cpu/minor/cpu.hh" 525163Sgblack@eecs.umich.edu#include "cpu/minor/pipe_data.hh" 537620Sgblack@eecs.umich.edu#include "cpu/minor/trace.hh" 544590Sgblack@eecs.umich.edu 554696Sgblack@eecs.umich.edunamespace Minor 564696Sgblack@eecs.umich.edu{ 574590Sgblack@eecs.umich.edu 585172Sgblack@eecs.umich.edu/* Forward declaration */ 595172Sgblack@eecs.umich.educlass Execute; 605172Sgblack@eecs.umich.edu 615172Sgblack@eecs.umich.educlass LSQ : public Named 625172Sgblack@eecs.umich.edu{ 637620Sgblack@eecs.umich.edu protected: 647682Sgblack@eecs.umich.edu /** My owner(s) */ 657682Sgblack@eecs.umich.edu MinorCPU &cpu; 667682Sgblack@eecs.umich.edu Execute &execute; 675172Sgblack@eecs.umich.edu 685172Sgblack@eecs.umich.edu protected: 695172Sgblack@eecs.umich.edu /** State of memory access for head access. */ 705172Sgblack@eecs.umich.edu enum MemoryState 715449Sgblack@eecs.umich.edu { 725449Sgblack@eecs.umich.edu MemoryRunning, /* Default. Step dcache queues when possible. */ 735449Sgblack@eecs.umich.edu MemoryNeedsRetry /* Request rejected, will be asked to retry */ 745172Sgblack@eecs.umich.edu }; 754590Sgblack@eecs.umich.edu 764590Sgblack@eecs.umich.edu /** Print MemoryState values as shown in the enum definition */ 775163Sgblack@eecs.umich.edu friend std::ostream &operator <<(std::ostream &os, 785163Sgblack@eecs.umich.edu MemoryState state); 795163Sgblack@eecs.umich.edu 805163Sgblack@eecs.umich.edu /** Coverage of one address range with another */ 815163Sgblack@eecs.umich.edu enum AddrRangeCoverage 827620Sgblack@eecs.umich.edu { 835163Sgblack@eecs.umich.edu PartialAddrRangeCoverage, /* Two ranges partly overlap */ 845163Sgblack@eecs.umich.edu FullAddrRangeCoverage, /* One range fully covers another */ 855163Sgblack@eecs.umich.edu NoAddrRangeCoverage /* Two ranges are disjoint */ 865163Sgblack@eecs.umich.edu }; 875163Sgblack@eecs.umich.edu 885163Sgblack@eecs.umich.edu /** Exposable data port */ 895163Sgblack@eecs.umich.edu class DcachePort : public MinorCPU::MinorCPUPort 904519Sgblack@eecs.umich.edu { 914519Sgblack@eecs.umich.edu protected: 925163Sgblack@eecs.umich.edu /** My owner */ 935163Sgblack@eecs.umich.edu LSQ &lsq; 945163Sgblack@eecs.umich.edu 955163Sgblack@eecs.umich.edu public: 965163Sgblack@eecs.umich.edu DcachePort(std::string name, LSQ &lsq_, MinorCPU &cpu) : 975163Sgblack@eecs.umich.edu MinorCPU::MinorCPUPort(name, cpu), lsq(lsq_) 985163Sgblack@eecs.umich.edu { } 995163Sgblack@eecs.umich.edu 1004519Sgblack@eecs.umich.edu protected: 1014519Sgblack@eecs.umich.edu bool recvTimingResp(PacketPtr pkt) override 1024519Sgblack@eecs.umich.edu { return lsq.recvTimingResp(pkt); } 1035172Sgblack@eecs.umich.edu 1045172Sgblack@eecs.umich.edu void recvReqRetry() override { lsq.recvReqRetry(); } 1055172Sgblack@eecs.umich.edu 1065172Sgblack@eecs.umich.edu bool isSnooping() const override { return true; } 1075172Sgblack@eecs.umich.edu 1085173Sgblack@eecs.umich.edu void recvTimingSnoopReq(PacketPtr pkt) override 1095172Sgblack@eecs.umich.edu { return lsq.recvTimingSnoopReq(pkt); } 1105172Sgblack@eecs.umich.edu 1115172Sgblack@eecs.umich.edu void recvFunctionalSnoop(PacketPtr pkt) override { } 1125172Sgblack@eecs.umich.edu }; 1134590Sgblack@eecs.umich.edu 1145163Sgblack@eecs.umich.edu DcachePort dcachePort; 1155163Sgblack@eecs.umich.edu 1167620Sgblack@eecs.umich.edu public: 1177620Sgblack@eecs.umich.edu /** Derived SenderState to carry data access info. through address 1185163Sgblack@eecs.umich.edu * translation, the queues in this port and back from the memory 1194519Sgblack@eecs.umich.edu * system. */ 1204519Sgblack@eecs.umich.edu class LSQRequest : 1214519Sgblack@eecs.umich.edu public BaseTLB::Translation, /* For TLB lookups */ 1224519Sgblack@eecs.umich.edu public Packet::SenderState /* For packing into a Packet */ 1235163Sgblack@eecs.umich.edu { 1245163Sgblack@eecs.umich.edu public: 1257620Sgblack@eecs.umich.edu /** Owning port */ 1265163Sgblack@eecs.umich.edu LSQ &port; 1277620Sgblack@eecs.umich.edu 1285163Sgblack@eecs.umich.edu /** Instruction which made this request */ 1297626Sgblack@eecs.umich.edu MinorDynInstPtr inst; 1305163Sgblack@eecs.umich.edu 1315163Sgblack@eecs.umich.edu /** Load/store indication used for building packet. This isn't 1325163Sgblack@eecs.umich.edu * carried by Request so we need to keep it here */ 1334696Sgblack@eecs.umich.edu bool isLoad; 1345163Sgblack@eecs.umich.edu 1354696Sgblack@eecs.umich.edu /** Dynamically allocated and populated data carried for 1364696Sgblack@eecs.umich.edu * building write packets */ 1374696Sgblack@eecs.umich.edu PacketDataPtr data; 1384696Sgblack@eecs.umich.edu 1394696Sgblack@eecs.umich.edu /* Requests carry packets on their way to the memory system. 1404696Sgblack@eecs.umich.edu * When a Packet returns from the memory system, its 1414696Sgblack@eecs.umich.edu * request needs to have its packet updated as this 1424696Sgblack@eecs.umich.edu * may have changed in flight */ 1434696Sgblack@eecs.umich.edu PacketPtr packet; 1444696Sgblack@eecs.umich.edu 1454696Sgblack@eecs.umich.edu /** The underlying request of this LSQRequest */ 1464696Sgblack@eecs.umich.edu Request request; 1475449Sgblack@eecs.umich.edu 1485449Sgblack@eecs.umich.edu /** Fault generated performing this request */ 1495449Sgblack@eecs.umich.edu Fault fault; 1505449Sgblack@eecs.umich.edu 1515449Sgblack@eecs.umich.edu /** Res from pushRequest */ 1525449Sgblack@eecs.umich.edu uint64_t *res; 1535449Sgblack@eecs.umich.edu 1545449Sgblack@eecs.umich.edu /** Was skipped. Set to indicate any reason (faulted, bad 1555449Sgblack@eecs.umich.edu * stream sequence number, in a fault shadow) that this 1565449Sgblack@eecs.umich.edu * request did not perform a memory transfer */ 1574696Sgblack@eecs.umich.edu bool skipped; 1584696Sgblack@eecs.umich.edu 1594519Sgblack@eecs.umich.edu /** This in an access other than a normal cacheable load 1604590Sgblack@eecs.umich.edu * that's visited the memory system */ 1615163Sgblack@eecs.umich.edu bool issuedToMemory; 1625163Sgblack@eecs.umich.edu 1634590Sgblack@eecs.umich.edu enum LSQRequestState 1645163Sgblack@eecs.umich.edu { 1655163Sgblack@eecs.umich.edu NotIssued, /* Newly created */ 1665163Sgblack@eecs.umich.edu InTranslation, /* TLB accessed, no reply yet */ 1675163Sgblack@eecs.umich.edu Translated, /* Finished address translation */ 1685163Sgblack@eecs.umich.edu Failed, /* The starting start of FailedDataRequests */ 1695163Sgblack@eecs.umich.edu RequestIssuing, /* Load/store issued to memory in the requests 1705163Sgblack@eecs.umich.edu queue */ 1714590Sgblack@eecs.umich.edu StoreToStoreBuffer, /* Store in transfers on its way to the 1727620Sgblack@eecs.umich.edu store buffer */ 1737620Sgblack@eecs.umich.edu RequestNeedsRetry, /* Retry needed for load */ 1745163Sgblack@eecs.umich.edu StoreInStoreBuffer, /* Store in the store buffer, before issuing 1755163Sgblack@eecs.umich.edu a memory transfer */ 1764590Sgblack@eecs.umich.edu StoreBufferIssuing, /* Store in store buffer and has been 1775163Sgblack@eecs.umich.edu issued */ 1785163Sgblack@eecs.umich.edu StoreBufferNeedsRetry, /* Retry needed for store */ 1794590Sgblack@eecs.umich.edu /* All completed states. Includes 1805163Sgblack@eecs.umich.edu completed loads, TLB faults and skipped requests whose 1815293Sgblack@eecs.umich.edu seqNum's no longer match */ 1825163Sgblack@eecs.umich.edu Complete 1835163Sgblack@eecs.umich.edu }; 1845163Sgblack@eecs.umich.edu 1855163Sgblack@eecs.umich.edu LSQRequestState state; 1865163Sgblack@eecs.umich.edu 1875293Sgblack@eecs.umich.edu protected: 1885163Sgblack@eecs.umich.edu /** BaseTLB::Translation interface */ 1895163Sgblack@eecs.umich.edu void markDelayed() { } 1905163Sgblack@eecs.umich.edu 1915163Sgblack@eecs.umich.edu public: 1925163Sgblack@eecs.umich.edu LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_, 1934590Sgblack@eecs.umich.edu PacketDataPtr data_ = NULL, uint64_t *res_ = NULL); 1945172Sgblack@eecs.umich.edu 1955172Sgblack@eecs.umich.edu virtual ~LSQRequest(); 1966047Sgblack@eecs.umich.edu 1975172Sgblack@eecs.umich.edu public: 1985172Sgblack@eecs.umich.edu /** Make a packet to use with the memory transaction */ 1995172Sgblack@eecs.umich.edu void makePacket(); 2007620Sgblack@eecs.umich.edu 2017620Sgblack@eecs.umich.edu /** Was no memory access attempted for this request? */ 2025172Sgblack@eecs.umich.edu bool skippedMemAccess() { return skipped; } 2035172Sgblack@eecs.umich.edu 2045172Sgblack@eecs.umich.edu /** Set this request as having been skipped before a memory 2054519Sgblack@eecs.umich.edu * transfer was attempt */ 206 void setSkipped() { skipped = true; } 207 208 /** Does address range req1 (req1_addr to req1_addr + req1_size - 1) 209 * fully cover, partially cover or not cover at all the range req2 */ 210 static AddrRangeCoverage containsAddrRangeOf( 211 Addr req1_addr, unsigned int req1_size, 212 Addr req2_addr, unsigned int req2_size); 213 214 /** Does this request's address range fully cover the range 215 * of other_request? */ 216 AddrRangeCoverage containsAddrRangeOf(LSQRequest *other_request); 217 218 /** Start the address translation process for this request. This 219 * will issue a translation request to the TLB. */ 220 virtual void startAddrTranslation() = 0; 221 222 /** Get the next packet to issue for this request. For split 223 * transfers, it will be necessary to step through the available 224 * packets by calling do { getHeadPacket ; stepToNextPacket } while 225 * (!sentAllPackets) and by retiring response using retireResponse */ 226 virtual PacketPtr getHeadPacket() = 0; 227 228 /** Step to the next packet for the next call to getHeadPacket */ 229 virtual void stepToNextPacket() = 0; 230 231 /** Have all packets been sent? */ 232 virtual bool sentAllPackets() = 0; 233 234 /** True if this request has any issued packets in the memory 235 * system and so can't be interrupted until it gets responses */ 236 virtual bool hasPacketsInMemSystem() = 0; 237 238 /** Retire a response packet into the LSQRequest packet possibly 239 * completing this transfer */ 240 virtual void retireResponse(PacketPtr packet_) = 0; 241 242 /** Is this a request a barrier? */ 243 virtual bool isBarrier(); 244 245 /** This request, once processed by the requests/transfers 246 * queues, will need to go to the store buffer */ 247 bool needsToBeSentToStoreBuffer(); 248 249 /** Set state and output trace output */ 250 void setState(LSQRequestState new_state); 251 252 /** Has this request been completed. This includes *all* reasons 253 * for completion: successful transfers, faults, skipped because 254 * of preceding faults */ 255 bool isComplete() const; 256 257 /** MinorTrace report interface */ 258 void reportData(std::ostream &os) const; 259 }; 260 261 typedef LSQRequest *LSQRequestPtr; 262 263 friend std::ostream & operator <<(std::ostream &os, 264 AddrRangeCoverage state); 265 266 friend std::ostream & operator <<(std::ostream &os, 267 LSQRequest::LSQRequestState state); 268 269 protected: 270 /** Special request types that don't actually issue memory requests */ 271 class SpecialDataRequest : public LSQRequest 272 { 273 protected: 274 /** TLB interace */ 275 void finish(const Fault &fault_, RequestPtr request_, 276 ThreadContext *tc, BaseTLB::Mode mode) 277 { } 278 279 public: 280 /** Send single translation request */ 281 void startAddrTranslation() { } 282 283 /** Get the head packet as counted by numIssuedFragments */ 284 PacketPtr getHeadPacket() 285 { fatal("No packets in a SpecialDataRequest"); } 286 287 /** Step on numIssuedFragments */ 288 void stepToNextPacket() { } 289 290 /** Has no packets to send */ 291 bool sentAllPackets() { return true; } 292 293 /** Never sends any requests */ 294 bool hasPacketsInMemSystem() { return false; } 295 296 /** Keep the given packet as the response packet 297 * LSQRequest::packet */ 298 void retireResponse(PacketPtr packet_) { } 299 300 public: 301 SpecialDataRequest(LSQ &port_, MinorDynInstPtr inst_) : 302 /* Say this is a load, not actually relevant */ 303 LSQRequest(port_, inst_, true, NULL, 0) 304 { } 305 }; 306 307 /** FailedDataRequest represents requests from instructions that 308 * failed their predicates but need to ride the requests/transfers 309 * queues to maintain trace ordering */ 310 class FailedDataRequest : public SpecialDataRequest 311 { 312 public: 313 FailedDataRequest(LSQ &port_, MinorDynInstPtr inst_) : 314 SpecialDataRequest(port_, inst_) 315 { state = Failed; } 316 }; 317 318 /** Request for doing barrier accounting in the store buffer. Not 319 * for use outside that unit */ 320 class BarrierDataRequest : public SpecialDataRequest 321 { 322 public: 323 bool isBarrier() { return true; } 324 325 public: 326 BarrierDataRequest(LSQ &port_, MinorDynInstPtr inst_) : 327 SpecialDataRequest(port_, inst_) 328 { state = Complete; } 329 }; 330 331 /** SingleDataRequest is used for requests that don't fragment */ 332 class SingleDataRequest : public LSQRequest 333 { 334 protected: 335 /** TLB interace */ 336 void finish(const Fault &fault_, RequestPtr request_, 337 ThreadContext *tc, BaseTLB::Mode mode); 338 339 /** Has my only packet been sent to the memory system but has not 340 * yet been responded to */ 341 bool packetInFlight; 342 343 /** Has the packet been at least sent to the memory system? */ 344 bool packetSent; 345 346 public: 347 /** Send single translation request */ 348 void startAddrTranslation(); 349 350 /** Get the head packet as counted by numIssuedFragments */ 351 PacketPtr getHeadPacket() { return packet; } 352 353 /** Remember that the packet has been sent */ 354 void stepToNextPacket() { packetInFlight = true; packetSent = true; } 355 356 /** Has packet been sent */ 357 bool hasPacketsInMemSystem() { return packetInFlight; } 358 359 /** packetInFlight can become false again, so need to check 360 * packetSent */ 361 bool sentAllPackets() { return packetSent; } 362 363 /** Keep the given packet as the response packet 364 * LSQRequest::packet */ 365 void retireResponse(PacketPtr packet_); 366 367 public: 368 SingleDataRequest(LSQ &port_, MinorDynInstPtr inst_, 369 bool isLoad_, PacketDataPtr data_ = NULL, uint64_t *res_ = NULL) : 370 LSQRequest(port_, inst_, isLoad_, data_, res_), 371 packetInFlight(false), 372 packetSent(false) 373 { } 374 }; 375 376 class SplitDataRequest : public LSQRequest 377 { 378 protected: 379 /** Event to step between translations */ 380 EventFunctionWrapper translationEvent; 381 protected: 382 /** Number of fragments this request is split into */ 383 unsigned int numFragments; 384 385 /** Number of fragments in the address translation mechanism */ 386 unsigned int numInTranslationFragments; 387 388 /** Number of fragments that have completed address translation, 389 * (numTranslatedFragments + numInTranslationFragments) <= 390 * numFragments. When numTranslatedFramgents == numFragments, 391 * translation is complete */ 392 unsigned int numTranslatedFragments; 393 394 /** Number of fragments already issued (<= numFragments) */ 395 unsigned int numIssuedFragments; 396 397 /** Number of fragments retired back to this request */ 398 unsigned int numRetiredFragments; 399 400 /** Fragment Requests corresponding to the address ranges of 401 * each fragment */ 402 std::vector<Request *> fragmentRequests; 403 404 /** Packets matching fragmentRequests to issue fragments to memory */ 405 std::vector<Packet *> fragmentPackets; 406 407 protected: 408 /** TLB response interface */ 409 void finish(const Fault &fault_, RequestPtr request_, 410 ThreadContext *tc, BaseTLB::Mode mode); 411 412 public: 413 SplitDataRequest(LSQ &port_, MinorDynInstPtr inst_, 414 bool isLoad_, PacketDataPtr data_ = NULL, 415 uint64_t *res_ = NULL); 416 417 ~SplitDataRequest(); 418 419 public: 420 /** Make all the Requests for this transfer's fragments so that those 421 * requests can be sent for address translation */ 422 void makeFragmentRequests(); 423 424 /** Make the packets to go with the requests so they can be sent to 425 * the memory system */ 426 void makeFragmentPackets(); 427 428 /** Start a loop of do { sendNextFragmentToTranslation ; 429 * translateTiming ; finish } while (numTranslatedFragments != 430 * numFragments) to complete all this requests' fragments' address 431 * translations */ 432 void startAddrTranslation(); 433 434 /** Get the head packet as counted by numIssuedFragments */ 435 PacketPtr getHeadPacket(); 436 437 /** Step on numIssuedFragments */ 438 void stepToNextPacket(); 439 440 bool hasPacketsInMemSystem() 441 { return numIssuedFragments != numRetiredFragments; } 442 443 /** Have we stepped past the end of fragmentPackets? */ 444 bool sentAllPackets() { return numIssuedFragments == numFragments; } 445 446 /** For loads, paste the response data into the main 447 * response packet */ 448 void retireResponse(PacketPtr packet_); 449 450 /** Part of the address translation loop, see startAddTranslation */ 451 void sendNextFragmentToTranslation(); 452 }; 453 454 /** Store buffer. This contains stores which have been committed 455 * but whose memory transfers have not yet been issued. Load data 456 * can be forwarded out of the store buffer */ 457 class StoreBuffer : public Named 458 { 459 public: 460 /** My owner */ 461 LSQ &lsq; 462 463 /** Number of slots, this is a bound on the size of slots */ 464 const unsigned int numSlots; 465 466 /** Maximum number of stores that can be issued per cycle */ 467 const unsigned int storeLimitPerCycle; 468 469 public: 470 /** Queue of store requests on their way to memory */ 471 std::deque<LSQRequestPtr> slots; 472 473 /** Number of occupied slots which have not yet issued a 474 * memory access */ 475 unsigned int numUnissuedAccesses; 476 477 public: 478 StoreBuffer(std::string name_, LSQ &lsq_, 479 unsigned int store_buffer_size, 480 unsigned int store_limit_per_cycle); 481 482 public: 483 /** Can a new request be inserted into the queue? */ 484 bool canInsert() const; 485 486 /** Delete the given request and free the slot it occupied */ 487 void deleteRequest(LSQRequestPtr request); 488 489 /** Insert a request at the back of the queue */ 490 void insert(LSQRequestPtr request); 491 492 /** Look for a store which satisfies the given load. Returns an 493 * indication whether the forwarding request can be wholly, 494 * partly or not all all satisfied. If the request can be 495 * wholly satisfied, the store buffer slot number which can be used 496 * is returned in found_slot */ 497 AddrRangeCoverage canForwardDataToLoad(LSQRequestPtr request, 498 unsigned int &found_slot); 499 500 /** Fill the given packet with appropriate date from slot 501 * slot_number */ 502 void forwardStoreData(LSQRequestPtr load, unsigned int slot_number); 503 504 /** Number of stores in the store buffer which have not been 505 * completely issued to the memory system */ 506 unsigned int numUnissuedStores() { return numUnissuedAccesses; } 507 508 /** Count a store being issued to memory by decrementing 509 * numUnissuedAccesses. Does not count barrier requests as they 510 * will be handles as barriers are cleared from the buffer */ 511 void countIssuedStore(LSQRequestPtr request); 512 513 /** Drained if there is absolutely nothing left in the buffer */ 514 bool isDrained() const { return slots.empty(); } 515 516 /** Try to issue more stores to memory */ 517 void step(); 518 519 /** Report queue contents for MinorTrace */ 520 void minorTrace() const; 521 }; 522 523 protected: 524 /** Most recent execSeqNum of a memory barrier instruction or 525 * 0 if there are no in-flight barriers. Useful as a 526 * dependency for early-issued memory operations */ 527 std::vector<InstSeqNum> lastMemBarrier; 528 529 public: 530 /** Retry state of last issued memory transfer */ 531 MemoryState state; 532 533 /** Maximum number of in-flight accesses issued to the memory system */ 534 const unsigned int inMemorySystemLimit; 535 536 /** Memory system access width (and snap) in bytes */ 537 const unsigned int lineWidth; 538 539 public: 540 /** The LSQ consists of three queues: requests, transfers and the 541 * store buffer storeBuffer. */ 542 543 typedef Queue<LSQRequestPtr, 544 ReportTraitsPtrAdaptor<LSQRequestPtr>, 545 NoBubbleTraits<LSQRequestPtr> > 546 LSQQueue; 547 548 /** requests contains LSQRequests which have been issued to the TLB by 549 * calling ExecContext::readMem/writeMem (which in turn calls 550 * LSQ::pushRequest and LSQRequest::startAddrTranslation). Once they 551 * have a physical address, requests at the head of requests can be 552 * issued to the memory system. At this stage, it cannot be clear that 553 * memory accesses *must* happen (that there are no preceding faults or 554 * changes of flow of control) and so only cacheable reads are issued 555 * to memory. 556 * Cacheable stores are not issued at all (and just pass through 557 * 'transfers' in order) and all other transfers are stalled in requests 558 * until their corresponding instructions are at the head of the 559 * inMemInsts instruction queue and have the right streamSeqNum. */ 560 LSQQueue requests; 561 562 /** Once issued to memory (or, for stores, just had their 563 * state changed to StoreToStoreBuffer) LSQRequests pass through 564 * transfers waiting for memory responses. At the head of transfers, 565 * Execute::commitInst can pick up the memory response for a request 566 * using LSQ::findResponse. Responses to be committed can then 567 * have ExecContext::completeAcc on them. Stores can then be pushed 568 * into the store buffer. All other transfers will then be complete. */ 569 LSQQueue transfers; 570 571 /* The store buffer contains committed cacheable stores on 572 * their way to memory decoupled from subsequence instruction execution. 573 * Before trying to issue a cacheable read from 'requests' to memory, 574 * the store buffer is checked to see if a previous store contains the 575 * needed data (StoreBuffer::canForwardDataToLoad) which can be 576 * forwarded in lieu of a memory access. If there are outstanding 577 * stores in the transfers queue, they must be promoted to the store 578 * buffer (and so be commited) before they can be correctly checked 579 * for forwarding. */ 580 StoreBuffer storeBuffer; 581 582 protected: 583 /** Count of the number of mem. accesses which have left the 584 * requests queue and are in the 'wild' in the memory system and who 585 * *must not* be interrupted as they are not normal cacheable 586 * accesses. This is a count of the number of in-flight requests 587 * with issuedToMemory set who have visited tryToSendRequest at least 588 * once */ 589 unsigned int numAccessesInMemorySystem; 590 591 /** Number of requests in the DTLB in the requests queue */ 592 unsigned int numAccessesInDTLB; 593 594 /** The number of stores in the transfers queue. Useful when 595 * testing if the store buffer contains all the forwardable stores */ 596 unsigned int numStoresInTransfers; 597 598 /** The number of accesses which have been issued to the memory 599 * system but have not been committed/discarded *excluding* 600 * cacheable normal loads which don't need to be tracked */ 601 unsigned int numAccessesIssuedToMemory; 602 603 /** The request (from either requests or the store buffer) which is 604 * currently waiting have its memory access retried */ 605 LSQRequestPtr retryRequest; 606 607 /** Address Mask for a cache block (e.g. ~(cache_block_size-1)) */ 608 Addr cacheBlockMask; 609 610 protected: 611 /** Try and issue a memory access for a translated request at the 612 * head of the requests queue. Also tries to move the request 613 * between queues */ 614 void tryToSendToTransfers(LSQRequestPtr request); 615 616 /** Try to send (or resend) a memory request's next/only packet to 617 * the memory system. Returns true if the request was successfully 618 * sent to memory (and was also the last packet in a transfer) */ 619 bool tryToSend(LSQRequestPtr request); 620 621 /** Clear a barrier (if it's the last one marked up in lastMemBarrier) */ 622 void clearMemBarrier(MinorDynInstPtr inst); 623 624 /** Move a request between queues */ 625 void moveFromRequestsToTransfers(LSQRequestPtr request); 626 627 /** Can a request be sent to the memory system */ 628 bool canSendToMemorySystem(); 629 630 /** Snoop other threads monitors on memory system accesses */ 631 void threadSnoop(LSQRequestPtr request); 632 633 public: 634 LSQ(std::string name_, std::string dcache_port_name_, 635 MinorCPU &cpu_, Execute &execute_, 636 unsigned int max_accesses_in_memory_system, unsigned int line_width, 637 unsigned int requests_queue_size, unsigned int transfers_queue_size, 638 unsigned int store_buffer_size, 639 unsigned int store_buffer_cycle_store_limit); 640 641 virtual ~LSQ(); 642 643 public: 644 /** Step checks the queues to see if their are issuable transfers 645 * which were not otherwise picked up by tests at the end of other 646 * events. 647 * 648 * Steppable actions include deferred actions which couldn't be 649 * cascaded on the end of a memory response/TLB response event 650 * because of resource congestion. */ 651 void step(); 652 653 /** Is their space in the request queue to be able to push a request by 654 * issuing an isMemRef instruction */ 655 bool canRequest() { return requests.unreservedRemainingSpace() != 0; } 656 657 /** Returns a response if it's at the head of the transfers queue and 658 * it's either complete or can be sent on to the store buffer. After 659 * calling, the request still remains on the transfer queue until 660 * popResponse is called */ 661 LSQRequestPtr findResponse(MinorDynInstPtr inst); 662 663 /** Sanity check and pop the head response */ 664 void popResponse(LSQRequestPtr response); 665 666 /** Must check this before trying to insert into the store buffer */ 667 bool canPushIntoStoreBuffer() const { return storeBuffer.canInsert(); } 668 669 /** A store has been committed, please move it to the store buffer */ 670 void sendStoreToStoreBuffer(LSQRequestPtr request); 671 672 /** Are there any accesses other than normal cached loads in the 673 * memory system or having received responses which need to be 674 * handled for their instruction's to be completed */ 675 bool accessesInFlight() const 676 { return numAccessesIssuedToMemory != 0; } 677 678 /** A memory barrier instruction has been issued, remember its 679 * execSeqNum that we can avoid issuing memory ops until it is 680 * committed */ 681 void issuedMemBarrierInst(MinorDynInstPtr inst); 682 683 /** Get the execSeqNum of the last issued memory barrier */ 684 InstSeqNum getLastMemBarrier(ThreadID thread_id) const 685 { return lastMemBarrier[thread_id]; } 686 687 /** Is there nothing left in the LSQ */ 688 bool isDrained(); 689 690 /** May need to be ticked next cycle as one of the queues contains 691 * an actionable transfers or address translation */ 692 bool needsToTick(); 693 694 /** Complete a barrier instruction. Where committed, makes a 695 * BarrierDataRequest and pushed it into the store buffer */ 696 void completeMemBarrierInst(MinorDynInstPtr inst, 697 bool committed); 698 699 /** Single interface for readMem/writeMem to issue requests into 700 * the LSQ */ 701 void pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data, 702 unsigned int size, Addr addr, Request::Flags flags, 703 uint64_t *res); 704 705 /** Push a predicate failed-representing request into the queues just 706 * to maintain commit order */ 707 void pushFailedRequest(MinorDynInstPtr inst); 708 709 /** Memory interface */ 710 bool recvTimingResp(PacketPtr pkt); 711 void recvReqRetry(); 712 void recvTimingSnoopReq(PacketPtr pkt); 713 714 /** Return the raw-bindable port */ 715 MinorCPU::MinorCPUPort &getDcachePort() { return dcachePort; } 716 717 void minorTrace() const; 718}; 719 720/** Make a suitable packet for the given request. If the request is a store, 721 * data will be the payload data. If sender_state is NULL, it won't be 722 * pushed into the packet as senderState */ 723PacketPtr makePacketForRequest(Request &request, bool isLoad, 724 Packet::SenderState *sender_state = NULL, PacketDataPtr data = NULL); 725} 726 727#endif /* __CPU_MINOR_NEW_LSQ_HH__ */ 728