Skip to content

Instantly share code, notes, and snippets.

@songouyang
Last active December 20, 2018 05:54
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 songouyang/9f20fa135574acc31063095bf5f9c682 to your computer and use it in GitHub Desktop.
Save songouyang/9f20fa135574acc31063095bf5f9c682 to your computer and use it in GitHub Desktop.
csapp cache lab
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include "cachelab.h"
typedef struct arguments {
int h;
int v;
int s;
int E;
int b;
char * t;
} Arguments;
typedef struct cache_line {
int valid_bit;
int tag_bit;
int times;
} CacheLine;
typedef CacheLine * CacheSet;
typedef CacheSet * Cache;
void get_args(Arguments * args, int argc, char ** argv) {
int opt;
while(-1 != (opt = getopt(argc, argv, "hvs:E:b:t:"))) {
switch(opt) {
case 'h':
args->h = 1;
break;
case 'v':
args->v = 1;
break;
case 's':
args->s = atoi(optarg);
break;
case 'E':
args->E = atoi(optarg);
break;
case 'b':
args->b = atoi(optarg);
break;
case 't':
args->t = (char*)malloc(sizeof(char) * strlen(optarg));
strcpy(args->t, optarg);
break;
default:
fprintf(stderr, "wrong argument\n");
exit(0);
break;
}
}
}
void process_help(Arguments args) {
if(args.h == 1 || args.s == -1 ||
args.E == -1 || args.b == -1 ||
args.t == NULL) {
FILE * fp = fopen("help.txt", "rt");
char c;
while(fscanf(fp, "%c", &c) != EOF) {
putchar(c);
}
fclose(fp);
exit(0);
}
}
int hit_count = 0;
int miss_count = 0;
int eviction_count = 0;
void init_args(Arguments * args) {
args->h = 0;
args->v = 0;
args->s = -1;
args->E = -1;
args->b = -1;
args->t = NULL;
}
void init_cache(Cache * cache, Arguments * args) {
int set_size = 1 << args->s;
int num_lines = args->E;
*cache = (CacheSet *)malloc(sizeof(CacheSet) * set_size);
for(int i =0; i<set_size; ++i) {
(*cache)[i] = (CacheLine*)malloc(sizeof(CacheLine)*num_lines);
for(int j = 0; j<num_lines; ++j) {
(*cache)[i][j].valid_bit = 0;
(*cache)[i][j].tag_bit = -1;
(*cache)[i][j].times = 0;
}
}
}
void process(Cache * cache, Arguments * args, int address) {
address >>= args->b;
int set_index = 0;
int tag_bits, i;
long mask = 0xffffffffffffffff >> (64 - args->s);
set_index = mask & address;
address >>= args->s;
tag_bits = address;
CacheSet set = (*cache)[set_index];
for (i = 0; i < args->E; ++i) {
if (set[i].valid_bit == 1) {
set[i].times++;
}
}
for (i = 0; i < args->E; ++i) {
if (set[i].valid_bit == 1 && set[i].tag_bit == tag_bits) {
if(args->v) printf(" hit");
set[i].times = 0;
++hit_count;
return;
}
}
++miss_count;
if(args->v) printf(" miss");
for (i = 0; i < args->E; ++i) {
if (set[i].valid_bit == 0) {
set[i].tag_bit = tag_bits;
set[i].valid_bit = 1;
set[i].times = 0;
return;
}
}
++eviction_count;
if(args->v) printf(" eviction");
int max_index = 0, max_time = set[0].times;
for (i = 0; i < args->E; ++i) {
if (set[i].times > max_time) {
max_index = i;
max_time = set[i].times;
}
}
set[max_index].tag_bit = tag_bits;
set[max_index].times = 0;
}
int main(int argc, char ** argv) {
Arguments args;
init_args(&args);
get_args(&args, argc, argv);
process_help(args);
Cache cache;
init_cache(&cache, &args);
FILE * fp = fopen(args.t, "r");
if(fp == NULL) {
printf("%s: No such file or directory\n", args.t);
exit(1);
}
char op;
unsigned address;
int size = -1;
while(fscanf(fp, " %c %x,%d", &op, &address, &size) > 0) {
if(size==-1) continue;
switch(op) {
case 'I':
break;
case 'M':
if(args.v) printf("M, %x, %d", address, size);
process(&cache, &args, address);
process(&cache, &args, address);
if(args.v) printf("\n");
break;
case 'L':
if(args.v) printf("L, %x, %d", address, size);
process(&cache, &args, address);
if(args.v) printf("\n");
break;
case 'S':
if(args.v) printf("S, %x, %d", address, size);
process(&cache, &args, address);
if(args.v) printf("\n");
break;
default:
printf("Error: invalid operation.");
exit(0);
}
}
fclose(fp);
printSummary(hit_count, miss_count, eviction_count);
for(int i = 0; i<(1<<args.s); ++i) {
free(cache[i]);
}
free(cache);
return 0;
}
/*
* trans.c - Matrix transpose B = A^T
*
* Each transpose function must have a prototype of the form:
* void trans(int M, int N, int A[N][M], int B[M][N]);
*
* A transpose function is evaluated by counting the number of misses
* on a 1KB direct mapped cache with a block size of 32 bytes.
*/
#include <stdio.h>
#include "cachelab.h"
int is_transpose(int M, int N, int A[N][M], int B[M][N]);
/*
* transpose_submit - This is the solution transpose function that you
* will be graded on for Part B of the assignment. Do not change
* the description string "Transpose submission", as the driver
* searches for that string to identify the transpose function to
* be graded.
*/
char transpose_submit_desc[] = "Transpose submission";
void transpose_submit(int M, int N, int A[N][M], int B[M][N]) {
int i, j, k, h;
int a1, a2, a3, a4, a5, a6, a7, a8;
if(N==32&&M==32) {
for (i = 0; i < N; i+=8) {
for (j = 0; j < M; j+=8) {
for(k=i; k<i+8; ++k) {
a1 = A[k][j];
a2 = A[k][j+1];
a3 = A[k][j+2];
a4 = A[k][j+3];
a5 = A[k][j+4];
a6 = A[k][j+5];
a7 = A[k][j+6];
a8 = A[k][j+7];
B[j][k] = a1;
B[j+1][k] = a2;
B[j+2][k] = a3;
B[j+3][k] = a4;
B[j+4][k] = a5;
B[j+5][k] = a6;
B[j+6][k] = a7;
B[j+7][k] = a8;
}
}
}
} else if(N==64&&M==64) {
for(i=0; i<N; i+=8) {
for(j=0; j<M; j+=8) {
for(k=j; k<j+4; ++k) {
a1=A[k][i];
a2=A[k][i+1];
a3=A[k][i+2];
a4=A[k][i+3];
a5=A[k][i+4];
a6=A[k][i+5];
a7=A[k][i+6];
a8=A[k][i+7];
B[i][k]=a1;
B[i][k+4]=a5;
B[i+1][k]=a2;
B[i+1][k+4]=a6;
B[i+2][k]=a3;
B[i+2][k+4]=a7;
B[i+3][k]=a4;
B[i+3][k+4]=a8;
}
for(k=i; k<i+4; ++k) {
a1=B[k][j+4];
a2=B[k][j+5];
a3=B[k][j+6];
a4=B[k][j+7];
a5=A[j+4][k];
a6=A[j+5][k];
a7=A[j+6][k];
a8=A[j+7][k];
B[k][j+4]=a5;
B[k][j+5]=a6;
B[k][j+6]=a7;
B[k][j+7]=a8;
B[k+4][j]=a1;
B[k+4][j+1]=a2;
B[k+4][j+2]=a3;
B[k+4][j+3]=a4;
}
for(k=i+4; k<i+8; ++k) {
a1=A[j+4][k];
a2=A[j+5][k];
a3=A[j+6][k];
a4=A[j+7][k];
B[k][j+4]=a1;
B[k][j+5]=a2;
B[k][j+6]=a3;
B[k][j+7]=a4;
}
}
}
} else if(M==61&&N==67) {
for(i=0; i<N; i+=16) {
for(j=0; j<M; j+=16) {
for(k=i; k<i+16&&k<N; ++k) {
for(h=j; h<j+16&&h<M; ++h) {
B[h][k] = A[k][h];
}
}
}
}
}
}
/*
* You can define additional transpose functions below. We've defined
* a simple one below to help you get started.
*/
/*
* trans - A simple baseline transpose function, not optimized for the cache.
*/
char trans_desc[] = "Simple row-wise scan transpose";
void trans(int M, int N, int A[N][M], int B[M][N]) {
int i, j, tmp;
for (i = 0; i < N; i++) {
for (j = 0; j < M; j++) {
tmp = A[i][j];
B[j][i] = tmp;
}
}
}
/*
* registerFunctions - This function registers your transpose
* functions with the driver. At runtime, the driver will
* evaluate each of the registered functions and summarize their
* performance. This is a handy way to experiment with different
* transpose strategies.
*/
void registerFunctions() {
/* Register your solution function */
registerTransFunction(transpose_submit, transpose_submit_desc);
/* Register any additional transpose functions */
registerTransFunction(trans, trans_desc);
}
/*
* is_transpose - This helper function checks if B is the transpose of
* A. You can check the correctness of your transpose by calling
* it before returning from the transpose function.
*/
int is_transpose(int M, int N, int A[N][M], int B[M][N]) {
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < M; ++j) {
if (A[i][j] != B[j][i]) {
return 0;
}
}
}
return 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment