0%

今天做的cacheLab

就学习的反思

试问这样一个问题,倘若我没有上网搜别人的成果,大概我是不能(人不能把自己说死,但我配做人吗)写出来的吧,因为这里面getopt的使用,miss的各种定义,实际上都是学习得来的,换句话说就是duplicate,问题在于,我能否记住和熟练,不过我也知道,有些知识是工具性的,有些则是思想,比如这个cache就是重要的思想,我做这个Lab其实最重要的也就是记住了缓存的设计理念以及由此推理出来的locality对程序(正好我也在刷算法题)的性能的影响或者说指导作用。
我的参考超文本链接:
https://zhuanlan.zhihu.com/p/79058089

PartA源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include "cachelab.h"
#include <unistd.h>
#include <math.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <limits.h>
#include <stdio.h>
#include <stdint.h>

typedef struct cache_line
{
int valid;
int tag;
int stamp;
/* data */
}cache_line, *cache_set, **cache;

extern char* optarg;
int b,t,s,B,S,E,isVerbose = 0;
char traceName[100];//store the traceFileName
int hit_count, miss_count, eviction_count;
cache myCache = NULL;

void printHelp(){
printf("Usage: ./csim-ref [-hv] -s <num> -E <num> -b <num> -t <file>\n"
"Options:\n"
" -h Print this help message.\n"
" -v Optional verbose flag.\n"
" -s <num> Number of set index bits.\n"
" -E <num> Number of lines per set.\n"
" -b <num> Number of block offset bits.\n"
" -t <file> Trace file.\n\n"
"Examples:\n"
" linux> ./csim-ref -s 4 -E 1 -b 4 -t traces/yi.trace\n"
" linux> ./csim-ref -v -s 8 -E 2 -b 4 -t traces/yi.trace\n");
}

void updateStamp(){
for(int i = 0; i < S; i++){
for (int j = 0; j < E; j++){
if(myCache[i][j].valid){//just to assure us that it's pointful.
myCache[i][j].stamp++;//time has passed
}
}
}
}
void update(uint64_t address){
uint64_t mask = UINT64_MAX >> ((uint64_t)64 - (uint64_t)s);
int set_index = (address >> b) & mask;
int tag_index = address >> (b + s);
int MAX_STAMP = INT_MIN;
int MAX_STAMP_INDEX = -1;//note down the to-be-evicted cache_line.
for(int i = 0; i < E; i++){
if(myCache[set_index][i].tag == tag_index){//hit and set the stamp to zero,hit refers to find the block no matter valid or not
myCache[set_index][i].stamp = 0;
++hit_count;
return;
}
}
miss_count++;
for(int i = 0; i < E; i++){
if(myCache[set_index][i].valid == 0)//cold miss
{
myCache[set_index][i].stamp = 0;
myCache[set_index][i].tag = tag_index;//then it will load the block/cache_line
myCache[set_index][i].valid = 1;
return;
}
}
//miss and not found the block when it's already warmed up(not cold miss)
//need to evict some cache_line(the set is full and you need to tackle the mapping), since conflict miss happens, same set_index but not same block
//search for the largest stamp
for(int i = 0; i < E; i++){
if(myCache[set_index][i].stamp > MAX_STAMP){
MAX_STAMP = myCache[set_index][i].stamp;
MAX_STAMP_INDEX = i;
}
}
//evict it
++eviction_count;
myCache[set_index][MAX_STAMP_INDEX].tag = tag_index;//now replacement has taken place;
myCache[set_index][MAX_STAMP_INDEX].stamp = 0;//is already valid;
myCache[set_index][MAX_STAMP_INDEX].valid = 1;
}
void parseTrace(const char *tarceName){
FILE* pFile = fopen(tarceName, "r");
char identifier;
uint64_t address;
int size; //in fact the aligned memory is proper, so we don't care about this "size";
// Reading lines like " M 20,1" or "L 19,3"

while(fscanf(pFile," %c %lx,%d", &identifier, &address, &size)>0)
{
updateStamp();//a time_piece has passed, the stamp++,or you are accessed rearward to be set zero.
switch(identifier){
/*data modified*/ case 'M':{
update(address);//load once
update(address);//store once
break;
}
/*data stored*/ case 'S':{
update(address);
break;
}
/*data loaded*/ case 'L':{
update(address);
break;
}
default:continue;
}

}

fclose(pFile); //remember to close file when done
}
void freeCache(){
for(int i = 0; i < S; i++){//trace's been tackled.
free(myCache[i]);
}
free(myCache);
}
void initCache(){
myCache = (cache_set*)malloc(S * sizeof(cache_set));
for(int i = 0; i < S; i++){
myCache[i] = (cache_line*)malloc(E * sizeof(cache_line));
for(int j = 0; j < E; j++){
myCache[i][j].stamp = -1;//unused
myCache[i][j].tag = -1;//waiting for changing
myCache[i][j].valid = 0;//cold cache
}
}
}
int main(int argc, char** argv)
{
int opt;
while(-1 != (opt = getopt(argc, argv, "hVs:E:b:t:"))){
switch (opt)
{
case 'h':
printHelp();
break;
case 'v':
isVerbose = 1;
break;
case 's':
{
s = atoi(optarg);
break;
}
case 'E':
{
E = atoi(optarg);
break;
}
case 'b':
b = atoi(optarg);
break;
case 't':{
strcpy(traceName, optarg);
break;
}
default:
printf("wrong argument!");
break;
}
}
S = 1 << s;
B = 1 << b;
initCache();
parseTrace(traceName);
freeCache();
printSummary(hit_count, miss_count, eviction_count);
return 0;
}