lsq_unit.hh (10327:5b6279635c49) | lsq_unit.hh (10333:6be8945d226b) |
---|---|
1/* | 1/* |
2 * Copyright (c) 2012-2013 ARM Limited | 2 * Copyright (c) 2012-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 --- 167 unchanged lines hidden (view full) --- 178 /** Returns if there is a memory ordering violation. Value is reset upon 179 * call to getMemDepViolator(). 180 */ 181 bool violation() { return memDepViolator; } 182 183 /** Returns the memory ordering violator. */ 184 DynInstPtr getMemDepViolator(); 185 | 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 --- 167 unchanged lines hidden (view full) --- 178 /** Returns if there is a memory ordering violation. Value is reset upon 179 * call to getMemDepViolator(). 180 */ 181 bool violation() { return memDepViolator; } 182 183 /** Returns the memory ordering violator. */ 184 DynInstPtr getMemDepViolator(); 185 |
186 /** Returns if a load became blocked due to the memory system. */ 187 bool loadBlocked() 188 { return isLoadBlocked; } 189 190 /** Clears the signal that a load became blocked. */ 191 void clearLoadBlocked() 192 { isLoadBlocked = false; } 193 194 /** Returns if the blocked load was handled. */ 195 bool isLoadBlockedHandled() 196 { return loadBlockedHandled; } 197 198 /** Records the blocked load as being handled. */ 199 void setLoadBlockedHandled() 200 { loadBlockedHandled = true; } 201 | |
202 /** Returns the number of free LQ entries. */ 203 unsigned numFreeLoadEntries(); 204 205 /** Returns the number of free SQ entries. */ 206 unsigned numFreeStoreEntries(); 207 208 /** Returns the number of loads in the LQ. */ 209 int numLoads() { return loads; } --- 83 unchanged lines hidden (view full) --- 293 294 /** Derived class to hold any sender state the LSQ needs. */ 295 class LSQSenderState : public Packet::SenderState 296 { 297 public: 298 /** Default constructor. */ 299 LSQSenderState() 300 : mainPkt(NULL), pendingPacket(NULL), outstanding(1), | 186 /** Returns the number of free LQ entries. */ 187 unsigned numFreeLoadEntries(); 188 189 /** Returns the number of free SQ entries. */ 190 unsigned numFreeStoreEntries(); 191 192 /** Returns the number of loads in the LQ. */ 193 int numLoads() { return loads; } --- 83 unchanged lines hidden (view full) --- 277 278 /** Derived class to hold any sender state the LSQ needs. */ 279 class LSQSenderState : public Packet::SenderState 280 { 281 public: 282 /** Default constructor. */ 283 LSQSenderState() 284 : mainPkt(NULL), pendingPacket(NULL), outstanding(1), |
301 noWB(false), isSplit(false), pktToSend(false) | 285 noWB(false), isSplit(false), pktToSend(false), cacheBlocked(false) |
302 { } 303 304 /** Instruction who initiated the access to memory. */ 305 DynInstPtr inst; 306 /** The main packet from a split load, used during writeback. */ 307 PacketPtr mainPkt; 308 /** A second packet from a split store that needs sending. */ 309 PacketPtr pendingPacket; --- 4 unchanged lines hidden (view full) --- 314 /** Whether or not it is a load. */ 315 bool isLoad; 316 /** Whether or not the instruction will need to writeback. */ 317 bool noWB; 318 /** Whether or not this access is split in two. */ 319 bool isSplit; 320 /** Whether or not there is a packet that needs sending. */ 321 bool pktToSend; | 286 { } 287 288 /** Instruction who initiated the access to memory. */ 289 DynInstPtr inst; 290 /** The main packet from a split load, used during writeback. */ 291 PacketPtr mainPkt; 292 /** A second packet from a split store that needs sending. */ 293 PacketPtr pendingPacket; --- 4 unchanged lines hidden (view full) --- 298 /** Whether or not it is a load. */ 299 bool isLoad; 300 /** Whether or not the instruction will need to writeback. */ 301 bool noWB; 302 /** Whether or not this access is split in two. */ 303 bool isSplit; 304 /** Whether or not there is a packet that needs sending. */ 305 bool pktToSend; |
306 /** Whether or not the second packet of this split load was blocked */ 307 bool cacheBlocked; |
|
322 323 /** Completes a packet and returns whether the access is finished. */ 324 inline bool complete() { return --outstanding == 0; } 325 }; 326 327 /** Writeback event, specifically for when stores forward data to loads. */ 328 class WritebackEvent : public Event { 329 public: --- 138 unchanged lines hidden (view full) --- 468 int stallingLoadIdx; 469 470 /** The packet that needs to be retried. */ 471 PacketPtr retryPkt; 472 473 /** Whehter or not a store is blocked due to the memory system. */ 474 bool isStoreBlocked; 475 | 308 309 /** Completes a packet and returns whether the access is finished. */ 310 inline bool complete() { return --outstanding == 0; } 311 }; 312 313 /** Writeback event, specifically for when stores forward data to loads. */ 314 class WritebackEvent : public Event { 315 public: --- 138 unchanged lines hidden (view full) --- 454 int stallingLoadIdx; 455 456 /** The packet that needs to be retried. */ 457 PacketPtr retryPkt; 458 459 /** Whehter or not a store is blocked due to the memory system. */ 460 bool isStoreBlocked; 461 |
476 /** Whether or not a load is blocked due to the memory system. */ 477 bool isLoadBlocked; 478 479 /** Has the blocked load been handled. */ 480 bool loadBlockedHandled; 481 | |
482 /** Whether or not a store is in flight. */ 483 bool storeInFlight; 484 | 462 /** Whether or not a store is in flight. */ 463 bool storeInFlight; 464 |
485 /** The sequence number of the blocked load. */ 486 InstSeqNum blockedLoadSeqNum; 487 | |
488 /** The oldest load that caused a memory ordering violation. */ 489 DynInstPtr memDepViolator; 490 491 /** Whether or not there is a packet that couldn't be sent because of 492 * a lack of cache ports. */ 493 bool hasPendingPkt; 494 495 /** The packet that is pending free cache ports. */ --- 205 unchanged lines hidden (view full) --- 701 int shift_amt = req->getVaddr() - storeQueue[store_idx].inst->effAddr; 702 703 if (storeQueue[store_idx].isAllZeros) 704 memset(data, 0, req->getSize()); 705 else 706 memcpy(data, storeQueue[store_idx].data + shift_amt, 707 req->getSize()); 708 | 465 /** The oldest load that caused a memory ordering violation. */ 466 DynInstPtr memDepViolator; 467 468 /** Whether or not there is a packet that couldn't be sent because of 469 * a lack of cache ports. */ 470 bool hasPendingPkt; 471 472 /** The packet that is pending free cache ports. */ --- 205 unchanged lines hidden (view full) --- 678 int shift_amt = req->getVaddr() - storeQueue[store_idx].inst->effAddr; 679 680 if (storeQueue[store_idx].isAllZeros) 681 memset(data, 0, req->getSize()); 682 else 683 memcpy(data, storeQueue[store_idx].data + shift_amt, 684 req->getSize()); 685 |
709 assert(!load_inst->memData); 710 load_inst->memData = new uint8_t[req->getSize()]; | 686 // Allocate memory if this is the first time a load is issued. 687 if (!load_inst->memData) { 688 load_inst->memData = new uint8_t[req->getSize()]; 689 } |
711 if (storeQueue[store_idx].isAllZeros) 712 memset(load_inst->memData, 0, req->getSize()); 713 else 714 memcpy(load_inst->memData, 715 storeQueue[store_idx].data + shift_amt, req->getSize()); 716 717 DPRINTF(LSQUnit, "Forwarding from store idx %i to load to " 718 "addr %#x\n", store_idx, req->getVaddr()); --- 64 unchanged lines hidden (view full) --- 783 return NoFault; 784 } 785 } 786 787 // If there's no forwarding case, then go access memory 788 DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %s\n", 789 load_inst->seqNum, load_inst->pcState()); 790 | 690 if (storeQueue[store_idx].isAllZeros) 691 memset(load_inst->memData, 0, req->getSize()); 692 else 693 memcpy(load_inst->memData, 694 storeQueue[store_idx].data + shift_amt, req->getSize()); 695 696 DPRINTF(LSQUnit, "Forwarding from store idx %i to load to " 697 "addr %#x\n", store_idx, req->getVaddr()); --- 64 unchanged lines hidden (view full) --- 762 return NoFault; 763 } 764 } 765 766 // If there's no forwarding case, then go access memory 767 DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %s\n", 768 load_inst->seqNum, load_inst->pcState()); 769 |
791 assert(!load_inst->memData); 792 load_inst->memData = new uint8_t[req->getSize()]; | 770 // Allocate memory if this is the first time a load is issued. 771 if (!load_inst->memData) { 772 load_inst->memData = new uint8_t[req->getSize()]; 773 } |
793 794 ++usedPorts; 795 796 // if we the cache is not blocked, do cache access 797 bool completedFirst = false; | 774 775 ++usedPorts; 776 777 // if we the cache is not blocked, do cache access 778 bool completedFirst = false; |
798 if (!lsq->cacheBlocked()) { 799 MemCmd command = 800 req->isLLSC() ? MemCmd::LoadLockedReq : MemCmd::ReadReq; 801 PacketPtr data_pkt = new Packet(req, command); 802 PacketPtr fst_data_pkt = NULL; 803 PacketPtr snd_data_pkt = NULL; | 779 MemCmd command = req->isLLSC() ? MemCmd::LoadLockedReq : MemCmd::ReadReq; 780 PacketPtr data_pkt = new Packet(req, command); 781 PacketPtr fst_data_pkt = NULL; 782 PacketPtr snd_data_pkt = NULL; |
804 | 783 |
805 data_pkt->dataStatic(load_inst->memData); | 784 data_pkt->dataStatic(load_inst->memData); |
806 | 785 |
807 LSQSenderState *state = new LSQSenderState; 808 state->isLoad = true; 809 state->idx = load_idx; 810 state->inst = load_inst; 811 data_pkt->senderState = state; | 786 LSQSenderState *state = new LSQSenderState; 787 state->isLoad = true; 788 state->idx = load_idx; 789 state->inst = load_inst; 790 data_pkt->senderState = state; |
812 | 791 |
813 if (!TheISA::HasUnalignedMemAcc || !sreqLow) { | 792 if (!TheISA::HasUnalignedMemAcc || !sreqLow) { 793 // Point the first packet at the main data packet. 794 fst_data_pkt = data_pkt; 795 } else { 796 // Create the split packets. 797 fst_data_pkt = new Packet(sreqLow, command); 798 snd_data_pkt = new Packet(sreqHigh, command); |
814 | 799 |
815 // Point the first packet at the main data packet. 816 fst_data_pkt = data_pkt; 817 } else { | 800 fst_data_pkt->dataStatic(load_inst->memData); 801 snd_data_pkt->dataStatic(load_inst->memData + sreqLow->getSize()); |
818 | 802 |
819 // Create the split packets. 820 fst_data_pkt = new Packet(sreqLow, command); 821 snd_data_pkt = new Packet(sreqHigh, command); | 803 fst_data_pkt->senderState = state; 804 snd_data_pkt->senderState = state; |
822 | 805 |
823 fst_data_pkt->dataStatic(load_inst->memData); 824 snd_data_pkt->dataStatic(load_inst->memData + sreqLow->getSize()); | 806 state->isSplit = true; 807 state->outstanding = 2; 808 state->mainPkt = data_pkt; 809 } |
825 | 810 |
826 fst_data_pkt->senderState = state; 827 snd_data_pkt->senderState = state; | 811 bool successful_load = true; 812 if (!dcachePort->sendTimingReq(fst_data_pkt)) { 813 successful_load = false; 814 } else if (TheISA::HasUnalignedMemAcc && sreqLow) { 815 completedFirst = true; |
828 | 816 |
829 state->isSplit = true; 830 state->outstanding = 2; 831 state->mainPkt = data_pkt; | 817 // The first packet was sent without problems, so send this one 818 // too. If there is a problem with this packet then the whole 819 // load will be squashed, so indicate this to the state object. 820 // The first packet will return in completeDataAccess and be 821 // handled there. 822 ++usedPorts; 823 if (!dcachePort->sendTimingReq(snd_data_pkt)) { 824 // The main packet will be deleted in completeDataAccess. 825 state->complete(); 826 // Signify to 1st half that the 2nd half was blocked via state 827 state->cacheBlocked = true; 828 successful_load = false; |
832 } | 829 } |
830 } |
|
833 | 831 |
834 if (!dcachePort->sendTimingReq(fst_data_pkt)) { 835 // Delete state and data packet because a load retry 836 // initiates a pipeline restart; it does not retry. | 832 // If the cache was blocked, or has become blocked due to the access, 833 // handle it. 834 if (!successful_load) { 835 if (!sreqLow) { 836 // Packet wasn't split, just delete main packet info |
837 delete state; | 837 delete state; |
838 delete data_pkt->req; | 838 delete req; |
839 delete data_pkt; | 839 delete data_pkt; |
840 if (TheISA::HasUnalignedMemAcc && sreqLow) { 841 delete fst_data_pkt->req; | 840 } 841 842 if (TheISA::HasUnalignedMemAcc && sreqLow) { 843 if (!completedFirst) { 844 // Split packet, but first failed. Delete all state. 845 delete state; 846 delete req; 847 delete data_pkt; |
842 delete fst_data_pkt; | 848 delete fst_data_pkt; |
843 delete snd_data_pkt->req; | |
844 delete snd_data_pkt; | 849 delete snd_data_pkt; |
850 delete sreqLow; 851 delete sreqHigh; |
|
845 sreqLow = NULL; 846 sreqHigh = NULL; | 852 sreqLow = NULL; 853 sreqHigh = NULL; |
847 } 848 849 req = NULL; 850 851 // If the access didn't succeed, tell the LSQ by setting 852 // the retry thread id. 853 lsq->setRetryTid(lsqID); 854 } else if (TheISA::HasUnalignedMemAcc && sreqLow) { 855 completedFirst = true; 856 857 // The first packet was sent without problems, so send this one 858 // too. If there is a problem with this packet then the whole 859 // load will be squashed, so indicate this to the state object. 860 // The first packet will return in completeDataAccess and be 861 // handled there. 862 ++usedPorts; 863 if (!dcachePort->sendTimingReq(snd_data_pkt)) { 864 865 // The main packet will be deleted in completeDataAccess. 866 delete snd_data_pkt->req; | 854 } else { 855 // Can't delete main packet data or state because first packet 856 // was sent to the memory system 857 delete data_pkt; 858 delete req; 859 delete sreqHigh; |
867 delete snd_data_pkt; | 860 delete snd_data_pkt; |
868 869 state->complete(); 870 871 req = NULL; | |
872 sreqHigh = NULL; | 861 sreqHigh = NULL; |
873 874 lsq->setRetryTid(lsqID); | |
875 } 876 } | 862 } 863 } |
877 } | |
878 | 864 |
879 // If the cache was blocked, or has become blocked due to the access, 880 // handle it. 881 if (lsq->cacheBlocked()) { 882 if (req) 883 delete req; 884 if (TheISA::HasUnalignedMemAcc && sreqLow && !completedFirst) { 885 delete sreqLow; 886 delete sreqHigh; 887 } 888 | |
889 ++lsqCacheBlocked; 890 | 865 ++lsqCacheBlocked; 866 |
891 // There's an older load that's already going to squash. 892 if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum) 893 return NoFault; | 867 iewStage->blockMemInst(load_inst); |
894 | 868 |
895 // Record that the load was blocked due to memory. This 896 // load will squash all instructions after it, be 897 // refetched, and re-executed. 898 isLoadBlocked = true; 899 loadBlockedHandled = false; 900 blockedLoadSeqNum = load_inst->seqNum; | |
901 // No fault occurred, even though the interface is blocked. 902 return NoFault; 903 } 904 905 return NoFault; 906} 907 908template <class Impl> --- 35 unchanged lines hidden --- | 869 // No fault occurred, even though the interface is blocked. 870 return NoFault; 871 } 872 873 return NoFault; 874} 875 876template <class Impl> --- 35 unchanged lines hidden --- |