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

📄 ms.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees *    of Leland Stanford Junior University. *  * This file is part of the SimOS distribution.  * See LICENSE file for terms of the license.  * */	/*	 *  ms  -  The simulator component of MXS.	 *	 *	Simulates a variety of architectures, from a statically	 *	scheduled R3000-like processor, to a dynamically	 *	scheduled processor with speculative execution.	 *	 *	Jim Bennett	 *	1993, 1994, 1995	 */#ifdef MIPSY_MXS#include <sys/types.h>#endif#include "ms.h"#ifdef MIPSY_MXS#include "cpu_state.h"#include "pcache.h"#include "cp0.h"#elseextern void ms_cache_callbacks (struct s_cpu_state *st);#endifint ms_writeback (struct s_cpu_state *st);void ms_issue (struct s_cpu_state *st);void ms_execute (struct s_cpu_state *st);void ms_ldst_dep (struct s_cpu_state *st);void ms_memory (struct s_cpu_state *st);void free_inst (struct s_cpu_state *st, int inum);#ifdef MIPSY_MXS	/*	 *  ms_cycle_once  -  Step the given processor forward by one	 *			cycle.	 */void ms_cycle_once (struct s_cpu_state *st)	{	WorkList *w;/* Main loop.  Each time around the loop we emulate a single CPU cycle,	*//* so this should be coded as tightly as possible.			*/		IncStat(ST_RUN_CYCLES);		st->work_cycle++;		if (st->work_cycle >= TICK_COUNT)			{		/* Every 100,000 cycles, reset	*/					/* the work clock and put out	*/					/* a tick mark.			*/			st->work_cycle -= TICK_COUNT;			st->work_ticks++;#if 0			if (st->icount == 			    ((CPUState *)(st->mipsyPtr))->numInstructions) {			    /* No isntruction graded since last time - trouble */        			    ms_break (st, NULL, "TIMOUT");			}			st->icount =  ((CPUState *)(st->mipsyPtr))->numInstructions;#endif#ifdef PRINT_DOTS			printf (".0x%x",st->grad.pc); fflush(stdout);			if ((st->work_ticks & 0x3f) == 0) 				printf ("\n\r0x%x", st->grad.pc);#endif			for (w=st->work_head; (w); w = w->next)				w->cycle -= TICK_COUNT;			}#ifdef BREAKPOINT		if ((st->work_ticks == (cycbrk/TICK_COUNT)) &&		    (st->work_cycle == (cycbrk % TICK_COUNT)))			ms_break (st, NULL, "CYCBRK");#endif	/* Perform the per cycle operations: Writeback, Fetch, Issue,	*/	/* Execute, and Memory access.					*/		ms_writeback (st);		ms_fetch (st);		ms_issue (st);		ms_execute (st);		ms_ldst_dep (st);     /* Update load/store dependencies	*/		ms_memory (st);		ms_graduate (st);		ms_except (st);	}#else	/*	 *  ms_cycle_loop  -  All set up, let the machine run	 */void ms_cycle_loop (struct s_cpu_state *st)	{	int	watchdog;	WorkList *w;/* Main loop.  Each time around the loop we emulate a single CPU cycle,	*//* so this should be coded as tightly as possible.			*/	watchdog = 0;	while (1)		{#ifdef DEBUG_CHECKS		watchdog++;		if (watchdog >= 1000)			ms_break (st, NULL, "TIMOUT");#endif		st->work_cycle++;		if (st->work_cycle >= TICK_COUNT)			{		/* Every 100,000 cycles, reset	*/					/* the work clock and put out	*/					/* a tick mark.			*/			st->work_cycle -= TICK_COUNT;			st->work_ticks++;#ifdef PRINT_DOTS			printf (".0x%x",st->grad.pc); fflush(stdout);			if ((st->work_ticks & 0x3f) == 0) 				printf ("\n\r0x%x", st->grad.pc);#endif			for (w=st->work_head; (w); w = w->next)				w->cycle -= TICK_COUNT;			}#ifdef BREAKPOINT		if ((st->work_ticks == (cycbrk/TICK_COUNT)) &&		    (st->work_cycle == (cycbrk % TICK_COUNT)))			ms_break (st, NULL, "CYCBRK");#endif	/* Perform the per cycle operations: Writeback, Fetch, Issue,	*/	/* Execute, and Memory access.					*/		if (ms_writeback (st))			watchdog = 0;		/* Reset watchdog timer */						/* every time some work */						/* is done.             */		ms_fetch (st);		ms_issue (st);		ms_execute (st);		ms_ldst_dep (st);     /* Update load/store dependencies	*/		ms_memory (st);		ms_graduate (st);		ms_cache_callbacks (st);skip_to_end:	;		}	}#endif /* MIPSY_MXS */	/*	 *  ms_writeback  -  WRITEBACK the results of previous operations,	 *		and unlock registers.  Handled by the work list	 *		mechanism (see the routine reg_writeback, below,	 *		for the actual operations).	 *	 *	As an indicator for the watchdog timer, ms_writeback	 *	returns the amount of work performed.	 */int ms_writeback (struct s_cpu_state *st)	{	int	loop_counter;	WorkList *w;	w=st->work_head;	st->wbacks = 0;	loop_counter = 0;	while ((w) && (st->work_cycle >= w->cycle))		{		loop_counter++;				/* Perform work list item if	*/				/* it is due this cycle.	*/		(*w->f)((void *)st, w->arg2);		st->free_tail->next = w;		st->free_tail = w;		w = w->next;		st->free_tail->next = NULL;		if ((st->work_head = w) == NULL)			st->work_tail = NULL;		}	return (loop_counter);	}	/*	 *  update_excuse  -  Change the reason why a given register	 *			is not available.	 */void update_excuse (void *st, void *ix)	{	int	reg_ix = (int)ix >> 1;	STX->reg_excuse[reg_ix] = STX->new_excuse[reg_ix];	STX->new_excuse[reg_ix] = ST_NO_EXCUSE;	}	/*	 *  unstall_fetch  -  Clear a branch stall condition for a thread	 *				 */void unstall_fetch (void *st, void *ix)	{	THREAD	*th;	th = &STX->threads [(int)ix];	th->stall_branch = 0;	UpdateStallFetch (th);	}	/*	 *  finish_call  -  Complete call processing by unstalling the	 *		    fetch unit and writing back the link pointer	 */void finish_call (void *st, void *ix)	{	INST	*ip;	BrTREE	*br;	THREAD	*th;	int	inum, branch_node;	ip = (INST *)ix;	inum = ip - STX->iwin;	branch_node = STX->iwin_br_node[inum];	if (branch_node >= 0)		{		br = &STX->branch_tree [branch_node];		th = &STX->threads [br->thread];		th->stall_branch = 0;		UpdateStallFetch (th);		prune_branch (STX, branch_node);		}	if (ip->r1 == 0) 	    free_inst(st,inum);	else	    reg_writeback (STX, (void *)ip->r1);	}	/*	 *  finish_branch  -  Complete branch processing by unstalling the	 *		      fetch unit and freeing the branch instruction	 */void finish_branch (void *st, void *ix)	{	INST	*ip;	BrTREE	*br;	THREAD	*th;	int	inum, branch_node;	ip = (INST *)ix;	inum = ip - STX->iwin;	branch_node = STX->iwin_br_node[inum];	if (branch_node >= 0)		{		br = &STX->branch_tree [branch_node];		th = &STX->threads [br->thread];		th->stall_branch = 0;		UpdateStallFetch (th);		prune_branch (STX, branch_node);		}	free_inst (STX, inum);	}	/*	 *  free_spec_inst  -  Free up instruction slot belonging to a	 *			speculated instruction.	 *	 *	Just like free_inst, except that this instruction might	 *	be on someone's dependents list, so we have to fix that.	 *	Also, the register owned by this instruction needs to	 *	be freed.	 */void free_spec_inst (struct s_cpu_state *st, int this_inst)	{	INST	*ip;	int	i, j, inum, reg_ix;		/* Update the dependent lists.				*/	ip = &st->iwin [this_inst];	if (ip->r2 > 0)		{		reg_ix = ip->r2 >> 1;		if (this_inst == st->reg_otherhalf2 [reg_ix])			st->reg_otherhalf2 [reg_ix] = -1;		inum = st->reg_owner [reg_ix << 1];		for (i=0, j=0; i<st->iwin_index2 [inum]; j++)			{			st->iwin_dep2 [inum][i] = st->iwin_dep2 [inum][j];			if (st->iwin_dep2 [inum][j] == this_inst)				st->iwin_index2 [inum]--;			else				i++;			}		if (inum != st->reg_owner [(reg_ix << 1) + 1])		    {		    inum = st->reg_owner [(reg_ix << 1) + 1];		    for (i=0, j=0; i<st->iwin_index2 [inum]; j++)			{			st->iwin_dep2 [inum][i] = st->iwin_dep2 [inum][j];			if (st->iwin_dep2 [inum][j] == this_inst)				st->iwin_index2 [inum]--;			else				i++;			}		    }		}	if (ip->r3 > 0)		{		reg_ix = ip->r3 >> 1;		if (this_inst == st->reg_otherhalf3 [reg_ix])			st->reg_otherhalf3 [reg_ix] = -1;		inum = st->reg_owner [reg_ix << 1];		for (i=0, j=0; i<st->iwin_index3 [inum]; j++)			{			st->iwin_dep3 [inum][i] = st->iwin_dep3 [inum][j];			if (st->iwin_dep3 [inum][j] == this_inst)				st->iwin_index3 [inum]--;			else				i++;			}		if (inum != st->reg_owner [(reg_ix << 1) + 1])		    {		    inum = st->reg_owner [(reg_ix << 1) + 1];		    for (i=0, j=0; i<st->iwin_index3 [inum]; j++)			{			st->iwin_dep3 [inum][i] = st->iwin_dep3 [inum][j];			if (st->iwin_dep3 [inum][j] == this_inst)				st->iwin_index3 [inum]--;			else				i++;			}		    }		}		/* Take care of the target (destination) register	*/	if (ip->r1 > 0)		{			/* Special registers get the full treatment,	*/			/* since they might have dependents that aren't	*/			/* descended from this thread.			*/		if (st->iwin_flags[this_inst] & IWIN_CTL)			{			reg_writeback ((void *)st, (void *)ip->r1);			return;			}		else			{			REGSTAT	*rs;			reg_ix = ip->r1 >> 1;			rs = &st->reg_rstat [reg_ix];			if (rs->reg_status & REG_DMAP)				rs->reg_status &= ~REG_DMAP;			else				{				rs->reg_status &= ~REG_IN_WIN;				st->reg_excuse[reg_ix] = ST_NO_EXCUSE;				st->new_excuse[reg_ix] = ST_NO_EXCUSE;				CheckRegFree (st, rs, reg_ix);				}			}		}		/* Then free like a regular instruction.		*/	free_inst (st, this_inst);	}	/*	 *  reg_writeback  -  Perform WRITEBACK actions:	 *	 *	1.  Free slot of completing instruction	 *	2.  Decrement ref counts of source registers for	 *		completing instruction	 *	3.  Clear dependent flags of instructions waiting for	 *		this result	 *	4.  Update register status (no longer "in window")	 *	5.  Free load/store buffer entry of loads	 */void reg_writeback (void *st, void *ix)	{	int	inum, inum2, dwi;	int	reg_ix = (int)ix >> 1;	REGSTAT	*rs;	WorkDecls;#ifdef DEBUG_CHECKS	if ((int)ix == 0) {	    fprintf(stderr, "r0 passed to reg_writeback\n");	    ms_break(st, NULL, "r0write");	}#endif		/* If we haven't exceeded allowed write backs, unlock	*/		/* the register.					*/	if (STX->wbacks < WBACK_WIDTH)		{#ifdef BREAKPOINT		if ((int)ix == trace_preg)			printf (		  "Register %d value = 0x%8.8x  %12.6f  %12.6f\r\n", (int)ix,		    STX->regs[(int)ix], *(float *)&STX->regs[(int)ix],					*(double *)&STX->regs[(int)ix] );#endif		STX->wbacks++;		inum = STX->reg_owner [(int)ix];		rs = &STX->reg_rstat [reg_ix];		if (rs->reg_status & REG_DMAP)			{			rs->reg_status &= ~REG_DMAP;				/* If this is the first half of a two	*/				/* instruction definition, turn off the	*/				/* dependent flags of the instruction	*/				/* that writes the other half of the	*/				/* register.				*/			inum2 = STX->reg_otherhalf2 [reg_ix];			if (inum2 >= 0)				{				STX->iwin_flags [inum2] &= ~IWIN_DEP2;				CheckInstAvail (STX, inum2);				}			inum2 = STX->reg_otherhalf3 [reg_ix];			if (inum2 >= 0)				{				STX->iwin_flags [inum2] &= ~IWIN_DEP3;				CheckInstAvail (STX, inum2);				}				/* Transfer dependent list to the other	*/				/* instruction that defines this register */			inum2 = STX->reg_owner [((int)ix) ^ 0x01];			STX->reg_owner [(int)ix] = inum2;			for (dwi = 0; dwi < STX->iwin_index2[inum]; dwi++)			  STX->iwin_dep2 [inum2] [STX->iwin_index2[inum2]++] =				STX->iwin_dep2 [inum] [dwi];			for (dwi = 0; dwi < STX->iwin_index3[inum]; dwi++)			  STX->iwin_dep3 [inum2] [STX->iwin_index3[inum2]++] =				STX->iwin_dep3 [inum] [dwi];			}		else			{				/* Turn off REG_IN_WIN status of this	*/

⌨️ 快捷键说明

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