-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathmain.c
More file actions
executable file
·376 lines (344 loc) · 9.89 KB
/
main.c
File metadata and controls
executable file
·376 lines (344 loc) · 9.89 KB
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
/* main.c
* Jen Hanni
*
* The main reads the file 'test.txt' and
* pass on the command and addresses to the appropriate functions.
*
* test.txt contains lines of the form:
* 2 10019d94
* where the first single digit is 'n'
* and the second string is the address in hex
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
// only change these lines when changing total size of the cache!
// LINES is the total number of lines (16384 for a 16K line cache)
// WAYS is the total number of ways (columns) in that cache
// MAXLINE and MAXWAY are LINES-- and WAYS-- respectively
#define LINES 16483
#define WAYS 16
#define MAXLINE 16482
#define MAXWAY 5
#define M 0
#define E 1
#define S 2
#define I 3
typedef struct
{
int MESIbits;
int LRUbits;
int tag;
int address;
} cacheLine;
// initialize a multi-dimensional array [row][col]
// creates the single global cache
cacheLine L2cache[LINES][WAYS];
FILE *ifp,*ofp;
// step through the cache and set initial values
// LRU bit will be the same value as the way
// MESI bit begins invalid (empty)
// Tag bits set to null because access decisions based on MESI
void setLRUbitsToWay()
{
int index;
int way;
for (index = 0; index <= MAXLINE; index++)
{
for (way = 0; way <= MAXWAY; way++)
{
L2cache[index][way].LRUbits = way;
L2cache[index][way].MESIbits = 3;
L2cache[index][way].tag = 0;
}
}
}
// check every way in the given index to see if the given tag exists
// tag in each way of the appropriate index
int checkTag(int index, int tag)
{
int way;
for (way = 0; way <= MAXWAY; way++)
{
if (L2cache[index][way].tag == tag)
return way;
}
return WAYS;
}
// given an index, this function returns the least recently used way
// LRU bits of 0 give the least recently used way
// LRU bits of MAXWAY give most recently used way
int checkLRU(int index)
{
int way;
for (way = 0; way <= MAXWAY; way++)
{
if (L2cache[index][way].LRUbits == 0)
return way;
}
return WAYS;
}
// this function updates the LRU bits to reflect a new most recently used way
void updateLRU(int index, int ourway)
{
// if the LRU bits of our way are already the most recently used, we do nothing
if (L2cache[index][ourway].LRUbits == MAXWAY)
return;
else
{
int ourbits = L2cache[index][ourway].LRUbits;
int testbits = ourbits++;
int testway;
for (testbits = 0; testbits <= MAXWAY; testbits++)
{
testway = 0;
while (testway <= MAXWAY)
{
if (testbits == L2cache[index][testway].LRUbits)
{
L2cache[index][testway].LRUbits--;
break;
}
else
testway++;
}
}
L2cache[index][ourway].LRUbits = MAXWAY;
}
}
// This function takes in an index and tests all ways within that index,
// returning a 0 if it finds any valid way and a 1 if it does not.
int testIndex(int index, int way)
{
for (way = 0; way <= MAXWAY; way++)
{
if (L2cache[index][way].MESIbits != I)
{
return 0;
}
}
return 1;
}
// The cache displays all indices containing at least one way with a
// valid MESI bit
void cacheDisplay()
{
int index;
int way;
ofp = fopen("display.txt", "a");
for (index = 0; index <= MAXLINE; index++)
{
if (testIndex(index,way) == 0)
{
fprintf(ofp,"INDEX: 0x%-8x\n",index);
fflush(ofp);
for (way = 0; way <= MAXWAY; way++)
{
fprintf(ofp,"WAY %-8d LRU: %-4d MESI: %-10d TAG: %-8d"
" ADDR: 0x%-8x\n",
way,
L2cache[index][way].LRUbits,
L2cache[index][way].MESIbits,
L2cache[index][way].tag,
L2cache[index][way].address);
fflush(ofp);
}
}
}
fprintf(ofp,"---------------------------------------------------------------------\n");
fflush(ofp);
}
int main()
{
memset(L2cache, 0, sizeof (cacheLine));
// initialize the counters
int refCount = 0;
int readCount = 0;
int writeCount = 0;
int hitCount = 0;
int missCount = 0;
int hitM = 0;
int hit = 0;
int way;
// initialize the input from the tracefile
int n;
int addr;
// initialize the LRU bits to the way
setLRUbitsToWay();
// open the tracefile, make it available to 'r' read
// open the output file to make it available to append each iteration's result
ifp = fopen("testfile.din", "r");
ofp = fopen("display.txt", "w");
// set it up to read line by line, set n and addr accordingly
while (fscanf(ifp, "%d %x\n", &n, &addr) != EOF)
{
// parse 32-bit hex address
int tag = addr >> 20;
int index = (addr >> 6) & 16383;
// get 1 bit from the fifth position to check later whether 1 or 0
// int byteSelect = (addr >> 5) & ~(~0 << 1);
refCount++;
switch (n)
{
// n = 0 read data request from L1 cache
// n = 2 instruction fetch (treated as a read request from L1 cache)
case 0:
case 2:
readCount++;
way = checkTag(index, tag);
// if the tag exists
if (way <= MAXWAY)
{
int MESI = L2cache[index][way].MESIbits;
// if this tag exists and it's valid as per its MESI bits
if (MESI == M || MESI == E || MESI == S)
{
hitCount++;
updateLRU(index, way);
// MESI remains unchanged
}
// if this tag exists but it's been invalidated and can't be used...
// we fetch from DRAM and pass on to L1 cache, update to exclusive
else
{
missCount++;
updateLRU(index, way);
L2cache[index][way].MESIbits = E;
}
}
// this tag simply doesn't exist in the cache in any form
else
{
missCount++;
// use the LRU bits to determine which way to evict
way = checkLRU(index);
updateLRU(index, way);
L2cache[index][way].tag = tag;
L2cache[index][way].MESIbits = E;
}
L2cache[index][way].address = addr;
break;
// 1 write data request from L1 cache
case 1:
writeCount++;
way = checkTag(index, tag);
if (way <= MAXWAY)
{
int MESI = L2cache[index][way].MESIbits;
// if this tag exists and it's valid per its MESI bits...
if (MESI == M || MESI == E || MESI == S)
hitCount++;
// if this tag exists MESI bits say invalid, needs to be set M
else
missCount++;
}
// if this tag simply doesn't exist in the cache in any form...
// this covers the very unlikely odd case where L1 has what L2 doesn't
else
{
missCount++;
way = checkLRU(index);
L2cache[index][way].tag = tag;
}
updateLRU(index, way);
L2cache[index][way].MESIbits = M;
L2cache[index][way].address = addr;
break;
// 4 snooped a read request from another processor
case 4:
readCount++;
way = checkTag(index, tag);
// if the tag exists
if (way <= MAXWAY)
{
int MESI = L2cache[index][way].MESIbits;
// if this tag exists and is valid and modified per its MESI bits...
if (MESI == M || MESI == E || MESI == S)
{
hitCount++;
// if modified, send copy to other cache, then L1, then to DRAM
if (MESI == M)
hitM++;
else
hit++;
// then set MESI to shared
L2cache[index][way].MESIbits = S;
L2cache[index][way].address = addr;
}
// if the tag exists but it's invalid then we don't have it...
else
missCount++;
}
break;
// 3 snooped invalidate command from another processor
// 5 snooped write request from another processor
case 3:
case 5:
if (n == 5)
writeCount++;
way = checkTag(index, tag);
// if the tag exists...
if (way <= MAXWAY)
{
int MESI = L2cache[index][way].MESIbits;
if (MESI == M || MESI == E || MESI == S)
{
hitCount++;
L2cache[index][way].MESIbits = I;
L2cache[index][way].address = addr;
updateLRU(index, way);
}
else
missCount++;
}
else
missCount++;
break;
// 6 snooped read for ownership request
case 6:
readCount++;
way = checkTag(index, tag);
// if the tag exists
if (way <= MAXWAY)
{
int MESI = L2cache[index][way].MESIbits;
// serve if modified tag exists, then invalidate
if (MESI == M || MESI == E || MESI == S)
{
hitCount++;
if (MESI == M)
hitM++;
L2cache[index][way].MESIbits = I;
updateLRU(index, way);
L2cache[index][way].address = addr;
}
else // if we don't have it, do nothing
missCount++;
}
break;
// 8 clear the cache entirely
case 8:
fprintf(ofp,"Reference %d called for the cache to be reset. No ways are valid.\n"
"---------------------------------------------------------------------\n",
refCount);
fflush(ofp);
setLRUbitsToWay();
break;
// 9 print the cache but change/destroy nothing
case 9:
fprintf(ofp,"Reference %d displayed only indices containing valid ways.\n",refCount);
fflush(ofp);
cacheDisplay();
break;
} // end switch statement
} // end while loop
float hitRatio = (float) hitCount / refCount;
printf(" Total References: %d\n Reads: %d\n Writes: %d\n Hits: %d\n"
" Misses %d\n Hit ratio: %f\n"
"---------------------------------------------------------------------\n",
refCount,readCount,writeCount,hitCount,missCount,hitRatio);
fflush(ofp);
return 0;
} // end main()