ms_st_init.c 6.79 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_st_init  -  Initialize the MXS simulator state for one CPU
	 *
	 *	Jim Bennett
	 *	1993, 1994, 1995
	 */

#include <stdlib.h>
#include <string.h>
#include <ieeefp.h>
#include "ms.h"
#include "simutil.h"

int	true_inst_hi = 0;		/* Instruction count (optional)	*/
int	true_inst_lo = 0;

int	min_special_preg = -1;		/* Range of special physical reg's */
int	max_special_preg = -1;

#ifdef BREAKPOINT
int	brkpt = 0;
int	jmpbrk = 0x77650001;		/* Unlikely value */
int	cycbrk = -1;
int	linbrk = -1;
int	membrk = 0;
int	opcbrk = -1;

int	trace_reg = -1;			/* Register for tracing		*/
int	trace_preg = -1;		/* Physical version of above	*/
#endif

#ifdef PRINT_INST
int	enable_iprint = 0;
int	enable_fprint = 0;
int	enable_eprint = 0;
int	iprint_frequency = 1;
#endif

char	*statfilename = NULL;
#ifdef TRACE
char	*tracefilename = NULL;
FILE	*tracefile = NULL;
int	trace_writes = 0;
#endif

	/*
	 *  ms_st_init  -  Initialize the simulator state structure
	 */

void ms_st_init (struct s_cpu_state *st)
	{
	THREAD	*th;
	int	i, j;

/* Initialize floating point rounding mode.				*/

	st->round_mode = 0;
	set_rm (0);

/* Initialize the graduation point thread, or thread 0 if not precise	*/

#ifdef PRECISE
	th = &st->grad;
#else
	th = &st->threads [0];
#endif
	th->thread_st = TH_ACTIVE;
	th->stall_fetch = 0;
	th->branch_dly = 0;
	th->branch_likely = 0;
	th->stall_branch = 0;
	th->stall_thread = 0;
	th->stall_fpc = 0;
	th->stall_icache = 0;
	th->stall_except = 0;
	th->stall_itlbmiss = 0;
	th->stall_cp0 = 0;
	th->stall_sc = 0;
	th->stall_sys = 0;
	th->branch_sp = 0;
	th->branch_node = 0;

	for (i=0, j=0; i<FPREG;   i++, j+=2)
		th->regnames[i] = j;
	for (i=FPREG;  i<MAX_FP;  i++, j++ )
		th->regnames[i] = j;
	for (i=MAX_FP; i<MAX_VAR; i++, j+=2)
		th->regnames[i] = j;

	for (i=0; i<MAX_VAR/2; i++)
		th->half_def[i] = 0;

/* Initialize stall status of functional units.				*/

	st->stall_issue = 0;
	st->stall_type = ST_NO_EXCUSE;

/* Initialize the instruction window					*/

	ms_iwin_init (st);

/* Initialize exception handling mechanism				*/

        st->exception_pending = 0;

/* Initialize branch prediction tables					*/

	for (i=0; i<BP_TABLE_SIZE; i++)
		{
		st->bp_bits [i] = BP_TAKEN;
		st->bp_targets [i] = -1;
		}
	for (i=0; i<BP_RETURN_STACK; i++)
		st->branch_stack [i] = -1;
	st->branch_sp = 0;

/* Initialize the worklist mechanism.  Put all items on the free list	*/
/* to start with.  Clear statistics counters.				*/

	for (i=0; i<MAX_WORK_ITEMS; i++)
		st->worklist[i].next = &st->worklist[i+1];
	st->free_head = &st->worklist[0];
	st->free_tail = &st->worklist[MAX_WORK_ITEMS-1];
	st->free_tail->next = NULL;
	st->work_head = NULL;
	st->work_tail = NULL;
	st->work_cycle = 0;
	st->work_ticks = 0;
        bzero((char *) &(st->stats[0]), sizeof(st->stats));

/* Initialize the load/store queue and memory callbacks		*/

	for (i=0; i<MAX_CALLBACK; i++)
		st->callbacks[i].next_cb = i + 1;
	st->cb_free = 0;
	st->callbacks[MAX_CALLBACK-1].next_cb = -1;
	}


	/*
	 *  ms_iwin_init  -  Initialization specific to the instruction
	 *		     window.  Called when restarting after an
	 *		     exception.
	 */

void ms_iwin_init (struct s_cpu_state *st)
	{
	int	i, reg_ix;
	THREAD	*th;
	BrTREE	*br;

/* Initialize branch processing machinery.  Put all the threads on the	*/
/* free list, except the first, and initialize the first thread.	*/

	for (i=0; i<THREAD_WIDTH; i++)
		{
		th = &st->threads [i];
		th->pc = ((i+1) >= THREAD_WIDTH ? -1 : i+1);
		}

	th = &st->threads [0];
#ifdef PRECISE
	*th = st->grad;			/* Copy from the graduating	*/
#endif					/* (precise) thread.		*/
	st->active_thread = th;
	st->free_thread = 1;
	st->nthreads = 1;
	st->nactive = 1;

/* Then do the same for the branch tree nodes.				*/

	for (i=0; i<2*THREAD_WIDTH; i++)
		{
		br = &st->branch_tree [i];
		br->thread = ((i+1) >= (2*THREAD_WIDTH) ? -1 : i+1);
		}
	st->free_branch_node = 1;

	br = &st->branch_tree [0];
	br->thread = 0;
	br->thread_st = th->thread_st;
	br->lchild = -1;
	br->rchild = -1;
	br->condition = 0;
	br->resolution = 0;
	br->indirect = 0;
	br->jret = 0;
	br->call = 0;
	br->uncond = 0;
	br->restore = 0;
	br->iwin_head_th = -1;
	br->iwin_tail_th = -1;

/* Clear all of the registers and their associated state		*/
/* (rename tables, etc.)						*/

	for (i=0; i<MAX_PREG; i++)
		{
		st->regs [i] = 0;
		st->reg_owner [i] = 0;
		}

	for (i=0; i<MAX_PREG/2; i++)
		{
		st->reg_excuse [i] = ST_NO_EXCUSE;
		st->new_excuse [i] = ST_NO_EXCUSE;
		st->reg_rstat[i].reg_status = 0;
		st->reg_rstat[i].reg_ref = 0;
		st->reg_rstat[i].reg_nmap = 0;
		st->reg_rstat[i].reg_nclaims = 0;
		}

/* Acquire mappings for all the registers belonging to this thread,	*/
/* and put the other registers on the free list.			*/

	for (i = 0; i < MAX_VAR; i++)
		{
		if ((i < FPREG) || (i >= MAX_FP))
			{
			reg_ix = th->regnames[i] >> 1;
			AcquireRegMap (&st->reg_rstat[reg_ix], th, i);
			st->reg_rstat[reg_ix].reg_status |= REG_BUSY;
			}
		else
		if ((i < FPCTL) || (i >= TOT_REG))
			{
			if ((i & 0x01) == 0)
				{
				reg_ix = th->regnames[i] >> 1;
				AcquireRegMap (&st->reg_rstat[reg_ix], th, i);
				st->reg_rstat[reg_ix].reg_status |= REG_BUSY;
				}
			}
		else
			{
			reg_ix = th->regnames[i] >> 1;
			AcquireRegMap (&st->reg_rstat[reg_ix], th, i);

			if (min_special_preg == -1)
				{
				min_special_preg = reg_ix;
				max_special_preg = reg_ix;
				}
			if (reg_ix < min_special_preg)
				min_special_preg = reg_ix;
			if (reg_ix > max_special_preg)
				max_special_preg = reg_ix;
			}
		}

	st->reg_nextfree = -1;
	for (i=0; i<MAX_PREG/2; i++)
		{
		if ((st->reg_rstat[i].reg_status & REG_MAPPED) == 0)
			{
			st->reg_freelist [i] = st->reg_nextfree;
			st->reg_nextfree = i;
			}
		}

/* Initialize the instructions window fields.				*/

	st->iwin_ninst = 0;
	for (i=0; i<TOTAL_INST; i++)
		{
		st->iwin_flags [i] = 0;
		st->iwin_freelist [i] = i+1;
		st->iwin_index2 [i] = 0;
		st->iwin_index3 [i] = 0;
		}
	st->iwin_freelist [TOTAL_INST-1] = -1;
	st->iwin_nextfree = 0;
	st->iwin_headpri = -1;
	st->iwin_tailpri = -1;
#ifdef PRECISE
	st->iwin_headgrad = -1;
	st->iwin_tailgrad = -1;
#endif
	st->iwin_next_avail = -1;
	st->iwin_last_avail = -1;
	st->iwin_head_ldst = -1;
	st->iwin_tail_ldst = -1;
	st->iwin_nldst = 0;
#ifdef ONE_PHASE_LS
	st->iwin_nstores = 0;
#endif

/* Initialize execution unit.						*/

	st->ex_count = 0;
/* Initialize the ldst unit.                                           */
        ldst_init(st);

	}

void
set_rm(int mode) 
{
   fp_rnd newmode;

   switch (mode) {
   case 0:
      newmode = FP_RN;
      break;
   case 1:
      newmode = FP_RZ;
      break;
   case 2:
      newmode = FP_RP;
      break;
   case 3:
      newmode = FP_RM;
      break;
   }

   fpsetround(newmode);
}