CacheLab实验

这是一个模拟缓冲访问的实验(虽然我没看懂题目要求)。

因为英文看着费劲,所以在网上找了一些解释。这个星期就慢慢研究一下吧。

实验要求:模拟缓存工作,要根据输入的指令和数据输出命中率等信息(看完了整个实验的要求,仍然一头雾水,谁写的实验介绍啊)

内存单元包含内容

这里用一个结构类型记录内存的信息

struct line{
	int valid;//表示这块内存行内有没有数值存放
	int time;//表示多久没有使用
}

预先设置参数

有一些变量全局都需要使用,所以提前定义;

int s, v = 0, e, b;
long S;
struct line *cache[];

接收参数

因为需要接收参数,所以需要给main函数加入参数,形如:

int main(int argc, char* argv[])
{
	····
	return 0;
}

网上找了一些其他的资料,发现也有用getopt()这个函数的,需要包含“getopt.h”这个头文件。因为没用过而且看起来很麻烦就用上面的方法吧

update函数

在每次调用操作函数之前,都需要调用update将内存行结构体里的time+1;

void update(){
	int i;
	for(i = 0;i < S;i++){
		int j;
		for(j = 0;j < e;j++){
			cache[i*e+j].time++;
		}
	}
}

Load函数

Load是读取内存,如果对应的内存没有值,即valid==0,那么就hits++,并且再将它的valid重新置为1。

void Load(long addr){
	update();
	long mask = 0;
	mask = ((~mask)<<(s+e))|(~((~mask)<<e));
	long set = addr&mask;
	mask = 0;
	mask = ~((~mask)<<(e+s));
	long tag = mask&addr;
	if(cache[set*e+tag].valid==0){
		if(v)
			printf("miss\n");
		misses++;
		cache[set*e+tag].valid=1;
		cache[set*e+tag].time=0;
	}
	else{
		if(v)
			printf("hit\n");
		hits++;
		cache[set*e+tag].time=0;
	}
}

Store函数

void Store(long addr){
	update();
	long mask = 0;
	mask = ((~mask)<<(s+e))|(~((~mask)<<e));
	long set = addr&mask;
	mask = 0;
	mask = ~((~mask)<<(e+s));
	long tag = mask&addr;
	if(cache[set*e+tag].valid==1){
		if(v)
			printf("miss\n");
		misses++;
		int i, t = 0;
		for(i = 0;i < S;i++){
			int j;
			for(j = 0;j < e;j++){
				if(cache[i*e+j].valid==0){
					t = 1;
					cache[i*e+j].time=0;
					cache[i*e+j].valid=1;
					goto A;
				}
			}
		}
		A:;
		if(t){
			if(v){
				printf("evition\n");
			}
			int time = 0;
			for(i = 0;i < S;i++){
				int j;
				for(j = 0;j < e;j++){
					if(cache[i*e+j].time>cache[time].time){
						time = i*e+j;
					}
				}
			}
			cache[time].time = 0;
		}
	}
	else{
		if(v)
			printf("hit\n");
		hits++;
		cache[set*e+tag].time=0;
	}
}

参数判断

根据它给出的范例文件‘csim-ref’,我们需要模仿这个文件进行输入输出。这个文件支持-h、v、E、s、b、t等一系列操作。 除了h、v之外,其他操作都带有后续的参数。这里贴上原文描述: 那么就需要构建一个判断语句,这里我采用switch,然后要将传入的参数字符串中的数字部分转换成整型保存。

首先是读取文件中的操作参数,格式如下:op address,size。其中op是操作类型,address是地址,size是操作空间大小。 那么就用如下方法读取:

while(!feof(fp)){
	char op;
	int size;
	long addr;
	fscanf(fp, "%c %x,%d", &op, &addr, &size);
	if(v)
		printf("%c %x,%d", op, addr, size)
	if(op == 'I'){
		continue;
	}
	else if(op == 'M'){
		Modify(addr);
	}
	else if(op == 'L'){
		Load(addr);
	}
	else{
		Store(addr);
	}
}