/** Return a pointer to a new line node with count of occurencies in line equal to 1. */ Line * newLine(int line) { Line * l = allocateLine(); l->number = line; l->count = 1; l->prev = NULL; return l; }
void CCache::doReqAck(MemRequest *mreq) /* CCache reqAck {{{1 */ { trackAddress(mreq); mreq->recoverReqAction(); AddrType addr = mreq->getAddr(); Line *l = cacheBank->readLine(addr); // It could be l!=0 if we requested a check in the lower levels to change state. if (l == 0) { l = allocateLine(addr, mreq); }else{ if (notifyHigherLevels(l,mreq)) { // FIXME I(0); I(mreq->hasPendingSetStateAck()); return; } } s_reqSetState[mreq->getAction()]->inc(mreq->getStatsFlag()); int16_t portid = router->getCreatorPort(mreq); GI(portid<0,mreq->isHomeNode()); l->adjustState(mreq, portid); Time_t when = port->reqDone(mreq)+dyn_hitDelay; mshr->retire(addr); avgMissLat.sample(mreq->getTimeDelay(when), mreq->getStatsFlag()); avgMemLat.sample(mreq->getTimeDelay(when)); if(mreq->isHomeNode()) { mreq->ackAbs(when); }else { router->scheduleReqAckAbs(mreq,when); } }
void LMVCache::pushLine(VMemPushLineReq *pushReq) { PAddr paddr = pushReq->getPAddr(); I(paddr); rdRevLVIDEnergy->inc(); // pushLine steps (LMVCache) // // 1-Check if combining that address was initiated // // 2-cleanupSet (may free LVIDs and/or lines) // // 3-Otherwise forwardLine if (isCombining(paddr) && (pushReq->getVersionRef()->isSafe())) { // Already combining, so add this line too // when the first push cauesd by displace() in allocateLine() in FMVCache, // if it hit the combine, it will enter this func. // Also, if it is not hit, then if is safe, it will enter the combineInit(); // this fuc will init a askPushLine(), and combine all the possible cacheline // from the upper level FMVCache. // add by hr combinePushLine(pushReq); #ifdef DEBUG if (isCombining(paddr) ){ ulong index = calcIndex4PAddr(paddr); for(ulong i=0; i < cache->getAssoc(); i++) { CacheLine *cl = cache->getPLine(index+i); if (cl->isInvalid()) continue; // All the cache lines for this addre must be gone I(!(cl->isHit(paddr) && cl->isSafe())); } } #endif //if the pushReq is in combing, and it is safe, so just return the req to FMVCache, //the FMVCache do nothing but destroy thr req. add by hr if (pushReq->getVersionRef()->isSafe()) { ackPushLine(pushReq); return; } }else{ // We can not loose messages I(pushReq->getAskPushReq() == 0); } if (pushReq->getVersionRef()->isKilled()) { ackPushLine(pushReq); return; } // when the pushReq is not safe and it is NOT getAskPushReq(), // then put it in the victim. add by hr // // first, try to transform the version in the pushReq to lvid. add by hr LVID *lvid = findCreateLVID(pushReq); if (lvid==0) { wrRevLVIDEnergy->inc(); if (pushReq->getVersionRef()->isSafe()) { I(!isCombining(pushReq->getPAddr())); combineInit(pushReq); // This func deal with the safe and not hit combine pushReq. It will // combine all the possible safe cacheline. and just put the safe line // in the combine, that is cMap. and init the askReq, which will later // hit the combine. add by hr ackPushLine(pushReq); }else{ recycleAllCache(pushReq->getVersionRef());// bao li!!!! add by hr forwardPushLine(pushReq); pushMiss.inc(); } return; } I(!lvid->isKilled()); LPAddr addr = lvid->calcLPAddr(paddr); CacheLine *cl = cache->findLine2Replace(addr); if (cl == 0) { cleanupSet(paddr); I(!lvid->isGarbageCollected()); cl = allocateLine(lvid, addr); GI(cl, cl->isInvalid() || (cl->getLVID() == lvid && cl->isHit(paddr)) ); if (cl == 0) { if (pushReq->getVersionRef()->isSafe()) { // initiate combine I(!isCombining(paddr)); combineInit(pushReq); ackPushLine(pushReq); }else{ I(!pushReq->getVersionRef()->isSafe()); forwardPushLine(pushReq); pushHalfMiss.inc(); } lvid->garbageCollect(); return; } }else{ cl->accessLine(); if (!cl->isInvalid()) { if(cl->isHit(addr)) { // The line was already here??? Race detected ackPushLine(pushReq); return; } I(!cl->isLocked()); if(!cl->hasState()) cl->invalidate(); else if(cl->isSafe()) { I(cl->isLeastSpecLine()); // It can be displaced at will (no combine) #ifdef TS_VICTIM_DISPLACE_CLEAN writeMemory(paddr); #else if (cl->isDirty()) writeMemory(paddr); #endif cl->invalidate(); }else{ I(0); } } I(cl->isInvalid()); } #ifdef DEBUG if (isCombining(paddr) ){ ulong index = calcIndex4PAddr(paddr); for(ulong i=0; i < cache->getAssoc(); i++) { CacheLine *cl = cache->getPLine(index+i); if (cl->isInvalid()) continue; // All the cache lines for this addre must be gone I(!(cl->isHit(paddr) && cl->isSafe())); } } #endif if (!pushReq->getVersionRef()->isKilled()) { if (!cl->isInvalid()) { GI(cl->hasState(), cl->getLVID() == lvid && cl->isHit(paddr)); cl->invalidate(); } if (lvid->getVersionRef()==0) { lvid = findCreateLVID(pushReq); I(lvid); } cl->resetState(addr, lvid, pushReq->getStateRef()); cl->setMsgSerialNumber(pushReq->getSerialNumber()); } ackPushLine(pushReq); }