📄 exec.cc
字号:
(proc->UnitsFree[inst->unit_type])--; // uMEM doesn't use this here if (STALL_ON_FULL) { proc->active_instr[inst->unit_type]--; inst->issuetime = proc->curr_cycle; } } //------------------------------------------------------------------------- /// issue memory instruction else { // do it based on uADDR instead proc->ReadyQueues[uADDR].Insert(insttagged); (proc->UnitsFree[uADDR])--; if (stat_sched) // uADDR is also statically scheduled { inst->addrissuetime = proc->curr_cycle; } }}/* * Simulate the time spent in execution;move instructions from the * ReadyQueues to the Running queues, and similarly, move functional * units off FreeingUnits. */void IssueQueues(ProcState * proc){ tagged_inst instt; instance *inst; UTYPE unit_type;#ifdef COREFILE if (proc->curr_cycle > DEBUG_TIME) fprintf(corefile, "Issuing cycle %d\n", proc->curr_cycle);#endif for (unit_type = UTYPE(0); unit_type < uMEM; unit_type = UTYPE(int(unit_type)+1)) { circq<tagged_inst> *q = &(proc->ReadyQueues[unit_type]); while (q->NumInQueue()) // we have already checked proc->UnitsFree[unit_type] { q->Delete(instt); if (!instt.ok()) { #ifdef COREFILE if (proc->curr_cycle > DEBUG_TIME) fprintf(corefile, "Nonmatching entry in ReadyQueue -- was %d, now %d\n", instt.inst_tag, instt.inst->tag);#endif LetOneUnitStalledGuyGo(proc, unit_type); continue; } inst = instt.inst; if (repeat[unit_type]) proc->FreeingUnits.insert(proc->curr_cycle + repeat[unit_type],unit_type); else (*(repfuncs[unit_type]))(inst,proc); if (latencies[unit_type]) // deterministic latency proc->Running.insert(proc->curr_cycle + latencies[unit_type], inst, inst->tag); else (*(latfuncs[unit_type]))(inst,proc); } }}/* * Move things from Running queues to Done heap, also issue instructions * for units that are freed up. Take off the heap of running instructions * that completed in time for the next cycle. Also free up the * appropriate units */void CompleteQueues(ProcState * proc){ long long cycle = proc->curr_cycle; UTYPE func_unit; instance *inst; long long inst_tag; while (proc->Running.num() != 0 && proc->Running.PeekMin() <= cycle) { proc->Running.GetMin(inst, inst_tag); // first check to see if it's been flushed if (inst_tag != inst->tag) { // it's been flushed #ifdef COREFILE if (proc->curr_cycle > DEBUG_TIME) fprintf(corefile, "Got nonmatching tag %d off Running\n", inst_tag);#endif continue; } if (inst->unit_type != uMEM) { (*(instr_func[inst->code.instruction]))(inst,proc);#if 0 #ifdef COREFILE if (inst->unit_type != uMEM || !IsStore(inst) || IsRMW(inst) ) { if (proc->curr_cycle > DEBUG_TIME) InstCompletionMessage(inst,proc); }#endif#endif proc->DoneHeap.insert(cycle, inst, inst->tag); } else { // if it's a uMEM, it must just be an address generation thing#ifdef COREFILE if (proc->curr_cycle > DEBUG_TIME) fprintf(corefile,"Address generated for tag %d\n",inst->tag);#endif Disambiguate(inst, proc); } } while (proc->FreeingUnits.num() != 0 && proc->FreeingUnits.PeekMin() <= cycle) { proc->FreeingUnits.GetMin(func_unit); LetOneUnitStalledGuyGo(proc, func_unit); }}/* * Updates the result registers/branch prediction tables that are changed * as a result of the instruction. */int update_cycle(ProcState * proc){ instance *inst; long long inst_tag; // Let us first check for the case when the branch was the last // instruction of the previous cycle, it may have completed // by now, so we need to look at this NOW! int over = 0; // Get everything corresponding to this cycle while (over != 1) { if ((proc->DoneHeap.num() == 0) || (proc->DoneHeap.PeekMin() > proc->curr_cycle)) return 0;#ifdef DEBUG if (proc->DoneHeap.GetMin(inst,inst_tag) != proc->curr_cycle) { // don't flag it otherwise, as that would just be a flush on // exception or some such.... if (inst->tag == inst_tag) {#ifdef COREFILE if (proc->curr_cycle > DEBUG_TIME) fprintf(corefile, "<decode.cc>Something is wrong! We have ignored some executions \for several cycles -- tag %d at %d!\n", inst->tag, proc->curr_cycle); #endif YS__errmsg(proc->proc_id / ARCH_cpus, " Ignored executions in %s\n", __FILE__); continue; } }#else proc->DoneHeap.GetMin(inst, inst_tag);#endif // if inst->tag != inst_tag, then it is an instruction that has // already been flushed out and we can ignore it if (inst->tag == inst_tag) {#ifdef COREFILE if (proc->curr_cycle > DEBUG_TIME) { fprintf(corefile, "INST %p - \n", inst); fprintf(corefile,"Marking tag %d as done\n", inst->tag); }#endif if (proc->stall_the_rest == inst->tag && !inst->branchdep && !proc->unpredbranch) unstall_the_rest(proc); // the instruction completed // Check if it is a branch instruction if (inst->code.cond_branch != 0 || inst->code.uncond_branch != 0) { if (inst->branchdep == 1) // used for unpredicted branches { // This is most probably an unconditional branch // This is an instruction because of which the rest of // the other instructions are stalled and waiting, // lets update the pc if (inst->code.annul || inst->tag+1 != proc->instruction_count) // no delay slot remaining { proc->pc = inst->newpc; // This would have been filled // at execution time proc->npc = proc->pc + SIZE_OF_SPARC_INSTRUCTION; } else // delay slot still waiting to issue { proc->pc = inst->pc+SIZE_OF_SPARC_INSTRUCTION; // should have already been set this way proc->npc = inst->newpc; } // Note: if there was a delay slot, we also need to fill in // that one's NPC value... HandleUnPredicted(inst, proc); proc->unpredbranch = 0; // go back to normal fetching, etc if (proc->stall_the_rest == inst->tag || proc->type_of_stall_rest == eBADBR) { // either on this tag itself or on the delay slot // but for this tag unstall_the_rest(proc); } } // Check if we did any fancy predictions if (inst->code.uncond_branch != 2 && inst->code.uncond_branch != 3 && inst->branchdep != 1) { // YES if (inst->mispredicted == 0) {#ifdef COREFILE if (proc->curr_cycle > DEBUG_TIME) fprintf(corefile, "Predicted branch correctly - tag %d\n", inst->tag);#endif // No error in our prediction // Delete the corresponding mapper table GoodPrediction(inst, proc); // Go on and graduate it as usual } else { // Error in prediction #ifdef COREFILE if (proc->curr_cycle > DEBUG_TIME) fprintf(corefile, "Mispredicted %s - tag %d\n", (inst->code.uncond_branch == 4)? "return" : "branch", inst->tag);#endif int origpred = inst->taken; // Now set pc and npc appropriately if (proc->copymappernext && inst->tag+1==proc->instruction_count) { // in this case, we have decoded and // completed the branch, but still haven't // gotten the delay slot instruction. So, we // need to set pc for the delay slot and set // npc for the branch target proc->pc = inst->pc+SIZE_OF_SPARC_INSTRUCTION; // this should have already been that // way, but anyway... proc->npc = inst->newpc; } else if (inst->code.annul && inst->code.cond_branch && !origpred) { // In this case, we had originally predicted // an annulled branch to be not-taken, but // it ended up being taken. In this case, // the upcoming pc needs to go to the delay // slot, while the npc needs to point to the // branch target proc->pc = inst->pc + SIZE_OF_SPARC_INSTRUCTION; proc->npc = inst->newpc; } else { // in any other circumstance, we go to the // branch target and continue execution from // there proc->pc = inst->newpc; proc->npc = proc->pc+SIZE_OF_SPARC_INSTRUCTION; } BadPrediction(inst, proc); // continue; // return (0); } } // End of if for predictions } //----------------------------------------------------------------- // do not clear dependencies if instruction triggers a hard // exception since the exception handler might change global state if ((inst->exception_code != OK) && (inst->exception_code != SOFT_LIMBO) && (inst->exception_code != SOFT_SL_COHE) && (inst->exception_code != SOFT_SL_REPL)) { proc->active_list.mark_done_in_active_list(inst->tag, inst->exception_code, proc->curr_cycle); continue; } //------------------------------------------------------------------- // Look at destination registers // make them not busy // Update physical register file if (inst->code.rd_regtype == REG_INT || inst->code.rd_regtype == REG_INT64) { if (inst->prd != 0) proc->phy_int_reg_file[inst->prd] = inst->rdvali; proc->intregbusy[inst->prd] = 0; proc->dist_stallq_int[inst->prd].ClearAll(proc); } else if (inst->code.rd_regtype == REG_FP) { proc->phy_fp_reg_file[inst->prd] = inst->rdvalf; proc->fpregbusy[inst->prd] = 0; proc->dist_stallq_fp[inst->prd].ClearAll(proc); proc->phy_int_reg_file[proc->intmapper[arch_to_log(proc, proc->cwp, STATE_FPRS)]] |= inst->code.rd >= 32 ? FPRS_DU : FPRS_DL; } else if (inst->code.rd_regtype == REG_FPHALF) { proc->phy_fp_reg_file[inst->prd] = inst->rsdvalf; float *address = (float *) (&proc->phy_fp_reg_file[inst->prd]);#ifdef ENDIAN_SWAP if (!(inst->code.rd & 1)) // the odd half address += 1;#else if (inst->code.rd & 1) // the odd half address += 1;#endif *address = inst->rdvalfh; proc->fpregbusy[inst->prd] = 0; proc->dist_stallq_fp[inst->prd].ClearAll(proc); proc->phy_int_reg_file[proc->intmapper[arch_to_log(proc, proc->cwp, STATE_FPRS)]] |= FPRS_DL; } else if (inst->code.rd_regtype == REG_INTPAIR) { 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); } // 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); // Update active list to show done and exception proc->active_list.mark_done_in_active_list(inst->tag, inst->exception_code, proc->curr_cycle); } else // the instruction has already been killed in some way { #ifdef COREFILE if (proc->curr_cycle > DEBUG_TIME) fprintf(corefile,"Got nonmatching tag %d off Doneheap\n",inst_tag);#endif } } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -