-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvmsim.java
More file actions
409 lines (367 loc) · 13.5 KB
/
Copy pathvmsim.java
File metadata and controls
409 lines (367 loc) · 13.5 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
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
import java.util.*;
import java.lang.Math;
import java.io.*;
public class vmsim{
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Exception{
//KB = 2^10 =1024
final int kiloByte= 1024;
final int addSize=32;
//check to ensure proper args
if(args.length<9){
System.out.println("must include command arguments in format:"+
"-a <opt|lru> –n <numframes> -p <pagesize in KB> -s <memory split> <tracefile>");
System.exit(0);
}
int mode=0; //base case lru
int numframes; //number of frames
int pagesize; //size of a page
String memsplit; //memory split
String tracefile; //string containing trace file name.
String alg=args[1].toUpperCase();
if(args[1].equals("opt"))mode=1;
numframes=Integer.parseInt(args[3]);
int frameNumSize= log2(numframes);
pagesize=Integer.parseInt(args[5]);
pagesize=pagesize*kiloByte;
memsplit=args[7];
String[] splits=memsplit.split(":");
int proc0Split=Integer.parseInt(splits[0]);
int proc1Split=Integer.parseInt(splits[1]);
int totSplit=proc0Split+proc1Split;
int proc0Frames=(numframes/totSplit)*proc0Split;
int proc1Frames=(numframes/totSplit)*proc1Split;
tracefile=args[8];
//num frames determines how many addresses can be stored at once (size of array)
//page size=
//address offset = num of bits in page size exponent ie 2^12 4Kb page size= 12 bit offset
int offset=log2(pagesize);
int[] stats=new int[3];
if(mode==0)
stats=LRU(pagesize,numframes, proc0Frames,proc1Frames,offset,tracefile);
if(mode==1)
stats=opt(pagesize,numframes, proc0Frames,proc1Frames,offset,tracefile);
System.out.println("Algorithm: "+alg);
System.out.println("Number of frames: "+numframes);
System.out.println("Page size: "+(pagesize/1024)+" KB");
System.out.println("Total memory accesses: "+stats[0]);
System.out.println("Total page faults: "+ stats[1]);
System.out.println("Total writes to disk: "+stats[2]);
}
//method to check if an index of linked list is dirty- for debugging
@SuppressWarnings("unchecked")
private static boolean isDirty(LinkedList<Boolean> list, int index){
if(list.get(index).booleanValue()==true){
return true;
}
else return false;
}
@SuppressWarnings("unchecked")
//helper method determines size of log base 2 of a number - used for offset
public static int log2(int n){
int res=(int) (Math.log(n)/Math.log(2));
return res;
}
//method to print my linked list in hex form for debugging
@SuppressWarnings("unchecked")
public static void printList(LinkedList<Long> list, LinkedList<Boolean> dlist){
for(int i=0;i<list.size();i++){
System.out.print("index:"+i+":"+Long.toHexString(list.get(i)));
if(isDirty(dlist,i)==true){
System.out.print("*");
}
System.out.println("");
}
}
@SuppressWarnings("unchecked")
public static int indexOf(LinkedList<Long> list, long address){
int i;
for(i=0;i<list.size();i++){
//System.out.println("list["+i+"]:"+list.get(i)+"looking for"+address);
if(list.get(i).longValue()==address){
return i;
}
}
return -1;
}
@SuppressWarnings("unchecked")
public static int[] LRU(int pagesize,int numFrames,int proc0Frames,int proc1Frames,int offset, String tracefile)throws Exception{
LinkedList p0= new LinkedList<Long>();
LinkedList p0dirty=new LinkedList<Boolean>();
LinkedList p1= new LinkedList<Long>();
LinkedList p1dirty=new LinkedList<Boolean>();
int pagefaults=0;
int memWrite=0;
int memAccesses=0;
int pnum;
String op;
boolean dirty=false;
String line="";
BufferedReader infile = new BufferedReader (new FileReader( tracefile ));
Long address;
while(infile.ready()){
line= infile.readLine();
String[] fields= line.split(" ");
op=fields[0];
if(op.equals("s")){ dirty=true;} //set the dirty bit
else{dirty=false;}
address=(Long.decode(fields[1]))>>offset; //address is now just the page num
pnum=Integer.parseInt(fields[2]); //process number
//shift to get page num for adresses
if(pnum==0){ //proc 0
int ind=indexOf(p0,address); //index of page in page table
if(ind==-1){ //if not in page table
//page fault
pagefaults++;
if(p0.size()==proc0Frames){ //if not room for more entries
p0.remove(); //remove head- least recently used
@SuppressWarnings("unchecked")
Boolean dRemoved=(Boolean)p0dirty.remove(); //and the head of the dirty list
if(dRemoved.booleanValue()==true){ //if it was dirty, increment memwrites
//disk write
memWrite++;
}
}
p0.addLast(address); //add our new page in
p0dirty.addLast(dirty);//and its dirty bit
}
else{ //address found in p0 list
//need to remove the index, and re add to beginning of list
@SuppressWarnings("unchecked")
Long removed=(Long)p0.remove(ind); //remove from its current index
@SuppressWarnings("unchecked")
Boolean dremoved=(Boolean)p0dirty.remove(ind); //along with dirty
if(dremoved.booleanValue()==true|| dirty==true){ //ensure that boolean remains dirty if it was before
dirty=true;
}
p0.addLast(removed); //add both to end of list
p0dirty.addLast(new Boolean(dirty));
}
}
if(pnum==1){ //proc 1
//same methodology as process 1 above
int ind=indexOf(p1,address);
if(ind==-1){
//page fault
pagefaults++;
if(p1.size()==proc1Frames){
p1.remove();
@SuppressWarnings("unchecked")
Boolean dRemoved=(Boolean)p1dirty.remove();
if(dRemoved.booleanValue()==true){
//disk write
memWrite++;
}
}
p1.addLast(address);
p1dirty.addLast(dirty);
}
else{ //address found in p0 list
//need to remove the index, and re add to beginning of list
@SuppressWarnings("unchecked")
Long removed=(Long)p1.remove(ind);
@SuppressWarnings("unchecked")
Boolean dremoved=(Boolean)p1dirty.remove(ind);
if(dremoved.booleanValue()==true|| dirty==true){
dirty=true;
}
p1.addLast(removed);
p1dirty.addLast(new Boolean(dirty));
}
}
memAccesses++;
}
infile.close();
int[] data=new int[3];
data[0]=memAccesses;
data[1]=pagefaults;
data[2]=memWrite;
return data;
}
@SuppressWarnings("unchecked")
public static int[]opt(int pagesize,int numFrames,int proc0Frames,int proc1Frames,int offset, String tracefile)throws Exception{
//hash table with Long, Linked List
//another with the dirty bits for the tables
Hashtable<Long,LinkedList<Integer>> p0table= new Hashtable<Long,LinkedList<Integer>>();
Hashtable<Long,LinkedList<Integer>> p1table= new Hashtable<Long,LinkedList<Integer>>();
LinkedList p0= new LinkedList<Long>();
LinkedList p0dirty=new LinkedList<Boolean>();
LinkedList p1= new LinkedList<Long>();
LinkedList p1dirty=new LinkedList<Boolean>();
int pagefaults=0;
int memWrite=0;
int memAccesses=0;
int pnum;
String op;
boolean dirty=false;
String line="";
BufferedReader infile;
infile=new BufferedReader(new FileReader(tracefile ));
Long address;
int i=0;
while(infile.ready()){
line= infile.readLine();
String[] fields= line.split(" ");
address=(Long.decode(fields[1]))>>offset;
pnum=Integer.parseInt(fields[2]);
Integer num=new Integer(i);
if(pnum==0){//add next line to the hashtables,
if(p0table.get(address)==null){ //avoid null pointer exception
LinkedList<Integer> addList=new LinkedList<Integer>(); //create a LL for the key
addList.add(num); //add the num to it
p0table.put(address,addList); //add to hash table
}
else{//pull keys linked list, add next index, replace it
LinkedList<Integer> addList=p0table.get(address);
addList.add(num);
p0table.put(address,addList);
}
}
if(pnum==1){ //same as up top, if null, create and add to table, if extant, pop and add to
if(p1table.get(address)==null){
LinkedList<Integer> addList=new LinkedList<Integer>();
addList.add(num);
p1table.replace(address,addList);
}
else{
LinkedList<Integer> addList=p1table.get(address);
addList.add(num);
p1table.replace(address,addList);
}
}
i++;
}
infile.close();
infile=new BufferedReader (new FileReader(tracefile )); //restart our reader for our stats pass
//now re trace the file to find pf and all that.
while(infile.ready()){
int num=0;
line= infile.readLine();
String[] fields= line.split(" ");
op=fields[0]; //get s or l
address=(Long.decode(fields[1]))>>offset; //get address, shift right by offset to get page num
pnum=Integer.parseInt(fields[2]); //process number
if(op.equals("s")){ dirty=true;} //setting correct dirty bit
else{dirty=false;}
if(pnum==0){
//opt is useful for selecting eviction. funct for non evictions should not change beyond hash table updates
int ind= indexOf(p0,address); //index of address in page table
if(ind==-1){ //if not in page table
//page fault
pagefaults++;
if(p0.size()==proc0Frames){// eviction time
//look through the page table, for each entry calculate the numaccesses till they are accessed again
//index with longest dist, removed.
int key=optremoval(p0,p0table,num); //find the optimal key to remove
@SuppressWarnings("unchecked")
Long removed=(Long) p0.remove(key); //remove from page table
@SuppressWarnings("unchecked")
Boolean drem=(Boolean) p0dirty.remove(key); //remove from dirty table
if(drem.booleanValue()==true){ //if dirty, mem write
memWrite++;
}
}
p0.add(address); //add new address to page table
p0dirty.add(dirty); //and to dirtytable
LinkedList<Integer> newlist= p0table.get(address); //pull our value from hashtable
if(newlist!=null){ //if it exists, remove to update to next instance in list
newlist.remove();
p0table.replace(address,newlist);
}
}
else{//page hit
@SuppressWarnings("unchecked")
Long removed=(Long)p0.remove(ind); //remove from page table to update to mru spot
@SuppressWarnings("unchecked")
Boolean dremoved=(Boolean)p0dirty.remove(ind); //same for dirty list
if(dremoved.booleanValue()==true|| dirty==true){ //make sure dirty bit is consistent
dirty=true;
}
p0.addLast(removed); //re add at tail
p0dirty.addLast(new Boolean(dirty)); //dirty to tail
LinkedList<Integer> newlist= p0table.get(address); //again, update table so next page instance is head of list
if(newlist!=null){
newlist.remove();
p0table.replace(address,newlist);
}
}
}
if(pnum==1){
//same methodology as p0 above
//opt is useful for selecting eviction. funct for non evictions should not change
int ind= indexOf(p1,address);
if(ind==-1){
//page fault
pagefaults++;
if(p1.size()==proc1Frames){// eviction time
//look through the page table, for each entry calculate the numaccesses till they are accessed again
//index with longest dist, removed.
int key=optremoval(p1,p1table,num);
@SuppressWarnings("unchecked")
Long removed=(Long) p1.remove(key);
@SuppressWarnings("unchecked")
Boolean drem=(Boolean) p1dirty.remove(key);
if(drem.booleanValue()==true){
memWrite++;
}
}
p1.add(address);
p1dirty.add(dirty);
LinkedList<Integer> newlist= p1table.get(address);
if(newlist!=null){
newlist.remove();
p1table.replace(address,newlist);
}
}
else{//page hit
@SuppressWarnings("unchecked")
Long removed=(Long)p1.remove(ind);
@SuppressWarnings("unchecked")
Boolean dremoved=(Boolean)p1dirty.remove(ind);
if(dremoved.booleanValue()==true|| dirty==true){
dirty=true;
}
p1.addLast(removed);
p1dirty.addLast(new Boolean(dirty));
LinkedList<Integer> newlist= p1table.get(address);
if(newlist!=null){
newlist.remove();
p1table.replace(address,newlist);
}
}
}
memAccesses++;
}
int[] data=new int[3]; //create int array to return appropriate data
data[0]=memAccesses;
data[1]=pagefaults;
data[2]=memWrite;
return data;
}
@SuppressWarnings("unchecked")
public static int optremoval(LinkedList<Long> list, Hashtable<Long, LinkedList<Integer>> table, int num){
int[] dists=new int[list.size()]; //array of distance to next instance of a page in the trace
for(int i=0;i<list.size();i++){ //loop through the page table to calc distances of each index
LinkedList temp=table.get(list.get(i)); //get the next index at which the address appears
if(temp!=null){ //avoid null cases
if(temp.size()>0){
Integer next=(Integer)temp.getFirst();
dists[i]=next.intValue() -num; //set the array val to the next appearance- current slot
}
else{ dists[i]=Integer.MAX_VALUE;} //in any non extant or null case, set to max int
}
else{
dists[i]=Integer.MAX_VALUE;
}
}
int max=dists[0]; //var to track max
int maxind=0; //and index of max
for(int j=1;j<dists.length;j++){
if(max<dists[j]){ //if max is less than current index, it becomes max, and j becomes index of max
max=dists[j];
maxind=j;
}
}
return maxind; //return max index
}
}