/** * Groupmembers: * 1. Anna Schlittenhardt * 2. Tuan-Dat Tran */ #include #include #include #include #include #include #include "cachelab.h" int v = 0; /* verbose */ int s = 0; /* set index */ int E = 0; /* Set of cache lines */ int b = 0; /* Block offset */ int S; /* Set of Set of cache lines*/ int B; /* Block size */ long long time = 0; FILE *tracefile; /* File to trace from */ struct cache_line **cache; /* cache */ int hit = 0, miss = 0, eviction = 0; struct cache_line { unsigned char v; unsigned int tag; unsigned int time; }; void print_help() { printf("Usage: ./csim-ref [-hv] -s -E -b -t \n"); printf(" -h: Optional help flag that prints usage info\n"); printf(" -v: Optional verbose flag that displays trace info\n"); printf(" -s : Number of set index bits (S = 2 s is the number of sets)\n"); printf(" -E : Associativity (number of lines per set)\n"); printf(" -b : Number of block bits (B = 2 b is the block size)\n"); printf(" -t : Name of the valgrind trace to replay\n"); } void init() { cache = (struct cache_line **) malloc(S*sizeof(struct cache_line *)); for (int i = 0; i < S; i++) { struct cache_line* cache_set = (struct cache_line *) malloc(E*sizeof(struct cache_line)); cache[i] = cache_set; for (int j = 0; j < E; j++) { cache_set[j].v = 0; cache_set[j].tag = 0; cache_set[j].time = 0; } } } void clean() { for (int i = 0; i < S; i++) { free(cache[i]); } free(cache); fclose(tracefile); } void accessMem (int addr) { unsigned int set = ((addr >> b) & ((1LL << s) - 1)); unsigned int tag = addr >> (b + s); struct cache_line *cache_set = cache[set]; long evic_time = 0; int evic_line = 0; for (int i = 0; i < E; i++) { if (cache_set[i].tag == tag && cache_set[i].v != 0){ if (v) { printf("hit "); } hit++; cache_set[i].time = time; time++; return; } } if (v) { printf("miss "); } miss++; for (int i = 0; i < E; i++) { if (cache_set[i].time < evic_time) { evic_line = i; evic_time = cache_set[i].time; } } if (cache_set[evic_line].v == 1) { if (v) { printf("eviction "); } eviction++; } cache_set[evic_line].v = 1; cache_set[evic_line].tag = tag; cache_set[evic_line].time = time; time++; return; } void trace() { char op; unsigned address; int size; while (fscanf(tracefile, " %c %x,%d", &op, &address, &size) > 0 ) { switch (op) { case 'M': if (v) { printf("%c %x,%d ", op, address, size); } accessMem(address); accessMem(address); printf("\n"); break; case 'L': if (v) { printf("%c %x,%d ", op, address, size); } accessMem(address); printf("\n"); break; case 'S': if (v) { printf("%c %x,%d ", op, address, size); } accessMem(address); printf("\n"); break; } } } int main(int argc, char *argv[]) { char c; while ((c = getopt(argc, argv, "s:E:b:t:vh")) != -1) { switch (c) { case 'h': print_help(); exit(0); break; case 'v': v = 1; break; case 's': s = atoi(optarg); break; case 'E': E = atoi(optarg); break; case 'b': b = atoi(optarg); break; case 't': tracefile = fopen(optarg, "r"); break; } } if (s == 0 || E == 0 || b == 0 || tracefile == NULL) { print_help(); exit(1); } S = pow(2, s); B = pow(2, b); init(); trace(); for (int i = 0; i < S; i++) { for (int j = 0; j < E; j++) { // printf("cache[%d][%d]: %c %x %ul\n", i, j, cache[i][j].v, cache[i][j].tag, cache[i][j].time); } } clean(); printSummary(hit, miss, eviction); return 0; }