Cache相关理解:
1)Cache是由硬件进行管理的,设计cache的目的是能够让最常访问的数据集中在访问速度最快的缓存中,使得alu读写数据速度快,效率高。
一个Cache可以看成是一个二维数组,这个数组内的元素就是一个cache_line结构体,这个cache_line结构体内部保存的有一个valid bit,一些tag bits,以及一个2^b bytes大小的数据块,这个数据块是连续的。
我们通过物理cache地址来进行寻址
cache 示意图
先通过set_index找到具体的sets,再写一个循环来找到valid是1,tag bits相同的cache中的line。再在line里面存放的block根据块偏移量找到对应的具体字节。
CSAPP搭配cache_lab
```
#include "stdio.h"
const int maxi=999;
cache _cache;
int hits=0;int evictions=0;int mises=0;
typedef struct{
unsigned int valid;//有效位
unsigned int tag_bit;//标识位
int time_stamp;
} cache_line,cache_asso*,cache**;
int getNum(char* str,int n);
void parse_command(char* argc[],int* S,int* E,int* b,char* filename,int* isVerbose)
void init(int S,int E);
void update_stamp(cache _cache,int S,int E);
void parse_addr(unsigned int addr);
void parse_trace(char* filename);
/*
使用LRU算法来寻找victim,LRU算法在具体实现的时候,
可以用权重来看,每一次访问时权重增加1,最重要被
替换的是权重最轻的那一个line
*/
int getNum(char* str,int n){
int sum=0;
for(int i=0;i<n;i++){
sum+=sum*10+str[i]-'0'
}
return sum;
}
void parse_command(char* argc[],int* S,int* E,int* b,char* filename,int* isVerbose){
if(strcmp(argc[1],"-v")==0) {
*isVerbose=1;
(*S)=getNum(argc[3],strlen(argc[3]));
(*E)=getNum(argc[5],strlen(argc[5]));
(*b)=getNum(argc[7],strlen(argc[7]));
filename=argc[9];
} else{
*isVerbose=0;
(*S)=getNum(argc[2],strlen(argc[2]));
(*E)=getNum(argc[4],strlen(argc[4]));
(*b)=getNum(argc[6],strlen(argc[6]));
filename=argc[8];
}
}
void init(int S,int E){
_cache=(cache)malloc(sizeof(cache_asso)*S);
for(int i=0;i<S;i++){
_cache[i]=(cache_asso)malloc(sizeof(cache_line)*E);
for(int j=0;j<E;j++){
_cache[i][j].tag=0;
_cache[i][j].valid=0;
_cache[i][j].time_stamp=0;
}
}
}
/*
memory address format:
高位 低位
tag == sets_index == block_offset
t s b
命中的原则是:
1.设置了有效位
2.请求地址的标记位与cache地址的标位一致
*/
int bi2decimal(unsigned int sets_index){
int ans=0;
while(sets_index){
int tmp=sets_index%10;
ans=ans*2+tmp;
sets_index=sets_index/10;
}
return ans;
}
bool isHit(unsigned int sets_index,unsigned int tag,int E){
int index=bi2decimal;
cache_asso s=_cache[index];
for(int i=0;i<E;i++){
if(s[i].valid==1 && s[i].tag_bit==tag){
s[i].time_stamp++;
return true;
}
}
return false;
}
void exec(unsigned int tag,int sets_index,int S,int E){
if(isHit(sets_index,tag,E)) hits++;
else mises++;
}
void parse_trace(char* filename,int S,int E,int s,int b){
FILE* fp;
fp=fopen(filename,"r");
if(fp==NULL) printf("Wrong reading file!");
char op[max];unsigned int addr;int offset;
FILE* fp;
fp = fopen(filename,"r");
char op;unsigned int addr;unsigned int offset;
while(fscanf(fp," %c %d,%d",&op,&addr,&offset)!=EOF){
unsigned int tag=addr>>(s+b);
unsigned int sets_index=addr>>b;;
exec(tag,sets_index,S,E);
}
fclose(fp);
for(int i=0;i<S:i++){
free(_cache[i]);
}
free(_cache);
}
int main(int argv,char* argc[]){
if(argv==1){
printf("Wrong input!");
return 0;
}
int S;int E;int isVerbose;char filename[maxi];
parse_command(argc,&S,&E,filename,&isVerbose);
init(S,E);
parse_trace(filename,S,E);
printf("hits:%d",hits,"evictions:%d",evictions,"mises:%d",mises);
return 0;
}
```