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:
parent
f5b6aef154
commit
068379a9ed
2 changed files with 103 additions and 59 deletions
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue