/************************************************************************ ** ** Dinero III Cache Simulator ** $Header: /var/home/markhill/DistributeDineroIII/RCS/cmdargs.c,v 3.3 89/05/04 09:57:25 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 ** ** Revised: ** Nitzan Weinberg ** Electrical and Computer Engineering Dept. ** Carnegie Mellon University ** 5000 Forbes Ave. ** Pittsburgh, PA 15213 ** nitzan@andrew.cmu.edu ** ** Source File: cmdargs.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" long atolKMG(); getcmdargs(argc,argv, /* Analyze command line arguments. */ cachep,policyp,ctrlp) register int argc; /* < */ register char *argv[]; /* < */ CACHETYPE *cachep; /* <> */ POLICYTYPE *policyp; /* <> */ CTRLTYPE *ctrlp; /* <> */ /* returns: OK if command line arguments are valid ** ERR otherwise */ { extern char *strcpy(); extern char *strcat(); register int i; register long int nextnum; int returnflag; char nextchar; returnflag = OK; /* defaults */ cachep->blocksize = ILLEGALNUM; cachep->Usize = 0; cachep->Dsize = 0; cachep->Isize = 0; cachep->assoc = 1; cachep->subblocksize = 0; cachep->wordsize = 4; /* in bytes */ cachep->buswidth = cachep->wordsize; /* bus width equals one word size */ policyp->replacement = LRU; policyp->fetch = DEMAND; policyp->prefetchdist = 1; policyp->abortprefetchpercent = 0; policyp->write = COPYBACK; policyp->writeallocate = WRITEALLOCATE; ctrlp->debug = NODEBUG; ctrlp->output = TERSE; ctrlp->skipcount = 0; ctrlp->maxcount = MAXCOUNT; ctrlp->Q = 0; /* for 370 port: 370 370 Set default filename to "TRACE DIN." */ #ifdef IBM370 strcpy(ctrlp->infilename, "TRACE DIN"); #endif /* ** Echo command line */ printf("\n"); printf("CMDLINE: "); for (i=0; i= 1 ) cachep->blocksize = nextnum; else { cachep->blocksize = ILLEGALNUM; returnflag = ERR; } break; case 'S' : nextnum = atolKMG(argv[i][2]=='\0' ? argv[++i] : &argv[i][2]); if (nextnum >= 0 ) cachep->subblocksize = nextnum; else { cachep->subblocksize = ILLEGALNUM; returnflag = ERR; } break; case 'u' : nextnum = atolKMG(argv[i][2]=='\0' ? argv[++i] : &argv[i][2]); if (nextnum >= 0 ) /* size 0 implies no unified cache. */ cachep->Usize = nextnum; else { cachep->Usize = ILLEGALNUM; returnflag = ERR; } break; case 'i' : nextnum = atolKMG(argv[i][2]=='\0' ? argv[++i] : &argv[i][2]); if (nextnum >= 0 ) cachep->Isize = nextnum; else { cachep->Isize = ILLEGALNUM; returnflag = ERR; } break; case 'd' : nextnum = atolKMG(argv[i][2]=='\0' ? argv[++i] : &argv[i][2]); if (nextnum >= 0 ) cachep->Dsize = nextnum; else { cachep->Dsize = ILLEGALNUM; returnflag = ERR; } break; case 'a' : nextnum = atolKMG(argv[i][2]=='\0' ? argv[++i] : &argv[i][2]); if (nextnum >= 1 ) cachep->assoc = nextnum; else { cachep->assoc = ILLEGALNUM; returnflag = ERR; } break; case 'W' : /* @@ added: word size in bytes */ nextnum = atolKMG(argv[i][2]=='\0' ? argv[++i] : &argv[i][2]); if (nextnum >= 1 ) cachep->wordsize = nextnum; else { cachep->wordsize = ILLEGALNUM; returnflag = ERR; } break; case 'B' : /* @@ added: bus width in bytes */ nextnum = atolKMG(argv[i][2]=='\0' ? argv[++i] : &argv[i][2]); if (nextnum >= 1 ) cachep->buswidth = nextnum; else { cachep->buswidth = ILLEGALNUM; returnflag = ERR; } break; /* ** POLICY */ case 'r' : nextchar = (argv[i][2]=='\0' ? argv[++i][0] : argv[i][2]); if (nextchar==LRU || nextchar==FIFO || nextchar==RANDOM) policyp->replacement = nextchar; else { policyp->replacement = ILLEGAL; returnflag = ERR; } break; case 'f' : nextchar = (argv[i][2]=='\0' ? argv[++i][0] : argv[i][2]); if ( nextchar==DEMAND || nextchar==ALWAYSPREFETCH || nextchar==LOADFORWARDPREFETCH || nextchar==SUBBLOCKPREFETCH || nextchar==MISSPREFETCH || nextchar==TAGGEDPREFETCH ) policyp->fetch = nextchar; else { policyp->fetch = ILLEGAL; returnflag = ERR; } break; case 'p' : nextnum = atolKMG(argv[i][2]=='\0' ? argv[++i] : &argv[i][2]); if (nextnum >= 1 ) policyp->prefetchdist = nextnum; else { policyp->prefetchdist = ILLEGALNUM; returnflag = ERR; } break; case 'P' : nextnum = atolKMG(argv[i][2]=='\0' ? argv[++i] : &argv[i][2]); if ((nextnum >= 0 ) && (nextnum <= 100)) policyp->abortprefetchpercent = nextnum; else { policyp->abortprefetchpercent = ILLEGALNUM; returnflag = ERR; } break; case 'w' : nextchar = (argv[i][2]=='\0' ? argv[++i][0] : argv[i][2]); if (nextchar==WRITETHROUGH || nextchar==COPYBACK) policyp->write = nextchar; else { policyp->write = ILLEGAL; returnflag = ERR; } break; case 'A' : nextchar = (argv[i][2]=='\0' ? argv[++i][0] : argv[i][2]); if (nextchar==NOWRITEALLOCATE || nextchar==WRITEALLOCATE) policyp->writeallocate = nextchar; else { policyp->writeallocate = ILLEGAL; returnflag = ERR; } break; /* ** CTRL */ case 'Q' : nextnum = atolKMG(argv[i][2]=='\0' ? argv[++i] : &argv[i][2]); if (nextnum >= 0) ctrlp->Q = nextnum; else { ctrlp->Q = ILLEGALNUM; returnflag = ERR; } break; case 'D' : nextnum = atolKMG(argv[i][2]=='\0' ? argv[++i] : &argv[i][2]); if (nextnum==NODEBUG || nextnum==DEBUG1 || nextnum==DEBUG2) ctrlp->debug = nextnum; else { ctrlp->debug = ILLEGALNUM; returnflag = ERR; } break; case 'o' : nextnum = atolKMG(argv[i][2]=='\0' ? argv[++i] : &argv[i][2]); if (nextnum==TERSE || nextnum==VERBOSE || nextnum==BUS || nextnum==BUS_SNOOP) ctrlp->output = nextnum; else { ctrlp->output = ILLEGALNUM; returnflag = ERR; } break; case 'Z' : nextnum = atolKMG(argv[i][2]=='\0' ? argv[++i] : &argv[i][2]); if (nextnum >= 0) ctrlp->skipcount = nextnum; else { ctrlp->skipcount = ILLEGALNUM; returnflag = ERR; } break; case 'z' : nextnum = atolKMG(argv[i][2]=='\0' ? argv[++i] : &argv[i][2]); if ((nextnum > 0) && (nextnum < LONG_MAX)) ctrlp->maxcount = nextnum; else { ctrlp->maxcount = ILLEGALNUM; returnflag = ERR; } break; /* for 370 port: 370 370 Get first word of filename and append DIN. Thus, "-f TRACE" 370 will cause file "TRACE DIN" to be read. */ #ifdef IBM370 case 'F' : if (argv[i][2]=='\0') { strcpy(ctrlp->infilename, argv[++i]); } else { strcpy(ctrlp->infilename, &argv[i][2]); } strcat(ctrlp->infilename, " DIN"); break; #endif default : printf("Argument %d is invalid: %s\n",i,argv[i]); returnflag = ERR; break; } } returnflag = errormessage(returnflag, (returnflag==ERR), "Illegal parameter or value." ); returnflag = errormessage(returnflag, (ctrlp->maxcount==ILLEGALNUM), "Max number of addresses to process (-z) should be greater than zero but not to exceed LONG_MAX for this machine." ); returnflag = errormessage(returnflag, (cachep->blocksize==ILLEGALNUM), "Blocksize not (correctly) specified." ); returnflag = errormessage(returnflag, (cachep->wordsize==ILLEGALNUM), "Wordsize not (correctly) specified." ); returnflag = errormessage(returnflag, (cachep->buswidth==ILLEGALNUM), "Bus width not (correctly) specified." ); returnflag = errormessage(returnflag, ((cachep->Usize<=0)&&(cachep->Isize<=0)&&(cachep->Dsize<=0)), "No cache size (correctly) specified." ); returnflag = errormessage(returnflag, ((cachep->Usize>0)&&(cachep->Isize>0)), "A unified and instruction cache may not be simulated in one run." ); returnflag = errormessage(returnflag, ((cachep->Usize>0)&&(cachep->Dsize>0)), "A unified and data cache may not be simulated in one run." ); returnflag = warningmessage(returnflag, ((cachep->Usize<=0)&&(cachep->Isize<=0)&&(cachep->Dsize>0)), "Some versions of dineroIII allowed: -d unified_cache_size -i0." ); returnflag = warningmessage(returnflag, ((cachep->Usize<=0)&&(cachep->Isize<=0)&&(cachep->Dsize>0)), "Unified caches should now be specified with: -u unified_cache_size." ); returnflag = errormessage(returnflag, ((cachep->Usize<=0)&&(cachep->Isize<=0)&&(cachep->Dsize>0)), "An instruction cache must be simulated with a data cache." ); returnflag = errormessage(returnflag, ((cachep->Usize<=0)&&(cachep->Isize>0)&&(cachep->Dsize<=0)), "A data cache must be simulated with an instruction cache." ); if (returnflag==OK) { if (cachep->Usize > 0) { /* If there is a U-cache */ returnflag = errormessage(returnflag, (((cachep->Usize % cachep->blocksize) != 0) || (cachep->Usize < cachep->blocksize)), "Unifed cache size must be multiple of the blocksize." ); returnflag = errormessage(returnflag, (((cachep->Usize % (cachep->blocksize*cachep->assoc)) != 0) || (cachep->Usize < (cachep->blocksize*cachep->assoc))), "Unified cache size must be multiple of the blocksize times the associativity." ); } if (cachep->Dsize > 0) { /* If there is a D-cache */ returnflag = errormessage(returnflag, (((cachep->Dsize % cachep->blocksize) != 0) || (cachep->Dsize < cachep->blocksize)), "Data cache size must be multiple of the blocksize." ); returnflag = errormessage(returnflag, (((cachep->Dsize % (cachep->blocksize*cachep->assoc)) != 0) || (cachep->Dsize < (cachep->blocksize*cachep->assoc))), "Data cache size must be multiple of the blocksize times the associativity." ); } if (cachep->Isize > 0) { /* If there is an I-cache */ returnflag = errormessage(returnflag, (((cachep->Isize % cachep->blocksize) != 0) || (cachep->Isize < cachep->blocksize)), "Instruction cache size must be multiple of the blocksize." ); returnflag = errormessage(returnflag, (((cachep->Isize % (cachep->blocksize*cachep->assoc)) != 0) || (cachep->Isize < (cachep->blocksize*cachep->assoc))), "I-cache size must be multiple of the blocksize times the associativity." ); } if (cachep->subblocksize > 0) { /* If there are sub-blocks */ returnflag = errormessage(returnflag, (((cachep->blocksize % cachep->subblocksize) != 0) || (cachep->blocksize <= cachep->subblocksize)), "Blocksize must be a proper multiple of the sub-blocksize." ); returnflag = errormessage(returnflag, ((cachep->subblocksize % cachep->wordsize) != 0), "sub-blocksize must be a proper multiple of the wordsize." ); returnflag = errormessage(returnflag, (cachep->subblocksize < cachep->wordsize), "sub-blocksize must be at least the size of a wordsize." ); returnflag = errormessage(returnflag, ((cachep->subblocksize % cachep->buswidth) != 0), "sub-blocksize must be a proper multiple of the bus width." ); returnflag = errormessage(returnflag, (cachep->buswidth > cachep->subblocksize), "Bus width should not exceed the sub-blocksize." ); returnflag = errormessage(returnflag, ((cachep->blocksize/cachep->subblocksize) > MAXNUMSUBBLOCKS), "Too many sub-blocks per block; implementation restriction is 32." ); } else { /* No sub-blocks */ returnflag = errormessage(returnflag, ((cachep->blocksize % cachep->wordsize) != 0), "blocksize must be a proper multiple of the wordsize." ); returnflag = errormessage(returnflag, (cachep->blocksize < cachep->wordsize), "blocksize must be a at least the size of a wordsize." ); returnflag = errormessage(returnflag, ((cachep->blocksize % cachep->buswidth) != 0), "blocksize must be a proper multiple of the bus width." ); returnflag = errormessage(returnflag, (cachep->buswidth > cachep->blocksize), "Bus width should not exceed the blocksize." ); returnflag = errormessage(returnflag, (policyp->fetch==LOADFORWARDPREFETCH), "LOADFORWARDPREFETCH (-fl) requires sub-blocks." ); returnflag = errormessage(returnflag, (policyp->fetch==SUBBLOCKPREFETCH), "SUBBLOCKPREFETCH (-fS) requires sub-blocks." ); } if (cachep->buswidth >= 0) { /* Bus Width */ returnflag = errormessage(returnflag, (((cachep->buswidth % cachep->wordsize) != 0) || (cachep->buswidth < cachep->wordsize)), "Bus width must be a proper multiple of the wordsize." ); } } return(returnflag); } /* ************************************************************ */ errormessage(olderrorflag,condition,message) /* Prints error message */ int olderrorflag; int condition; char *message; { int newerrorflag; /* ** E.G. USE: ** ** returnflag = errormessage(returnflag, ** (cachep->Isize==ILLEGALNUM), ** "Instruction cache size not specified." ** ); */ newerrorflag = olderrorflag; if (condition) { printf("ERROR: %s\n\n", message); newerrorflag = ERR; } return(newerrorflag); } /* ************************************************************ */ warningmessage(olderrorflag,condition,message) /* Prints error message */ int olderrorflag; int condition; char *message; { if (condition) { printf("WARNING: %s\n", message); } return(olderrorflag); /* warning does not affect errorflag */ } /* ************************************************************ */ echocmdargs( /* Echo command line arguments. */ cachep,policyp,ctrlp) CACHETYPE *cachep; /* < */ POLICYTYPE *policyp; /* < */ CTRLTYPE *ctrlp; /* < */ /* returns: OK */ { /* ** Echo parameters */ printf("CACHE (bytes): "); printf( "blocksize=%d, sub-blocksize=%d, wordsize=%d, Usize=%d, Dsize=%d, Isize=%d, bus-width=%d.\n", cachep->blocksize, cachep->subblocksize, cachep->wordsize, cachep->Usize, cachep->Dsize, cachep->Isize, cachep->buswidth); printf("POLICIES: "); printf( "assoc=%d-way, replacement=%c, fetch=%c(%d,%d), write=%c, allocate=%c.\n", cachep->assoc, policyp->replacement, policyp->fetch, policyp->prefetchdist,policyp->abortprefetchpercent, policyp->write, policyp->writeallocate); printf("CTRL: "); if (sizeof(long)>sizeof(int) ) { printf("debug=%d, output=%d, skipcount=%ld, maxcount=%ld, Q=%ld", ctrlp->debug, ctrlp->output, ctrlp->skipcount, ctrlp->maxcount,ctrlp->Q); } else { printf("debug=%d, output=%d, skipcount=%d, maxcount=%d, Q=%d", ctrlp->debug, ctrlp->output, ctrlp->skipcount, ctrlp->maxcount,ctrlp->Q); } /* for 370 port: 370 370 Echo input filename on 370. */ #ifdef IBM370 printf(", infilename=%s.\n", ctrlp->infilename); #else printf(".\n"); #endif } long atolKMG(str) char *str; /* ** Return long integer equal to value of ascii string that is sequence ** of digits possibly followed by one of the following suffixes: ** ** K, k 1024 ** M, m 1024**2 = 1048576 ** G, g 1024**3 = 1073741824 ** ** E.g., "64K" evaluated to integer 65536. ** ILLEGALNUM is returned for illegal suffixes or on overflow. */ { char str_buffer[256]; int length; char suffix; long root, multiplier, value; extern char *strcpy(); extern int strlen(); extern int atol(); strcpy(str_buffer,str); length = strlen(str_buffer); suffix = str_buffer[length-1]; switch (suffix) { case 'K' : case 'k' : multiplier = 1024; str_buffer[length-1] = NULL; break; case 'M' : case 'm' : multiplier = 1048576; /* 1024**2 */ str_buffer[length-1] = NULL; break; case 'G' : case 'g' : multiplier = 1073741824; /* 1024**3 */ str_buffer[length-1] = NULL; break; case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : case '8' : case '9' : multiplier = 1; break; default : multiplier = ILLEGALNUM; break; } if (multiplier!=ILLEGALNUM) { root = atol(str_buffer); value = root*multiplier; if (root!=(value/multiplier)) { value = ILLEGALNUM; } } else { value = ILLEGALNUM; } return(value); } /* ************************************************************ */