memory.c 3.33 KB

/*************************************************************************
 *
 *  File: memory.c
 *
 *
 *  $Header: /root/leakn64/depot/rf/sw/n64os20l/iosim/src/memory.c,v 1.2 2002/05/30 05:52:50 whs Exp $
 *
 */

#include <stdio.h>
#include "sim.h"

#define	DIR_LOAD	1

typedef unsigned long long physaddr_t;

static physaddr_t vtop(uint);

#define	MEMSIZE		(2*1024*1024)

#define	ICACHESIZE	(16*1024)
#define	ICACHELINESIZE	(32)
#define	ICACHEINDEX(a)	(((a)>>5)&0x1ff)

static struct {
	int valid;
	int ptag;
} icache[ICACHESIZE/ICACHELINESIZE];

#define	DCACHESIZE	(8*1024)
#define	DCACHELINESIZE	(16)
#define	DCACHEINDEX(a)	(((a)>>4)&0x1ff)

static struct {
	int valid;
	int dirty;
	int ptag;
} dcache[DCACHESIZE/DCACHELINESIZE];

#define	CACHETAG(a)	(((a)>>12)&0x1fffff)

static struct {
	int total;		/* total accesses */
	int inst;		/* instruction fetches */
	int insthits;		/* hits in icache */
	int instmisses;		/* misses in icache */
	int data;		/* data accesses */
	int loads;		/* loads */
	int loadhits;		/* load hits in dcache */
	int loadmisses;		/* load misses in dcache */
	int stores;		/* stores */
	int storehits;		/* store hits in dcache */
	int storemisses;	/* store misses in dcache */
} stats;

void
memory_access(ulong vaddr, ref_t ref, dir_t dir, sz_t sz)
{
	physaddr_t paddr;
	int index, ptag;

	stats.total++;

	paddr = vtop(vaddr);
	fprintf(stderr,
	    "vaddr 0x%08x 0x%09llx reference(%s)\tdirection(%s)\tsize(%d)\n",
		vaddr,
		paddr,
		ref == REF_INST ? "instruction" : "data",
		dir == DIR_LOAD ? "load" : "store",
		sz);
	ptag = CACHETAG(paddr);
	fprintf(stderr, "ptag = %x ", ptag);
	if (ref == REF_INST) {
		stats.inst++;
		index = ICACHEINDEX(paddr);
		fprintf(stderr, "index = %x\n", index);
		if (icache[index].valid) {
			if (icache[index].ptag == ptag) {
				stats.insthits++;
			} else {
				stats.instmisses++;
				icache[index].ptag = ptag;
			}
		} else {
			stats.instmisses++;
			icache[index].valid = 1;
			icache[index].ptag = ptag;
		}
	} else if (dir == DIR_LOAD) {
		stats.data++;
		stats.loads++;
		index = DCACHEINDEX(paddr);
		fprintf(stderr, "index = %x\n", index);
		if (dcache[index].valid) {
			if (dcache[index].ptag == ptag) {
				stats.loadhits++;
			} else {
				stats.loadmisses++;
				dcache[index].ptag = ptag;
			}
		} else {
			stats.loadmisses++;
			dcache[index].valid = 1;
			dcache[index].ptag = ptag;
		}
	} else {
		stats.data++;
		stats.loads++;
		index = DCACHEINDEX(paddr);
		fprintf(stderr, "index = %x\n", index);
		if (dcache[index].valid) {
			if (dcache[index].ptag == ptag) {
				stats.storehits++;
			} else {
				stats.storemisses++;
				dcache[index].ptag = ptag;
			}
		} else {
			stats.storemisses++;
			dcache[index].valid = 1;
			dcache[index].ptag = ptag;
		}
	}
}

void
memory_stats(void)
{
	printf("\n\n");
	printf("total accesses:\t\t\t%9d\n", stats.total);
	printf("\tinstruction fetches:\t%9d\n", stats.inst);
	printf("\t\thits:\t\t%9d\n", stats.insthits);
	printf("\t\tmisses:\t\t%9d\n", stats.instmisses);
	printf("\tdata accesses:\t\t%9d\n", stats.data);
	printf("\t\tloads:\t\t%9d\n", stats.loads);
	printf("\t\t\thits:\t%9d\n", stats.loadhits);
	printf("\t\t\tmisses:\t%9d\n", stats.loadmisses);
	printf("\t\tstores:\t\t%9d\n", stats.stores);
	printf("\t\t\thits:\t%9d\n", stats.storehits);
	printf("\t\t\tmisses:\t%9d\n", stats.storemisses);
}

static physaddr_t
vtop(uint addr)
{
	return(addr & (MEMSIZE-1));
}