📄 ms_grad.c
字号:
AddToStat (ST_GRAD_EMPTYSTALL, GRAD_WIDTH-i); } } else if ((st->iwin_flags[inum] & IWIN_LDST) && (st->iwin_flags[inum] & IWIN_LDSTBUF) && (st->inum2ldst[inum]->ls->status & LS_ST_STALL)) { record_ldst_stall(st, inum, GRAD_WIDTH-i); if (st->iwin_flags[inum] & IWIN_STORE) { AddToStat (ST_GRAD_STSTALL, GRAD_WIDTH-i); } else { AddToStat (ST_GRAD_LDSTALL, GRAD_WIDTH-i); } } else { record_pipeline_stall(st, th->pc,GRAD_WIDTH-i); if (!(st->iwin_flags[inum] & IWIN_ISSUED)) { if (st->iwin_flags[inum] & IWIN_FLUSH) { AddToStat(ST_GRAD_FLUSHSTALL, GRAD_WIDTH-i); } else { AddToStat(ST_GRAD_ISSUESTALL, GRAD_WIDTH-i); } } else if (st->iwin_flags[inum] & IWIN_LDST) { AddToStat(ST_GRAD_PHASEASTALL, GRAD_WIDTH-i); } else { AddToStat(ST_GRAD_MISCSTALL, GRAD_WIDTH-i); } } break; /* Rest of instructions not eligible */ } /* for graduation, quit. */#endif /* PRECISE */ } /* * ms_grad_dequeue - Remove instruction from graduation queue * * Also update the status of the destination register and * put the instruction slot on the free list. */void ms_grad_dequeue (struct s_cpu_state *st, int inum) {#ifdef PRECISE int tmpi, regname, reg_ix; REGSTAT *rs; tmpi = st->iwin_bgrd [inum];#ifdef DEBUG_CHECKS if ((st->iwin_flags [inum] & IWIN_FREED) == 0) { fprintf (stderr, "Attempt to graduate a live instruction\r\n"); ms_break (st, NULL, "ERR"); } if ((inum != st->iwin_headgrad) || (tmpi >= 0)) { fprintf (stderr, "Out of order graduation\r\n"); ms_break (st, NULL, "ERR"); }#endif /* DEBUG_CHECKS */ if (tmpi >= 0) st->iwin_grad [tmpi] = st->iwin_grad [inum]; else st->iwin_headgrad = st->iwin_grad [inum]; if ((tmpi = st->iwin_grad [inum]) >= 0) st->iwin_bgrd [tmpi] = st->iwin_bgrd [inum]; else st->iwin_tailgrad = st->iwin_bgrd [inum]; regname = 0; if (st->iwin_flags [inum] & IWIN_DEFINE) { /* On graduation of a non-speculative redefinition of a */ /* register, the previous name for the register should */ /* be freed. */ if (st->iwin_br_node [inum] == 0) regname = st->grad.regnames [st->iwin_lr1 [inum]]; /* On graduation of a speculative redefinition of a */ /* register, the current name should be freed. */ else { regname = st->iwin [inum] .r1; /* If another instruction will complete this */ /* definition, then hold off on freeing the */ /* register until then. */ for ( tmpi = st->iwin_grad[inum]; (tmpi >= 0) && (st->iwin_flags[tmpi] & IWIN_SQUASH); tmpi = st->iwin_grad[tmpi] ) { if (st->iwin [tmpi] .r1 == (regname ^ 0x01)) { st->iwin_flags [tmpi] |= IWIN_DEFINE; regname = 0; break; } } } } if (regname > 0) { reg_ix = regname >> 1; rs = &st->reg_rstat [reg_ix]; rs->reg_status |= REG_FREED; CheckRegFree (st, rs, reg_ix); } UnthreadInst (st, inum);#endif /* PRECISE */ } /* * ms_grad_enqueue - Add instruction to graduation queue */void ms_grad_enqueue (struct s_cpu_state *st, int inum) {#ifdef PRECISE if (st->iwin_tailgrad >= 0) { st->iwin_grad [st->iwin_tailgrad] = inum; st->iwin_bgrd [inum] = st->iwin_tailgrad; st->iwin_grad [inum] = -1; st->iwin_tailgrad = inum; } else { st->iwin_headgrad = inum; st->iwin_tailgrad = inum; st->iwin_bgrd [inum] = -1; st->iwin_grad [inum] = -1; }#endif /* PRECISE */ }#ifdef MIPSY_MXSstatic int pipeline_empty (struct s_cpu_state *st); /* * ms_except - Check for exceptions, and handle them for MXS */void ms_except (struct s_cpu_state *st) { THREAD *th; int inum;/* Have we got an ITLB miss? Can recognize this when the graduation *//* queue is empty and the thread corresponding to the root of the *//* branch tree is stalled on an ITLB miss. */ inum = st->iwin_headgrad; if (inum < 0) { th = &st->threads [st->branch_tree [0].thread]; if ((!st->exception_pending) && th->stall_itlbmiss) { st->exception_pending = 1; st->except = th->except; IncStat(ST_EXCEPT_ITLB); } } else if (!st->exception_pending) { /* Check for the case of a ITLB miss in the delay slot of a * branch. */ th = &st->threads [st->branch_tree [0].thread]; if (th->stall_itlbmiss && (st->iwin_br_node[inum] == 0) && (st->iwin_flags[inum] & IWIN_BRANCH)) { st->exception_pending = 1; st->except = th->except; IncStat(ST_EXCEPT_ITLB); } } /* Is there an interrupt hanging around? If so, recognize it. */ if (!st->exception_pending && InterruptIsPending (st) && InstIsInterruptable(st)) { CPUState *P = (CPUState *) (st->mipsyPtr); RECORD_EXCEPTION(P, EXC_INT, E_VEC, 0, P->CP0[C0_TLBHI],P->CP0[C0_CTXT],P->CP0[C0_XCTXT]); st->exception_pending = 1; st->except = GetLastException (st); IncStat(ST_EXCEPT_INTR); } th = &st->grad; if (((CPUState *)(st->mipsyPtr))->switchToMIPSY && !st->exception_pending) { if ((st->grad.pc < (K2BASE + K2SIZE)) && (!(th->thread_st & TH_BRANCH)) ) { st->exception_pending = 1; st->except = SWITCH2MIPSY_EXCEPTION; } } if (st->exception_pending && pipeline_empty (st)) { RecordExceptionStats(st); HandleException(st, st->except, (th->thread_st & TH_BRANCH) );#ifdef PRINT_INST if (enable_eprint) { PrintException(st, st->except); }#endif st->exception_pending = 0; } else if (st->exception_pending) { IncStat(ST_EXCEPT_WAIT); } } /* * pipeline_empty - Return TRUE if there are no outstanding * operations in the pipeline. */static int pipeline_empty (struct s_cpu_state *st) { if ((st->ex_count > 0) || (st->work_head)) return (0); return (1); }static int InstIsInterruptable(struct s_cpu_state *st) { int inum = st->iwin_headgrad ; if (inum >= 0) { if (((st->iwin_flags[inum] & (IWIN_LDST|IWIN_UNCACHED|IWIN_LDSTBUF)) == (IWIN_LDST|IWIN_UNCACHED|IWIN_LDSTBUF)) && IsLoad(st->inum2ldst[inum]->ls->lstype) && st->inum2ldst[inum]->dataPtr) { return 0; /* Don't abort unfinished uncached reads */ } if (((st->iwin[inum].op == OPLDHACK) || (st->iwin[inum].op == OPSDHACK)) && (st->iwin_flags[inum] & IWIN_ISSUED)) { return 0; /* Handle ld/sd hack instruction */ } } return 1;} static void RecordExceptionStats(struct s_cpu_state *st) { int inum, inwin = 0, ldst = 0, squashed = 0; for (inum = st->iwin_headgrad; inum >= 0; inum = st->iwin_grad[inum]) { inwin++; if (st->iwin_flags[inum] & IWIN_LDST) ldst++; if (st->iwin_flags[inum] & IWIN_SQUASH) squashed++; } IncStat(ST_EXCEPT_TAKEN) if (st->except == COHERENCY_EXCEPTION) { IncStat(ST_EXCEPT_COHERENCY); AddToStat(ST_EXCEPT_COHER_INST, inwin); AddToStat(ST_EXCEPT_COHER_SQUASH, squashed); AddToStat(ST_EXCEPT_COHER_LDST, ldst); } else if (st->except == SWITCH2MIPSY_EXCEPTION) { IncStat(ST_EXCEPT_SWITCH); AddToStat(ST_EXCEPT_SWITCH_INST, inwin); AddToStat(ST_EXCEPT_SQUASH, squashed); AddToStat(ST_EXCEPT_LDST, ldst); } else { AddToStat(ST_EXCEPT_INST, inwin); AddToStat(ST_EXCEPT_SQUASH, squashed); AddToStat(ST_EXCEPT_LDST, ldst); } }#endif /* MIPSY_MXS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -