|
@ -1,7 +1,152 @@ |
|
|
#include "cachelab.h" |
|
|
#include "cachelab.h" |
|
|
|
|
|
#include <stdio.h> |
|
|
|
|
|
#include <stdlib.h> |
|
|
|
|
|
#include <string.h> |
|
|
|
|
|
#include <unistd.h> |
|
|
|
|
|
#include <getopt.h> |
|
|
|
|
|
|
|
|
int main() |
|
|
|
|
|
|
|
|
typedef struct |
|
|
{ |
|
|
{ |
|
|
printSummary(0, 0, 0); |
|
|
|
|
|
|
|
|
unsigned tag; |
|
|
|
|
|
unsigned usedtime; |
|
|
|
|
|
} block; |
|
|
|
|
|
block *cache; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int getOpt(int argc,char **argv,int *s,int *E,int *b,int *verbose,char *tracefile); |
|
|
|
|
|
void printHelpMenu(); |
|
|
|
|
|
void cacheStateOut(char op,int type); |
|
|
|
|
|
void find(char op,unsigned addr,unsigned size,int time); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int hit,miss,eviction; |
|
|
|
|
|
int verbose; |
|
|
|
|
|
int s,E,b; |
|
|
|
|
|
|
|
|
|
|
|
int main(int argc,char **argv) |
|
|
|
|
|
{ |
|
|
|
|
|
FILE *fp; |
|
|
|
|
|
char tracefile[100]; |
|
|
|
|
|
char op[10]; |
|
|
|
|
|
unsigned addr,size; |
|
|
|
|
|
int t; |
|
|
|
|
|
|
|
|
|
|
|
getOpt(argc,argv,&s,&E,&b,&verbose,tracefile); // get option |
|
|
|
|
|
|
|
|
|
|
|
if(s<0||E<0||b<1){ |
|
|
|
|
|
printf("Invalid Cache parameter\n\n"); |
|
|
|
|
|
exit(1); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
cache = (block *)malloc(sizeof(block)* E<<s); |
|
|
|
|
|
memset(cache,0,sizeof(block)* E<<s); |
|
|
|
|
|
|
|
|
|
|
|
fp = fopen (tracefile,"r"); |
|
|
|
|
|
while(fscanf(fp,"%s%x,%d\n",op,&addr,&size) > 0){ |
|
|
|
|
|
if(verbose) |
|
|
|
|
|
printf("%s %x,%d ",op,addr,size); |
|
|
|
|
|
switch(op[0]){ |
|
|
|
|
|
case 'M': hit++; |
|
|
|
|
|
case 'L': |
|
|
|
|
|
case 'S': find(op[0],addr,size,++t); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
printSummary(hit, miss, eviction); |
|
|
|
|
|
free(cache); |
|
|
|
|
|
fclose(fp); |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void find(char op, unsigned addr,unsigned size,int time){ |
|
|
|
|
|
int i; |
|
|
|
|
|
unsigned tag = addr >>b >>s ; |
|
|
|
|
|
unsigned set_index = addr >> b &((1<<s) -1); |
|
|
|
|
|
block *cache_set = cache + E * set_index ; // set address |
|
|
|
|
|
block *eviction_block = cache_set; // LRU cacheline |
|
|
|
|
|
for(i = 0;i<E;i++){ |
|
|
|
|
|
if(cache_set[i].usedtime>0 && cache_set[i].tag ==tag){ //hit |
|
|
|
|
|
cache_set[i].usedtime = time; |
|
|
|
|
|
hit++; |
|
|
|
|
|
if(verbose) cacheStateOut(op,0); |
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
else if(!cache_set[i].usedtime){ // empty block |
|
|
|
|
|
miss++; |
|
|
|
|
|
cache_set[i].tag = tag; |
|
|
|
|
|
cache_set[i].usedtime = time; |
|
|
|
|
|
if(verbose) cacheStateOut(op,1); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
else if(cache_set[i].usedtime < eviction_block->usedtime) // !=tag , current block is older |
|
|
|
|
|
eviction_block = cache_set+i; |
|
|
|
|
|
} |
|
|
|
|
|
miss ++; |
|
|
|
|
|
eviction ++; |
|
|
|
|
|
eviction_block->tag = tag; // replace sacrifice cacheline |
|
|
|
|
|
eviction_block->usedtime = time; |
|
|
|
|
|
if(verbose) cacheStateOut(op,2); |
|
|
|
|
|
return ; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int getOpt(int argc,char **argv,int *s,int *E,int *b,int *verbose,char *tracefile) |
|
|
|
|
|
{ |
|
|
|
|
|
int oc; |
|
|
|
|
|
while((oc=getopt(argc,argv,"hvs:E:b:t:"))!=-1){ |
|
|
|
|
|
switch(oc){ |
|
|
|
|
|
case 'h': printHelpMenu();break; // print usage |
|
|
|
|
|
case 'v': *verbose=1;break; |
|
|
|
|
|
case 's': *s = atoi(optarg);break; |
|
|
|
|
|
case 'E': *E = atoi(optarg);break; |
|
|
|
|
|
case 'b': *b = atoi(optarg);break; |
|
|
|
|
|
case 't': strcpy(tracefile,optarg);break; |
|
|
|
|
|
default : printf("input error\n");break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
void cacheStateOut(char op,int type){ |
|
|
|
|
|
switch(type){ |
|
|
|
|
|
case 0: //hit |
|
|
|
|
|
switch(op){ |
|
|
|
|
|
case 'L': |
|
|
|
|
|
case 'S':printf("hit\n");break; |
|
|
|
|
|
case 'M':printf("hit hit\n");break; |
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
|
|
|
|
case 1: //miss |
|
|
|
|
|
switch(op){ |
|
|
|
|
|
case 'L': |
|
|
|
|
|
case 'S':printf("miss\n");break; |
|
|
|
|
|
case 'M':printf("miss hit\n");break; |
|
|
|
|
|
} |
|
|
|
|
|
case 2: //eviction |
|
|
|
|
|
switch(op){ |
|
|
|
|
|
case 'L': |
|
|
|
|
|
case 'S':printf("miss eviction\n");break; |
|
|
|
|
|
case 'M':printf("miss eviction hit\n");break; |
|
|
|
|
|
}break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void printHelpMenu(){ |
|
|
|
|
|
printf("Usage: ./csim [-hv] -s <num> -E <num> -b <num> -t <file>\n"); |
|
|
|
|
|
printf("Options:\n"); |
|
|
|
|
|
printf("-h Print this help message.\n"); |
|
|
|
|
|
printf("-v Optional verbose flag.\n"); |
|
|
|
|
|
printf("-s <num> Number of set index bits.\n"); |
|
|
|
|
|
printf("-E <num> Number of lines per set.\n"); |
|
|
|
|
|
printf("-b <num> Number of block offset bits.\n"); |
|
|
|
|
|
printf("-t <file> Trace file.\n\n\n"); |
|
|
|
|
|
printf("Examples:\n"); |
|
|
|
|
|
printf("linux> ./csim -s 4 -E 1 -b 4 -t traces/yi.trace\n"); |
|
|
|
|
|
printf("linux> ./csim -v -s 8 -E 2 -b 4 -t traces/yi.trace\n"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void checkOptarg(char *curOptarg){ |
|
|
|
|
|
if(curOptarg[0]=='-'){ |
|
|
|
|
|
printf("./csim :Missing required command line argument\n"); |
|
|
|
|
|
printHelpMenu(); |
|
|
|
|
|
exit(0); |
|
|
|
|
|
} |
|
|
|
|
|
} |