Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@stevelee477
Created January 26, 2019 06:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stevelee477/2c91dccedcfee65e17183be9c4e761f9 to your computer and use it in GitHub Desktop.
Save stevelee477/2c91dccedcfee65e17183be9c4e761f9 to your computer and use it in GitHub Desktop.
#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