ms_wrklst.h 2.5 KB
/*
 * 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_wrklst.h  -  Definitions for the worklist mechanism for
	 *		    the simulator.
	 *
	 *	The worklist mechanism is designed to handle instructions
	 *	take multiple cycles to execute.  These instructions are
	 *	handled by locking their destination register, and then
	 *	scheduling their completion for the appropriate cycle.
	 *
	 *	Most instructions complete in a single cycle, so they
	 *	don't need to use the worklist mechanism.
	 *
	 *	Jim Bennett
	 *	1993, 1994
	 */


	/* Worklist structure	*/

typedef struct s_wrklst
	{
	int	cycle;			/* Cycle when work is due	*/
	void	(*f)(void *st, void *a2);
					/* Operation to perform then	*/
	void	*arg2;			/* Argument to function	*/
	struct s_wrklst *next;
	} WorkList;

#define	STX	((struct s_cpu_state *)st)

#ifdef INLINE

	/*
	 *  Define INLINE to get worklist macros, for performance:
	 *
	 *	WorkDecls
	 *	Add_to_worklist(st, inc, func, arg)
	 *
	 *  WorkDecls is a declaration of variables used in Add_to_worklist,
	 *  so it should be included in any procedure that uses the
	 *  Add_to_worklist macro.  Add_to_worklist adds the given function
	 *  to the work list, to be executed at the cycle specified by
	 *  inc (increment from the current cycle).  Arg is an argument
	 *  that is passed to the function as its second argument.  The first
	 *  argument of the function is always st.
	 */

#define	WorkDecls	WorkList *wd_w, *wd_wlp; int wd_c

#define	Add_to_worklist(st, inc, func, argument2)	{	\
	wd_w = STX->free_head;					\
	if (wd_w == NULL) {					\
		fprintf (stderr, "Out of work items!!\n");	\
		exit (1);					\
	}							\
	STX->free_head = wd_w->next;				\
	wd_c = STX->work_cycle+(inc);				\
	wd_wlp = STX->work_tail;				\
	if (wd_wlp == NULL) {					\
		wd_w->next = NULL;				\
		STX->work_head = wd_w;				\
		STX->work_tail = wd_w;				\
	} else if (wd_c < wd_wlp->cycle) {			\
		wd_wlp = STX->work_head;			\
		if (wd_c < wd_wlp->cycle) {			\
			wd_w->next = wd_wlp;			\
			STX->work_head = wd_w;			\
		} else {					\
			for (; wd_wlp->next->cycle < wd_c;	\
				wd_wlp = wd_wlp->next);		\
			wd_w->next = wd_wlp->next;		\
			wd_wlp->next = wd_w;			\
		}						\
	} else {						\
		wd_w->next = NULL;				\
		wd_wlp->next = wd_w;				\
		STX->work_tail = wd_w;				\
	}							\
	wd_w->cycle = wd_c;					\
	wd_w->f = func;						\
	wd_w->arg2 = argument2;					\
}

#endif