Repository navigation
Expand file tree
/
Copy pathCache.cpp
More file actions
315 lines (248 loc) · 7.64 KB
/
Copy pathCache.cpp
File metadata and controls
315 lines (248 loc) · 7.64 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
/*
LRU Cache Simulator
3/4/19
Developers: Bruno E. Gracia Villalobos
Ryan Walker
*/
#include "Cache.h"
namespace G
{
typedef bitset<32> bits;
/*Constructor to initialize given values from the file*/
Cache::Cache(int& C, int&b, int&N)
{
capacity = C;
block_size = b;
assoc = N;
createCache();
cout << "Capacity: " << C << endl;
cout << "Block Size: " << b << endl;
cout << "Associativity: " << N << endl;
cout << "Total blocks: " << blocks << endl;
cout << "Total sets: " << sets << endl;
cout << "Offset bits: " << offset << endl;
cout << "Index bits: " << index << endl;
cout << "Tag bits: " << tag << endl;
}
Cache::~Cache() {
free(bank); //Free memory allocated for the array of structs
}
/*MAIN CONTROL*/
/*Test each individual memory address read in from the file to see if they're in the cache*/
void Cache::testMem()
{
/*Allocate buckets for total memory addresses into array of structs
Will allocate 16 bytes per bucket, for 4 bitsets per struct
Total memory allocated = 695521 * 16 bytes
*/
bank = (mem_address*)malloc(sizeof(mem_address)*memoryLength);
/*Store mem address, tag, index, offset into an array of structs*/
for(int i=0; i<memoryLength; i++)
{
bank[i].mem = memory.at(i);
bank[i].tag = getTag(memory.at(i));
bank[i].index = getIndex(memory.at(i));
bank[i].offset = getOffset(memory.at(i));
}
/*BEGIN CACHE OPERATION*/
int i=0;
for(; i<memoryLength; i++)
{
// cout << "__________________Checking______________" << endl;
// printMemAdr(bank[i]);
// insertion = make_pair(bank[i].tag, &bank[i]);
//
// mapCache.insert(insertion);
//
// cout << "MEM INSERTED: " <<mapCache.at(insertion.first)->mem << endl;
// checkEntry(bank[i].tag);
checkEntry(bank[i]);
// cout << "________END CHECKING____________________" << endl;
}
cout << "NUM ACCESSES " << i << endl;
cout << "HITS: " << hits << endl;
cout << "MISSES: " << misses << endl;
cout << "HIT RATE: " << (double)(hits)/(double)(i) << endl;
}
/*Print out the given mem address structure*/
void Cache::printMemAdr(mem_address& adr)
{
cout << "MEM:\t" << adr.mem <<
"\nTAG:\t" << adr.tag <<
"\nINDEX:\t" << adr.index <<
"\nOFFSET:\t" << adr.offset << endl;
}
/*Check a specific memory address to see if it's in the cache*/
void Cache::checkEntry(mem_address& adr)
{
int currentIndex = bitsToInt(adr.index); //grab our current set index from the cache
list<tagentry>* currentSet = &tagCache.at(currentIndex); //make a pointer for the set an n index
list<tagentry>::iterator* currentIt = &tagIt.at(currentIndex); //iterator for the nth set
*currentIt = find(currentSet->begin(), currentSet->end(), adr.tag); //search for the tag in the set at n index
/*Cache FULL*/
if(currentSet->size() == assoc)
{
/*Cache MISS*/
if( (*currentIt == currentSet->end()) )
{
misses++;
*currentIt = currentSet->begin(); //set iterator pointer to LRU
currentSet->erase(*currentIt); //erase LRU
currentSet->push_back(adr.tag); //push back the tag as the new MRU
/*Calculate position for iterator*/
*currentIt = currentSet->begin();
advance(*currentIt, distance(*currentIt, currentSet->end())-1); //advance to the last placement
}
/*Cache HIT*/
else
{
hits++;
currentSet->erase(*currentIt);
currentSet->push_back(adr.tag);
/*Calculate position for iterator*/
*currentIt = currentSet->begin();
advance(*currentIt, distance(*currentIt, currentSet->end())-1); //advance to the last placement
}
}
/*Cache NOT FULL*/
else if ( (currentSet->size() != 0) && (currentSet->size() < assoc))
{
/*Cache MISS, Compulsory Miss*/
if( (*currentIt == currentSet->end()) )
{
misses++;
currentSet->push_back(adr.tag);
/*Calculate position for iterator*/
*currentIt = currentSet->begin();
advance(*currentIt, distance(*currentIt, currentSet->end())-1); //advance to the last placement
}
/*Cache HIT*/
else
{
hits++;
currentSet->erase(*currentIt); //erase spot to move to MRU now
currentSet->push_back(adr.tag);
}
}
/*Cache NEW, Compulsory Miss*/
else if( (currentSet->size() == 0) && (*currentIt == currentSet->end()) )
{
misses++;
currentSet->push_back(adr.tag); //append to the back (MRU)
*currentIt = currentSet->begin(); //set iterator to this position since set is NEW
}
/*Check if iterator does not point to the same tag*/
if( (**currentIt) != adr.tag)
{
cout << "ERROR @ " << currentIndex << " mem:" << endl;
printMemAdr(adr);
printSet(*currentSet);
exit(0);
}
/*Pointer cleanup*/
currentSet = nullptr;
currentIt = nullptr;
delete currentSet;
delete currentIt;
}
/*Print the given list set of blocks in the cache*/
void Cache::printSet(list<tagentry>& l)
{
int i=0;
for(list<tagentry>::iterator j= l.begin(); j != l.end(); j++)
{
cout << "Index: " << i << " " << *j << endl;
i++;
}
}
/*Must delete the memory allocated for the mem_address pointer before deleting the entry from the list*/
void Cache::deleteMemEntry(mem_address*& adr)
{
cout << "Deleting ptr: " << adr << endl;
adr = nullptr;
delete adr;
}
/*Initialize values for the cache*/
void Cache::createCache()
{
blocks = capacity/block_size;
sets = blocks/assoc;
offset = log(block_size)/log(2);
index = log(sets)/log(2);
tag = 32 - offset - index;
hits = 0;
misses = 0;
/*Allocate space for the vectors*/
tagCache.resize(sets);
tagIt.resize(sets);
/*Initialize all iterators to their respective set's begin*/
for(int i=0; i<sets; i++)
{
tagIt.at(i) = tagCache.at(i).begin();
}
}
/*Read in the memory trace and store in a vector*/
void Cache::readMemory() {
ifstream file;
string line;
string file_name;
cout<<"Enter name of file with memory addresses: ";
cin>>file_name;
// file.open("example.trc", ios::in);
file.open(file_name, ios::in);
int j=0;
/*Read lines until end of file*/
while(!file.eof())
{
getline(file,line);
/*Break file read if there is only an \n character left in the file!*/
if(line.length()<2)
{
break;
}
/*Store hex address as a bitset in the storage vector*/
memory.push_back(hexToBin(line));
j++;
}
cout << "Read in " << j << " memory addresses from the file" << endl;
memoryLength = j; //keep track of total memory addresses on file
file.close();
}
/*Returns a bitset<32> for analyzing the memory address*/
bits Cache::hexToBin(string& s)
{
stringstream ss;
unsigned int n;
/*Send the string as hex to the stream*/
ss << hex << s;
ss >> n;
/*Construct bitset out of parsed int*/
bitset<32> b(n);
return b;
}
/*Returns the tag of the mema address as a bitset*/
bits Cache::getTag(bits& h)
{
bitset<32> b(h.to_string(), 0, tag);
return b;
}
/*Returns index bits of the mem address given*/
bits Cache::getIndex(bits& h)
{
bitset<32> b(h.to_string(), tag, index);
return b;
}
/*Returns offset bits of the mem address given*/
bits Cache::getOffset(bits& h)
{
bitset<32> b(h.to_string(), index+tag, 31);
return b;
}
/*Returns int from a bitset*/
int Cache::bitsToInt(bits& h)
{
int b = stoi(h.to_string(), nullptr, 2);
//can also use b.to_ulong();
return b;
}
}