diff -r 2e64a7166f10 -r 7026fe0f45b4 src/cpu/o3/O3CPU.py --- a/src/cpu/o3/O3CPU.py Mon May 13 15:11:29 2013 +0100 +++ b/src/cpu/o3/O3CPU.py Wed Jun 05 13:54:16 2013 +0100 @@ -52,7 +52,7 @@ activity = Param.Unsigned(0, "Initial count") - cachePorts = Param.Unsigned(200, "Cache Ports") + cachePorts = Param.Unsigned(2, "Cache Ports") decodeToFetchDelay = Param.Cycles(1, "Decode to fetch delay") renameToFetchDelay = Param.Cycles(1 ,"Rename to fetch delay") diff -r 2e64a7166f10 -r 7026fe0f45b4 src/cpu/o3/iew_impl.hh --- a/src/cpu/o3/iew_impl.hh Mon May 13 15:11:29 2013 +0100 +++ b/src/cpu/o3/iew_impl.hh Wed Jun 05 13:54:16 2013 +0100 @@ -1531,6 +1531,7 @@ broadcast_free_entries = true; } + ldstQueue.tick(); // Writeback any stores using any leftover bandwidth. ldstQueue.writebackStores(); diff -r 2e64a7166f10 -r 7026fe0f45b4 src/cpu/o3/lsq_unit.hh --- a/src/cpu/o3/lsq_unit.hh Mon May 13 15:11:29 2013 +0100 +++ b/src/cpu/o3/lsq_unit.hh Wed Jun 05 13:54:16 2013 +0100 @@ -436,7 +436,7 @@ /// @todo Consider moving to a more advanced model with write vs read ports /** The number of cache ports available each cycle. */ - int cachePorts; + unsigned int cachePorts; /** The number of used cache ports in this cycle. */ int usedPorts; @@ -523,6 +523,9 @@ /** Number of times the LSQ is blocked due to the cache. */ Stats::Scalar lsqCacheBlocked; + /** Number of times the LSQ ran up against cache ports limit. */ + Stats::Scalar lsqCachePortsLim; + public: /** Executes the load at the given index. */ Fault read(Request *req, Request *sreqLow, Request *sreqHigh, @@ -779,11 +782,24 @@ assert(!load_inst->memData); load_inst->memData = new uint8_t[64]; - ++usedPorts; + // if there are ports available and the cache is not blocked, do cache + // access + bool completedFirst = false; + if (usedPorts >= cachePorts) { + ++lsqCachePortsLim; + DPRINTF(LSQUnit, "Out of ports for this tick.\n"); - // if we the cache is not blocked, do cache access - bool completedFirst = false; - if (!lsq->cacheBlocked()) { + iewStage->decrWb(load_inst->seqNum); + if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum) + return NoFault; + + isLoadBlocked = true; + loadBlockedHandled = false; + blockedLoadSeqNum = load_inst->seqNum; + // No fault occurred, even though the interface is blocked. + return NoFault; + + } else if (!lsq->cacheBlocked()) { MemCmd command = req->isLLSC() ? MemCmd::LoadLockedReq : MemCmd::ReadReq; PacketPtr data_pkt = new Packet(req, command); @@ -819,6 +835,7 @@ state->mainPkt = data_pkt; } + ++usedPorts; if (!dcachePort->sendTimingReq(fst_data_pkt)) { // Delete state and data packet because a load retry // initiates a pipeline restart; it does not retry. @@ -847,8 +864,12 @@ // load will be squashed, so indicate this to the state object. // The first packet will return in completeDataAccess and be // handled there. - ++usedPorts; - if (!dcachePort->sendTimingReq(snd_data_pkt)) { + if (usedPorts < cachePorts && + dcachePort->sendTimingReq(snd_data_pkt)) { + ++usedPorts; + } else { + ++lsqCachePortsLim; + DPRINTF(LSQUnit, "Out of ports for this tick.\n"); // The main packet will be deleted in completeDataAccess. delete snd_data_pkt->req; diff -r 2e64a7166f10 -r 7026fe0f45b4 src/cpu/o3/lsq_unit_impl.hh --- a/src/cpu/o3/lsq_unit_impl.hh Mon May 13 15:11:29 2013 +0100 +++ b/src/cpu/o3/lsq_unit_impl.hh Wed Jun 05 13:54:16 2013 +0100 @@ -163,6 +163,8 @@ depCheckShift = params->LSQDepCheckShift; checkLoads = params->LSQCheckLoads; cachePorts = params->cachePorts; + if (cachePorts == 0) + fatal("Must have more than 0 cachePorts"); needsTSO = params->needsTSO; resetState(); @@ -247,6 +249,10 @@ lsqCacheBlocked .name(name() + ".cacheBlocked") .desc("Number of times an access to memory failed due to the cache being blocked"); + + lsqCachePortsLim + .name(name() + ".cachePortsLim") + .desc("Number of times cache could not be accessed because of cache ports limit"); } template @@ -766,8 +772,6 @@ continue; } - ++usedPorts; - if (storeQueue[storeWBIdx].inst->isDataPrefetch()) { incrStIdx(storeWBIdx); @@ -907,7 +911,6 @@ // Ensure there are enough ports to use. if (usedPorts < cachePorts) { - ++usedPorts; if (sendStore(snd_data_pkt)) { storePostSend(snd_data_pkt); } else { @@ -916,6 +919,8 @@ inst->seqNum); } } else { + ++lsqCachePortsLim; + DPRINTF(LSQUnit, "Out of ports for this tick.\n"); // Store the packet for when there's free ports. assert(pendingPkt == NULL); @@ -930,9 +935,6 @@ } } - // Not sure this should set it to 0. - usedPorts = 0; - assert(stores >= 0 && storesToWB >= 0); } @@ -1173,6 +1175,18 @@ bool LSQUnit::sendStore(PacketPtr data_pkt) { + // If more ports have been used than are available, there's a problem + assert(usedPorts <= cachePorts); + if (usedPorts == cachePorts) { + ++lsqCachePortsLim; + + assert(retryPkt == NULL); + retryPkt = data_pkt; + lsq->setRetryTid(lsqID); + DPRINTF(LSQUnit, "Out of ports for this tick.\n"); + return false; + } + if (!dcachePort->sendTimingReq(data_pkt)) { // Need to handle becoming blocked on a store. isStoreBlocked = true; @@ -1182,6 +1196,7 @@ lsq->setRetryTid(lsqID); return false; } + ++usedPorts; return true; } @@ -1196,7 +1211,7 @@ LSQSenderState *state = dynamic_cast(retryPkt->senderState); - if (dcachePort->sendTimingReq(retryPkt)) { + if (sendStore(retryPkt)) { // Don't finish the store unless this is the last packet. if (!TheISA::HasUnalignedMemAcc || !state->pktToSend || state->pendingPacket == retryPkt) { @@ -1214,10 +1229,6 @@ storePostSend(state->pendingPacket); } } - } else { - // Still blocked! - ++lsqCacheBlocked; - lsq->setRetryTid(lsqID); } } else if (isLoadBlocked) { DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, "