void SMPCache::returnAccess(MemRequest *mreq) { SMPMemRequest *sreq = static_cast<SMPMemRequest *>(mreq); MemOperation memOp = sreq->getMemOperation(); if(sreq->getRequestor() == this) { // request from this cache (response is ready) if(memOp == MemRead) { protocol->readMissAckHandler(sreq); } else if(memOp == MemReadW) { if(sreq->needsData()) { protocol->writeMissAckHandler(sreq); } else { protocol->invalidateAckHandler(sreq); } } else if(memOp == MemWrite) { I(!sreq->needsData()); I(sreq->needsSnoop()); protocol->invalidateAckHandler(sreq); } else if(memOp == MemPush) { protocol->writeBackAckHandler(sreq); } } else { receiveFromBelow(sreq); } }
TimeDelta_t SMPSystemBus::finalizePush(MemRequest *mreq) { PAddr addr = mreq->getPAddr(); SMPMemRequest *sreq = static_cast<SMPMemRequest *>(mreq); pendReqsTable.erase(mreq); if (mreq->isDataReq()) { int nLesserEpochs=processResponses(mreq); //Version combining has concluded //doVCRCB::scheduleAbs(busDelay*wrSize+nextSlot(mreq)+delay, this, mreq); if (VCRMaxCount.getValue()<VCRCount) VCRMaxCount.inc(); if (sreq->needsData()|| sreq->getMemOperation()==MemPush)VCRCount--; l2DataProv.sample(nLesserEpochs); mreq->getVcacheFlags()->clear(); //Account for all bus transfers for version combination return busDelay*nLesserEpochs; } else I(0);//Should not be called for any other reason return 0; }
void SMPSystemBus::finalizeAccess(MemRequest *mreq) { PAddr addr = mreq->getPAddr(); SMPMemRequest *sreq = static_cast<SMPMemRequest *>(mreq); pendReqsTable.erase(mreq); #ifdef TLS if (mreq->isDataReq()) { int nLesserEpochs=processResponses(mreq); //Version combining has concluded //doVCRCB::scheduleAbs(busDelay*wrSize+nextSlot(mreq)+delay, this, mreq); if (VCRMaxCount.getValue()<VCRCount) VCRMaxCount.inc(); if (sreq->needsData()|| sreq->getMemOperation()==MemPush)VCRCount--; l2DataProv.sample(nLesserEpochs); mreq->getVcacheFlags()->clear(); //Account for all bus transfers for version combination sreq->goUpAbs(busDelay*nLesserEpochs+nextSlot(mreq)+delay); } else sreq->goUpAbs(nextSlot(mreq)+delay); #else sreq->goUpAbs(nextSlot(mreq)+delay); #endif // request completed, respond to requestor // (may have to come back later to go to memory) }
void SMPSystemBus::doWrite(MemRequest *mreq) { SMPMemRequest *sreq = static_cast<SMPMemRequest *>(mreq); // no need to snoop, go straight to memory if(!sreq->needsSnoop()) { goToMem(mreq); return; } if(pendReqsTable.find(mreq) == pendReqsTable.end()) { unsigned numSnoops = getNumSnoopCaches(sreq); // operation is starting now, add it to the pending requests buffer pendReqsTable[mreq] = getNumSnoopCaches(sreq); if(!numSnoops) { // nothing to snoop on this chip finalizeWrite(mreq); return; // TODO: even if there is only one processor on each chip, // request is doing two rounds: snoop and memory } //VERSION COMBINING REGISTER ALLOCATED HERE #ifdef TLS if (mreq->isDataReq()&& sreq->needsData())VCRCount++; #endif // distribute requests to other caches, wait for responses for(uint i = 0; i < upperLevel.size(); i++) { if(upperLevel[i] != static_cast<SMPMemRequest *>(mreq)->getRequestor()) { upperLevel[i]->returnAccess(mreq); } } } else { // operation has already been sent to other caches, receive responses I(pendReqsTable[mreq] > 0); I(pendReqsTable[mreq] <= (int) upperLevel.size()); pendReqsTable[mreq]--; if(pendReqsTable[mreq] != 0) { // this is an intermediate response, request is not serviced yet return; } // this is the final response, request can go up now finalizeWrite(mreq); } }
int SMPSystemBus::processResponses(MemRequest *mreq) { SMPMemRequest *sreq = static_cast<SMPMemRequest *>(mreq); typedef std::vector<tls::CacheFlags>::iterator ItVcacheFlags; int nLesserEpochs=0; int wrSize=(sreq->getVcacheFlags())->size(); //I(wrSize<=nProcs); //MEM ACCESS IN NO LONGER NECESSARY //Epoch checks are now done in the MESI protocol //So if line with proper epoch is not found the tag is set to 0 //Consequently standard MESI causes request to go down to memory //Still has mem access code to prevent breaking further code if (sreq->getMemOperation()==MemReadW) { if (!wrSize) { //No other cache has line sreq->setClearOthersExposed(); if (sreq->needsData()) sreq->setMemAccess(); return 0; } else { sreq->clearSetOthersExposed(); sreq->clearClearOthersExposed() ; ItVcacheFlags itVcacheFlags; for (itVcacheFlags=sreq->getVcacheFlags()->begin();itVcacheFlags!=sreq->getVcacheFlags()->end();itVcacheFlags++) { //If there are lines with epoch number greater than mine then set Others exposed if((*itVcacheFlags).getEpoch()->getClock()<(sreq->getOriginalRequest()->getEpoch())->getClock()) { nLesserEpochs++; } else sreq->setSetOthersExposed(); } if (!nLesserEpochs) { sreq->setMemAccess(); sreq->setClearOthersExposed(); } //If write miss then Lesser epochs makes sense return sreq->needsData()? nLesserEpochs:0; } } if (sreq->getMemOperation()==MemRead) { if (!wrSize) { //No other cache has line if (sreq->needsData()) sreq->setMemAccess(); return 0; } else { sreq->clearMemAccess(); sreq->clearSetOthersExposed(); ItVcacheFlags itVcacheFlags; for (itVcacheFlags=sreq->getVcacheFlags()->begin();itVcacheFlags!=sreq->getVcacheFlags()->end();itVcacheFlags++) { //If there are lines with epoch number greater than mine then set exposed read if((*itVcacheFlags).getEpoch()->getClock()<(sreq->getOriginalRequest()->getEpoch())->getClock()) { nLesserEpochs++; } else sreq->setSetOthersExposed(); } if (!nLesserEpochs) sreq->setMemAccess(); return nLesserEpochs; } } if (sreq->getMemOperation()==MemPush) { ItVcacheFlags itVcacheFlags; for (itVcacheFlags=sreq->getVcacheFlags()->begin();itVcacheFlags!=sreq->getVcacheFlags()->end();itVcacheFlags++) { //Actual VCR if((*itVcacheFlags).getEpoch()->getClock()<(sreq->getOriginalRequest()->getEpoch())->getClock()) { nLesserEpochs++; } } return nLesserEpochs; } return 0;//All other cases }