void FetchEngine::realfetch(IBucket *bucket, EmulInterface *eint, FlowID fid, int32_t n2Fetch, uint16_t maxbb) { uint16_t tempmaxbb = maxbb; // FIXME: delete me AddrType lastpc = 0; bool lastdiff = false; #ifdef USE_FUSE RegType last_dest = LREG_R0; RegType last_src1 = LREG_R0; RegType last_src2 = LREG_R0; #endif do { DInst *dinst = 0; dinst = eint->executeHead(fid); if (dinst == 0) { //if (fid) //I(0); break; } #ifdef USE_FUSE if (/*!dinst->getStatsFlag() && */dinst->getPC() == 0) { if (dinst->getInst()->isLoad()) { MemRequest::sendReqReadWarmup(gms->getDL1(), dinst->getAddr()); dinst->scrap(eint); dinst = 0; } else if (dinst->getInst()->isStore()) { MemRequest::sendReqWriteWarmup(gms->getDL1(), dinst->getAddr()); dinst->scrap(eint); dinst = 0; } } if (dinst == 0) { // Drain cache (mostly) during warmup. FIXME: add a drain cache method? EventScheduler::advanceClock(); EventScheduler::advanceClock(); EventScheduler::advanceClock(); EventScheduler::advanceClock(); EventScheduler::advanceClock(); EventScheduler::advanceClock(); continue; } #endif if (lastpc == 0) { if (AlignedFetch) { n2Fetch -= ((dinst->getPC())>>FetchWidthBits) & (FetchWidth-1); } n2Fetch--; lastdiff = false; }else{ if ((lastpc+4) != dinst->getPC()) { // n2Fetch -= (dinst->getPC()-lastpc)>>2; n2Fetch--; if (lastdiff) { n2Fetch--; // Missed NOP } lastdiff = true; }else{ n2Fetch--; lastdiff = false; } } lastpc = dinst->getPC(); I(!missInst); dinst->setFetchTime(); #ifdef USE_FUSE if(dinst->getInst()->isControl()) { RegType src1 = dinst->getInst()->getSrc1(); if (dinst->getInst()->doesJump2Label() && dinst->getInst()->getSrc2() == LREG_R0 && (src1 == last_dest || src1 == last_src1 || src1 == last_src2 || src1 == LREG_R0) ) { //MSG("pc %x fusion with previous", dinst->getPC()); dinst->scrap(eint); continue; } } #endif bucket->push(dinst); if(dinst->getInst()->isControl()) { bool stall_fetch = processBranch(dinst, n2Fetch,&tempmaxbb); if (stall_fetch) { //bucket->push(dinst); break; } I(!missInst); }else{ //bucket->push(dinst); } #ifdef USE_FUSE last_dest = dinst->getInst()->getDst1(); last_src1 = dinst->getInst()->getSrc1(); last_src2 = dinst->getInst()->getSrc2(); #endif // Fetch uses getHead, ROB retires getTail } while(n2Fetch>0);
void DInst::killSilently() { I(getPendEvent()==0); I(getResource()==0); #ifdef SESC_BAAD if (fetch2Time == 0) { fetch1QSize--; }else if (renameTime == 0) { fetch2QSize--; }else if (issueTime == 0) { issueQSize--; }else if (schedTime == 0) { schedQSize--; }else if (exeTime == 0) { exeQSize--; }else{ retireQSize--; } #endif markIssued(); markExecuted(); if( getFetch() ) { getFetch()->unBlockFetch(); IS(setFetch(0)); } if (getInst()->isStore()) LDSTBuffer::storeLocallyPerformed(this); while (hasPending()) { DInst *dstReady = getNextPending(); if (!dstReady->isIssued()) { // Accross processor dependence if (dstReady->hasDepsAtRetire()) dstReady->clearDepsAtRetire(); I(!dstReady->hasDeps()); continue; } if (dstReady->isExecuted()) { // The instruction got executed even though it has dependences. This is // because the instruction got silently killed (killSilently) if (!dstReady->hasDeps()) dstReady->scrap(); continue; } if (!dstReady->hasDeps()) { I(dstReady->isIssued()); I(!dstReady->isExecuted()); Resource *dstRes = dstReady->getResource(); I(dstRes); dstRes->simTime(dstReady); } } #ifdef TASKSCALAR notifyDataDepViolation(DataDepViolationAtRetire); if (lvid) { // maybe got killSilently lvid = 0; lvidVersion->decOutsReqs(); lvidVersion->garbageCollect(); IS(lvidVersion=0); } I(lvidVersion==0); #endif I(!getFetch()); if (hasDeps()) return; I(nDeps == 0); // No deps src #if (defined TLS) I(!myEpoch); #endif I(!getFetch()); #if (defined MIPS_EMUL) context->delDInst(); context=0; #endif dInstPool.in(this); }