/************************************************************************
**
**	Dinero III Cache Simulator 
**	$Header: /var/home/markhill/DistributeDineroIII/RCS/output.c,v 3.3 89/05/04 09:57:39 markhill Exp $
**	Similar to Version 3.1, Released 8/7/85
**
**	Mark D. Hill
**	Computer Sciences Dept.
**	Univ. of Wisconsin
**	Madison, WI 53706
**	markhill@cs.wisc.edu
**
**	Developed DineroIII While Affiliated With:
**
**	Computer Science Division
**	University of California
**	Berkeley, California 94720
**
**	Source File:	output.c
**
************************************************************************/

/* 
**  Copyright 1985, 1989 Mark D. Hill
**
**  Permission to use, copy, modify, and distribute this
**  software and its documentation for any purpose and without
**  fee is hereby granted, provided that the above copyright
**  notice appear in all copies.  Mark D. Hill makes no
**  representations about the suitability of this software
**  for any purpose.  It is provided "as is" without expressed
**  or implied warranty.
*/  

#include "global.h"

/*
**	Used so that "numerator / NONZERO(denomenator)" will
**	never cause a divide-by-zero exception.
*/
#define NONZERO(i)	((i==0) ? 1.0 : (float)i)

outputmetric(cachep,policyp,ctrlp,m)
CACHETYPE *cachep;		/* <  */
POLICYTYPE *policyp;		/* <  */
CTRLTYPE *ctrlp;		/* <  */
METRICTYPE *m;			/* <  Too lazy to write "metricp" */
/*
** affects: none
** returns: OK
*/
{
int	demand_fetch_data,
	demand_fetch_alltype;
int	prefetch_fetch_data,
	prefetch_fetch_alltype;

int	demand_data,
	demand_alltype;
int	prefetch_data,
	prefetch_alltype;

float	floatnum;

/* Used in bus traffic calculations even if no prefetching. */
prefetch_fetch_alltype = 0;

/*
** Print Header
*/
printf("\n");
printf(" Metrics		Access Type:\n");
printf(
" (totals,fraction)	Total	Instrn	 Data	 Read	Write	 Misc\n");
printf(
" -----------------	------	------	------	------	------	------\n");

/*
** Print Fetch Numbers
*/
demand_fetch_data = m->fetch[XMISC] 
		  + m->fetch[XREAD]
	      	  + m->fetch[XWRITE];
demand_fetch_alltype = demand_fetch_data 
		  + m->fetch[XINSTRN];

printf(
" Demand Fetches		%6d	%6d	%6d	%6d	%6d	%6d\n",
		demand_fetch_alltype,
		m->fetch[XINSTRN],
		demand_fetch_data,
		m->fetch[XREAD],
		m->fetch[XWRITE],
		m->fetch[XMISC]
	);

floatnum = NONZERO(demand_fetch_alltype);

printf(
"			%6.4f	%6.4f	%6.4f	%6.4f	%6.4f	%6.4f\n",
		demand_fetch_alltype / floatnum,
		m->fetch[XINSTRN] / floatnum,
		demand_fetch_data / floatnum,
		m->fetch[XREAD] / floatnum,
		m->fetch[XWRITE] / floatnum,
		m->fetch[XMISC] / floatnum
	);

/*
** Prefetching?
*/
if (policyp->fetch!=DEMAND) {
prefetch_fetch_data = m->fetch[PREFETCH+XMISC] 
		  + m->fetch[PREFETCH+XREAD]
	      	  + m->fetch[PREFETCH+XWRITE];
prefetch_fetch_alltype = prefetch_fetch_data 
		  + m->fetch[PREFETCH+XINSTRN];

printf(
" Prefetch Fetches	%6d	%6d	%6d	%6d	%6d	%6d\n",
		prefetch_fetch_alltype,
		m->fetch[PREFETCH+XINSTRN],
		prefetch_fetch_data,
		m->fetch[PREFETCH+XREAD],
		m->fetch[PREFETCH+XWRITE],
		m->fetch[PREFETCH+XMISC]
	);

floatnum = NONZERO(prefetch_fetch_alltype);

printf(
"			%6.4f	%6.4f	%6.4f	%6.4f	%6.4f	%6.4f\n",
		prefetch_fetch_alltype / floatnum,
		m->fetch[PREFETCH+XINSTRN] / floatnum,
		prefetch_fetch_data / floatnum,
		m->fetch[PREFETCH+XREAD] / floatnum,
		m->fetch[PREFETCH+XWRITE] / floatnum,
		m->fetch[PREFETCH+XMISC] / floatnum
	);

printf( 
" Total Fetches		%6d	%6d	%6d	%6d	%6d	%6d\n",
		demand_fetch_alltype + prefetch_fetch_alltype,
		m->fetch[XINSTRN] + m->fetch[PREFETCH+XINSTRN],
		demand_fetch_data + prefetch_fetch_data,
		m->fetch[XREAD] + m->fetch[PREFETCH+XREAD],
		m->fetch[XWRITE] + m->fetch[PREFETCH+XWRITE],
		m->fetch[XMISC] + m->fetch[PREFETCH+XMISC]
	);

floatnum = NONZERO(demand_fetch_alltype + prefetch_fetch_alltype);

printf(
"			%6.4f	%6.4f	%6.4f	%6.4f	%6.4f	%6.4f\n",
		(demand_fetch_alltype + prefetch_fetch_alltype) / floatnum,
		(m->fetch[XINSTRN] + m->fetch[PREFETCH+XINSTRN]) / floatnum,
		(demand_fetch_data + prefetch_fetch_data) / floatnum,
		(m->fetch[XREAD] + m->fetch[PREFETCH+XREAD]) / floatnum,
		(m->fetch[XWRITE] + m->fetch[PREFETCH+XWRITE]) / floatnum,
		(m->fetch[XMISC] + m->fetch[PREFETCH+XMISC]) / floatnum
	);

 } /* End of prefetching. */
printf("\n");

/*
** End of Fetch Numbers
*/

/*
** Print Miss Numbers
*/
demand_data = m->miss[XMISC] 
		  + m->miss[XREAD]
	      	  + m->miss[XWRITE];
demand_alltype = demand_data 
		  + m->miss[XINSTRN];

printf(
" Demand Misses		%6d	%6d	%6d	%6d	%6d	%6d\n",
		demand_alltype,
		m->miss[XINSTRN],
		demand_data,
		m->miss[XREAD],
		m->miss[XWRITE],
		m->miss[XMISC]
	);


printf(
"			%6.4f	%6.4f	%6.4f	%6.4f	%6.4f	%6.4f\n",
		demand_alltype / NONZERO(demand_fetch_alltype),
		m->miss[XINSTRN] / NONZERO(m->fetch[XINSTRN]),
		demand_data / NONZERO(demand_fetch_data),
		m->miss[XREAD] / NONZERO(m->fetch[XREAD]),
		m->miss[XWRITE] / NONZERO(m->fetch[XWRITE]),
		m->miss[XMISC] / NONZERO(m->fetch[XMISC])
	);

/*
** Prefetching?
*/
if (policyp->fetch!=DEMAND) {
prefetch_data = m->miss[PREFETCH+XMISC] 
		  + m->miss[PREFETCH+XREAD]
	      	  + m->miss[PREFETCH+XWRITE];
prefetch_alltype = prefetch_data 
		  + m->miss[PREFETCH+XINSTRN];

printf(
" Prefetch Misses	%6d	%6d	%6d	%6d	%6d	%6d\n",
		prefetch_alltype,
		m->miss[PREFETCH+XINSTRN],
		prefetch_data,
		m->miss[PREFETCH+XREAD],
		m->miss[PREFETCH+XWRITE],
		m->miss[PREFETCH+XMISC]
	);

printf(
"			%6.4f	%6.4f	%6.4f	%6.4f	%6.4f	%6.4f\n",
		prefetch_alltype
			/ NONZERO(prefetch_fetch_alltype),
		m->miss[PREFETCH+XINSTRN] 
			/ NONZERO(m->fetch[PREFETCH+XINSTRN]),
		prefetch_data
			/ NONZERO(prefetch_fetch_data),
		m->miss[PREFETCH+XREAD] 
			/ NONZERO(m->fetch[PREFETCH+XREAD]),
		m->miss[PREFETCH+XWRITE] 
			/ NONZERO(m->fetch[PREFETCH+XWRITE]),
		m->miss[PREFETCH+XMISC] 
			/ NONZERO(m->fetch[PREFETCH+XMISC])
	);

printf( 
" Total Misses		%6d	%6d	%6d	%6d	%6d	%6d\n",
		demand_alltype + prefetch_alltype,
		m->miss[XINSTRN] + m->miss[PREFETCH+XINSTRN],
		demand_data + prefetch_data,
		m->miss[XREAD] + m->miss[PREFETCH+XREAD],
		m->miss[XWRITE] + m->miss[PREFETCH+XWRITE],
		m->miss[XMISC] + m->miss[PREFETCH+XMISC]
	);


printf(
"			%6.4f	%6.4f	%6.4f	%6.4f	%6.4f	%6.4f\n",
		(demand_alltype + prefetch_alltype)
		     / NONZERO(demand_fetch_alltype + prefetch_fetch_alltype),
		(m->miss[XINSTRN] + m->miss[PREFETCH+XINSTRN])
		     / NONZERO(m->fetch[XINSTRN] + m->fetch[PREFETCH+XINSTRN]),
		(demand_data + prefetch_data)
			/ NONZERO(demand_fetch_data + prefetch_fetch_data),
		(m->miss[XREAD] + m->miss[PREFETCH+XREAD])
			/ NONZERO(m->fetch[XREAD] + m->fetch[PREFETCH+XREAD]),
		(m->miss[XWRITE] + m->miss[PREFETCH+XWRITE])
			/ NONZERO(m->fetch[XWRITE] + m->fetch[PREFETCH+XWRITE]),
		(m->miss[XMISC] + m->miss[PREFETCH+XMISC])
			/ NONZERO(m->fetch[XMISC] + m->fetch[PREFETCH+XMISC])
	);

 } /* End of prefetching. */
printf("\n");

/*
** End of Misses Numbers
*/


/*
** Print Block Miss Numbers
*/
if (cachep->subblocksize!=0) {
demand_data = m->blockmiss[XMISC] 
		  + m->blockmiss[XREAD]
	      	  + m->blockmiss[XWRITE];
demand_alltype = demand_data 
		  + m->blockmiss[XINSTRN];

printf(
" Demand Block Misses	%6d	%6d	%6d	%6d	%6d	%6d\n",
		demand_alltype,
		m->blockmiss[XINSTRN],
		demand_data,
		m->blockmiss[XREAD],
		m->blockmiss[XWRITE],
		m->blockmiss[XMISC]
	);


printf(
"			%6.4f	%6.4f	%6.4f	%6.4f	%6.4f	%6.4f\n",
		demand_alltype / NONZERO(demand_fetch_alltype),
		m->blockmiss[XINSTRN] / NONZERO(m->fetch[XINSTRN]),
		demand_data / NONZERO(demand_fetch_data),
		m->blockmiss[XREAD] / NONZERO(m->fetch[XREAD]),
		m->blockmiss[XWRITE] / NONZERO(m->fetch[XWRITE]),
		m->blockmiss[XMISC] / NONZERO(m->fetch[XMISC])
	);

/*
** Prefetching?
*/
if (policyp->fetch!=DEMAND) {
prefetch_data = m->blockmiss[PREFETCH+XMISC] 
		  + m->blockmiss[PREFETCH+XREAD]
	      	  + m->blockmiss[PREFETCH+XWRITE];
prefetch_alltype = prefetch_data 
		  + m->blockmiss[PREFETCH+XINSTRN];

printf(
" Prefetch Block Misses	%6d	%6d	%6d	%6d	%6d	%6d\n",
		prefetch_alltype,
		m->blockmiss[PREFETCH+XINSTRN],
		prefetch_data,
		m->blockmiss[PREFETCH+XREAD],
		m->blockmiss[PREFETCH+XWRITE],
		m->blockmiss[PREFETCH+XMISC]
	);

printf(
"			%6.4f	%6.4f	%6.4f	%6.4f	%6.4f	%6.4f\n",
		prefetch_alltype
			/ NONZERO(prefetch_fetch_alltype),
		m->blockmiss[PREFETCH+XINSTRN] 
			/ NONZERO(m->fetch[PREFETCH+XINSTRN]),
		prefetch_data
			/ NONZERO(prefetch_fetch_data),
		m->blockmiss[PREFETCH+XREAD] 
			/ NONZERO(m->fetch[PREFETCH+XREAD]),
		m->blockmiss[PREFETCH+XWRITE] 
			/ NONZERO(m->fetch[PREFETCH+XWRITE]),
		m->blockmiss[PREFETCH+XMISC] 
			/ NONZERO(m->fetch[PREFETCH+XMISC])
	);

printf( 
" Total Block Misses	%6d	%6d	%6d	%6d	%6d	%6d\n",
		demand_alltype + prefetch_alltype,
		m->blockmiss[XINSTRN] + m->blockmiss[PREFETCH+XINSTRN],
		demand_data + prefetch_data,
		m->blockmiss[XREAD] + m->blockmiss[PREFETCH+XREAD],
		m->blockmiss[XWRITE] + m->blockmiss[PREFETCH+XWRITE],
		m->blockmiss[XMISC] + m->blockmiss[PREFETCH+XMISC]
	);


printf(
"			%6.4f	%6.4f	%6.4f	%6.4f	%6.4f	%6.4f\n",
		(demand_alltype + prefetch_alltype)
		     / NONZERO(demand_fetch_alltype + prefetch_fetch_alltype),
		(m->blockmiss[XINSTRN] + m->blockmiss[PREFETCH+XINSTRN])
		     / NONZERO(m->fetch[XINSTRN] + m->fetch[PREFETCH+XINSTRN]),
		(demand_data + prefetch_data)
			/ NONZERO(demand_fetch_data + prefetch_fetch_data),
		(m->blockmiss[XREAD] + m->blockmiss[PREFETCH+XREAD])
			/ NONZERO(m->fetch[XREAD] + m->fetch[PREFETCH+XREAD]),
		(m->blockmiss[XWRITE] + m->blockmiss[PREFETCH+XWRITE])
			/ NONZERO(m->fetch[XWRITE] + m->fetch[PREFETCH+XWRITE]),
		(m->blockmiss[XMISC] + m->blockmiss[PREFETCH+XMISC])
			/ NONZERO(m->fetch[XMISC] + m->fetch[PREFETCH+XMISC])
	);

 } /* End of prefetching. */
printf("\n");
 } /* End of block miss. */
/*
** End of Block Misses Numbers
*/

/*
**	Print Bus Traffic Numbers
*/
printf(
" Words From Memory	%6ld\n",
		m->bus_traffic_in / cachep->wordsize
	);
printf(
" ( / Demand Fetches)	%6.4f\n",
		(m->bus_traffic_in / cachep->wordsize)
		     / NONZERO(demand_fetch_alltype)
	);

printf(
" Words Copied-Back	%6ld\n",
		m->bus_traffic_out / cachep->wordsize
	);
printf(
" ( / Demand Writes)	%6.4f\n",
		(m->bus_traffic_out / cachep->wordsize)
		     / NONZERO(m->fetch[XWRITE])
	);

printf(
" Total Traffic (words)	%6ld\n",
		(m->bus_traffic_in + m->bus_traffic_out) / cachep->wordsize
	);
printf(
" ( / Demand Fetches)	%6.4f\n",
		((m->bus_traffic_in + m->bus_traffic_out) / cachep->wordsize)
		     / NONZERO(demand_fetch_alltype)
	);

printf(
" Total Bus Transactions (Bursts)  %6ld\n",
		m->bus_transactions_initiated
	);
printf(
" Total Bus Usage (Cycles)         %6ld\n",
		m->bus_usage
	);

 printf("\n");
/*
**	End of Bus Traffic
*/

} /* ***************************************************************** */




dumpaddr(number,dap)			/* Dumps decoded address */
long number;			/* <  */
register DECODEDADDRTYPE *dap;	/* <  */
/*
** affects: none
** returns: OK
*/
{
if (sizeof(long)>sizeof(int))
printf("\n### %ld ### Access=0x%x, Addr=0x%lx, TSB=0x%lx@%x@%x, subbit=0x%x.\n",
	number,dap->accesstype,dap->address,
        dap->tag,dap->set,dap->block,dap->validbit);  /* @@ changed second and third %x in print string into %lx */
else
printf("\n### %d ### Access=0x%x, Addr=0x%lx, TSB=0x%lx@%x@%x, subbit=0x%x.\n",
	number,dap->accesstype,dap->address,
        dap->tag,dap->set,dap->block,dap->validbit);  /* @@ changed second and third %x in print string into %lx */

} /* ***************************************************************** */




dumpstate(cachep,policyp)		/* Dumps info on stacks & free list */
register CACHETYPE *cachep;		/* <  */
POLICYTYPE *policyp;		/* <  */
/*
** affects: none
** returns: OK
*/
{
extern STACKNODETYPE *stack;	/* global ptr to top of stacks */
extern int bufferindex;		/* global index to buffer */
extern STACKNODETYPE freelist;	/* List head for free list */
extern int numnodes;		/* Count on storage allocated */
register int i;
register int sum;
register STACKNODETYPE *ptr;
int num_of_sets;

sum = 0;
num_of_sets = cachep->numIsets + cachep->numUorDsets;

printf("\nStack Number  Size   Cum Size\n");
printf(  "-----------   ----   --------\n");

for (i=0; i<num_of_sets; i++) 
	if (stack[i].tag>0) {
	   printf("%10x %6d %10d\t",i,stack[i].tag,(sum += stack[i].tag));
	   for (ptr=stack[i].next; ptr!=NULL; ptr=ptr->next) {
		printf("(%lx,%lx",ptr->tag,ptr->blockaddr);     /* @@ changed from %x into %lx */
		if ((cachep->subblocksize>0)||(ptr->valid!=VALID)) {
			printf(",V%x",ptr->valid);
		}
		if ((policyp->fetch==TAGGEDPREFETCH)
		   || (ptr->reference!=NOTREFERENCED)){
			printf(",R%x",ptr->reference);
		}
		if ((policyp->write==COPYBACK)||(ptr->dirty!=NOTDIRTY)) {
			printf(",D%x",ptr->dirty);
		}
	   	printf(")");
	   }
	   printf("\n");
	}

printf("%d elements allocated, %d on priority stacks, %d on freelist,\n",
	numnodes, sum, freelist.tag);
printf("%d unused in buffer%s\n", (BUFFERSIZE-bufferindex),
	((numnodes - sum - freelist.tag - BUFFERSIZE + bufferindex)==0
	? "." : "(*** error: stacks are inconsistent)."));

} /* ***************************************************************** */




dumpmetric(metricp,cachep)	/* Dumps cache performance measures */
METRICTYPE *metricp;		/* <  */
CACHETYPE *cachep;		/* <  */
/*
** affects: none
** returns: OK
*/
{
printf("\n Procedure dumpmetric unimplemented.\n\n");
		
} /* ***************************************************************** */




