Introduction
本次实验分为Part A与Part B,Part A是修改csim.c,Part B则是修改trans.c。本lab主要是为了深入理解cache的机制,完成了模拟cache行为的实现以及应用,以及理解缓存内存对C程序性能的影响。
Part A: Writing a Cache Simulator
在Part A中,需要在csim.c中编写一个缓存模拟器,该模拟器以valgrind内存跟踪作为输入,在此跟踪上模拟缓存内存的命中/未命中行为,并输出总的命中次数、未命中次数和驱逐次数。 在A部分的任务是填写csim.c文件,使其接受相同的命令行参数并产生与参考模拟器完全相同的输出。
具体需要实现的功能:
Usage: ./csim-ref [-hv] -s <s> -E <E> -b <b> -t <tracefile>
• -h: Optional help flag that prints usage info
• -v: Optional verbose flag that displays trace info
• -s <s>: Number of set index bits (S = 2s is the number of sets)
• -E <E>: Associativity (number of lines per set)
• -b <b>: Number of block bits (B = 2b is the block size)
• -t <tracefile>: Name of the valgrind trace to replay
例如:
linux> ./csim-ref -s 4 -E 1 -b 4 -t traces/yi.trace
hits:4 misses:5 evictions:3
linux> ./csim-ref -v -s 4 -E 1 -b 4 -t traces/yi.trace
L 10,1 miss
M 20,1 miss hit
L 22,1 hit
S 18,1 hit
L 110,1 miss eviction
L 210,1 miss eviction
M 12,1 miss eviction hit
hits:4 misses:5 evictions:3
当 CPU 要处理的字不在组中任何一行,且组中没有一个空行,那就必须从里面选取一个非空行进行替换。选取哪个空行进行替换呢?书上给了我们两种策略:
-
LFU,最不常使用策略。替换在过去某个窗口时间内引用次数最少的那一行
-
LRU,最近最少使用策略。替换最后一次访问时间最久远的哪一行
本实验要求采取的策略为 LRU,即被替换掉的块其最后的访问时间是距离现在最远的,体现在代码里可以设置一个时间戳,完成一次操作然后递增,替换的时候比大小就可以了。
下面这段代码主要实现了一个cache模拟器,通过命令行参数来设置模拟器的参数,并通过读取trace文件来模拟cache的操作。具体思路如下:
-
定义了全局变量h、v、hit_count、miss_count、eviction_count、t以及cache的参数s、E、b、S等,用于存储选项参数和统计结果。
-
定义了cache_line结构体,表示每一行cache的格式,包括合法位、标记位和时间戳。
-
初始化cache的函数init_cache(),通过malloc分配内存并初始化cache的参数。
-
更新cache中数据的函数update(),根据地址计算出set index和tag,然后根据LRU算法进行缺失、命中和替换的处理。
-
更新cache中时间戳的函数update_stamp(),用于维护LRU算法中的时间戳。
-
解析trace文件的函数parse_trace(),根据命令类型和地址信息更新cache并更新时间戳。
-
主函数main()通过getopt获取命令行参数,并根据参数设置cache的参数s、E、b、t,然后调用init_cache()初始化cache,调用parse_trace()解析trace文件,最后打印出统计结果。
-
打印帮助信息和summary的函数printUsage()和printSummary()分别用于显示帮助信息和输出命中率、缺失率和替换次数。
总体思路就是根据命令行参数设置cache的参数,读取trace文件模拟cache的操作,更新cache并统计命中、缺失、驱逐次数,最终打印出结果。
代码(包括注释)如下:
#include "cachelab.h"
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <limits.h>
#include &l