CSAPP:cache lab

#include "cachelab.h"
#include <stdio.h>
#include <stdlib.h>
typedef long long ll;
/*以下为要用到的变量*/
typedef struct {
    int val;                    //有效位
    int lastVisit;              //这一行上一次被使用的时间
    ll tag;                     //这一行的tag
}line_type;

typedef struct {
    line_type* line;            //set里的行
    int used;                   //已经被占用的行,used=E则这个set满了
}set_type;

typedef struct {
    set_type* set;
    int s, E, b;
}cache_type;

cache_type C;
int display = 0;
int hit_count = 0, miss_count = 0, eviction_count = 0;
int time = 0;
/*函数*/
char* readCMD(int argc, char** argv);
void readLINE(char opt, ll addr, int size);
void readFILE(char* name);
void Malloc();
void Free();
void Store(ll addr, int size);
void Load(ll addr, int size);
void Modify(ll addr, int size);
void error(int k);
ll getSet(ll addr, int s, int b);
ll getTag(ll addr, int t);
int main(int argc, char** argv) {
    char* file = readCMD(argc, argv);
    Malloc();
    readFILE(file);
    printSummary(hit_count, miss_count, eviction_count);
    Free();
    return 0;
}
ll getSet(ll addr, int s, int b) {
    int mask = 0x7fffffff;
    ll set;
    mask >>= (31 - s);
    addr >>= b;
    set = mask & addr;
    return set;
}
ll getTag(ll addr, int t) {
    int mask = 0x7fffffff;
    ll tag;
    mask >>= (31 - t); 
    addr >>= (32 - t);
    tag = mask & addr;
    return tag;
}
char* readCMD(int argc, char** argv) {
    int k = 1;
    char *file;
    while(k < argc) {
        switch(argv[k][1]) {
            case 'v':
                display = 1;
                k++;
            case 's':
                C.s = atoi(argv[k+1]);
                k+=2;
            case 'E':
                C.E = atoi(argv[k+1]);
                k+=2;
            case 'b':
                C.b = atoi(argv[k+1]);
                k+=2;
            case 't':
                file = argv[k+1];
                k+=2;
        }
    }
    return file;
}
void readLINE(char opt, ll addr, int size) {
    if(opt == 'S')
        Store(addr, size);
    else if(opt == 'L')
        Load(addr, size);
    else if(opt == 'M') 
        Modify(addr, size);
    return;
}
void readFILE(char* name) {
    ll addr;
    int size;
    char opt;
    FILE *f = fopen(name, "r");
    while(fscanf(f, "%c", &opt)==1) {   
        if(opt == ' ')
            fscanf(f, "%c %llx,%d\n", &opt, &addr, &size);
        else
            fscanf(f, "%llx,%d\n", &addr, &size);
        if(opt == 'I')
            continue;
        readLINE(opt, addr, size);
        time++;
    }
    return;
}
void Load(ll addr, int size) {
    ll set = getSet(addr, C.s, C.b);
    set_type cSet = C.set[set];
    int t = 32 - C.s - C.b;
    ll tag = getTag(addr, t);
    for(int i=0; i<C.E; i++) {
        if(cSet.line[i].val == 1 && cSet.line[i].tag == tag) {
            hit_count++;
            C.set[set].line[i].lastVisit = time;
            if(display)
                printf("L %llx,%d hit\n", addr, size);
            return;
        }
    }
    miss_count++;
    if(cSet.used == C.E) {
        eviction_count++;
        int Min = cSet.line[0].lastVisit;
        int cnt = 0;
        for(int i=1; i<C.E; i++) {
            if(cSet.line[i].lastVisit < Min) {
                Min = cSet.line[i].lastVisit;
                cnt = i;
            }
        }
        C.set[set].line[cnt].tag = tag;
        C.set[set].line[cnt].lastVisit = time;
        if(display)
            printf("L %llx,%d miss eviction\n", addr, size);
        return;
    }
    else {
        int k = cSet.used;
        C.set[set].line[k].val = 1;
        C.set[set].line[k].tag = tag;
        C.set[set].line[k].lastVisit = time;
        C.set[set].used++;
        if(display)
            printf("L %llx,%d miss\n", addr, size);
        return;
    }
}
void Store(ll addr, int size) {
    ll set = getSet(addr, C.s, C.b);
    set_type cSet = C.set[set];
    int t = 32 - C.s - C.b;
    int S = 1 << C.s;
    if(set >= S)
        error(2);
    ll tag = getTag(addr, t);
    for(int i=0; i<C.E; i++) {
        if(cSet.line[i].val == 1 && cSet.line[i].tag == tag) {
            hit_count++;
            C.set[set].line[i].lastVisit = time;
            if(display)
                printf("S %llx,%d hit\n", addr, size);
            return;
        }
    }
    miss_count++;
    if(cSet.used == C.E) {
        eviction_count++;
        int Min = cSet.line[0].lastVisit;
        int cnt = 0;
        for(int i=1; i<C.E; i++) {
            if(cSet.line[i].lastVisit < Min) {
                Min = cSet.line[i].lastVisit;
                cnt = i;
            }
        }
        C.set[set].line[cnt].tag = tag;
        C.set[set].line[cnt].lastVisit = time;
        if(display)
            printf("S %llx,%d miss eviction\n", addr, size);
        return;
    }
    else {
        int k = cSet.used;
        C.set[set].line[k].val = 1;
        C.set[set].line[k].tag = tag;
        C.set[set].line[k].lastVisit = time;
        C.set[set].used++;
        if(display)
            printf("S %llx,%d miss\n", addr, size);
        return;
    }
}
void Modify(ll addr, int size) {
    int flag = 0;
    printf("M %llx,%d", addr, size);
    ll set = getSet(addr, C.s, C.b);
    set_type cSet = C.set[set];
    int S = 1 << C.s;
    if(set >= S)
        error(2);
    int t = 32 - C.s - C.b;
    ll tag = getTag(addr, t);
    for(int i=0; i<C.E; i++) {
        if(cSet.line[i].val == 1 && cSet.line[i].tag == tag) {
            hit_count++;
            flag = 1;
            C.set[set].line[i].lastVisit = time;
            if(display)
                printf(" hit");
            break;
        }
    }
    if(!flag) {
        miss_count++;
        if(cSet.used == C.E) {
            eviction_count++;
            int Min = cSet.line[0].lastVisit;
            int cnt = 0;
            for(int i=1; i<C.E; i++) {
                if(cSet.line[i].lastVisit < Min) {
                    Min = cSet.line[i].lastVisit;
                    cnt = i;
                }
            }
            C.set[set].line[cnt].tag = tag;
            C.set[set].line[cnt].lastVisit = time;
            if(display)
                printf(" miss eviction");
        }
        else {
            int k = cSet.used;
            C.set[set].line[k].val = 1;
            C.set[set].line[k].tag = tag;
            C.set[set].line[k].lastVisit = time;
            C.set[set].used++;
            if(display)
                printf(" miss");
        }
    }
    hit_count++;
    printf(" hit\n");
}
void Malloc() {
    int S = 1 << C.s;
    C.set = malloc(sizeof(set_type) * S + 1);
    for(int i=0; i<S; i++) {
        C.set[i].line = malloc(sizeof(line_type) * C.E + 1);
        C.set[i].used = 0;
        for(int j=0; j<C.E; j++)
            C.set[i].line[j].val = 0;
    }
    return;
}
void Free() {
    int S = 1 << C.s;
    for(int i=0; i<S; i++)
        free(C.set[i].line);
    free(C.set);
    return;
}
void error(int k) {
    switch(k) {
        case 1:
            printf("Malloc Error");
            return;
        case 2:
            printf("OPT Error");
            return;
    }
}

猜你喜欢

转载自blog.csdn.net/pkuout/article/details/76096042