summaryrefslogtreecommitdiff
path: root/src/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu')
-rw-r--r--src/cpu/o3/lsq_unit.hh11
-rw-r--r--src/cpu/o3/lsq_unit_impl.hh151
2 files changed, 103 insertions, 59 deletions
diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh
index 21f48ce02..3123e246d 100644
--- a/src/cpu/o3/lsq_unit.hh
+++ b/src/cpu/o3/lsq_unit.hh
@@ -213,9 +213,14 @@ class LSQUnit {
private:
void writeback(DynInstPtr &inst, PacketPtr pkt);
+ void storePostSend(Packet *pkt);
+
/** Completes the store at the specified index. */
void completeStore(int store_idx);
+ /** Handles doing the retry. */
+ void recvRetry();
+
/** Increments the given store index (circular queue). */
inline void incrStIdx(int &store_idx);
/** Decrements the given store index (circular queue). */
@@ -399,6 +404,8 @@ class LSQUnit {
/** The index of the above store. */
int stallingLoadIdx;
+ PacketPtr sendingPkt;
+
bool isStoreBlocked;
/** Whether or not a load is blocked due to the memory system. */
@@ -504,7 +511,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
"storeHead: %i addr: %#x\n",
load_idx, store_idx, storeHead, req->getPaddr());
-#if 0
+#if FULL_SYSTEM
if (req->getFlags() & LOCKED) {
cpu->lockAddr = req->getPaddr();
cpu->lockFlag = true;
@@ -559,7 +566,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
DPRINTF(LSQUnit, "Forwarding from store idx %i to load to "
"addr %#x, data %#x\n",
- store_idx, req->getVaddr(), *(load_inst->memData));
+ store_idx, req->getVaddr(), data);
PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast);
data_pkt->dataStatic(load_inst->memData);
diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh
index 62bb96610..a768b021c 100644
--- a/src/cpu/o3/lsq_unit_impl.hh
+++ b/src/cpu/o3/lsq_unit_impl.hh
@@ -125,18 +125,7 @@ template <class Impl>
void
LSQUnit<Impl>::DcachePort::recvRetry()
{
- panic("Retry unsupported for now!");
- // we shouldn't get a retry unless we have a packet that we're
- // waiting to transmit
-/*
- assert(cpu->dcache_pkt != NULL);
- assert(cpu->_status == DcacheRetry);
- PacketPtr tmp = cpu->dcache_pkt;
- if (sendTiming(tmp)) {
- cpu->_status = DcacheWaitResponse;
- cpu->dcache_pkt = NULL;
- }
-*/
+ lsq->recvRetry();
}
template <class Impl>
@@ -615,55 +604,34 @@ LSQUnit<Impl>::writebackStores()
req->getPaddr(), *(inst->memData),
storeQueue[storeWBIdx].inst->seqNum);
- if (!dcachePort->sendTiming(data_pkt)) {
- // Need to handle becoming blocked on a store.
- isStoreBlocked = true;
- } else {
- if (isStalled() &&
- storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) {
- DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
- "load idx:%i\n",
- stallingStoreIsn, stallingLoadIdx);
- stalled = false;
- stallingStoreIsn = 0;
- iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
- }
-
- if (!(req->getFlags() & LOCKED)) {
- assert(!storeQueue[storeWBIdx].inst->isStoreConditional());
- // Non-store conditionals do not need a writeback.
- state->noWB = true;
-
- // The store is basically completed at this time. This
- // only works so long as the checker doesn't try to
- // verify the value in memory for stores.
- storeQueue[storeWBIdx].inst->setCompleted();
- if (cpu->checker) {
- cpu->checker->tick(storeQueue[storeWBIdx].inst);
+ // @todo: Remove this SC hack once the memory system handles it.
+ if (req->getFlags() & LOCKED) {
+ if (req->getFlags() & UNCACHEABLE) {
+ req->setScResult(2);
+ } else {
+ if (cpu->lockFlag) {
+ req->setScResult(1);
+ } else {
+ req->setScResult(0);
+ // Hack: Instantly complete this store.
+ completeDataAccess(data_pkt);
+ incrStIdx(storeWBIdx);
+ continue;
}
}
+ } else {
+ // Non-store conditionals do not need a writeback.
+ state->noWB = true;
+ }
- if (data_pkt->result != Packet::Success) {
- DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n",
- storeWBIdx);
-
- DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n",
- storeQueue[storeWBIdx].inst->seqNum);
-
- //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum);
-
- //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size());
-
- // @todo: Increment stat here.
- } else {
- DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n",
- storeWBIdx);
-
- DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n",
- storeQueue[storeWBIdx].inst->seqNum);
- }
+ if (!dcachePort->sendTiming(data_pkt)) {
+ // Need to handle becoming blocked on a store.
+ isStoreBlocked = true;
- incrStIdx(storeWBIdx);
+ assert(sendingPkt == NULL);
+ sendingPkt = data_pkt;
+ } else {
+ storePostSend(data_pkt);
}
}
@@ -769,6 +737,53 @@ LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
template <class Impl>
void
+LSQUnit<Impl>::storePostSend(Packet *pkt)
+{
+ if (isStalled() &&
+ storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) {
+ DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
+ "load idx:%i\n",
+ stallingStoreIsn, stallingLoadIdx);
+ stalled = false;
+ stallingStoreIsn = 0;
+ iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
+ }
+
+ if (!storeQueue[storeWBIdx].inst->isStoreConditional()) {
+ // The store is basically completed at this time. This
+ // only works so long as the checker doesn't try to
+ // verify the value in memory for stores.
+ storeQueue[storeWBIdx].inst->setCompleted();
+ if (cpu->checker) {
+ cpu->checker->tick(storeQueue[storeWBIdx].inst);
+ }
+ }
+
+ if (pkt->result != Packet::Success) {
+ DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n",
+ storeWBIdx);
+
+ DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n",
+ storeQueue[storeWBIdx].inst->seqNum);
+
+ //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum);
+
+ //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size());
+
+ // @todo: Increment stat here.
+ } else {
+ DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n",
+ storeWBIdx);
+
+ DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n",
+ storeQueue[storeWBIdx].inst->seqNum);
+ }
+
+ incrStIdx(storeWBIdx);
+}
+
+template <class Impl>
+void
LSQUnit<Impl>::writeback(DynInstPtr &inst, PacketPtr pkt)
{
iewStage->wakeCPU();
@@ -840,6 +855,28 @@ LSQUnit<Impl>::completeStore(int store_idx)
}
template <class Impl>
+void
+LSQUnit<Impl>::recvRetry()
+{
+ assert(sendingPkt != NULL);
+
+ if (isStoreBlocked) {
+ if (dcachePort->sendTiming(sendingPkt)) {
+ storePostSend(sendingPkt);
+ sendingPkt = NULL;
+ isStoreBlocked = false;
+ } else {
+ // Still blocked!
+ }
+ } else if (isLoadBlocked) {
+ DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, "
+ "no need to resend packet.\n");
+ } else {
+ DPRINTF(LSQUnit, "Retry received but LSQ is no longer blocked.\n");
+ }
+}
+
+template <class Impl>
inline void
LSQUnit<Impl>::incrStIdx(int &store_idx)
{