Category : Miscellaneous Language Source Code
Archive   : DINEROII.ZIP
Filename : FETCH.C

 
Output of file : FETCH.C contained in archive : DINEROII.ZIP
/************************************************************************
**
** Dinero III Cache Simulator
** $Header: /var/home/markhill/DistributeDineroIII/RCS/fetch.c,v 3.3 89/05/04 09:57:29 markhill Exp $
** Similar to Version 3.1, Released 8/7/85
**
** Mark D. Hill
** Computer Sciences Dept.
** Univ. of Wisconsin
** Madison, WI 53706
** [email protected]
**
** Developed DineroIII While Affiliated With:
**
** Computer Science Division
** University of California
** Berkeley, California 94720
**
** Source File: fetch.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"

fetch( /* Get addr from input stream & decode*/
cachep,ctrlp,metricp,dap)
CACHETYPE *cachep; /* < */
CTRLTYPE *ctrlp; /* < */
METRICTYPE *metricp; /* <> */
register DECODEDADDRTYPE *dap; /* > */

/* affects: many things indirectly
** returns: EOF or ~EOF
*/
{
int addr;
int thelabel;
static int flushcount = -2; /* No of addr since last cache flush,
-1=>no flushing */

if (flushcount==-2) { /* Initialize */
flushcount = ((ctrlp->Q<1) ? -1 : 0); /* flush? */
} /* end init */


if ((flushcount>=0) && (flushcount++ >= ctrlp->Q)) {
flushcount=1;
flushcache(cachep,ctrlp,metricp);
}



/* for 370 port:
370
370 Must do file I/O on 3081.
370
*/
#ifdef IBM370
if (readfrominputstream370(&thelabel,&addr,ctrlp,
ctrlp->infilep)==EOF) return(EOF);
#else
if (readfrominputstream(&thelabel,&addr,ctrlp)==EOF) return(EOF);
#endif

else {
if (thelabel == XFLUSH) flushcache(cachep,ctrlp,metricp);
breakupaddr(addr,thelabel,dap,cachep);

/* ******* debug -D ***** */
/* dumpaddr(0, dap); */
return(~EOF);
}

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


prefetch(
cachep,policyp,dap,miss,stackptr)
CACHETYPE *cachep; /* < */
POLICYTYPE *policyp; /* < */
register DECODEDADDRTYPE *dap; /* < */
int miss;
STACKNODETYPE *stackptr;


/*
** This routine decides whether to start a prefetch access.
** If so the prefetch is pushed on the addrstack to be read
** instead of the next address trace address.
*/
{
int prefetchaddr;
extern long random();

/*
** See if prefetch needs to be aborted (because of data reference
** interference. Note: 0 <= random() <= 2^31-1 and
** 0 <= random()/MAXINTPERCENT < 100.
*/
if (policyp->abortprefetchpercent > 0 ) {
if (random()/MAXINTPERCENT < policyp->abortprefetchpercent) {
return;
}
}

/*
** Calculate address to prefetch
*/
prefetchaddr = dap->address + cachep->prefetchdisplacement;

/*
** Switch on prefetch policy
*/
switch (policyp->fetch) {

case ALWAYSPREFETCH:
push_addrstack((PREFETCH+dap->accesstype),prefetchaddr);
break;

case LOADFORWARDPREFETCH:
/*
** Don't prefetch into next block.
*/
if (
(dap->address/cachep->blocksize)==(prefetchaddr/cachep->blocksize)
) {
push_addrstack((PREFETCH+dap->accesstype),prefetchaddr);
}
break;

case SUBBLOCKPREFETCH:
/*
** Don't prefetch into next block; wrap around within block instead.
*/
if (
(dap->address/cachep->blocksize)!=(prefetchaddr/cachep->blocksize)
) {
prefetchaddr = prefetchaddr - cachep->blocksize;
}
push_addrstack((PREFETCH+dap->accesstype),prefetchaddr);
break;

case MISSPREFETCH:
if (miss) {
push_addrstack((PREFETCH+dap->accesstype),prefetchaddr);
}
break;

/*
** Tagged prefetch (see Smith, "cache Memories," ~p.20) initiates
** a prefetch on the first demand reference to a (sub)-block. Thus,
** a prefetch is initiated on a demand miss or the first demand
** reference to a (sub)-block that was brought into the cache by a
** prefetch.
**
** Tagged prefetching is implemented using demand reference bits
** that are active only when tagged prefetching is selected. A
** prefetch is started on a demand miss and on a refernce to a
** (sub)-block whose reference bit was not previously set.
*/
case TAGGEDPREFETCH:
if ((miss) || ((dap->validbit & stackptr->reference)==0)) {
push_addrstack((PREFETCH+dap->accesstype),prefetchaddr);
}
break;

case DEMAND:
default :
printf("\n---Error in prefetch policy:%c\n",policyp->fetch);
exit(1);
}

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





/* for 370 port:
370
370 Must do file I/O on 3081.
370
*/
#ifdef IBM370

readfrominputstream370(labelp,addrp,ctrlp,theinfilep) /* get next addr */
int *labelp;
int *addrp;
CTRLTYPE *ctrlp;
FILE *theinfilep;
{
register int readflag;
char linebuffer[256];
char *fgets(); /* fgets(s,n,stream) gets n-1 chars from stream
** or until a newline; changes newline to nullchar;
** returns ptr to the sting.
*/

/*
** Read in ASCII from standard input
** Expect ONE label and addr in hex per line.
** Rest of data input line is ignored so it may
** be used for comments.
**
** WARNING: If more than one tuple is put on a line,
** all but the first tuple will be ignored.
*/

/*
** Get tuple from addrstack if any are there.
*/
if (pop_addrstack(labelp,addrp)>=0) return(~EOF);

linebuffer[0] = NULL;
fgets(linebuffer,255,theinfilep);

#ifdef FAST_BUT_DANGEROUS_INPUT
readflag = sscanxx(linebuffer,labelp,addrp);
#else
readflag = sscanf(linebuffer,"%x %x",labelp,addrp);
#endif

if (readflag==2) {
ctrlp->tracecount++;
if (ctrlp->tracecount > ctrlp->maxcount) {
return(EOF);
}
else {
return(~EOF);
}
}
else {
if (readflag!=EOF) {
printf("\n **** Error in standard input.\n");
}
return(EOF);
}

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

#else

readfrominputstream(labelp,addrp,ctrlp) /* get next addr */
int *labelp;
int *addrp;
CTRLTYPE *ctrlp;
{
register int readflag;
char linebuffer[255];
char *gets(); /* Gets chars from stdin until a newline;
** changes newline to nullchar; returns ptr
** to the sting.
*/

/*
** Read in ASCII from standard input
** Expect ONE label and addr in hex per line.
** Rest of data input line is ignored so it may
** be used for comments.
**
** WARNING: If more than one tuple is put on a line,
** all but the first tuple will be ignored.
*/

/*
** Get tuple from addrstack if any are there.
*/
if (pop_addrstack(labelp,addrp)>=0) return(~EOF);

linebuffer[0] = NULL;
gets(linebuffer);

#ifdef FAST_BUT_DANGEROUS_INPUT
readflag = sscanxx(linebuffer,labelp,addrp);
#else
readflag = sscanf(linebuffer,"%x %x",labelp,addrp);
#endif

if (readflag==2) {
ctrlp->tracecount++;
if (ctrlp->tracecount > ctrlp->maxcount) {
return(EOF);
}
else {
return(~EOF);
}
}
else {
if (readflag!=EOF) {
printf("\n **** Error in standard input.\n");
}
return(EOF);
}

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

#endif





breakupaddr( /* Decode address */
addr,labl,dap,cachep)
register int addr; /* < address */
register int labl; /* < type of reference */
register DECODEDADDRTYPE *dap; /* <> fields of this ptr are altered */
CACHETYPE *cachep; /* < */
/*
** affects: none
** returns: OK
*/
{

/*
** These unsigned integers are so that 32-bit address with
** an MSB of 1 will be shifted correctly with a divide.
*/

unsigned int theaddr;
unsigned int theblocksize, thenumUorDsets, thenumIsets;

theaddr = addr;

theblocksize = cachep->blocksize;
thenumUorDsets = cachep->numUorDsets;
thenumIsets = cachep->numIsets;

dap->address = theaddr;
dap->accesstype = labl;
dap->block = theaddr % theblocksize;
dap->blockaddr = theaddr - dap->block;

if (cachep->subblocksize==0) {
dap->validbit = VALID;
}
else {
dap->subblocknum = dap->block / cachep->subblocksize;
dap->validbit = VALID<subblocknum;
}

switch ( labl ) {

case XREAD :
case XWRITE :
case PREFETCH+XREAD :
case PREFETCH+XWRITE :
dap->set = (theaddr / theblocksize) % thenumUorDsets;
dap->tag = (theaddr / theblocksize) / thenumUorDsets;
break;

case XINSTRN :
case PREFETCH+XINSTRN :
if (thenumIsets != 0) { /* I-Cache */
dap->set = ((theaddr / theblocksize) % thenumIsets)
+ thenumUorDsets;
dap->tag = (theaddr / theblocksize) / thenumIsets;
}
else { /* Mixed Cache; put in data cache set */
dap->set = (theaddr / theblocksize) % thenumUorDsets;
dap->tag = (theaddr / theblocksize) / thenumUorDsets;
}
break;

case PREFETCH+XMISC :
dap->set = (theaddr / theblocksize) % thenumUorDsets;
dap->tag = (theaddr / theblocksize) / thenumUorDsets;
break;

default :
dap->accesstype = XMISC;
dap->set = (theaddr / theblocksize) % thenumUorDsets;
dap->tag = (theaddr / theblocksize) / thenumUorDsets;
break;
}

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






flushcache( /* Flush cache */
cachep,ctrlp,metricp)
CACHETYPE *cachep; /* < */
CTRLTYPE *ctrlp; /* < */
METRICTYPE *metricp; /* <> */

/* affects:
** returns:
*/
{
extern int copybackstack();
extern int putonfreelist();

int stacknum;

for (stacknum=0; stacknum<(cachep->numsets); stacknum++) {
copybackstack(cachep,ctrlp,metricp,stacknum);
putonfreelist(stacknum,&(stack[stacknum]));
}

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




init_addrstack ()
/*
** NOTE: size_addrstack points beyond valid data. A 3-address
** stack would have array entries 0, 1, and 2 filled and
** size_addrstack equal to 3.
*/
{
int i;

for (i=0; i addrstack[i].label = XMISC;
addrstack[i].address = 0;
}

size_addrstack = 0;
}



push_addrstack (labl, addr)
int labl;
int addr;

{
if (size_addrstack == MAXNUMADDRSTACK) {
/* error: addr stack overflow */
printf("Error: addr stack overflow\n");
return(-2);
}
else {
addrstack[size_addrstack].label = labl;
addrstack[size_addrstack].address = addr;
size_addrstack++;
return(size_addrstack);
}
}


pop_addrstack (lablp, addrp)
int *lablp;
int *addrp;

{
if (size_addrstack == 0) {
/* addr stack empty */
return(-1);
}
else {
size_addrstack--;
*lablp = addrstack[size_addrstack].label;
*addrp = addrstack[size_addrstack].address;
return(size_addrstack);
}
}


print_addrstack ()
{
int i;

printf("addrstack(%d of %d): ", size_addrstack, MAXNUMADDRSTACK);

for (i=size_addrstack-1; i>=0; i--) {
printf("%d@%d, ", addrstack[i].label, addrstack[i].address);
}

printf("end.\n");
}







#ifdef FAST_BUT_DANGEROUS_INPUT
/*
** The above "ifdef" enables a fast C-function called "sscanxx"
** to interpret input characters instead of the library function
** "sscanf" because a profile showed that dineroIII was spending
** 35% to 50% of this time in sscanf. The function "sscanxx" runs
** about 6 times faster than "sscanf." The function "sscanxx,"
** selected by the compile-time flag FAST_BUT_DANGEROUS_INPUT in
** global.h, make dineroIII run in 60 to 70% of the time with the
** option diabled.
*/

#define CHAR_ZERO '0'
#define CHAR_NINE '9'
#define CHAR_LOWERCASE_A 'a'
#define CHAR_LOWERCASE_F 'f'

#define HEX 4

#define CHAR_DIGIT_OFFSET '0'
#define CHAR_LOWERCASE_ABCDEF_OFFSET 'a'-10

#define WHITE_SPACE ((*ptr==' ')||(*ptr=='\t'))

#define CHAR_HEX_DIGIT \
((((digit = *ptr)>=CHAR_ZERO) && (digit<=CHAR_NINE)) \
|| ((digit>=CHAR_LOWERCASE_A) && (digit<=CHAR_LOWERCASE_F)))

#define HEX_CHAR_OFFSET \
((digit>=CHAR_LOWERCASE_A) && (digit<=CHAR_LOWERCASE_F) \
? /* a-f */ \
CHAR_LOWERCASE_ABCDEF_OFFSET \
: /* 0-9 */ \
CHAR_DIGIT_OFFSET \
)


sscanxx(linebuffer,num1p,num2p)
char linebuffer[];
int *num1p;
int *num2p;
/*
** This routine is designed to do the same function as
** sscanf(linebuffer,"%x %x",labelp,addrp). It was added
** because gprof said that 35 to 50% of dineroIII's run time
** was being spent in sscanf. This routine runs eight
** times faster.
**
** The routine is not exactly the same as sscanf:
**
** (1) It is implementation dependent.
** (2) Hex numbers cannot be preceded by "0x."
** (3) Legal digits are "0-9" and "a-f;" "A-F" will not
** be interpretted correctly.
** (4) The reponse to input errors is undefined.
*/
{
register char digit;
register char *ptr;
register int num;

/*
** Exit with EOF if the buffer is empty.
*/
if (*(ptr = linebuffer)==NULL) return(EOF);

while (WHITE_SPACE) ptr++;

/*
** Convert first hex number.
*/
num = 0;
while (CHAR_HEX_DIGIT) {
num = (num< ptr++;
}
*num1p = num;

/* Skip white space. */
while (WHITE_SPACE) ptr++;

/*
** Convert second hex number.
*/
num = 0;
while (CHAR_HEX_DIGIT) {
num = (num< ptr++;
}
*num2p = num;

return(2);
}

#endif




  3 Responses to “Category : Miscellaneous Language Source Code
Archive   : DINEROII.ZIP
Filename : FETCH.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/