Fixes for some outstanding issues in the LSQ. It should now be able to retry. It should also be able to handle LL/SC (through hacks) for the UP case.

src/cpu/o3/lsq_unit.hh:
    Handle being able to retry (untested but hopefully very close to working).

    Handle lock flag for LL/SC hack.  Hopefully the memory system will add in LL/SC soon.

    Better output message.
src/cpu/o3/lsq_unit_impl.hh:
    Handle being able to retry (untested but should be very close to working).

    Make SC's work (hopefully) while the memory system doesn't have a LL/SC implementation.

--HG--
extra : convert_revision : bffa721b21405c88a9c6b3d9b9080957f8a2638f
This commit is contained in:
Kevin Lim 2006-06-09 11:46:35 -04:00
parent f5b6aef154
commit 068379a9ed
2 changed files with 103 additions and 59 deletions

View file

@ -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);

View file

@ -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);
// @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 (!dcachePort->sendTiming(data_pkt)) {
// Need to handle becoming blocked on a store.
isStoreBlocked = true;
assert(sendingPkt == NULL);
sendingPkt = data_pkt;
} 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);
}
}
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);
}
incrStIdx(storeWBIdx);
storePostSend(data_pkt);
}
}
@ -767,6 +735,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)
@ -839,6 +854,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)