193 lines
6.5 KiB
Python
193 lines
6.5 KiB
Python
|
#! /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 ''
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|