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);
DInst *LSQFull::executing(DInst *dinst) /* dinst got executed (out-of-order) {{{1 */ { I(dinst->getAddr()); AddrType tag = calcWord(dinst); const Instruction *inst = dinst->getInst(); DInst *faulty = 0; #if 0 AddrDInstQMap::const_iterator instIt = instMap.begin(); I(instIt != instMap.end()); I(!dinst->isExecuted()); while(instIt != instMap.end()) { if (instIt->first != tag){ instIt++; continue; } #endif std::pair<AddrDInstQMap::iterator, AddrDInstQMap::iterator> ret; ret = instMap.equal_range(tag); for (AddrDInstQMap::iterator instIt=ret.first; instIt!=ret.second; ++instIt) { I(instIt->first == tag); //inst->dump("Executed"); DInst *qdinst = instIt->second; if(qdinst == dinst) { continue; } const Instruction *qinst = qdinst->getInst(); //bool beforeInst = qdinst->getID() < dinst->getID(); bool oooExecuted = qdinst->getID() > dinst->getID(); if(oooExecuted){ if(qdinst->isExecuted() && qdinst->getPC() != dinst->getPC()) { if(inst->isStore() && qinst->isLoad()) { if (faulty == 0) faulty = qdinst; else if (faulty->getID() < qdinst->getID()) faulty = qdinst; } } }else{ if (!dinst->isLoadForwarded() && inst->isLoad() && qinst->isStore() && qdinst->isExecuted()) { dinst->setLoadForwarded(); stldForwarding.inc(dinst->getStatsFlag()); } } } I(!dinst->isExecuted()); // first clear, then mark executed return faulty; } /* }}} */ void LSQFull::remove(DInst *dinst) /* Remove from the LSQ {{{1 (in-order) */ { I(dinst->getAddr()); //const Instruction *inst = dinst->getInst(); std::pair<AddrDInstQMap::iterator,AddrDInstQMap::iterator> rangeIt; //rangeIt = instMap.equal_range(calcWord(dinst)); AddrDInstQMap::iterator instIt = instMap.begin(); //for(AddrDInstQMap::iterator it = rangeIt.first; it != rangeIt.second ; it++) { while(instIt != instMap.end()){ if(instIt->second == dinst) { instMap.erase(instIt); return; } instIt++; } }