forked from remzi-arpacidusseau/ostep-homework
-
Notifications
You must be signed in to change notification settings - Fork 0
/
paging-linear-translate.py
executable file
·194 lines (160 loc) · 6.64 KB
/
paging-linear-translate.py
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
#! /usr/bin/env python
from __future__ import print_function
import sys
from optparse import OptionParser
import random
import math
def mustbepowerof2(bits, size, msg):
if math.pow(2,bits) != size:
print('Error in argument: %s' % msg)
sys.exit(1)
def mustbemultipleof(bignum, num, msg):
if (int(float(bignum)/float(num)) != (int(bignum) / int(num))):
print('Error in argument: %s' % msg)
sys.exit(1)
def convert(size):
length = len(size)
lastchar = size[length-1]
if (lastchar == 'k') or (lastchar == 'K'):
m = 1024
nsize = int(size[0:length-1]) * m
elif (lastchar == 'm') or (lastchar == 'M'):
m = 1024*1024
nsize = int(size[0:length-1]) * m
elif (lastchar == 'g') or (lastchar == 'G'):
m = 1024*1024*1024
nsize = int(size[0:length-1]) * m
else:
nsize = int(size)
return nsize
#
# main program
#
parser = OptionParser()
parser.add_option('-A', '--addresses', default='-1',
help='a set of comma-separated pages to access; -1 means randomly generate',
action='store', type='string', dest='addresses')
parser.add_option('-s', '--seed', default=0, help='the random seed', action='store', type='int', dest='seed')
parser.add_option('-a', '--asize', default='16k', help='address space size (e.g., 16, 64k, 32m, 1g)', action='store', type='string', dest='asize')
parser.add_option('-p', '--physmem', default='64k', help='physical memory size (e.g., 16, 64k, 32m, 1g)', action='store', type='string', dest='psize')
parser.add_option('-P', '--pagesize', default='4k', help='page size (e.g., 4k, 8k, whatever)', action='store', type='string', dest='pagesize')
parser.add_option('-n', '--numaddrs', default=5, help='number of virtual addresses to generate', action='store', type='int', dest='num')
parser.add_option('-u', '--used', default=50, help='percent of virtual address space that is used', action='store', type='int', dest='used')
parser.add_option('-v', help='verbose mode', action='store_true', default=False, dest='verbose')
parser.add_option('-c', help='compute answers for me', action='store_true', default=False, dest='solve')
(options, args) = parser.parse_args()
print('ARG seed', options.seed)
print('ARG address space size', options.asize)
print('ARG phys mem size', options.psize)
print('ARG page size', options.pagesize)
print('ARG verbose', options.verbose)
print('ARG addresses', options.addresses)
print('')
random.seed(options.seed)
asize = convert(options.asize)
psize = convert(options.psize)
pagesize = convert(options.pagesize)
addresses = str(options.addresses)
if psize <= 1:
print('Error: must specify a non-zero physical memory size.')
exit(1)
if asize < 1:
print('Error: must specify a non-zero address-space size.')
exit(1)
if psize <= asize:
print('Error: physical memory size must be GREATER than address space size (for this simulation)')
exit(1)
if psize >= convert('1g') or asize >= convert('1g'):
print('Error: must use smaller sizes (less than 1 GB) for this simulation.')
exit(1)
mustbemultipleof(asize, pagesize, 'address space must be a multiple of the pagesize')
mustbemultipleof(psize, pagesize, 'physical memory must be a multiple of the pagesize')
# print some useful info, like the darn page table
pages = int(psize / pagesize);
import array
used = array.array('i')
pt = array.array('i')
for i in range(0,pages):
used.insert(i,0)
vpages = int(asize / pagesize)
# now, assign some pages of the VA
vabits = int(math.log(float(asize))/math.log(2.0))
mustbepowerof2(vabits, asize, 'address space must be a power of 2')
pagebits = int(math.log(float(pagesize))/math.log(2.0))
mustbepowerof2(pagebits, pagesize, 'page size must be a power of 2')
vpnbits = vabits - pagebits
pagemask = (1 << pagebits) - 1
# import ctypes
# vpnmask = ctypes.c_uint32(~pagemask).value
vpnmask = 0xFFFFFFFF & ~pagemask
#if vpnmask2 != vpnmask:
# print 'ERROR'
# exit(1)
# print 'va:%d page:%d vpn:%d -- %08x %08x' % (vabits, pagebits, vpnbits, vpnmask, pagemask)
print('')
print('The format of the page table is simple:')
print('The high-order (left-most) bit is the VALID bit.')
print(' If the bit is 1, the rest of the entry is the PFN.')
print(' If the bit is 0, the page is not valid.')
print('Use verbose mode (-v) if you want to print the VPN # by')
print('each entry of the page table.')
print('')
print('Page Table (from entry 0 down to the max size)')
for v in range(0,vpages):
done = 0
while done == 0:
if ((random.random() * 100.0) > (100.0 - float(options.used))):
u = int(pages * random.random())
if used[u] == 0:
used[u] = 1
done = 1
# print('%8d - %d' % (v, u))
if options.verbose == True:
print(' [%8d] ' % v, end='')
else:
print(' ', end='')
print('0x%08x' % (0x80000000 | u))
pt.insert(v,u)
else:
# print('%8d - not valid' % v)
if options.verbose == True:
print(' [%8d] ' % v, end='')
else:
print(' ', end='')
print('0x%08x' % 0)
pt.insert(v,-1)
done = 1
print('' )
#
# now, need to generate virtual address trace
#
addrList = []
if addresses == '-1':
# need to generate addresses
for i in range(0, options.num):
n = int(asize * random.random())
addrList.append(n)
else:
addrList = addresses.split(',')
print('Virtual Address Trace')
for vStr in addrList:
# vaddr = int(asize * random.random())
vaddr = int(vStr)
if options.solve == False:
print(' VA 0x%08x (decimal: %8d) --> PA or invalid address?' % (vaddr, vaddr))
else:
paddr = 0
# split vaddr into VPN | offset
vpn = (vaddr & vpnmask) >> pagebits
if pt[vpn] < 0:
print(' VA 0x%08x (decimal: %8d) --> Invalid (VPN %d not valid)' % (vaddr, vaddr, vpn))
else:
pfn = pt[vpn]
offset = vaddr & pagemask
paddr = (pfn << pagebits) | offset
print(' VA 0x%08x (decimal: %8d) --> %08x (decimal %8d) [VPN %d]' % (vaddr, vaddr, paddr, paddr, vpn))
print('')
if options.solve == False:
print('For each virtual address, write down the physical address it translates to')
print('OR write down that it is an out-of-bounds address (e.g., segfault).')
print('')