-
Notifications
You must be signed in to change notification settings - Fork 0
/
set.cxx
executable file
·368 lines (333 loc) · 8.5 KB
/
set.cxx
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
/* set.cxx
* implementaiton of the set class for the cache simulator
*
* ECEN 4593, Fall 2010
* Danny Gale, Chris Messick
*
* REVISION HISTORY:
* 11/8/2010 Danny Gale created
*
*/
using namespace std;
// COMPILER INCLUDES
#include <iostream>
#include <iomanip>
#include <fstream>
// PROJECT INCLUDES
#include "set.h"
#include "cacheline.h"
#include "defines.h"
// CONSTRUCTOR
set::set()
{
associativity = 1;
}
// DESTRUCTOR
set::~set()
{
cacheLine * cursor = head;
cacheLine * temp = head;
while (cursor != 0)
{
temp = cursor;
cursor = cursor->get_next();
delete temp;
}
}
// Inserts a cacheLine pointed to by newLine into the set
// INCREASES SIZE BY 1
/*
void set::add_line()
{
cacheLine * temp;
if (size >= associativity)
{
cerr << "Set trying to increase beyond associativity. Exiting.";
exit(ES_SET_SIZE);
}
else
{
// add to lines
temp = head;
head = new cacheLine;
head->set_next(temp);
size++;
}
}
*/
// returns a pointer to a block
cacheLine * set::get_block(unsigned i)
{
cacheLine * it;
unsigned j = 0;
if (head == 0)
cout << "Set is empty" << endl;
else
{
it = head;
for(j = 0; j < i; j++)
{
it = it->get_next();
if (it == 0)
return it;
}
}
cout << "returning block # " << j << " from get_block" << endl;
return it;
}
// resizes the dynamic array
// DELETES THE CONTENTS OF THE SET
void set::set_associativity(unsigned assoc)
{
cacheLine * cursor = head;
cacheLine * temp;
//unsigned i;
// delete the old array of lines
while(cursor != 0)
{
temp = cursor;
cursor = cursor->get_next();
delete temp;
}
// update the associativity
associativity = assoc;
size = 0;
head = 0;
}
// returns a cacheLine * if one was evicted
cacheLine * set::update_LRU(cacheLine * mostRecent)
{
/*
cacheLine * cursor, * prevCursor, * oldHead, *retPtr = 0;
enum LRU_STATE_T { SEARCH_SET, MOVE_TO_HEAD, SIZE_COMPARE, EVICT_TAIL,
MAKE_BLOCK, DONE };
LRU_STATE_T state = SEARCH_SET;
while (state != DONE)
{
switch(state)
{
case SEARCH_SET:
if (head == 0)
{
state = SIZE_COMPARE;
break;
}
else
{
cursor = head;
prevCursor = cursor;
while (cursor->get_next() != 0)
{
if (cursor->get_tag() == mostRecent->get_tag() && cursor->get_valid())
{
// found it
state = MOVE_TO_HEAD;
}
prevCursor = cursor;
}
// didn't find it
// cursor currently points to tail
// and prevCursor points to previous node
// unless associativity is 1, in which case they both point to the head
state = SIZE_COMPARE;
break;
}
break;
case MOVE_TO_HEAD:
if (prevCursor == cursor)
{
*/
#ifdef _DEBUG_SET_UPDATELRU_
cout << "\t_DEBUG_SET_UPDATELRU_\tmost recent: tag = " << mostRecent->get_tag() << endl;
#endif
cacheLine * cursor, * prevCursor, * oldHead, * retPtr = 0;
#ifdef _DEBUG_SET_UPDATELRU_
cout << "\t_DEBUG_SET_UPDATELRU_\tchecking set (size = " << size << ", assoc = " << associativity << ") for tag " << mostRecent->get_tag() << endl;
#endif
if (head == 0)
{
#ifdef _DEBUG_SET_UPDATELRU_
cout << "\t_DEBUG_SET_UPDATELRU_\tset is empty. setting mostRecent as head. returning" << endl;
#endif
head = mostRecent;
size++;
return 0;
}
else if (head == mostRecent)
{
#ifdef _DEBUG_SET_UPDATELRU_
cout << "\t_DEBUG_SET_UPDATELRU_\ttag was found at the head. returning" << endl;
#endif
return 0;
}
else if (associativity == 1)
{
// simply replace the current head with most recent, return the current head
retPtr = head;
head = mostRecent;
return retPtr;
}
else
{
prevCursor = head;
// check the set to see if it's currently in the list
for (cursor = head; cursor->get_next() != 0; cursor = cursor->get_next())
{
if (cursor->get_next() == mostRecent)
{ // found it, one spot beyond cursor
#ifdef _DEBUG_SET_UPDATELRU_
cout << "\t_DEBUG_SET_UPDATELRU_\ttag has been found in the set not at the head. moving to head and returning" << endl;
#endif
// if it's not already the head
// move it to the head
oldHead = head;
head = cursor->get_next();
cursor->set_next(cursor->get_next()->get_next());
head->set_next(oldHead);
return 0;
}
#ifdef _DEBUG_SET_UPDATELRU_
cout << "\t_DEBUG_SET_UPDATELRU_\tcursor = " << cursor << ", prevCursor = " << prevCursor << endl;
#endif
}
#ifdef _DEBUG_SET_UPDATELRU_
cout << "\t_DEBUG_SET_UPDATELRU_\ttag was NOT found in the set" << endl;
#endif
// ok, we didn't find it
// we need to evict the least recently used one
// IF the set is full
// which is currently pointed to by cursor
#ifdef _DEBUG_SET_UPDATELRU_
cout << "\t_DEBUG_SET_UPDATELRU_\tcursor = " << cursor << ", prevCursor = " << prevCursor << endl;
#endif
if (size == associativity)
{ // set is full, size doesn't change
#ifdef _DEBUG_SET_UPDATELRU_
cout << "\t_DEBUG_SET_UPDATELRU_\tsize == associativity. SET IS FULL. cursor = " << cursor << ", prevCursor = " << prevCursor << endl;
#endif
if (cursor->get_next() == 0)
{ // found at the end of the list.
#ifdef _DEBUG_SET_UPDATELRU_
cout << "\t_DEBUG_SET_UPDATELRU_\tCursor is currently at the end of the list" << endl;
#endif
oldHead = head;
head = mostRecent;
head->set_next(oldHead);
prevCursor->set_next(0);
retPtr = cursor;
}
else
{
retPtr = cursor->get_next();
cursor->set_next(0);
mostRecent->set_next(head);
head = mostRecent;
}
#ifdef _DEBUG_SET_UPDATELRU_
cout << "\t_DEBUG_SET_UPDATELRU_\tset is full. evicting least recently used block" << endl;
#endif
}
else if (size < associativity)
{
#ifdef _DEBUG_SET_UPDATELRU_
cout << "\t_DEBUG_SET_UPDATELRU_\tset is NOT full. adding to head of set" << endl;
#endif
oldHead = head;
head = mostRecent;
mostRecent->set_next(oldHead);
retPtr = 0;
size++;
}
else
{
#ifdef _DEBUG_SET_UPDATELRU_
cout << "\t_DEBUG_SET_UPDATELRU_\tERROR: SET IS OVERSIZE" << endl;
exit(ES_LINES_OVERSIZE);
#endif
}
#ifdef _DEBUG_SET_UPDATELRU_
cout << "\t_DEBUG_SET_UPDATELRU_\treturning retPtr = " << retPtr << endl;
#endif
return retPtr;
}
}
// searches the list of lines for a given tag
// if the tag is found and the valid bit is set,
// a pointer to the block is returned
// otherwise 0 is returned
cacheLine * set::find_line(unsigned t)
{
/*
if (associativity == 1)
{
if (size == 0)
{
//cout << "_FIND_LINE_ size = 0" << endl;
return 0;
}
if (head->get_tag() == t)
{
//cout << "_FIND_LINE_ found" << endl;
return head;
}
else
{
//cout << "_FIND_LINE_ not found" << endl;
return 0;
}
}
else
{
cout << "findline error" << endl;
exit(0);
}
*/
#ifdef _DEBUG_SET_FINDLINE_
cout << "\t_DEBUG_SET_FINDLINE_\tlooking for tag " << t << endl;
#endif
cacheLine * it = 0;
if (head == 0)
{
#ifdef _DEBUG_SET_FINDLINE_
cout << "\t_DEBUG_SET_FINDLINE_\tEmpty set. Returning 0" << endl;
#endif
return 0;
}
#ifdef _DEBUG_SET_FINDLINE_
cout << "\t_DEBUG_SET_FINDLINE_\tset not empty," << endl;
#endif
for (it = head; it != 0; it = it->get_next())
{
#ifdef _DEBUG_SET_FINDLINE_
cout << "\t_DEBUG_SET_FINDLINE_\tit = " << it << " tag = " << it->get_tag() << " valid = " << it->get_valid() << endl;
#endif
if (it->get_tag() == t && it->get_valid() == true)
{
#ifdef _DEBUG_SET_FINDLINE_
cout << "\t_DEBUG_SET_FINDLINE_\treturning it: " << it << endl;
#endif
return it;
}
}
return 0;
}
void set::output_blocks(ofstream & outfile)
{
#ifdef _DEBUG_SET_OUTPUTBLOCKS_
cout << "assoc = " << associativity << ". size = " << size << " ";
#endif
cacheLine * it;
unsigned i = 0;
for (it = head; it != 0 && i < size; it = it->get_next())
{
if (it->get_valid())
outfile << "V ";
else
outfile << " ";
if (it->get_dirty())
outfile << "D ";
else
outfile << " ";
outfile << setw(6) << hex << it->get_tag() << " ";
}
}