void LMVCache::combineInit(CacheLine *cl) { I(cl); I(cl->isSafe()); #ifndef TS_VICTIM_DISPLACE_CLEAN I(cl->isDirty()); #endif PAddr paddr = cl->getPAddr(); wrLVIDEnergy->inc(); combWriteEnergy->inc(); I(!isCombining(paddr)); if (cl->isLeastSpecLine()) { #ifndef TS_VICTIM_DISPLACE_CLEAN I(cl->isDirty()); #endif writeMemory(paddr); combineHalfMiss.inc(); cl->invalidate(); return; } combineInit(paddr, cl->getVersionDuplicate(), cl); I(cl->isInvalid()); }
void LMVCache::displaceLine(CacheLine *cl) { if (cl->isInvalid()) return; wrLVIDEnergy->inc(); if (cl->accessLine()) { // The cache may be killed or restarted. The cache line state must be // updated accordingly I(cl->isInvalid()); return; } if (!cl->isSafe()) { #ifdef TS_TIMELINE TraceGen::add(cl->getVersionRef()->getId(),"Disp=%lld",globalClock); #endif taskHandler->restart(cl->getVersionRef()); nRestartDisp.inc(); cl->invalidate(); return; } if (cl->isRestarted() || !cl->hasState()) { // Note: It is possible to send (cl->isSafe() && !cl->isDirty()), but then // the locality is much worse. cl->invalidate(); return; } #ifndef TS_VICTIM_DISPLACE_CLEAN if (!cl->isDirty()) { I(cl->isSafe()); cl->invalidate(); return; } #endif PAddr paddr = cl->getPAddr(); I(!isCombining(paddr)); #ifdef TS_VICTIM_DISPLACE_CLEAN writeMemory(paddr); #else if (cl->isDirty()) writeMemory(paddr); #endif cl->invalidate(); I(cl->isInvalid()); return; }
QString KCharSelectData::display(const QChar &c, const QFont &font) { if (!isDisplayable(c)) { return QString("<b>") + i18n("Non-printable") + "</b>"; } else { QString s = QString("<font size=\"+4\" face=\"") + font.family() + "\">"; if (isCombining(c)) { s += displayCombining(c); } else { s += "&#" + QString::number(c.unicode()) + ';'; } s += "</font>"; return s; } }
void LMVCache::writeCheck(VMemWriteReq *vreq) { VMemWriteReq *nreq = GMVCache::writeCheck(vreq, vbus); I(nreq); I(nreq->getOrigRequest() == vreq); if (!vreq->hasCacheSentData() ) { // If the cache did not provide data, set the cacheSentData bit so // that no readMiss is performed if (isCombining(vreq->getPAddr())) vreq->setCacheSentData(); } I(vreq->getType() == VWriteCheck); I(nreq->getType() == VWriteCheckAck); vreq->decnRequests(); // The just received packet nreq->setLatency(cachePort->nextSlotDelta()+hitDelay); vbus->writeCheckAck(nreq); }
void LMVCache::read(VMemReadReq *readReq) { TimeDelta_t latency = cachePort->nextSlotDelta(); VMemReadReq *remReadAck= GMVCache::read(readReq, latency); if (remReadAck) { // Do nothing, GMVCache::read did it }else if (isCombining(readReq->getPAddr())) { hitInc(MemRead); readReq->setCacheSentData(); nReadHalfHit.inc(); remReadAck = VMemReadReq::createReadAck(this ,readReq ,readReq->getVersionDuplicate()); readReq->incPendingMsg(); remReadAck->getState()->setLeastSpecLine(); }else{ // if it got here, there is no data to send, and other cache has sent data nReadMiss.inc(); remReadAck = VMemReadReq::createReadAck(this, readReq, 0); readReq->incPendingMsg(); } remReadAck->setLatency(latency+missDelay); I(vbus); readReq->decPendingMsg(); vbus->readAck(remReadAck); }
void LMVCache::combineInit(const VMemPushLineReq *vreq) { I(vreq); I(vreq->getVersionRef()->isSafe()); PAddr paddr = vreq->getPAddr(); I(!isCombining(paddr)); combWriteEnergy->inc(); if (vreq->getStateRef()->isLeastSpecLine()) { // write to a non-version cache combineHit.inc(); #ifdef TS_VICTIM_DISPLACE_CLEAN writeMemory(paddr); #else if (vreq->getStateRef()->isDirty()) writeMemory(paddr); #endif return; } combineInit(paddr, vreq->getVersionDuplicate(), vreq->getStateRef()); }
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); }
LMVCache::CacheLine *LMVCache::allocateLine(LVID *lvid, LPAddr addr) { // Displacement order: // // 1-Initiate a combine of safe lines // // 2-Writeback & invalidate a combine line // // 3-Restart the most speculative line (if no forwarding) CacheLine *cl = cache->findLine(addr); if (cl) return cl; // Already allocated :) PAddr paddr = calcPAddr(lvid, addr); cl = cache->findLine2Replace(addr); if (cl) { if (cl->isInvalid()) return cl; wrLVIDEnergy->inc(); if( cl->accessLine() ) { return cl; }else if (!cl->hasState()) { cl->invalidate(); return cl; } I(cl->isLeastSpecLine()); #ifdef TS_VICTIM_DISPLACE_CLEAN writeMemory(paddr); #endif cl->invalidate(); return cl; } ulong index = calcIndex4PAddr(paddr); for(ulong i=0; i < cache->getAssoc(); i++) { CacheLine *cl2 = cache->getPLine(index+i); I(!cl2->isInvalid()); // no findLine2Replace(addr) if (cl2->isSafe()) { if (cl==0) cl = cl2; else if (*(cl2->getVersionRef()) < *(cl->getVersionRef())) cl = cl2; } } if(cl) { I(cl->isSafe()); #ifdef TS_VICTIM_DISPLACE_CLEAN I(!isCombining(cl->getPAddr())); combineInit(cl); #else if (cl->isDirty()) { I(!isCombining(cl->getPAddr()));//delete by hr combineInit(cl); }else{ cl->invalidate(); wrLVIDEnergy->inc(); } #endif I(cl->isInvalid()); return cl; } cl = getLineMoreSpecThan(lvid->getVersionRef(), paddr); if (cl==0) cl = cache->findLine2Replace(addr, true); I(cl); I(!cl->isInvalid()); I(!cl->isKilled()); if (*(cl->getVersionRef()) <= *(lvid->getVersionRef())) { // OPT2: No allocate, too speculative request return 0; } // OPT3: Task more Spec (restartit #ifdef TS_TIMELINE TraceGen::add(cl->getVersionRef()->getId(),"Alloc=%lld",globalClock); #endif taskHandler->restart(cl->getVersionRef()); nRestartAlloc.inc(); I(!cl->isLocked()); if (cl->accessLine()) { wrLVIDEnergy->inc(); }else if (!cl->isInvalid()) { I(!cl->isDirty() && !cl->hasState()); wrLVIDEnergy->inc(); cl->invalidate(); } I(cl->isInvalid()); return cl; }