CSAPP:cache lab

来源:互联网 发布:香蕉网络电视免费tv 编辑:程序博客网 时间:2024/06/05 19:05
#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;    }}