-
-
Save stevelee477/2c91dccedcfee65e17183be9c4e761f9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "cachelab.h" | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <getopt.h> | |
#include <stdlib.h> | |
#include <stdbool.h> // bool to _Bool | |
#include <errno.h> | |
#include <unistd.h> | |
typedef struct { | |
bool vaild; | |
uint64_t tag; | |
uint64_t time_counter; | |
}line; | |
typedef line *entry_of_lines; | |
typedef entry_of_lines *entry_of_sets; | |
typedef struct { | |
int hit; | |
int miss; | |
int eviction; | |
}result; | |
entry_of_sets InitializeCache (uint64_t, uint64_t); | |
void ReleaseMemory (entry_of_sets, uint64_t, uint64_t); | |
result ReadAndTest (FILE *, entry_of_sets, uint64_t, uint64_t, uint64_t, uint64_t, bool); | |
result HitMissEviction (entry_of_lines, result, uint64_t, uint64_t, bool); | |
int main(int argc, char * const argv[]) { | |
result Result = {0, 0, 0}; | |
const char *help_message = "Usage: \"Your complied program\" [-hv] -s <s> -E <E> -b <b> -t <tracefile>\n" \ | |
"<s> <E> <b> should all above zero and below 64.\n" \ | |
"Complied with std=c99\n"; | |
const char *command_options = "hvs:E:b:t:"; | |
FILE *tracefile = NULL; | |
entry_of_sets cache = NULL; | |
bool verbose = false; | |
uint64_t s = 0; | |
uint64_t b = 0; | |
uint64_t S = 0; | |
uint64_t E = 0; | |
char ch; | |
while((ch = getopt(argc, argv, command_options)) != -1) { | |
switch (ch) { | |
case 'h': { | |
printf("%s", help_message); | |
exit(EXIT_SUCCESS); | |
} | |
case 'v': { | |
verbose = true; | |
break; | |
} | |
case 's': { | |
if (atol(optarg) <= 0) { | |
printf("%s", help_message); | |
exit(EXIT_FAILURE); | |
} | |
s = atol(optarg); | |
S = 1 << s; | |
break; | |
} | |
case 'E': { | |
if (atol(optarg) <= 0) { | |
printf("%s", help_message); | |
exit(EXIT_FAILURE); | |
} | |
E = atol(optarg); | |
break; | |
} | |
case 'b': | |
{ | |
if (atol(optarg) <= 0) | |
{ | |
printf("%s", help_message); | |
exit(EXIT_FAILURE); | |
} | |
b = atol(optarg); | |
break; | |
} | |
case 't': { | |
if (((tracefile = fopen(optarg, "r")) == NULL)) { | |
perror("Failed to open tracefile"); | |
exit(EXIT_FAILURE); | |
} | |
break; | |
} | |
default: { | |
printf("%s", help_message); | |
exit(EXIT_FAILURE); | |
} | |
} | |
} | |
if (s == 0 || b ==0 || E == 0 || tracefile == NULL) { | |
printf("%s", help_message); | |
exit(EXIT_FAILURE); | |
} | |
cache = InitializeCache(S, E); | |
Result = ReadAndTest(tracefile, cache, S, E, s, b, verbose); | |
ReleaseMemory(cache, S, E); | |
printSummary(Result.hit, Result.miss, Result.eviction); | |
return 0; | |
} | |
entry_of_sets InitializeCache (uint64_t S, uint64_t E) { | |
entry_of_sets cache; | |
if ((cache = calloc(S, sizeof(entry_of_lines))) == NULL) { | |
perror("Failed to calloc entry_of_sets"); | |
exit(EXIT_FAILURE); | |
} | |
for (uint64_t i = 0; i < S; i++) { | |
if ((cache[i] = calloc(E, sizeof(line))) == NULL) { | |
perror("Failed to calloc line in sets"); | |
exit(EXIT_FAILURE); | |
} | |
} | |
return cache; | |
} | |
void ReleaseMemory (entry_of_sets cache, uint64_t S, uint64_t E) { | |
for (uint64_t i = 0; i < S; i++) { | |
free(cache[i]); | |
} | |
free(cache); | |
} | |
result ReadAndTest (FILE *tracefile, entry_of_sets cache, uint64_t S, uint64_t E, uint64_t s, uint64_t b, bool verbose) { | |
result Result = {0, 0, 0}; | |
char ch; | |
uint64_t address; | |
while ((fscanf(tracefile, " %c %lx%*[^\n]", &ch, &address)) == 2) { | |
if (ch == 'I') { | |
continue; | |
} else { | |
uint64_t set_index_mask = (1 << s) - 1; | |
uint64_t set_index = (address >> b) & set_index_mask; | |
uint64_t tag = (address >> b) >> s; | |
entry_of_lines search_line = cache[set_index]; | |
if (ch == 'L' || ch == 'S') { | |
if (verbose) printf("%c %lx", ch, address); | |
Result = HitMissEviction(search_line, Result, E, tag, verbose); | |
} else if (ch == 'M') { | |
if (verbose) printf("%c %lx", ch, address); | |
Result = HitMissEviction(search_line, Result, E, tag, verbose); | |
Result = HitMissEviction(search_line, Result, E, tag, verbose); | |
} else { | |
continue; | |
} | |
} | |
} | |
return Result; | |
} | |
result HitMissEviction (entry_of_lines search_line, result Result, uint64_t E, uint64_t tag, bool verbose) { | |
uint64_t oldest_time = UINT64_MAX; | |
uint64_t youngest_time = 0; | |
uint64_t oldest_block = UINT64_MAX; | |
bool hit_flag = false; | |
for (uint64_t i = 0; i < E; i++) { | |
if (search_line[i].tag == tag && search_line[i].vaild){ | |
if (verbose) printf("hit\n"); | |
hit_flag = true; | |
Result.hit++; | |
search_line[i].time_counter++; | |
break; | |
} | |
} | |
if (!hit_flag) { | |
if (verbose) printf("miss"); | |
Result.miss++; | |
uint64_t i; | |
for (i = 0; i < E; i++) { | |
if (search_line[i].time_counter < oldest_time) { | |
oldest_time = search_line[i].time_counter; | |
oldest_block = i; | |
} | |
if (search_line[i].time_counter > youngest_time) { | |
youngest_time = search_line[i].time_counter; | |
} | |
} | |
search_line[oldest_block].time_counter = youngest_time + 1; | |
search_line[oldest_block].tag = tag; | |
if (search_line[oldest_block].vaild) { | |
if (verbose) printf("and eviction\n"); | |
Result.eviction++; | |
} else { | |
if (verbose) printf("\n"); | |
search_line[oldest_block].vaild = true; | |
} | |
} | |
return Result; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment