add ostep homeworks
This commit is contained in:
192
related_info/ostep/ostep4-paging-linear-translate.py
Executable file
192
related_info/ostep/ostep4-paging-linear-translate.py
Executable file
@@ -0,0 +1,192 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
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 = psize / pagesize;
|
||||
import array
|
||||
used = array.array('i')
|
||||
pt = array.array('i')
|
||||
for i in range(0,pages):
|
||||
used.insert(i,0)
|
||||
vpages = 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:
|
||||
done = 1
|
||||
# print '%8d - %d' % (v, u)
|
||||
if options.verbose == True:
|
||||
print ' [%8d] ' % v,
|
||||
else:
|
||||
print ' ',
|
||||
print '0x%08x' % (0x80000000 | u)
|
||||
pt.insert(v,u)
|
||||
else:
|
||||
# print '%8d - not valid' % v
|
||||
if options.verbose == True:
|
||||
print ' [%8d] ' % v,
|
||||
else:
|
||||
print ' ',
|
||||
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 ''
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user