cachelab

77 阅读2分钟

@TOC

版权所有 抄袭必究

part A

lab 介绍

本实验在学习csapp上的高速缓存cache的命中、不命中、LRU替换等机制后,在LINUX机器上使用C语言模拟缓存行为。

ps:这个题看似是模拟cache的行为的题目,实际上是一个模拟LRU机制的算法题,阅读完实验PDF介绍后,我们可以将其转化为算法题来做

转化后

input

./csim-ref -v -s 4 -E 1 -b 4 -t traces/yi.
I 10,1
 L 10,1
 M 20,1 
 L 22,1
 S 18,1
 L 110,1
 L 210,1
 M 12,1

output

hits:4 misses:5 evictions:3

思路分析

这里我们简单介绍一下hits、misses、evictions数量的由来

第一行的I 10,1是初始化,不用管他

首先我们理解一下“地址”的概念

地址:标记标.......标记标记 组索引组.......索引组索引 块偏移......块块偏移

写代码中我们只需要将组索引和标记拿到手,然后用组索引去定位高速缓存阵列中的组,用标记去检测是否匹配就行了

首先我们观察一下第二行的 L 10,1这个可以拆分为L 0000 0001 , 1四个部分,其中L是指的load data(加载数据),0000就是指的是target,0001就是指的组索引,逗号后面的部分是size不用去管它

然后就拿这个去匹配,为了方便匹配我们可以开一个二维数组记录高速缓存中的每行的的状态

如果冲突了就采用LRU替换策略,如果不懂LRU策略,可以去刷刷这个题

代码实现

前期准备工作做好了之后,我们就可以开始写代码了

首先定义一个记录每行信息的结构体block,在这里为了实现LRU缓存,我们增加一个时间戳time

struct block
{
    bool valid;
    long long target;
    int time;
};

然后就可以定义我们需要的一系列变量了

int hit=0; //命中的次数
int miss=0;//错过的次数
int evictions=0;//冲突并替换的次数
int nowtime=1;//现在的时间
int m=(sizeof(void *)*8);//地址的大小
int verbose=false;//是否打印每次去匹配的log
char str[256];//获取输入的字符串
struct block ***cache;//我们定义的二维数组,数组内容是结构体
int s,E,b,S,B,t,C;//高速缓存的大小参数
FILE *fp;//即将读取的文件

接着读取初始化数据

void getoptions(int argc,char* argv[])
{
    int op;
    while((op=getopt(argc,argv,"hvs:E:b:t:"))!=-1)
    {
        switch(op)
        {
            case 'h':
                printf("This is help~");
                exit(0);
            case 'v':
                verbose=true;
                break;
            case 's':
                s=atoi(optarg);
                S=1<<s;
                break;
            case 'E':
                E=atoi(optarg);
                break;
            case 'b':
                b=atoi(optarg);
                B=1<<b;
                break;
            case 't':
                fp=fopen(optarg,"r");
                if(fp==NULL)
                {
                    printf("CAN'T OPREN