📄 memunit.cc
字号:
if (inst->prd != 0) proc->phy_int_reg_file[inst->prd] = inst->rdvalipair.a; proc->phy_int_reg_file[inst->prdp] = inst->rdvalipair.b; proc->intregbusy[inst->prd] = 0; proc->intregbusy[inst->prdp] = 0; proc->dist_stallq_int[inst->prd].ClearAll(proc); proc->dist_stallq_int[inst->prdp].ClearAll(proc); break; default: break; } /* Do the same for rcc too. */ if (inst->prcc != 0) proc->phy_int_reg_file[inst->prcc] = inst->rccvali; proc->intregbusy[inst->prcc] = 0; proc->dist_stallq_int[inst->prcc].ClearAll(proc); } }} /**************************************************************************//* FlushMems : Flush the memory queues in the event of a branch mispredn *//**************************************************************************/void FlushMems(long long tag, ProcState * proc){ instance *junk; long long tl_tag; while (proc->ambig_st_tags.GetTail(tl_tag) && tl_tag > tag) proc->ambig_st_tags.RemoveTail(); #ifdef STORE_ORDERING while (proc->MemQueue.NumItems()) { proc->MemQueue.GetTail(junk); if (junk->tag > tag) { proc->MemQueue.RemoveTail(); // DeleteFromTail(junk); if (junk->mem_ready) { // This can happen because of non-blocking writes // of an ordinary load that was marked ready past a done load // that is stuck in the memunit (in which case we rely on // the "ctr==0" requirement to stall issue) if (simulate_ilp) proc->ReadyUnissuedStores--; } if (junk->in_memunit == 0) {#ifdef DEBUG if (!IsStore(junk) || IsRMW(junk)) YS__errmsg("How can tag %lld be flushed from the memunit, even after it has already been graduated?\n", junk->tag); // stores can come out of the memunit by being marked ready, // and that's ok even with NB writes#endif #ifdef COREFILE if (YS__Simtime > DEBUG_TIME) fprintf(corefile, "Deleting memop for tag %lld which is not in_memunit.\n", junk->tag);#endif if (junk->inuse == 2) { junk->inuse = 0; proc->meminstances.Putback(junk); } else DeleteInstance(junk, proc); } junk->memprogress = 2; } else break; } //------------------------------------------------------------------------- // ifdef STORE_ORDERING#else while (proc->StoreQueue.NumItems()) { proc->StoreQueue.GetTail(junk); if (junk->tag > tag) { proc->StoreQueue.RemoveTail(); // DeleteFromTail(junk); junk->memprogress = 2; } else break; } while (proc->LoadQueue.NumItems()) { proc->LoadQueue.GetTail(junk); if (junk->tag > tag) { proc->LoadQueue.RemoveTail(); // DeleteFromTail(junk); junk->memprogress = 2; // mark this for done ones } else break; } while (proc->st_tags.GetTail(tl_tag) && tl_tag > tag) proc->st_tags.RemoveTail(); while (proc->rmw_tags.GetTail(tl_tag) && tl_tag > tag) proc->rmw_tags.RemoveTail(); int mbchg = 0; MembarInfo mb; while (proc->membar_tags.GetTail(mb) && mb.tag > tag) { if (mb.SYNC) proc->sync = 0; proc->membar_tags.RemoveTail(); mbchg = 1; #ifdef COREFILE if (proc->curr_cycle > DEBUG_TIME) fprintf(corefile,"Flushing out membar %lld\n", mb.tag);#endif } if (mbchg) ComputeMembarQueue(proc);#endif}/*************************************************************************//* Disambiguate : Called when the address is newly generated for an *//* : instruction. Checks if newly disambiguated stores *//* : conflict with previously issued loads *//*************************************************************************/void Disambiguate(instance * inst, ProcState * proc){ inst->addr_ready = 1; inst->time_addr_ready = YS__Simtime; if (!IsStore(inst)) return; if (!simulate_ilp) inst->mem_ready = 1; instance *conf; MemQLink<instance *> *ldindex = NULL; long long lowambig = LLONG_MAX; proc->ambig_st_tags.Remove(inst->tag); proc->ambig_st_tags.GetMin(lowambig); proc->LoadQueue.GetMin(conf); #ifndef STORE_ORDERING while ((ldindex = proc->LoadQueue.GetNext(ldindex)) != NULL)#else while ((ldindex = proc->MemQueue.GetNext(ldindex)) != NULL)#endif { conf = ldindex->d;#ifdef STORE_ORDERING if (IsStore(conf)) continue;#endif if (conf->tag >= inst->tag) { if (conf->limbo) { if (overlap(conf, inst)) { conf->limbo--; if (spec_stores == SPEC_EXCEPT) { if (conf->exception_code == OK || conf->exception_code == SERIALIZE) { // mark this a soft exception conf->exception_code = SOFT_LIMBO; proc->active_list.flag_exception(conf->tag, SOFT_LIMBO); } // the following needs to be done regardless // of the exception code (ie, you may have // already had an exception caused by // SOFT_SL) // mark this as being "done" so that way it // actually graduates MemQLink<instance *> *confindex = ldindex;#ifndef STORE_ORDERING ldindex = proc->LoadQueue.GetPrev(ldindex); proc->LoadQueue.Remove(confindex);#else ldindex = proc->MemQueue.GetPrev(ldindex); proc->MemQueue.Remove(confindex);#endif conf->in_memunit = 0; // We can bring something into the memqueue // right now, but we don't have to, since // that's definitely going to get flushed proc->DoneHeap.insert(proc->curr_cycle, conf, conf->tag); } else if (spec_stores == SPEC_LIMBO) { conf->memprogress = 0; conf->vsbfwd = 0; proc->redos++; // going to have to redo it conf->issuetime = LLONG_MAX; }#ifdef DEBUG else YS__errmsg(proc->proc_id / ARCH_cpus, "Disambiguate limbo redos should not be seen with SPEC_STALL?\n");#endif } // if (overlap(inst, conf)) else if (lowambig > conf->tag) { proc->unlimbos++; conf->limbo--; conf->memprogress = 1; if (!conf->limbo) {#ifndef STORE_ORDERING ldindex = proc->LoadQueue.GetPrev(ldindex);#else ldindex = proc->MemQueue.GetPrev(ldindex);#endif proc->DoneHeap.insert(proc->curr_cycle, conf, conf->tag); } PerformMemOp(conf, proc); } else { conf->limbo --; if (!conf->limbo) { conf->memprogress = 1; conf->in_memunit = 0;#ifndef STORE_ORDERING ldindex = proc->LoadQueue.GetPrev(ldindex); proc->LoadQueue.Remove(conf);#else ldindex = proc->MemQueue.GetPrev(ldindex); proc->MemQueue.Remove(conf);#endif proc->DoneHeap.insert(proc->curr_cycle, conf, conf->tag); } } } else if ((conf->memprogress < 0) && overlap(conf, inst)) { proc->kills++; if (spec_stores == SPEC_EXCEPT) { if (conf->exception_code == OK || conf->exception_code == SERIALIZE) { conf->exception_code = SOFT_LIMBO; proc-> active_list.flag_exception(conf->tag, SOFT_LIMBO); } } else if (spec_stores == SPEC_LIMBO) conf->kill = 1;#ifdef DEBUG else YS__errmsg(proc->proc_id / ARCH_cpus, "Should never get a disambiguate kill on a SPEC_STALL?\n");#endif } } }}/*#########################################################################*/#ifndef STORE_ORDERING/**************************************************************************//**************************************************************************/ int IssueBarrier(ProcState *proc){ if (!L1DQ_FULL[proc->proc_id]) { DCache_recv_barrier(proc->proc_id); return 1; } else return 0; // was 0 - error}void IssueLoads(ProcState*);void IssueStores(ProcState*);/* * Called every cycle by IssueQueues() -- calls IssueLoads, IssueStores, * and IssuePrefetch. Also responsible for maintaining MEMBAR status. */int IssueMem(ProcState * proc){ instance *memop; long long minrmw = LLONG_MAX; proc->minload = LLONG_MAX, proc->minstore = LLONG_MAX; /* these will leave min-values alone if nothing there */ if (proc->LoadQueue.GetMin(memop)) proc->minload = MIN(proc->minload, memop->tag); proc->st_tags.GetMin(proc->minstore); proc->rmw_tags.GetMin(minrmw); proc->minload = MIN(proc->minload, minrmw); proc->minstore = MIN(proc->minstore, minrmw); MembarInfo mb; int mbchg = 0; while (proc->membar_tags.GetMin(mb)) { if ((!(mb.LL || mb.LS) || proc->minload > mb.tag) && (!(mb.SL || mb.SS) || proc->minstore > mb.tag) && (!mb.MEMISSUE || (proc->minstore>mb.tag && proc->minload>mb.tag)) && (!mb.MEMISSUE || UBuffers[proc->proc_id]->num_entries == 0) && !mb.SYNC) {#ifdef COREFILE if (proc->curr_cycle > DEBUG_TIME) fprintf(corefile, "Breaking down membar %lld\n", mb.tag);#endif if (!IssueBarrier(proc)) return 0; mbchg = 1; proc->membar_tags.Remove(mb); } else break; } if (mbchg) { ComputeMembarQueue(proc); if (Speculative_Loads) { // We need to go through the Load Queue and find done items. MemQLink<instance *> *ldindex = NULL; while ((ldindex = proc->LoadQueue.GetNext(ldindex)) != NULL && (proc->minstore >= proc->SLtag || ldindex->d->tag <= proc->SLtag) && (proc->minload >= proc->LLtag || ldindex->d->tag <= proc->LLtag)) { instance *memop2 = ldindex->d; if (memop2->memprogress == 1 && !memop2->limbo) { /* Get next one out first before this one is removed. */ ldindex = proc->LoadQueue.GetPrev(ldindex); /* This function will remove the access from the LoadQueue */ PerformMemOp(memop2, proc); } } } } proc->prefs = 0; // zero prefetches so far this cycle IssueStores(proc); IssueLoads(proc); if (Prefetch) StartPrefetch(proc); return 0;}/*************************************************************************//* ComputeMembarQueue : reset SS/LS/LL/SL tags based on membar queue *//*************************************************************************/void ComputeMembarQueue(ProcState * proc){ // guaranteed to be out of range proc->SStag = proc->LStag = proc->SLtag = proc->LLtag = proc->MEMISSUEtag = -1; MemQLink<MembarInfo> *stepper = NULL; while ((stepper = proc->membar_tags.GetNext(stepper)) != NULL) { if (stepper->d.SS && proc->SStag == -1) proc->SStag = stepper->d.tag; if (stepper->d.LS && proc->LStag == -1) proc->LStag = stepper->d.tag; if (stepper->d.SL && proc->SLtag == -1) proc->SLtag = stepper->d.tag; if (stepper->d.LL && proc->LLtag == -1) proc->LLtag = stepper->d.tag; if (stepper->d.MEMISSUE && proc->MEMISSUEtag == -1) proc->MEMISSUEtag = stepper->d.tag; if (stepper->d.SYNC && !proc->sync) proc->sync = 1; }}/***************************************************************************//* ComputeMembarInfo : On a memory barrier instruction, suitably updates *//* : the processor's memory-barrier implementation flags *//***************************************************************************/void ComputeMembarInfo(ProcState * proc, const MembarInfo & mb){ if (mb.SS && proc->SStag == -1) proc->SStag = mb.tag; if (mb.LS && proc->LStag == -1) proc->LStag = mb.tag; if (mb.SL && proc->SLtag == -1) proc->SLtag = mb.tag; if (mb.LL && proc->LLtag == -1) proc->LLtag = mb.tag; if (mb.MEMISSUE && proc->MEMISSUEtag == -1) proc->MEMISSUEtag = mb.tag;}/**************************************************************************//* IssueStores : Get elements from store queue and check for dependences, *//* : resource availability and issue it *//**************************************************************************/void IssueStores(ProcState * proc){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -