📄 exec.cc
字号:
int dests = 1; if (code.wpchange != WPC_NONE) { if (code.wpchange == WPC_SAVE) { if (proc->cansave) { if (proc->cleanwin - proc->canrestore != 0) win_num = unsigned (win_num + 1) % NUM_WINS; else { exception_code = CLEANWINDOW; dests = 0; lrd = lrcc = 0; strucdep = 2; } } else { // SAVE EXCEPTION. Do not let this instruction act properly. exception_code = WINOVERFLOW; dests = 0; lrd = lrcc = 0; strucdep = 2; } } else if (code.wpchange == WPC_RESTORE) { if (proc->canrestore) win_num = unsigned(win_num + NUM_WINS - 1) % NUM_WINS; else { // RESTORE EXCEPTION. exception_code = WINUNDERFLOW; dests = 0; lrd = lrcc = 0; strucdep = 2; } } else if ((code.wpchange == WPC_FLUSHW) && (proc->cansave != NUM_WINS-2)) { exception_code = WINOVERFLOW; dests = 0; lrd = lrcc = 0; strucdep = 2; } } if (dests) { // ALWAYS, except for win exceptions /* Convert the destination condition code register */ lrcc = arch_to_log(proc, win_num, code.rcc); /* Convert the Destination Register */ if (code.rd_regtype == REG_FP || code.rd_regtype == REG_FPHALF) { lrd = code.rd; strucdep = 1; /* To go to the right place in check_dependencies */ } else { lrd = arch_to_log(proc, win_num, code.rd); strucdep = 2; /* To go to the right place in check_dependencies */ } } /***************************************************************/ /******************* Memory barrier instructions ***************/ /***************************************************************/#ifndef STORE_ORDERING if (code.instruction == iMEMBAR && code.rs1 == STATE_MEMBAR) { // decode a membar and put it in its queue MembarInfo mb; mb.tag = tag; mb.SS = (code.aux2 & MB_StoreStore) != 0; mb.LS = (code.aux2 & MB_LoadStore) != 0; mb.SL = (code.aux2 & MB_StoreLoad) != 0; mb.LL = (code.aux2 & MB_LoadLoad) != 0; mb.MEMISSUE = (code.aux1 & MB_MEMISSUE) != 0; mb.SYNC = (code.aux1 & MB_SYNC) != 0; ComputeMembarInfo(proc, mb); proc->membar_tags.Insert(mb); }#endif // Check if we are a delay slot if (proc->copymappernext == 1) { /* There is a message for me by the previous branch to take care of copying the shadow mapping, Let me store this information. */ branchdep = 2; proc->copymappernext = 0; /* We don't want the next instruction to do the same thing */ } pc = proc->pc; npc = proc->npc; int tmppc = proc->pc; /* We need this to check if we are having a jump in the instruction addressing */ // Check if we are getting into a branch instruction. At the end of this // and the next stage, we would have got the pc and npc for the next // instruction, and also identified if there are any branch dependencies if (code.cond_branch || code.uncond_branch) decode_branch_instruction(&code, this, proc); else { /* For all non control transfer instructions */ proc->pc = proc->npc; proc->npc = proc->pc + SIZE_OF_SPARC_INSTRUCTION; } if ((proc->pc != tmppc + SIZE_OF_SPARC_INSTRUCTION && proc->pc != tmppc + 2 * SIZE_OF_SPARC_INSTRUCTION) && !proc->stall_the_rest) { // not taken branch with no DELAYs /* We are doing a jump at this stage to a different portion of the address space, next fetch should begin only in the next cycle, so stall the rest of fetches this cycle */ proc->stall_the_rest = -1; proc->type_of_stall_rest = eBR; } // Note that if we are starting a new cycle, this will get reset anyway, so // we needn't bother about this instruction being the last one of a cycle! return (0);}/*=========================================================================== * check_dependencies() implements the dependecy checking logic of the * processor. */int check_dependencies(instance * inst, ProcState * proc){ short next_free_phys_reg = 0; proc->intmapper[ZEROREG] = 0; proc->intregbusy[proc->intmapper[ZEROREG]] = 0; // NOTE: INT_PAIR takes the standard INT route except that it maps // the second dest register where other instructions would map // "rcc". This is OK in the SPARC since the only instructions (LDD, // LDDA) with an INT_PAIR destination do not have a CC destination // in stat_sched, addr. gen is also lumped in with these if (STALL_ON_FULL && inst->strucdep) { if (stat_sched || (proc->active_instr[inst->unit_type] >= proc->max_active_instr[inst->unit_type])) { // Make sure there's space in the issue queue before // even trying to get renaming registers, etc. proc->stall_the_rest = inst->tag; proc->type_of_stall_rest = eISSUEQFULL; return 11; } } /*************************************/ /* Check for structural stalls first */ /*************************************/ if (inst->strucdep != 0) { switch(inst->strucdep) { case 1: // FP destination register // No free memory for rd fp next_free_phys_reg = proc->free_fp_list->getfreereg(); if (next_free_phys_reg == -1) { proc->stall_the_rest = inst->tag; proc->type_of_stall_rest = eRENAME; inst->strucdep = 1; return (1); } inst->prd = next_free_phys_reg; // Note: no break here, we have to do the next step too case 3: // Copy old mapping to active list if (proc->active_list.NumEntries() == proc->max_active_list) { // No space in active list for fp inst->strucdep = 1; proc->free_fp_list->addfreereg(inst->prd); inst->prd = 0; proc->stall_the_rest = inst->tag; proc->type_of_stall_rest = eNOEFF_LOSS; return (3); } // NOTE: This code is used for both FP and FPHALF if (inst->code.rd_regtype == REG_FP) proc->active_list.add_to_active_list(inst, inst->lrd, proc->fpmapper[inst->lrd], REG_FP, proc); else // FPHALF proc->active_list.add_to_active_list(inst, unsigned(inst->lrd)&~1U, proc->fpmapper[unsigned(inst->lrd)&~1U], REG_FP,proc); // NOW, change the mapper to point to the new mapping proc->cwp = inst->win_num; if (((inst->code.wpchange == WPC_SAVE) || (inst->code.wpchange == WPC_RESTORE)) && (inst->exception_code != WINOVERFLOW) && (inst->exception_code != WINUNDERFLOW)) { proc->cansave -= inst->code.wpchange; proc->canrestore += inst->code.wpchange; #ifdef COREFILE if (YS__Simtime > DEBUG_TIME) fprintf(corefile, "Changing cwp. Now CANSAVE %d, CANRESTORE %d\n", proc->cansave, proc->canrestore);#endif } if (inst->code.rd_regtype == REG_FP) proc->fpmapper[inst->lrd] = inst->prd; else // REG_FPHALF proc->fpmapper[unsigned(inst->lrd)&~1U] = inst->prd; // Update busy register table proc->fpregbusy[inst->prd] = 1; inst->strucdep = 5; break; case 2: // Int destination register if (inst->lrd == ZEROREG) { inst->strucdep = 4; inst->prd = proc->intmapper[ZEROREG]; } else { // No free memory for rd int next_free_phys_reg = proc->free_int_list->getfreereg(); if (next_free_phys_reg == -1) { proc->stall_the_rest = inst->tag; proc->type_of_stall_rest = eRENAME; inst->strucdep = 2; return (2); } inst->prd = next_free_phys_reg; // Note: no break } case 4: // Copy old mapping to active list if (proc->active_list.NumEntries() == proc->max_active_list) { if (inst->prd != proc->intmapper[ZEROREG]) { inst->strucdep = 2; proc->free_int_list->addfreereg(inst->prd); inst->prd = proc->intmapper[ZEROREG]; } proc->stall_the_rest = inst->tag; proc->type_of_stall_rest = eNOEFF_LOSS; return (4); } proc->active_list.add_to_active_list(inst, inst->lrd, proc->intmapper[inst->lrd], REG_INT, proc); // NOW, change the mapper to point to the new mapping proc->cwp = inst->win_num; if (((inst->code.wpchange == WPC_SAVE) || (inst->code.wpchange == WPC_RESTORE)) && (inst->exception_code != WINOVERFLOW) && (inst->exception_code != WINUNDERFLOW)) { proc->cansave -= inst->code.wpchange; proc->canrestore += inst->code.wpchange;#ifdef COREFILE if (YS__Simtime > DEBUG_TIME) fprintf(corefile, "Changing cwp. Now CANSAVE %d, CANRESTORE %d\n", proc->cansave, proc->canrestore);#endif } proc->intmapper[inst->lrd] = inst->prd; // Update busy register table if (inst->prd != proc->intmapper[ZEROREG]) proc->intregbusy[inst->prd] = 1; inst->strucdep = 5; break ; default: break; } switch(inst->strucdep) { case 5: if (inst->code.rd_regtype == REG_INTPAIR) { // in this case, we need to map the second register // of the pair rather than the cc register inst->prcc = proc->intmapper[ZEROREG]; // cc not used if (inst->code.rd & 1) // odd destination register { inst->exception_code = ILLEGAL; inst->prdp = 0; } else { next_free_phys_reg = proc->free_int_list->getfreereg(); if (next_free_phys_reg == -1) { proc->stall_the_rest = inst->tag; proc->type_of_stall_rest = eRENAME; inst->strucdep = 5; return (5); } inst->prdp = next_free_phys_reg; } // No break here as we have to do the next part anyway } else { inst->prdp = proc->intmapper[ZEROREG]; // pair not used if (inst->lrcc == ZEROREG) { inst->strucdep = 6; inst->prcc = proc->intmapper[ZEROREG]; } else { // rcc no free list register next_free_phys_reg = proc->free_int_list->getfreereg(); if (next_free_phys_reg == -1) { proc->stall_the_rest = inst->tag; proc->type_of_stall_rest = eRENAME; inst->strucdep = 5; return (5); } inst->prcc = next_free_phys_reg; // No break here as we have to do the next part anyway } } case 6: // active list full#ifdef DEBUG // Copy old mapping to active list if (proc->active_list.NumEntries() == proc->max_active_list) { // THIS CASE SHOULD NEVER HAPPEN SINCE ACTIVE LIST IS IN PAIRS YS__errmsg(proc->proc_id / ARCH_cpus, "Tag %lld: Active list full in case 6 -- that should never happen.", inst->tag); inst->strucdep = 6; proc->stall_the_rest = inst->tag; // rest of the instructions should // not be decoded proc->type_of_stall_rest = eNOEFF_LOSS; return (6); }#endif if (inst->code.rd_regtype == REG_INTPAIR) { proc->active_list.add_to_active_list(inst, inst->lrd + 1, proc->intmapper[inst->lrd + 1], REG_INT, proc); // NOW, change the mapper to point to the new mapping proc->intmapper[inst->lrd+1] = inst->prdp; // Update busy register table proc->intregbusy[inst->prdp] = 1; } else { proc->active_list.add_to_active_list(inst, inst->lrcc, proc->intmapper[inst->lrcc], REG_INT, proc); // NOW, change the mapper to point to the new mapping proc->intmapper[inst->lrcc] = inst->prcc; // Update busy register table if (inst->prcc != proc->intmapper[ZEROREG]) proc->intregbusy[inst->prcc] = 1; } proc->stalledeff--; // it made it into active list, so it's // no longer an eff problem! #ifdef COREFILE if (proc->stalledeff < 0) YS__errmsg(proc->proc_id / ARCH_cpus, "STALLED EFFICIENCY DROPS BELOW 0\n");#endif inst->strucdep = (inst->unit_type == uMEM) ? 10 : 0; break; default : break; } } //------------------------------------------------------------------------- // Check for branch dependencies here // If branchdep = 1, then that means we do not know what to // fetch next(maybe other than the delay slot, things will // stall automatically after the branch as the next pc will // be -1 till this gets done, so nothing we need to do.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -