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 ---