#! /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 ''