# 一、Cache 模拟器实验
## 1.1 实验目的
- 理解 cache 工作原理;
- 如何实现一个高效的模拟器
## 1.2 实验环境
Linux 64-bit ,C 语言
## 1.3 实验思路
### 1.3.1 cache 模拟
建立 cache 的数据结构,包括有效位 valid、标签位 tag 和使用记录器 lru。实现代码如下:
```c++
typedef struct cache_line {
char valid;
mem_addr_t tag;
unsigned long long int lru;
} cache_line_t;
```
定义 cache 组:用数组模拟 cache 组,即建立关于 cache 组的一个指针,然后动态开辟所需要 cache 的数量。实现代码如下:
```c++
typedef cache_line_t* cache_set_t;
```
定义 cache:用 cache_set 数组模拟 cache,即一个 cache 包含多个 cache 组,同样先创建一个 cache 指针,然后根据所需要 cache 组的大小动态开辟 cache 的实际大小。实现代码如下:
```c++
typedef cache_set_t* cache_t;
```
### 1.3.2 输入输出参数
- verbosity:显示轨迹信息,输入指令中含-v 则 verbosity 置 1,表示要进行轨迹信息输出,否则 verbosity 置 0。
- s:组索引位数,输入指令中-s 后面的数据为组索引位数,用 S=2s 表示所需要的 cache 组数。
- b:内存块内地址位数,输入指令-b 后面的数据为块内存地址组数,用 B=2b 表示所需要划分 cache 的内存块大小。
- E:关联度(每组包含的缓存行数),输入指令后面的数据为关联度,即每一组有多少个块。
- miss_count:用于记录未命中的次数。
- hit_count:用于记录命中的次数。
- eviction_count:用于记录淘汰的次数。
### 1.3.3 函数 initCache()
功能:初始化 cache。
实现方法:对于给定的参数 S、B、E 利用 malloc 函数动态开辟 cache 所需要的内存大小。实现代码如下:
```c++
void initCache() {
int i,j;
cache = (cache_set_t*) malloc(sizeof(cache_set_t) * S);
for (i=0; i<S; i++) {
cache[i]=(cache_line_t*) malloc(sizeof(cache_line_t) * E);
for (j=0; j<E; j++) {
cache[i][j].valid = 0;
cache[i][j].tag = 0;
cache[i][j].lru = 0;
}
}
set_index_mask = (mem_addr_t) (pow(2, s) - 1);
}
```
### 1.3.4 函数 freeCache()
功能:释放 cache 所占用的内存。
实现方法:用循环遍历 cache 所申请的指针数组内存块,以此 free 掉各个内存块。实现代码如下:
```c++
void freeCache() {
int i;
for(i=0; i<S; i++) {
free(cache[i]);
}
free(cache);
}
```
### 1.3.5 函数 accessData()
功能:模拟 cache 进行的访问,给出所访问内存地址对应的是否命中或者是否淘汰。
实现方法:将输入地址和 set_index_mask 求与后得到一个索引,然后输入地址的前 s+b 位作为标签。依次查询每个块,并对比所需要的索引和标签,如果找到了相应数据,则 hit_count 加 1,否则 miss_count 加 1。并且在未命中时,先查询块中是否有空位置,有的话直接占用此空位置,否则需要找到 lru 最小的行(即最近访问时间间隔最长的行),然后进行数据的替换,eviction_count 加 1。实现代码如下:
```c++
void accessData(mem_addr_t addr) {
int i;
unsigned long long int eviction_lru = ULONG_MAX;
unsigned int eviction_line = 0;
int haveEmpty=0;//是否含有空位置
mem_addr_t set_index = (addr >> b) & set_index_mask;
mem_addr_t tag = addr >> (s+b);
int hit=0;
cache_set_t cache_set = cache[set_index];
for(i=0; i<E; i++) //E:相联度 即每一个组内有几块{
//所查询的块在cache内
if(cache_set[i].tag==tag&&cache_set[i].valid==1) {
if(verbosity) printf("hit ");
hit_count++;
cache_set[i].lru = ULONG_MAX;
hit = 1;
}
else if(!haveEmpty&&cache_set[i].valid==0) {
haveEmpty=1;
eviction_line=i;
}
else if(cache_set[i].valid==1) {
//每进行一次查询,含有数据的块lru减1
cache_set[i].lru--;
//找到lru最小的位置,作为预备淘汰
if(cache_set[i].lru<eviction_lru) {
eviction_lru=cache_set[i].lru;
eviction_line=i;
}
}
}
//未命中
if(hit==0) {
if(verbosity) printf("miss ");
miss_count++;
if(cache_set[eviction_line].valid==1)//有淘汰{
if(verbosity) printf("eviction ");
eviction_count ++;
}
cache_set[eviction_line].valid=1;
cache_set[eviction_line].lru=ULONG_MAX;
cache_set[eviction_line].tag=tag;
}
}
```
### 1.3.6 函数 replayTrace
功能:读取 trace 轨迹文件的内容,并根据其指令进行模拟内存访问的过程。
实现方法:通过文件读取函数 fscanf 进行文件流出读取,并将读取的内容赋值到 operation、addr 和 len 变量中,分别代表操作类型、地址、长度。然后根据 operation 的类型进行相应的函数调用。I 指令忽略,S 和 L 指令进行一次 cache 查询,即调用一次 accessData 函数,M 指令进行两次 cache 查询。实现代码如下:
```c++
void replayTrace(char* trace_fn) {
mem_addr_t addr=0;
unsigned int len=0;
char operation;
FILE* trace_fp = fopen(trace_fn, "r");
while(fscanf(trace_fp,"%c %llx,%d",&operation,&addr,&len)!=EOF) {
if(operation=='I'&&verbosity)
printf("%c %llx,%u ",operation,addr,len);
else if(operation=='L'||operation=='S'||operation=='M') {
if(verbosity) printf("%c %llx,%u ",operation,addr,len);
accessData(addr);
if(operation=='M') accessData(addr);
if(verbosity) printf("\n");
}
}
fclose(trace_fp);
}
```
### 1.3.7 函数 printUsage()
功能:当有输入格式错误或者输入-h 指令时,输出相应的信息。
实现方法:用 printf 函数输出相关信息。实现代码如下:
```c++
void printUsage(char* argv[]) {
printf("Usage: %s [-hv] -s <num> -E <num> -b <num> -t <file>\n", argv[0]);
printf("Options:\n");
printf(" -h Print this help message.\n");
printf(" -v Optional verbose flag.\n");
printf(" -s <num> Number of set index bits.\n");
printf(" -E <num> Number of lines per set.\n");
printf(" -b <num> Number of block offset bits.\n");
printf(" -t <file> Trace file.\n");
printf("\nExamples:\n");
printf(" linux> %s -s 4 -E 1 -b 4 -t traces/yi.trace\n", argv[0]);
printf(" linux> %s -v -s 8 -E 2 -b 4 -t traces/yi.trace\n", argv[0]);
exit(0);
}
```
## 1.4 实验结果和分析
修改完成 csim.c 文件后,进行 make 编译,并运行 test-csim,得到的测试结果如下:
![1](./photo/1-325a3ade69f5b7c7ff97958fa0dee3d4.png)
由运行结果可知,cache 模拟正确。
# 二、总结和体会
对 cache 进行的实验模拟算是比较简单的实验,仅仅只是模拟一个建议的 cache 然后对指令访问的命中和淘汰进行记录。需要考虑的函数实现大概就是 accessData 和 replayTrace,前者要进行 cache 内数据的查找和替换,后者是对文件的读取和指令类型判断。总体上来说,完成 cache 模拟实验加深了对 cache 运行模式的认知,也很好的理解了 LRU 淘汰策略的工作机制。
# 三、对实验课程的建议
所给的实验说明比较少,初步读完后并不知道需要如何开始实验,建议多给一些相关的提示,如需要实现的函数构建、cache 设计的基本思路等。
实验总体难度偏低,可以加大实验难度。
# 四、使用说明
1. 实验环境为Linux-64位
2. 实验所需要设计的文件位csim.c,即设计cache并进行模拟仿真
3. 所有的make文件均已经编写好,完成csim.c的编写后,在命令行输入如下命令进行编译
```
$ make clean
$ make
```
4. 编译完后会得到csim输出文件,输入对应的指令即可以模拟cache运行�
没有合适的资源?快使用搜索试试~ 我知道了~
基于C语言进行Cache模拟器实验【100012397】
共31个文件
trace:5个
c:5个
png:5个
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 173 浏览量
2023-05-24
14:12:11
上传
评论
收藏 93.57MB ZIP 举报
温馨提示
Cache模拟器实验,加深对cache运行模式的认知,理解LRU淘汰策略的工作机制。 对 cache 进行的实验模拟算是比较简单的实验,仅仅只是模拟一个建议的 cache 然后对指令访问的命中和淘汰进行记录。需要考虑的函数实现大概就是 accessData 和 replayTrace,前者要进行 cache 内数据的查找和替换,后者是对文件的读取和指令类型判断。总体上来说,完成 cache 模拟实验加深了对 cache 运行模式的认知,也很好的理解了 LRU 淘汰策略的工作机制。
资源推荐
资源详情
资源评论
收起资源包目录
100012397-基于C语言进行Cache模拟器实验.zip (31个子文件)
systemstructure
LICENSE 1KB
cachelab-handout
csim-ref 21KB
test-trans 26KB
README 1KB
Makefile 771B
trans.c 2KB
tracegen.c 3KB
csim 20KB
tracegen 21KB
周大伟U201815553.tar 20KB
traces
long.trace 3.34MB
yi2.trace 112B
dave.trace 41B
trans.trace 8KB
yi.trace 58B
csim.c 7KB
.csim_results 19B
driver.py 5KB
test-trans.c 8KB
test-csim 16KB
cachelab.c 2KB
cachelab.h 1KB
计算机系统结构实验.pptx 11.04MB
.gitignore 430B
Xshell-7.0.0054p.rar 82.14MB
photo
1-325a3ade69f5b7c7ff97958fa0dee3d4.png 48KB
104409_d06873eb_8206880.png 27KB
104634_342ad697_8206880.png 127KB
105139_1e60fb84_8206880.png 235KB
104253_2194c746_8206880.png 67KB
README.md 9KB
共 31 条
- 1
资源评论
神仙别闹
- 粉丝: 2706
- 资源: 7641
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功