csapp 实验 Cache Lab: Understanding Cache Memories

来源:互联网 发布:java十个数输出最小值 编辑:程序博客网 时间:2024/06/05 10:35

实验指导书

http://csapp.cs.cmu.edu/3e/cachelab.pdf

Part A: Writing a Cache Simulator

这里的LRU和之前上课学的不一样,首先会对地址进行哈希运算再LRU。
如果E=1,那就不是LRU了。
不需要真的保存数据,只需要计算hit, miss, eviction次数即可。

#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <math.h>#include <memory.h>#include "cachelab.h"#include <limits.h>int S, E, B;int hit = 0, miss = 0, eviction = 0;//保存结果/* * valid是表示当前cacheLine是否已被使用,addr存放地址,time存放时间,从1开始 */typedef struct {    int valid;    long addr;    int time;} cacheLine;cacheLine *cache;/* * 返回1表示hit,2表示miss,4表示eviction,所以6表示miss和eviction * 读入一条指令,可能为L,M,S。 * L与S的效果相同,首先对B取余数找到对应区间(在这里就是cache的第几行),然后遍历该行, *(获取地址是否存在信息、存在的索引或最小索引、当前最大time) * 看看地址是否存在,若存在则根据对应index更新time。 * 若不存在,则更新time最小的cacheLine。 */int readCacheLine(cacheLine *cache, char type, long addr);void printHelp() {    printf("Usage: ./csim-wrc [-hv] -s <s> -E <E> -b <b> -t <tracefile>\n"                   "• -h: Optional help flag that prints usage info\n"                   "• -v: Optional verbose flag that displays trace info\n"                   "• -s <s>: Number of set index bits (S = 2^s is the number of sets)\n"                   "• -E <E>: Associativity (number of lines per set)\n"                   "• -b <b>: Number of block bits (B = 2^b is the block size)\n"                   "• -t <tracefile>: Name of the valgrind trace to replay\n");}/* * 返回0代表成功 * 1是读入参数错误 * 2是分配内存失败 * 3是打开文件失败 */int main(int argc, char *argv[]) {    opterr = 0;    int verboseFlag = 0;    int oc;    int error = 0;    int in = 0;    char *filePath = NULL;    while ((error == 0) && ((oc = getopt(argc, argv, "s:E:b:t:hv")) != -1)) {        in = 1;        switch (oc) {            case 's':                S = (int) pow(2, atoi(optarg));                break;            case 'E':                E = atoi(optarg);                break;            case 'b':                B = (int) pow(2, atoi(optarg));                break;            case 't':                filePath = optarg;                break;            case 'v':                verboseFlag = 1;                break;            case 'h':            case '?':            default:                error = 1;                printHelp();                break;        }    }    //输入错误时输出用法    if (in == 0 && oc == -1)        printHelp();    if (error == 0) {        FILE *file = fopen(filePath, "r");        if (file == NULL) {            printf("找不到文件");            return 3;        }        cache = (cacheLine *) malloc(S * E * sizeof(cacheLine));        if (cache == NULL) {            printf("内存分配失败");            return 2;        }        memset(cache, 0, S * E * sizeof(cacheLine));        char type;        int size;        long addr;        while (!feof(file)) {            int tr = fscanf(file, " %c %lx,%x", &type, &addr, &size);            if (tr != 3)                continue;            if (type != 'I') {                int rclResult = readCacheLine(cache, type, addr);                char *temp1 = NULL;                switch (rclResult) {                    case 1:                        hit++;                        temp1 = "hit";                        if (type == 'M')                            hit++;                        break;                    case 2:                        miss++;                        temp1 = "miss";                        break;                    case 3:                        miss++;                        hit++;                        temp1 = "miss";                        break;                    case 6:                        miss++;                        eviction++;                        temp1 = "miss";                        break;                    case 7:                    default:                        miss++;                        eviction++;                        hit++;                        temp1 = "miss";                        break;                }                if (verboseFlag) {                    printf("%c %lx,%x %s", type, addr, size, temp1);                    if (rclResult == 6) {                        printf(" eviction");                    } else if (rclResult == 3) {                        printf(" hit");                    } else if (rclResult == 7) {                        printf(" eviction hit");                    } else if (rclResult == 1 && type == 'M') {                        printf(" hit");                    }                    printf("\n");                }            }        }        free(cache);        cache = NULL;        printSummary(hit, miss, eviction);    }//    printSummary(0, 0, 0);    return error;}int readCacheLine(cacheLine *cache, char type, long addr) {    int result = 0;    int sIndex = (int) ((addr / B) % S);    int eIndex = 0, minTime = INT_MAX, maxTime = -1, exist = 0, insert = 0;    for (int i = 0; i < E; ++i) {        cacheLine *ptr = (cache + sIndex * E + i);        if (insert == 0 && result == 0) {            if (ptr->valid != 1) {                ptr->valid = 1;                ptr->addr = addr;                insert = 1;                exist = 0;                result = 2;                eIndex = i;                if (type == 'M')                    result = 3;                //这里还不能break,要找到最大时间            } else {                //如果addr已存在,则索引为当前索引,否则为time最小的索引                if ((ptr->addr / B) == (addr / B)) {                    exist = 1;                    eIndex = i;                    result = 1;                }                if (minTime > ptr->time) {                    minTime = ptr->time;                    if (exist == 0)                        eIndex = i;                }            }        }        if (ptr->time > maxTime)            maxTime = ptr->time;    }    cacheLine *ptr = (cache + sIndex * E + eIndex);    //更新而不是插入    if (insert == 0) {        if (exist == 0) {            ptr->addr = addr;            result = 6;            if (type == 'M')                result = 7;        }    }    ptr->time = maxTime + 1;    return result;}

已通过traces目录给出的用例测试