⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ms.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
				/* reg and see if it is now free.	*/			rs->reg_status &= ~REG_IN_WIN;			STX->reg_excuse[reg_ix] = ST_NO_EXCUSE;			STX->new_excuse[reg_ix] = ST_NO_EXCUSE;			CheckRegFree (STX, rs, reg_ix);				/* Turn off dependent flags of inst's	*/				/* waiting for this result.		*/			for (dwi = 0; dwi < STX->iwin_index2[inum]; dwi++)				{				inum2 = STX->iwin_dep2 [inum] [dwi];				STX->iwin_flags [inum2] &= ~IWIN_DEP2;				CheckInstAvail (STX, inum2);				}			for (dwi = 0; dwi < STX->iwin_index3[inum]; dwi++)				{				inum2 = STX->iwin_dep3 [inum] [dwi];				STX->iwin_flags [inum2] &= ~IWIN_DEP3;				CheckInstAvail (STX, inum2);				}			}			/* Then release this instruction slot.		*/		free_inst (STX, inum);		}	else		/* Otherwise, put it back on the queue for next cycle	*/		{		Add_to_worklist (STX, 1, reg_writeback, ix);		}	}void reg0_writeback (void *st, void *ix)       {       STX->regs[0] = 0;  /* Keep R0 zero */       free_inst (STX, (int) ix);       }	/*	 *  free_inst  -  Free up instruction slot in instruction window	 *	 *	For the precise interrupts model, just set a flag to	 *	indicate that the instruction can be freed.	 */void free_inst (struct s_cpu_state *st, int inum)	{	int	reg_ix;	REGSTAT	*rs;	INST	*ip;#ifdef DEBUG_CHECKS	if (!(st->iwin_flags [inum] & IWIN_BUSY))		{		fprintf (stderr, "Error: instruction slot already free\r\n");		ms_break (st, NULL, "ERR");		}#ifdef PRECISE	if (st->iwin_flags [inum] & IWIN_FREED)		{		fprintf (stderr, "Error: instruction slot already free\r\n");		ms_break (st, NULL, "ERR"); 		}#endif /* PRECISE *//* These checks are somewhat expensive.  Comment out for now:	{	int	i, pri;	for (i=0, pri=st->iwin_head_ldst; (i<10) && (pri >= 0);					i++, pri = st->iwin_ldst [pri])		{		if (pri == inum)			{			fprintf (stderr,				"Error: freed instruction still in use\r\n");			ms_break (st, NULL, "ERR");			}		}	for (i=0, pri=st->iwin_headpri; (i<10) && (pri >= 0);					i++, pri = st->iwin_pri [pri])		{		if (pri == inum)			{			fprintf (stderr,				"Error: freed instruction still in use\r\n");			ms_break (st, NULL, "ERR");			}		}	for (i=0, pri=st->iwin_next_avail; (i<10) && (pri >= 0);					i++, pri = st->iwin_avail_list [pri])		{		if (pri == inum)			{			fprintf (stderr,				"Error: freed instruction still in use\r\n");			ms_break (st, NULL, "ERR");			}		}	for (i=0, pri=st->iwin_nextfree; (i<10) && (pri >= 0);					i++, pri = st->iwin_freelist [pri])		{		if (pri == inum)			{			fprintf (stderr,			    "Error: Error: instruction slot already free\r\n");			ms_break (st, NULL, "ERR");			}		}	}*/#endif /* DEBUG_CHECKS */#ifdef PRECISE	st->iwin_flags [inum] |= IWIN_FREED;#else	UnthreadInst (st, inum);#endif		/* Decrement reference counts of source		*/		/* registers for this instruction.		*/	ip = &st->iwin [inum];	if (ip->r2 > 0)		{		reg_ix = ip->r2 >> 1;		rs = &st->reg_rstat [reg_ix];		rs->reg_ref--;		CheckRegFree (st, rs, reg_ix);		}	if (ip->r3 > 0)		{		reg_ix = ip->r3 >> 1;		rs = &st->reg_rstat [reg_ix];		rs->reg_ref--;		CheckRegFree (st, rs, reg_ix);		}	}#ifndef INLINE	/*	 *  UnthreadInst  -  Remove instruction from its thread and	 *	put it back on the free list.	 */void UnthreadInst (struct s_cpu_state *st, int inum)	{	int	br_node;		/* Remove from the instruction chain of its thread	*/	br_node = st->iwin_br_node [inum];	if (br_node >= 0)		{		int	tmpi;		BrTREE	*br;		br = &st->branch_tree [br_node];		if ((tmpi = st->iwin_bthread [inum]) >= 0)			st->iwin_thread [tmpi] = st->iwin_thread [inum];		else			br->iwin_head_th = st->iwin_thread [inum];		if ((tmpi = st->iwin_thread [inum]) >= 0)			st->iwin_bthread [tmpi] = st->iwin_bthread [inum];		else			br->iwin_tail_th = st->iwin_bthread [inum];		}		/* Put instruction back on free list	*/	st->iwin_freelist [inum] = st->iwin_nextfree;	st->iwin_nextfree = inum;	st->iwin_flags [inum] = 0;	st->iwin_index2 [inum] = 0;	st->iwin_index3 [inum] = 0;	}	/*	 *  AcquireRegMap  -  Mark physical register mapped, and track	 *			number of times it is mapped.	 */void AcquireRegMap (REGSTAT *rs, THREAD *th, int lreg)	{	rs->reg_nmap++;	rs->reg_status |= REG_MAPPED;	if ((rs->reg_status & REG_CLAIMED) &&	    (th->half_def[lreg >> 1] & REGNAME_CLAIM))		rs->reg_nclaims++;	}	/*	 *  ReleaseRegMap  -  Decrement map count for register and mark	 *			it unmapped when the count reaches 0.	 */void ReleaseRegMap (struct s_cpu_state *st, THREAD *th, int reg_ix, int lreg)	{	int	lreg_ix;	REGSTAT	*rs;	rs = &st->reg_rstat[reg_ix];	rs->reg_nmap--;	if (rs->reg_nmap == 0)		{		rs->reg_status &= ~REG_MAPPED;		CheckRegFree (st, rs, reg_ix);		}	lreg_ix = lreg>>1;	if ((rs->reg_status & REG_CLAIMED) &&	    (th->half_def[lreg_ix] & REGNAME_CLAIM))		{		rs->reg_nclaims--;		CheckRegFree (st, rs, reg_ix);		if ((rs->reg_status & REG_CLAIMED) == 0)			th->half_def[lreg_ix] &= ~REGNAME_CLAIM;		}	}	/*	 *  CheckRegFree  -  Update register state	 *	 *  For normal registers, they become free when the number of	 *  references drops to zero, and there is no other reason to	 *  stay busy (i.e. they aren't still mapped and aren't in the	 *  instruction window).	 *	 *  In the PRECISE case, when the writer of a register graduates,	 *  the prior name for that register is available.  This is	 *  indicated by setting the REG_FREED flag.	 *	 *  For special registers, they stay mapped all the time, so	 *  just check if they are still in the instruction window.	 *	 *  For claimed registers (the other half of double precision	 *  registers), unclaim them if writeback has happened, the	 *  number of claims is zero, and the number of references	 *  is zero.  This guarantees that a subsequent claimant can	 *  write to the register without interfering with any thread	 *  relying on a prior value in that register.	 *	 *  The reg number for this routine has already been divided by 2	 */void CheckRegFree (struct s_cpu_state *st, REGSTAT *rs, int reg_ix)	{	if ((rs->reg_status & REG_CLAIMED) && (rs->reg_nclaims <= 0) &&            (rs->reg_ref <= 0) && ((rs->reg_status & REG_IN_WIN) == 0) )		rs->reg_status &= ~REG_CLAIMED;#ifdef PRECISE	if (rs->reg_status & REG_FREED)		{		if (rs->reg_status & REG_MAPPED)			rs->reg_status = REG_MAPPED;		else			{			rs->reg_status = 0;			st->reg_freelist [reg_ix] = st->reg_nextfree;			st->reg_nextfree = reg_ix;			}		}	if (preg_is_special (reg_ix) && ((rs->reg_status &			  (REG_BUSY | REG_IN_WIN | REG_MAPPED | REG_DMAP))						== (REG_BUSY + REG_MAPPED)) )			rs->reg_status = REG_MAPPED;#else	if ((rs->reg_nclaims <= 0) && (rs->reg_ref <= 0) &&	    ((rs->reg_status & REG_IN_WIN) == 0) )		{		if ((rs->reg_status &		    (REG_BUSY | REG_IN_WIN | REG_MAPPED | REG_DMAP))						== REG_BUSY)			{			rs->reg_status = 0;			st->reg_freelist [reg_ix] = st->reg_nextfree;			st->reg_nextfree = reg_ix;			}		else		if (preg_is_special (reg_ix) && ((rs->reg_status &			  (REG_BUSY | REG_IN_WIN | REG_MAPPED | REG_DMAP))						== (REG_BUSY + REG_MAPPED)) )			rs->reg_status = REG_MAPPED;		}#endif /* PRECISE */	}	/*	 *  CheckInstAvail  -  Check if the instruction is now available for	 *			execution	 *	 *	Inum is the index of the instruction to check	 */void CheckInstAvail (struct s_cpu_state *st, int inum)	{#ifdef DEBUG_CHECKS	if (!(st->iwin_flags [inum] & IWIN_BUSY))		{		fprintf (stderr, "Instruction slot not in use\r\n");		ms_break (st, NULL, "ERR");		}#endif		/* Check if the instruction is unencumbered	*/	if (st->iwin_flags [inum] &(IWIN_DEP2 | IWIN_DEP3 | IWIN_FLUSH | IWIN_AVAIL | IWIN_LDST_DEP | IWIN_BRDLY))		return;		/* Don't allow speculative writes to special registers	*/	if ((st->iwin_flags [inum] & (IWIN_SPEC | IWIN_CTL)) ==						(IWIN_SPEC | IWIN_CTL))		return;		/* Then mark it available and add it to the available	*/		/* list.						*/	st->iwin_flags [inum] |= IWIN_AVAIL;#ifdef PRIORITIZE_AVAIL_LIST		/* Insert the instruction into the available list in	*/		/* priority order.					*/	pri = st->iwin_headpri;	avail = st->iwin_next_avail;	last_avail = -1;	while (pri != inum)		{#ifdef DEBUG_CHECKS		if (pri < 0)			{			fprintf (stderr,		  "Error - Available instruction not in priority list\r\n");			ms_break (st, NULL, "ERR");			}#endif		if (pri == avail)			{			last_avail = avail;			avail = st->iwin_avail_list [avail];			}		pri = st->iwin_pri [pri];		}	st->iwin_avail_list [inum] = avail;	if (last_avail < 0)		st->iwin_next_avail = inum;	else		st->iwin_avail_list [last_avail] = inum;#else		/* Otherwise just add newly available instructions	*/		/* to the tail of the available list.			*/	if (st->iwin_next_avail >= 0)		{		st->iwin_avail_list [st->iwin_last_avail] = inum;		st->iwin_last_avail = inum;		}	else		{		st->iwin_next_avail = inum;		st->iwin_last_avail = inum;		}	st->iwin_avail_list [inum] = -1;#endif	}#endif /* !INLINE */	/*	 *  ms_issue  -  ISSUE instructions that are ready to go.	 *		 Chase down the priority chain, issuing the first	 *		 available instructions.	 */void ms_issue (struct s_cpu_state *st)	{	int	pri, prev_pri, reg_ix, ex_count, issues;		/* If issue is stalled, skip it and retry execution.	*/		/* Pending interrupts stall issue.			*/	if (st->exception_pending)		{		AddToStat (ST_ISSUE_STALLED, ISSUE_WIDTH);		AddToStat (ST_EXCEPT, ISSUE_WIDTH);		return;		}	if (st->stall_issue)		{		AddToStat (ST_ISSUE_STALLED, ISSUE_WIDTH);		AddToStat (st->stall_type, ISSUE_WIDTH);#ifdef DEBUG_CHECKS		if (st->stall_type == ST_NO_EXCUSE)			{			fprintf (stderr,  "No excuse stall type\r\n");			ms_break (st, NULL, "ERR");			}#endif		return;		}	AddToStat (ST_ISSUE_TRIED, ISSUE_WIDTH);	for (issues=0, ex_count=0;	     (issues<ISSUE_WIDTH) && (ex_count<(2*ISSUE_WIDTH)); )		{			/* Get next available instruction	*/		pri = st->iwin_next_avail;		prev_pri = -1;		while (pri >= 0)		    {		    if ((st->iwin_flags [pri] & IWIN_LDST) && (!PhaseA (pri)))			{				/* If it's a memory operation, make	*/				/* sure that there is room for it.	*/			if (ldst_buffer_reserve (st) >= 0) break;				/* No room, proceed to next instruction	*/			prev_pri = pri;			pri = st->iwin_avail_list [pri];			continue;			}		    break;		    }		if (pri < 0) break;		if (pri == st->iwin_next_avail)		    st->iwin_next_avail = st->iwin_avail_list [pri];		else		    st->iwin_avail_list [prev_pri] = st->iwin_avail_list [pri];		if (pri == st->iwin_last_avail)		    st->iwin_last_avail = prev_pri;#ifdef DEBUG_CHECKS		if (!(st->iwin_flags [pri] & IWIN_BUSY))			{			fprintf (stderr,			  "Inconsistent instruction window state\r\n");			ms_break (st, NULL, "ERR");			}#endif			/* Then issue to execution unit		*/		st->ex [ex_count++] = pri;		st->iwin_flags [pri] |= IWIN_ISSUED;			/* and remove from priority chain,	*/			/* except for Phase A of loads/stores.	*/		if (st->iwin_flags [pri] & IWIN_LDST)		    {		    if (!PhaseA (pri))			{#ifdef PREF_DEBUG               {                  INST *ip = &st->iwin [pri];                  if (is_store(ip->op))                     CPUPrint("CPU %d ISSUE Store addr = %08x cycle = %d\n",                               CPUNUM(st), Ireg(ip->r2) + ip->imm, st->work_cycle);                  else if (is_load(ip->op))                     CPUPrint("CPU %d ISSUE Load addr = %08x cycle = %d\n",                               CPUNUM(st), Ireg(ip->r2) + ip->imm, st->work_cycle);                  else if (is_prefetch(ip->op))                     CPUPrint("CPU %d ISSUE Prefetch addr = %08x cycle = %d\n",                               CPUNUM(st), Ireg(ip->r2) + ip->imm, st->work_cycle);               }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -