csapp 实验 Cache Lab: Understanding Cache Memories

实验指导书

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目录给出的用例测试

猜你喜欢

转载自blog.csdn.net/ZhaoBuDaoFangXia/article/details/72626369