📄 ms.c
字号:
#endif ms_ldst_dequeue (st, pri); ms_pri_dequeue (st, pri); IncStat (ST_EXECUTED); issues++;#ifdef ONE_PHASE_LS /* Update store count and set flag to */ /* force update of load/store status. */ if (st->iwin_flags [pri] & IWIN_STORE) st->iwin_nstores--;#endif } else { /* Don't count Phase A as issue */ IncStat (ST_PHASE_A); } } else { ms_pri_dequeue (st, pri); IncStat (ST_EXECUTED); issues++; } } /* Special check for flush instructions (not issued */ /* until all preceeding instructions have issued). */ if (ex_count == 0) { /* If there is exactly one instruction in the */ /* buffer, and it is waiting for the window to */ /* flush, and it belongs to branch node 0 (=> */ /* it is no longer speculative), and it has no */ /* unresolved dependencies, then issue it. */ pri = st->iwin_headpri; if ((pri >= 0) && (st->iwin_flags [pri] & IWIN_FLUSH) && (pri == st->iwin_tailpri) &&#ifdef PRECISE (pri == st->iwin_headgrad) &&#endif (st->iwin_br_node [pri] == 0) && (!(st->iwin_flags [pri] & (IWIN_DEP2 | IWIN_DEP3))) ) { st->ex [ex_count++] = pri; st->iwin_flags [pri] |= IWIN_ISSUED; if (st->iwin_flags [pri] & IWIN_LDST) ms_ldst_dequeue (st, pri); ms_pri_dequeue (st, pri); IncStat (ST_EXECUTED); issues++; } } /* Update statistics of successful and unsuccessful */ /* instruction issue tries. */ for (pri = st->iwin_headpri; issues<ISSUE_WIDTH; pri = st->iwin_pri [pri] ) { if (pri < 0) { AddToStat (ST_IWIN_EMPTY, ISSUE_WIDTH-issues); break; } if (!(st->iwin_flags [pri] & IWIN_ISSUED) || (st->iwin_flags [pri] & IWIN_LDST_DEP)) { /* If it isn't issued because it */ /* depends on an inst still in the */ /* window, skip it. */ if (st->iwin_flags [pri] & IWIN_DEP2) { reg_ix = st->iwin [pri] .r2 >> 1; if (st->reg_excuse [reg_ix] == ST_NOT_ISSUED) continue; } if (st->iwin_flags [pri] & IWIN_DEP3) { reg_ix = st->iwin [pri] .r3 >> 1; if (st->reg_excuse [reg_ix] == ST_NOT_ISSUED) continue; } issues++; IncStat (ST_INST_STALLED); if (st->iwin_flags [pri] & IWIN_LDST_DEP) { IncStat (ST_LDST_DEP); } else if (st->iwin_flags [pri] & IWIN_DEP2) { IncStat (ST_REG_DEP); reg_ix = st->iwin [pri] .r2 >> 1; IncStat (st->reg_excuse [reg_ix]);#ifdef DEBUG_CHECKS if (st->reg_excuse [reg_ix] == ST_NO_EXCUSE) { fprintf (stderr, "Register absent without excuse\r\n"); ms_break (st, NULL, "ERR"); }#endif } else if (st->iwin_flags [pri] & IWIN_DEP3) { IncStat (ST_REG_DEP); reg_ix = st->iwin [pri] .r3 >> 1; IncStat (st->reg_excuse [reg_ix]);#ifdef DEBUG_CHECKS if (st->reg_excuse [reg_ix] == ST_NO_EXCUSE) { fprintf (stderr, "Register absent without excuse\r\n"); ms_break (st, NULL, "ERR"); }#endif } else if (st->iwin_flags [pri] & IWIN_FLUSH) { IncStat (ST_IWIN_FLUSH); } else if (st->iwin_flags [pri] & IWIN_BRDLY) { IncStat (ST_BR_DLY); } else if ((st->iwin_flags [pri] & (IWIN_SPEC | IWIN_CTL)) == (IWIN_SPEC | IWIN_CTL)) { IncStat (ST_SPEC_CTL); } else if (st->iwin_flags [pri] & IWIN_LDST) { if (ldst_buffer_reserve (st) >= 0) { ldst_buffer_release (st); IncStat (ST_NO_EXCUSE); } else { IncStat (ST_LDST_FULL); } } else { IncStat (ST_NO_EXCUSE);#ifdef DEBUG_CHECKS if ((ex_count<(2*ISSUE_WIDTH)) && (st->stall_type == ST_NO_EXCUSE)) { fprintf (stderr, "No excuse for unissued instruction\r\n"); ms_break (st, NULL, "ERR"); }#endif } } } st->ex_count = ex_count; } /* * ms_pri_dequeue - Remove instruction from priority queue */void ms_pri_dequeue (struct s_cpu_state *st, int pri) { int inum; st->iwin_ninst--; if ((inum = st->iwin_bpri [pri]) >= 0) st->iwin_pri [inum] = st->iwin_pri [pri]; else st->iwin_headpri = st->iwin_pri [pri]; if ((inum = st->iwin_pri [pri]) >= 0) st->iwin_bpri [inum] = st->iwin_bpri [pri]; else st->iwin_tailpri = st->iwin_bpri [pri]; } /* * ms_pri_enqueue - Add instruction to priority queue */void ms_pri_enqueue (struct s_cpu_state *st, int pri) { st->iwin_ninst++; if (st->iwin_tailpri >= 0) { st->iwin_pri [st->iwin_tailpri] = pri; st->iwin_bpri [pri] = st->iwin_tailpri; st->iwin_pri [pri] = -1; st->iwin_tailpri = pri; } else { st->iwin_headpri = pri; st->iwin_tailpri = pri; st->iwin_bpri [pri] = -1; st->iwin_pri [pri] = -1; } } /* * ms_ldst_dequeue - Remove instruction from load/store queue */void ms_ldst_dequeue (struct s_cpu_state *st, int inum) { int tmpi;#ifdef DEBUG_CHECKS st->iwin_nldst--; if (st->iwin_nldst < 0) { fprintf (stderr, "Underflow in load/store queue\r\n"); ms_break (st, NULL, "ERR"); }#endif if ((tmpi = st->iwin_bldst [inum]) >= 0) st->iwin_ldst [tmpi] = st->iwin_ldst [inum]; else st->iwin_head_ldst = st->iwin_ldst [inum]; if ((tmpi = st->iwin_ldst [inum]) >= 0) st->iwin_bldst [tmpi] = st->iwin_bldst [inum]; else st->iwin_tail_ldst = st->iwin_bldst [inum]; } /* * ms_ldst_enqueue - Add instruction to load/store queue */void ms_ldst_enqueue (struct s_cpu_state *st, int inum) {#ifdef DEBUG_CHECKS st->iwin_nldst++; if (st->iwin_nldst > IWIN_SIZE) { fprintf (stderr, "Overflow in load/store queue\r\n"); ms_break (st, NULL, "ERR"); }#endif st->iwin_flags [inum] |= IWIN_LDST; if (st->iwin_tail_ldst >= 0) { st->iwin_ldst [st->iwin_tail_ldst] = inum; st->iwin_bldst [inum] = st->iwin_tail_ldst; st->iwin_ldst [inum] = -1; st->iwin_tail_ldst = inum; } else { st->iwin_head_ldst = inum; st->iwin_tail_ldst = inum; st->iwin_bldst [inum] = -1; st->iwin_ldst [inum] = -1; } } /* * ms_execute - EXECUTE the instructions in the execution unit. */ void ms_execute (struct s_cpu_state *st) { INST *ip; BrTREE *br; THREAD *th; int exi, ex_count, inum; ex_count = st->ex_count; exi = (st->stall_issue ? st->stall_issue-1 : 0); for (; exi < ex_count; exi++) { st->stall_issue = 0; st->stall_type = ST_NO_EXCUSE; inum = st->ex [exi]; ip = &st->iwin [inum]; if (st->iwin_flags [inum] & IWIN_SQUASH) { if (st->iwin_flags [inum] & IWIN_LDST) { if (PhaseA(inum)) { ms_ldst_dequeue (st, inum); ms_pri_dequeue (st, inum); IncStat (ST_PRUNED); } else ldst_buffer_release (st); } free_spec_inst (st, inum); continue; } br = &st->branch_tree [st->iwin_br_node[inum]]; th = &st->threads [br->thread];#ifdef BREAKPOINT st->iwin_curi = inum;#endif if (PhaseA (inum)) { /* Special case for Phase A issue of */ /* load/store instructions. */ /* Do the address computation */#ifndef ONE_PHASE_LS st->iwin_addr [inum] = Ireg(ip->r2) + ip->imm; if (!is_prefetch(ip->op) && (ip->r1 >= 0)) st->reg_excuse[ip->r1>>1] = ST_PC_DLY;#ifdef MIPSY_MXS { PA paddr; uint tlbFlavor; Result ret; if (is_store(ip->op)) tlbFlavor = TLB_WRITING; else tlbFlavor = TLB_READING; if (is_prefetch(ip->op)) { ret = TranslateVirtualNoSideeffect((CPUState *)st->mipsyPtr, (VA) st->iwin_addr[inum], &paddr); if (ret != SUCCESS) st->iwin_paddr[inum] = (PA) -1; else st->iwin_paddr[inum] = paddr; st->iwin_flags [inum] |= (IWIN_ADDR_VALID | IWIN_LDST_DEP); st->iwin_flags [inum] &= ~IWIN_AVAIL; } else { void *bdoorAddr = 0; ret = TranslateVirtual((CPUState *)st->mipsyPtr, (VA) st->iwin_addr[inum], &paddr, &tlbFlavor, &bdoorAddr); if (ret != SUCCESS) { st->iwin_except [inum] = GetLastException(st); st->iwin_paddr[inum] = (PA) -1; st->iwin_flags [inum] |= (IWIN_TLBFAULT | IWIN_ADDR_VALID | IWIN_LDST_DEP); st->iwin_flags [inum] &= ~IWIN_AVAIL; } else { st->iwin_paddr[inum] = paddr; st->iwin_flags [inum] |= (IWIN_ADDR_VALID | IWIN_LDST_DEP); st->iwin_flags [inum] &= ~IWIN_AVAIL; if (tlbFlavor) { st->iwin_flags[inum] |= IWIN_UNCACHED; } } } }#else /* MIPSY_MXS */ st->iwin_paddr [inum] = st->iwin_addr [inum]; st->iwin_flags [inum] |= (IWIN_ADDR_VALID | IWIN_LDST_DEP); st->iwin_flags [inum] &= ~(IWIN_AVAIL | IWIN_ISSUED);#endif /* MIPSY_MXS */#endif /* !ONE_PHASE_LS */ } else { (*optab[ip->op])(st, ip, th); Ireg(0) = 0; /* Keep r0 == 0 */ /* If stalled, remember where. */ if (st->stall_issue) { st->stall_issue = exi+1; break; } /* Writeback reg if single cycle inst */ /* and free up instruction slot. */ /* No need or want to writeback faulted inst or * load/store instructions . */ if ((lat_tab [ip->op] <= 1) && !(st->iwin_flags[inum] & (IWIN_FAULT+IWIN_LDST))) { if (ip->r1 > 0) reg_writeback ((void *)st, (void *)ip->r1); else free_inst (st, inum); } } } if (exi == st->ex_count) st->ex_count = 0; }#ifdef BREAKPOINTvoid ms_break (struct s_cpu_state *st, INST *ip, char *typ) { int t, flagp, inum; int branch_node; BrTREE *br; THREAD *th; /* If no instruction specified for the breakpoint, then */ /* pick a recent instruction of some current thread. */ if (ip == NULL) { br = &st->branch_tree[0]; while (br->lchild >= 0) { if (st->branch_tree[br->lchild].iwin_tail_th >= 0) br = &st->branch_tree[br->lchild]; else break; } inum = br->iwin_tail_th; ip = &st->iwin[inum]; } else { inum = ip - st->iwin; branch_node = st->iwin_br_node [inum]; br = &st->branch_tree[branch_node]; } th = &st->threads[br->thread]; printf ("%s:", typ); printf ("% 7d%0.5d @0x%8.8x: ", st->work_ticks, st->work_cycle, th->debugpc); print_inst (stdout, ip); flagp = 0; if ((ip->r2 > 0) && (ip->r2 < MAX_VAR)) { t = th->regnames[ip->r2]; printf (" ["); print_reg_contents (stdout, ip->r2, &st->regs[t]); flagp = 1; } if ((ip->r3 > 0) && (ip->r3 < MAX_VAR)) { t = th->regnames[ip->r3]; if (flagp) printf (", "); else printf (" ["); print_reg_contents (stdout, ip->r3, &st->regs[t]); flagp = 1; } if (flagp) printf ("]\r\n"); else printf ("\r\n"); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -