if (!lsqPtr->isSwitchedOut()) {
lsqPtr->writeback(inst, pkt);
}
+
+ if (pkt->senderState)
+ delete pkt->senderState;
+
+ delete pkt->req;
delete pkt;
}
const char *
LSQUnit<Impl>::WritebackEvent::description()
{
- return "Store writeback event";
+ return "Store writeback";
}
template<class Impl>
//iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum);
+ assert(!pkt->wasNacked());
+
if (isSwitchedOut() || inst->isSquashed()) {
iewStage->decrWb(inst->seqNum);
- delete state;
- delete pkt;
- return;
} else {
if (!state->noWB) {
writeback(inst, pkt);
}
delete state;
+ delete pkt->req;
delete pkt;
}
template<class Impl>
void
-LSQUnit<Impl>::init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries,
- unsigned maxSQEntries, unsigned id)
+LSQUnit<Impl>::init(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params, LSQ *lsq_ptr,
+ unsigned maxLQEntries, unsigned maxSQEntries, unsigned id)
{
+ cpu = cpu_ptr;
+ iewStage = iew_ptr;
+
DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
switchedOut = false;
blockedLoadSeqNum = 0;
}
-template<class Impl>
-void
-LSQUnit<Impl>::setCPU(O3CPU *cpu_ptr)
-{
- cpu = cpu_ptr;
-
-#if USE_CHECKER
- if (cpu->checker) {
- cpu->checker->setDcachePort(dcachePort);
- }
-#endif
-}
-
template<class Impl>
std::string
LSQUnit<Impl>::name() const
.desc("Number of times an access to memory failed due to the cache being blocked");
}
+template<class Impl>
+void
+LSQUnit<Impl>::setDcachePort(Port *dcache_port)
+{
+ dcachePort = dcache_port;
+
+#if USE_CHECKER
+ if (cpu->checker) {
+ cpu->checker->setDcachePort(dcachePort);
+ }
+#endif
+}
+
template<class Impl>
void
LSQUnit<Impl>::clearLQ()
Fault
LSQUnit<Impl>::executeLoad(DynInstPtr &inst)
{
+ using namespace TheISA;
// Execute a specific load.
Fault load_fault = NoFault;
DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n",
inst->readPC(),inst->seqNum);
+ assert(!inst->isSquashed());
+
load_fault = inst->initiateAcc();
// If the instruction faulted, then we need to send it along to commit
// realizes there is activity.
// Mark it as executed unless it is an uncached load that
// needs to hit the head of commit.
- if (!(inst->req && inst->req->isUncacheable()) ||
+ if (!(inst->hasRequest() && inst->uncacheable()) ||
inst->isAtCommit()) {
inst->setExecuted();
}
iewStage->instToCommit(inst);
iewStage->activityThisCycle();
+ } else if (!loadBlocked()) {
+ assert(inst->effAddrValid);
+ int load_idx = inst->lqIdx;
+ incrLdIdx(load_idx);
+ while (load_idx != loadTail) {
+ // Really only need to check loads that have actually executed
+
+ // @todo: For now this is extra conservative, detecting a
+ // violation if the addresses match assuming all accesses
+ // are quad word accesses.
+
+ // @todo: Fix this, magic number being used here
+ if (loadQueue[load_idx]->effAddrValid &&
+ (loadQueue[load_idx]->effAddr >> 8) ==
+ (inst->effAddr >> 8)) {
+ // A load incorrectly passed this load. Squash and refetch.
+ // For now return a fault to show that it was unsuccessful.
+ DynInstPtr violator = loadQueue[load_idx];
+ if (!memDepViolator ||
+ (violator->seqNum < memDepViolator->seqNum)) {
+ memDepViolator = violator;
+ } else {
+ break;
+ }
+
+ ++lsqMemOrderViolation;
+
+ return genMachineCheckFault();
+ }
+
+ incrLdIdx(load_idx);
+ }
}
return load_fault;
DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n",
store_inst->readPC(), store_inst->seqNum);
+ assert(!store_inst->isSquashed());
+
// Check the recently completed loads to see if any match this store's
// address. If so, then we have a memory ordering violation.
int load_idx = store_inst->lqIdx;
++storesToWB;
}
- if (!memDepViolator) {
- while (load_idx != loadTail) {
- // Really only need to check loads that have actually executed
- // It's safe to check all loads because effAddr is set to
- // InvalAddr when the dyn inst is created.
-
- // @todo: For now this is extra conservative, detecting a
- // violation if the addresses match assuming all accesses
- // are quad word accesses.
-
- // @todo: Fix this, magic number being used here
- if ((loadQueue[load_idx]->effAddr >> 8) ==
- (store_inst->effAddr >> 8)) {
- // A load incorrectly passed this store. Squash and refetch.
- // For now return a fault to show that it was unsuccessful.
- memDepViolator = loadQueue[load_idx];
- ++lsqMemOrderViolation;
-
- return genMachineCheckFault();
+ assert(store_inst->effAddrValid);
+ while (load_idx != loadTail) {
+ // Really only need to check loads that have actually executed
+ // It's safe to check all loads because effAddr is set to
+ // InvalAddr when the dyn inst is created.
+
+ // @todo: For now this is extra conservative, detecting a
+ // violation if the addresses match assuming all accesses
+ // are quad word accesses.
+
+ // @todo: Fix this, magic number being used here
+ if (loadQueue[load_idx]->effAddrValid &&
+ (loadQueue[load_idx]->effAddr >> 8) ==
+ (store_inst->effAddr >> 8)) {
+ // A load incorrectly passed this store. Squash and refetch.
+ // For now return a fault to show that it was unsuccessful.
+ DynInstPtr violator = loadQueue[load_idx];
+ if (!memDepViolator ||
+ (violator->seqNum < memDepViolator->seqNum)) {
+ memDepViolator = violator;
+ } else {
+ break;
}
- incrLdIdx(load_idx);
+ ++lsqMemOrderViolation;
+
+ return genMachineCheckFault();
}
- // If we've reached this point, there was no violation.
- memDepViolator = NULL;
+ incrLdIdx(load_idx);
}
return store_fault;
assert(!inst->memData);
inst->memData = new uint8_t[64];
- TheISA::IntReg convertedData =
- TheISA::htog(storeQueue[storeWBIdx].data);
-
- //FIXME This is a hack to get SPARC working. It, along with endianness
- //in the memory system in general, need to be straightened out more
- //formally. The problem is that the data's endianness is swapped when
- //it's in the 64 bit data field in the store queue. The data that you
- //want won't start at the beginning of the field anymore unless it was
- //a 64 bit access.
- memcpy(inst->memData,
- (uint8_t *)&convertedData +
- (TheISA::ByteOrderDiffers ?
- (sizeof(TheISA::IntReg) - req->getSize()) : 0),
- req->getSize());
-
- PacketPtr data_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast);
+ memcpy(inst->memData, storeQueue[storeWBIdx].data, req->getSize());
+
+ MemCmd command =
+ req->isSwap() ? MemCmd::SwapReq :
+ (req->isLocked() ? MemCmd::StoreCondReq : MemCmd::WriteReq);
+ PacketPtr data_pkt = new Packet(req, command,
+ Packet::Broadcast);
data_pkt->dataStatic(inst->memData);
LSQSenderState *state = new LSQSenderState;
inst->seqNum);
// @todo: Remove this SC hack once the memory system handles it.
- if (req->isLocked()) {
+ if (inst->isStoreConditional()) {
// Disable recording the result temporarily. Writing to
// misc regs normally updates the result, but this is not
// the desired behavior when handling store conditionals.
inst->seqNum);
WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this);
wb->schedule(curTick + 1);
- delete state;
completeStore(storeWBIdx);
incrStIdx(storeWBIdx);
continue;
}
if (!dcachePort->sendTiming(data_pkt)) {
- if (data_pkt->result == Packet::BadAddress) {
- panic("LSQ sent out a bad address for a completed store!");
- }
// Need to handle becoming blocked on a store.
- DPRINTF(IEW, "D-Cache became blcoked when writing [sn:%lli], will"
+ DPRINTF(IEW, "D-Cache became blocked when writing [sn:%lli], will"
"retry later\n",
inst->seqNum);
isStoreBlocked = true;
}
}
+ if (memDepViolator && squashed_num < memDepViolator->seqNum) {
+ memDepViolator = NULL;
+ }
+
int store_idx = storeTail;
decrStIdx(store_idx);
storeQueue[store_idx].inst = NULL;
storeQueue[store_idx].canWB = 0;
+ // Must delete request now that it wasn't handed off to
+ // memory. This is quite ugly. @todo: Figure out the proper
+ // place to really handle request deletes.
+ delete storeQueue[store_idx].req;
+
storeQueue[store_idx].req = NULL;
--stores;
#endif
}
- 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);
}
LSQUnit<Impl>::recvRetry()
{
if (isStoreBlocked) {
+ DPRINTF(LSQUnit, "Receiving retry: store blocked\n");
assert(retryPkt != NULL);
if (dcachePort->sendTiming(retryPkt)) {
- if (retryPkt->result == Packet::BadAddress) {
- panic("LSQ sent out a bad address for a completed store!");
- }
storePostSend(retryPkt);
retryPkt = NULL;
isStoreBlocked = false;