📄 branchpred.cc
字号:
inst2->npc = proc->pc; if (inst2->branchdep == 2) {#ifdef DEBUG if (proc->stall_the_rest != inst2->tag) YS__errmsg(proc->proc_id / ARCH_cpus, "BRANCH STALLING ERROR P%d(%lld/%d) %s:%d!!", proc->proc_id, inst->tag, inst->pc, __FILE__, __LINE__);#endif if (!STALL_ON_FULL || proc->type_of_stall_rest != eMEMQFULL) unstall_the_rest(proc); inst2->branchdep = 0; instance *inst3 = proc->BranchDepQ.GetNext(proc); #ifdef DEBUG // result should be inst2 itself, if anything if (inst3 && inst3->tag != inst2->tag) /* wouldn't have been in branchq on renaming stall */ YS__errmsg(proc->proc_id / ARCH_cpus, "BRANCH STALLING ERROR P%d(%lld/%d) %s:%d!!", proc->proc_id, inst->tag, inst->pc, __FILE__, __LINE__);#endif if (inst3) inst3->stallqs--; } else // Copy the corresponding mapper entry to the original mappers // Also copy the busy state of the integers at that instant CopyBranchQ(tag_to_use, proc); // Flush the mapper tables to remove this and later branches if any FlushBranchQ(tag_to_use, proc); // We should flush the memory queue too so that the loads and stores dont // keep waiting to verify that the branch is done or not... FlushMems(tag_to_use, proc); // Flush all entries in the stallQ which were sent in after the branch. // Must be flushed before active list since some entries in stallQ are not // in active list. FlushStallQ(tag_to_use, proc); FlushFetchQ(proc); // Flush the active list to remove any entries after the branch // While flushing, put back the registers in the free list int pre = proc->active_list.NumElements(); FlushActiveList(tag_to_use, proc); int post = proc->active_list.NumElements();#ifndef NOSTAT StatrecUpdate(proc->BadPredFlushes, pre - post, 1);#endif return;}/* * we assume that proc->pc and proc->npc have been set properly before * calling HandleUnPredicted */void HandleUnPredicted(instance * inst, ProcState * proc){ long long tag_to_use = inst->tag; instance *inst2; if (inst->code.annul == 0) { tag_to_use = inst->tag + 1; inst2 = convert_tag_to_inst(tag_to_use, proc); } else inst2 = inst; if (tag_to_use == proc->instruction_count) // The delay slot has not been issued yet! return; // to indicate that the next instruction after this one is the point from // which the processor will be fetching after this misprediction inst2->npc = proc->pc; inst2->branchdep = 0;}/* * FlushBranchQ : Flush all elements (shadow mappers) in the branchq */void FlushBranchQ(long long tag, ProcState *proc){ BranchQElement *junk; while (proc->branchq.NumItems()) { proc->branchq.GetTail(junk); if (junk->tag >= tag) { proc->branchq.RemoveTail(); DeleteMapTable(junk->specmap, proc); DeleteBranchQElement(junk, proc); } else break; }}void FlushFetchQ(ProcState *proc){ Queue<fetch_queue_entry> *fetch_queue = proc->fetch_queue; fetch_queue_entry fqe; while (!fetch_queue->Empty()) { fetch_queue->GetHead(fqe); DeleteInstance(fqe.inst, proc); fetch_queue->Dequeue(); }}/* * GetElement : Get branch queue element that matches given tag */BranchQElement *GetElement(long long tag, ProcState * proc){ MemQLink<BranchQElement *> *stepper = NULL; BranchQElement *junk = NULL; while ((stepper = proc->branchq.GetNext(stepper)) != NULL) { junk = stepper->d; if (junk->tag == tag) return junk; } return NULL;}/* * RemoveFromBranchQ : Remove entry specified by tag from branch queue * for successful predictions */int RemoveFromBranchQ(long long tag, ProcState * proc) { // this part is like the way we handle memory system BranchQElement *junk = GetElement(tag, proc); if (junk == NULL) return -1; junk->done = 1; proc->branchq.Remove(junk); DeleteMapTable(junk->specmap, proc); DeleteBranchQElement(junk, proc); instance *i = proc->BranchDepQ.GetNext(proc); if (i != NULL) { i->stallqs--; if (AddBranchQ(i->tag, proc) != 0) YS__errmsg(proc->proc_id / ARCH_cpus, "SERIOUS ERROR IN REVIVING A SLEPT BRANCH!!!" " P%d(%lld/%d) %s:%d!!\n", proc->proc_id, i->tag, i->pc, __FILE__, __LINE__); i->branchdep = 0;#ifdef COREFILE if (YS__Simtime > DEBUG_TIME) fprintf(corefile, "shadow mapper allocated for tag %lld\n", i->tag);#endif #ifdef DEBUG if (proc->stall_the_rest != i->tag) YS__errmsg(proc->proc_id / ARCH_cpus, "SERIOUS ERROR IN REVIVING A SLEPT BRANCH!!!" " P%d(%lld/%d) %s:%d!!\n", proc->proc_id, i->tag, i->pc, __FILE__, __LINE__);#endif if (!STALL_ON_FULL || proc->type_of_stall_rest != eMEMQFULL) unstall_the_rest(proc); } return 0;}/* * AddBranchQ: Initialize shadow mappers and add to list of outstanding * branches. return -1 if out of shadow mappers */int AddBranchQ(long long tag, ProcState * proc){ if (proc->branchq.NumItems() >= MAX_SPEC) { /* out of speculations */#ifdef COREFILE if (proc->curr_cycle > DEBUG_TIME) fprintf(corefile, "Out of shadow mappers !\n");#endif return (-1); } MapTable *specmap = NewMapTable(proc);#ifdef DEBUG if (specmap == NULL) YS__errmsg(proc->proc_id / ARCH_cpus, "Got a NULL map table entry!!");#endif int n; long long *src, *dest; src = (long long*)proc->intmapper; dest = (long long*)specmap->imap; for (n = 0; n < (sizeof(short)*NO_OF_LOG_INT_REGS) / sizeof(long long); n++) dest[n] = src[n]; src = (long long*)proc->fpmapper; dest = (long long*)specmap->fmap; for (n = 0; n < (sizeof(short)*NO_OF_LOG_FP_REGS) / sizeof(long long); n++) dest[n] = src[n]; /* Add it into our Branch List */ proc->branchq.Insert(NewBranchQElement(tag, specmap, proc)); return (0);}/* * CopyBranchQ : Set up the state after a branch misprediction */int CopyBranchQ(long long tag, ProcState * proc){ /* Let us get the entry corresponding to this tag */ BranchQElement *entry = GetElement(tag, proc); if (entry == NULL) {#ifdef COREFILE if (proc->curr_cycle > DEBUG_TIME) fprintf(corefile, "<branchspec.cc> Error : Shadow mapper not " "found for tag %lld\n", tag);#endif return (-1); } /* Change the mappers to point to the right ones */ MapTable *tmpmap = proc->activemaptable; proc->activemaptable = entry->specmap; entry->specmap = tmpmap; proc->intmapper = proc->activemaptable->imap; proc->fpmapper = proc->activemaptable->fmap; return (0);}/* * FlushActiveList : Flush the active list on a branch misprediction */int FlushActiveList(long long tag, ProcState * proc){ proc->copymappernext = 0; proc->unpredbranch = 0; unstall_the_rest(proc); /* Flush out the active list suitable freeing the physical registers used too. */ return (proc->active_list.flush_active_list(tag, proc));}/* * Flush stall queue elements on branch misprediction */int FlushStallQ(long long tag, ProcState * proc){ instance *tmpinst; if (proc->inst_save != NULL && proc->inst_save->tag > tag) { /* Check for tag > tagof our valid instructions */ tmpinst = proc->inst_save; if (tmpinst->code.wpchange && !(tmpinst->strucdep > 0 && tmpinst->strucdep < 5) && tmpinst->exception_code != WINOVERFLOW && tmpinst->exception_code != WINUNDERFLOW && tmpinst->exception_code != CLEANWINDOW) { if (tmpinst->code.wpchange != WPC_FLUSHW) { /* unupdate CWP that has been changed */ proc->cwp = (proc->cwp + NUM_WINS - tmpinst->code.wpchange) % NUM_WINS; proc->cansave += tmpinst->code.wpchange; proc->canrestore -= tmpinst->code.wpchange; } } if (tmpinst->strucdep > 0 && tmpinst->strucdep < 7) { // renaming only partially done FlushTagConverter(tmpinst->tag, proc); DeleteInstance(tmpinst, proc); proc->inst_save = NULL; } else tmpinst->tag = -1; } return (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -