Cache lab is more difficult than two labs I did before. You have to know what’s meaning of cache. And code some program to pass the examiner.
PART A
#include "cachelab.h"
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <limits.h>
#include <getopt.h>
#include <string.h>
int h,v,s,E,b,S; // global arguments
int hit_count ,
miss_count ,
eviction_count; // arguments from printSummary
char t[1000]; // store the cache file
typedef struct{
int valid_bits;
int tag;
int stamp;
}cache_line, *cache_asso, **cache; // cache structure。valid && tag && time stamp
cache _cache_ = NULL; // Define the 2 dimensional array
// print helper
void printUsage()
{
printf("Usage: ./csim-ref [-hv] -s <num> -E <num> -b <num> -t <file>\n"
"Options:\n"
" -h Print this help message.\n"
" -v Optional verbose flag.\n"
" -s <num> Number of set index bits.\n"
" -E <num> Number of lines per set.\n"
" -b <num> Number of block offset bits.\n"
" -t <file> Trace file.\n\n"
"Examples:\n"
" linux> ./csim-ref -s 4 -E 1 -b 4 -t traces/yi.trace\n"
" linux> ./csim-ref -v -s 8 -E 2 -b 4 -t traces/yi.trace\n");
}
// initialize the cache
void init_cache()
{
// We should allocate the memrory line by line in multi-dimensional array
_cache_ = (cache)malloc(sizeof(cache_asso) * S);
for(int i = 0; i < S; ++i)
{
_cache_[i] = (cache_asso)malloc(sizeof(cache_line) * E);
for(int j = 0; j < E; ++j)
{
_cache_[i][j].valid_bits = 0;
_cache_[i][j].tag = -1;
_cache_[i][j].stamp = -1;
}
}
}
void update(unsigned int address)
{
// set index && tag
int setindex_add = (address >> b) & ((-1U) >> (64 - s));
int tag_add = address >> (b + s);
int max_stamp = INT_MIN;
int max_stamp_index = -1;
for(int i = 0; i < E; ++i) //If the cache tag is the same as addr_tag, means to hit it.
{
if(_cache_[setindex_add][i].tag == tag_add)
{
_cache_[setindex_add][i].stamp = 0;
++hit_count;
return ;
}
}
for(int i = 0; i < E; ++i) // check whether exist the empty line
{
if(_cache_[setindex_add][i].valid_bits == 0)
{
_cache_[setindex_add][i].valid_bits = 1;
_cache_[setindex_add][i].tag = tag_add;
_cache_[setindex_add][i].stamp = 0;
++miss_count;
return ;
}
}
++eviction_count;
++miss_count;
for(int i = 0; i < E; ++i)
{
if(_cache_[setindex_add][i].stamp > max_stamp)
{
max_stamp = _cache_[setindex_add][i].stamp;
max_stamp_index = i;
}
}
_cache_[setindex_add][max_stamp_index].tag = tag_add;
_cache_[setindex_add][max_stamp_index].stamp = 0;
return ;
}
void update_stamp()
{
for(int i = 0; i < S; ++i)
for(int j = 0; j < E; ++j)
if(_cache_[i][j].valid_bits == 1)
++_cache_[i][j].stamp;
}
void parse_trace()
{
FILE* fp = fopen(t, "r"); // read file
if(fp == NULL)
{
printf("open error");
exit(-1);
}
char operation;
unsigned int address;
int size;
while(fscanf(fp, " %c %xu,%d\n", &operation, &address, &size) > 0)
{
switch(operation)
{
// Pass the I instructions
case 'L':
update(address);
break;
case 'M':
update(address);
case 'S':
update(address);
}
update_stamp();
}
fclose(fp);
for(int i = 0; i < S; ++i)
free(_cache_[i]);
free(_cache_); // when we finished this part, we don't forget to free the cache
}
//===============================================================
int main(int argc, char* argv[])
{
h = 0;
v = 0;
hit_count = miss_count = eviction_count = 0;
int opt; // get the operation signal from function
while(-1 != (opt = (getopt(argc, argv, "hvs:E:b:t:"))))
{
switch(opt)
{
case 'h':
h = 1;
printUsage();
break;
case 'v':
v = 1;
printUsage();
break;
case 's':
s = atoi(optarg);
break;
case 'E':
E = atoi(optarg);
break;
case 'b':
b = atoi(optarg);
break;
case 't':
strcpy(t, optarg);
break;
default:
printUsage();
break;
}
}
if(s<=0 || E<=0 || b<=0 || t==NULL) // If we input invaid argument, we will exit.
return -1;
S = 1 << s; // S=2^s
FILE* fp = fopen(t, "r");
if(fp == NULL)
{
printf("open error");
exit(-1);
}
init_cache(); // init the cache
parse_trace(); // update the trace
printSummary(hit_count, miss_count, eviction_count);
return 0;
}
PART B
void transpose_submit(int M, int N, int A[N][M], int B[M][N]) {
// S = 5, E = 1, B = 5
// at most 12 local int variables
if(M == 32 && N == 32)
{
for (int i = 0; i < N; i += 8) {
for (int j = 0; j < M; j += 8) {
for(int k = i; k < i + 8; k++)
{
int tmp1 = A[k][j];
int tmp2 = A[k][j+1];
int tmp3 = A[k][j+2];
int tmp4 = A[k][j+3];
int tmp5 = A[k][j+4];
int tmp6 = A[k][j+5];
int tmp7 = A[k][j+6];
int tmp8 = A[k][j+7];
B[j][k] = tmp1;
B[j+1][k] = tmp2;
B[j+2][k] = tmp3;
B[j+3][k] = tmp4;
B[j+4][k] = tmp5;
B[j+5][k] = tmp6;
B[j+6][k] = tmp7;
B[j+7][k] = tmp8;
}
}
}
}
else if(M == 64 && N == 64)
{
for (int i = 0; i < N; i += 4) {
for (int j = 0; j < M; j += 4) {
for(int k = i; k < i + 4; k += 2)
{
int tmp1 = A[k][j];
int tmp2 = A[k][j+1];
int tmp3 = A[k][j+2];
int tmp4 = A[k][j+3];
int tmp5 = A[k+1][j];
int tmp6 = A[k+1][j+1];
int tmp7 = A[k+1][j+2];
int tmp8 = A[k+1][j+3];
B[j][k] = tmp1;
B[j+1][k] = tmp2;
B[j+2][k] = tmp3;
B[j+3][k] = tmp4;
B[j][k+1] = tmp5;
B[j+1][k+1] = tmp6;
B[j+2][k+1] = tmp7;
B[j+3][k+1] = tmp8;
}
}
}
}
else if(M == 61 && N == 67)
{
for (int i = 0; i < N; i += 16) {
for (int j = 0; j < M; j += 16) {
for(int k = i; k < i + 16 && k < N; k ++)
for(int l = j; l < j + 16 && l < M; l++)
B[l][k] = A[k][l];
}
}
}
return;
}