Cache Lab

CACHE Lab

是真的不想写,对C的很多细节都忘了,简直是 折 磨
不写就不会提高了,,,人要变强就要变秃,我还是继续写吧,,,
奥利给干了兄弟们!

Part.A

C补漏

  1. 从命令行对输入数据的读取用getopt()
    主要用来解析输入的命令。atoi函数是将字符转换成整数的函数。
  2. C自定义函数放在main前面,否则要加函数原型。
  3. C中布尔用_Bool,正确与否用1/0。
  4. FILE 类型管理文件,本次lab中用FILE定义了输入文件的路径
  5. 利用fscanf()来实现对trace文件中字符的读取。函数原型为int fscanf(FILE * stream, const char * format, [argument...]);这里并不需要提前把所有trace都读进去,只需要每次读一行处理一行
  6. 利用malloc()来实现对内存的申请,C 库函数 void *malloc(size_t size)分配所需的内存空间,并返回一个指向它的指针(指针要经过强制类型转换为需要的指针)。申请完毕后要释放
    下面看看申请一维,二维,三维数组时的例子:
	//一维数组m
	char *p = (char *)malloc(m*sizeof(char));//申请一个大小为m的char数组
	...
	free(p);//释放空间
	
	//二维数组m*n
	char **p = (char **)malloc(m*sizeof(char*));
  	for(int i=0;i<m;i++){
  		p[i]=(char *)malloc(n*sizeof(char));
 	}//申请一个大小为m*n的char数组
 	...
 	for(int i=0;i<m;i++){
 		free(p[i]);
 	}
	free(p);//释放空间
	
	//三维数组m*n*k
	char*** p = (char***)malloc(m*sizeof(char**));
	for(int i=0;i<m;i++){
		p[i]=(char**)malloc(n*sizeof(char*));
	}
	for(int i=0;i<m;i++){
		for(int j=0;j<n;j++){
			p[i][j]=(char*)malloc(k*sizeof(char));
		}
	}//申请一个m*n*k的三位数组
	...
	for(int i=0;i<m;i++){
		for(int j=0;j<n;j++){
			free(p[i][j]);
		}
	}
	for(int i=0;i<m;i++){
		free(p[i]);
	}
	free(p);//释放空间

数据结构设计与需要注意的点

在这里插入图片描述

  1. 在动态分配内存时,每一行并不需要分配大小为b的内存,因为我们的缓存模拟器只需要模拟缓存是否命中,而不需要存储里面的实际内容。
  2. cache_line的设计:cache的每一行用一个cache_line的struct表示,根据1,并不用实际分配内存。cache_line的实际数据结构包含三个量:
    tag用于查看地址是否存在于缓存中
    valid_bit用于标记是否已经初始化
    stamp用于记录该line有多久没有更新,stamp值越大,被替换的优先级就越大。
  3. Cache[2^s][E] 数组用于存放cache_line。
  4. 由于地址值要进行右移,用unsigned比较好,否则会引入符号位。
  5. 时间戳算法:每个cache_line都有一个stamp变量,记录该line有多少轮没有更新。在查找未命中而替换时,替换E个cache_line中stamp值最大的那个。每次只要更新,就把该值置为0。每输入完一个数据,就对Cache数组中的所有cache_line进行时间戳更新。

代码

#include "cachelab.h"
#include <getopt.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stddef.h>
typedef struct{
	int valid_bits;
	unsigned  tag;
	int stamp;
}cache_line;//定义结构体为cache中的每一行
char* filepath = NULL;//路径
int s,E,b,S;// s is set ,E  is line,each line have 2^b bits ,S is 2^s set
int hit=0,miss=0,eviction=0;
cache_line** cache = NULL;//定义cache为代表缓存的数组
void init(){
	cache = (cache_line**)malloc(sizeof(cache_line*)*S);             
	for(int i=0;i<S;i++)
		*(cache+i) = (cache_line*)malloc(sizeof(cache_line)*E);//malloc cache[S][E],给数组分配动态空间
	for(int i=0;i<S;i++){
		for(int j=0;j<E;j++){
			cache[i][j].valid_bits = 0;      // set all valid_bits is zero
			cache[i][j].tag = 0xffffffff;    //no address
			cache[i][j].stamp = 0;           //time is 0;		
		}	
	}
}
void update(unsigned address){//cache中的s值可以直接通过地址找到,但是E值却只能通过遍历来看是否匹配
	unsigned s_address =(address>>b) & ((0xffffffff)>>(32-s));                //set`s index
	unsigned t_address = address>>(s+b);                                 //tag`s index
	for(int i=0;i<E;i++){
		if((*(cache+s_address)+i)->tag ==t_address){
			cache[s_address][i].stamp = 0;       
			hit++;
			return;
		}
	}//命中,将时间戳记为0
	for(int i=0;i<E;i++){
		if(cache[s_address][i].valid_bits == 0){
			cache[s_address][i].tag = t_address;
			cache[s_address][i].valid_bits = 1;
			cache[s_address][i].stamp = 0;       //now ,this is load
			miss++;
			return;
		}
	}//初始化加载
	//下面是没有命中,但是缓存已经初始化完的情况,此时开始替换。
	int max_stamp=0;
	int max_i;
	for(int i=0;i<E;i++){
		if(cache[s_address][i].stamp >max_stamp){
			max_stamp = cache[s_address][i].stamp;
			max_i = i;
		}
	}//遍历整个E,找一个长时间没有更新的(stamp值最大的),对其进行替换。
	eviction++;
	miss++;
	cache[s_address][max_i].tag = t_address;
	cache[s_address][max_i].stamp = 0;	//更新tag和stamp值
}
void time(){
	for(int i=0;i<S;i++){
		for(int j=0;j<E;j++){
			if(cache[i][j].valid_bits == 1)
				cache[i][j].stamp++;		
		}	
	}
}//每一轮之后都要更新所有时间戳,统统加一
int main(int argc,char *argv[])
{
	int opt;         
	while((opt = getopt(argc,argv,"s:E:b:t:")) !=-1){           //parse command line arguments
		switch(opt){
		case 's':
			s=atoi(optarg);
			break;
		case 'E':
			E=atoi(optarg);
			break;
		case 'b':
			b=atoi(optarg);
			break;
		case 't':
			filepath = optarg;
			break;
		}
	}
	S = 1<<s;
	init();
	FILE* file=fopen(filepath,"r");
	if(file == NULL){     // read trace file
		printf("Open file wrong");		
		exit(-1);
	}
	char operation;
	unsigned address;
	int size;	
	while(fscanf(file," %c %x,%d",&operation,&address,&size)>0){
		switch(operation){
			case 'L':
				update(address);
				break;
			case 'M':
				update(address);//M后面没有break,代表读写两次
			case 'S':
				update(address);
				break;
		}
		time();
	}
	for(int i=0;i<S;i++)                  //free cache[S][E]
		free(*(cache+i));
	free(cache);
	fclose(file);	                //close file	
    printSummary(hit,miss,eviction);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值