lab-05-Rushilwiz/cache.c
2024-04-10 21:00:29 -04:00

171 lines
5.2 KiB
C

// PID: 730677144
// I pledge the COMP 211 honor code.
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "bit_utils.h"
#include "cache.h"
#include "memory.h"
/**
* Global variables. The extern ones are initialized in memory.c and are
* accessible via the extern keyword
*/
extern unsigned int* phy_memory;
extern unsigned int* block_location;
extern unsigned int addr_bits;
cache_line** cache;
int initialize_cache(unsigned int number_of_lines) {
unsigned int line;
// Allocate memory for the cache (array of cache lines).
cache = malloc(sizeof(cache_line*) * number_of_lines);
// For each cache line, allocate memory and initialize the cache line.
if (cache != NULL) {
for (line = 0; line < number_of_lines; line++) {
cache[line] = (cache_line*)malloc(sizeof(cache_line));
cache[line]->tag = EMPTY;
cache[line]->hit_count = 0;
cache[line]->block =
malloc(sizeof(unsigned int) * (int)exp2(NUM_BLOCK_OFFSET_BITS));
}
} else {
return FAIL;
}
return OK;
}
int cread(unsigned int cmf, unsigned int* hex_addr, bool* hit, bool* replace) {
// Either the value at the requested hexadecimal address or FAIL
int ret_val = FAIL;
// Initialize these variables by
// extracting the line (for DM, not FA), tag, and block offset bits from
// hex_addr
unsigned int line, tag, block_offset;
// (Optional) Indicates a line that is open and thus usable
int open_line;
// (Optional) For DM, indicates the cache line that should be replaced
int replace_line;
// For FA, keeps track of LFU cache line
int min_hit_cnt = (int)1E10;
// For FA, keeps track of index of LFU cache line
int min_line;
// Variables that are passed by reference
// Must indicate to the driver code whether there was a cache hit and
// whether we had to overwrite and replace something
*hit = false;
*replace = false;
if ((cmf == DM) && ((*hex_addr) < exp2(addr_bits))) {
tag = bit_select(*hex_addr, addr_bits - 1, addr_bits - NUM_TAG_BITS_DM);
line = bit_select(*hex_addr, addr_bits - NUM_TAG_BITS_DM - 1,
NUM_BLOCK_OFFSET_BITS);
block_offset = bit_select(*hex_addr, NUM_BLOCK_OFFSET_BITS - 1, 0);
if (cache[line]->tag == tag) {
// hit
*hit = true;
cache[line]->hit_count++;
ret_val = cache[line]->block[block_offset];
} else {
// miss
if (cache[line]->tag == EMPTY) {
open_line = line;
} else {
replace_line = line;
*replace = true;
}
cache[line]->tag = tag;
cache[line]->hit_count = 1;
unsigned int mem_index =
block_location[*hex_addr >> NUM_BLOCK_OFFSET_BITS];
memcpy(cache[line]->block, phy_memory + mem_index,
sizeof(unsigned int) * (int)exp2(NUM_BLOCK_OFFSET_BITS));
ret_val = cache[line]->block[block_offset];
}
} else if ((cmf == FA) && ((*hex_addr) < exp2(addr_bits))) {
tag = bit_select(*hex_addr, addr_bits - 1, addr_bits - NUM_TAG_BITS_FA);
block_offset = bit_select(*hex_addr, NUM_BLOCK_OFFSET_BITS - 1, 0);
for (line = 0; line < NUM_LINES; line++) {
if (cache[line]->tag == tag) {
// hit
*hit = true;
cache[line]->hit_count++;
ret_val = cache[line]->block[block_offset];
break;
}
}
if (!(*hit)) {
for (line = 0; line < NUM_LINES; line++) {
if (cache[line]->tag == EMPTY) {
replace_line = line;
break;
}
}
if (line == NUM_LINES) {
for (line = 0; line < NUM_LINES; line++) {
if (cache[line]->hit_count < min_hit_cnt) {
min_hit_cnt = cache[line]->hit_count;
min_line = line;
}
}
replace_line = min_line;
*replace = true;
}
cache[replace_line]->tag = tag;
cache[replace_line]->hit_count = 1;
unsigned int mem_index =
block_location[*hex_addr >> NUM_BLOCK_OFFSET_BITS];
memcpy(cache[replace_line]->block, phy_memory + mem_index,
sizeof(unsigned int) * (int)exp2(NUM_BLOCK_OFFSET_BITS));
ret_val = cache[replace_line]->block[block_offset];
}
}
// Print state of cache after mapping algorithm is applied
cprint();
return ret_val;
}
void cprint() {
unsigned int line;
printf("\n---------------------------------------------\n");
printf("line\ttag\tnum of hits\n");
printf("---------------------------------------------\n");
for (line = 0; line < NUM_LINES; line++) {
if (cache[line]->tag == EMPTY) {
printf("%d\t%d\t%d\n", line, cache[line]->tag,
cache[line]->hit_count);
} else {
printf("%d\t%02X\t%d\n", line, cache[line]->tag,
cache[line]->hit_count);
}
}
}