《操作系统》的实验代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

192 lines
6.5 KiB

преди 9 години
  1. #! /usr/bin/env python
  2. import sys
  3. from optparse import OptionParser
  4. import random
  5. import math
  6. def mustbepowerof2(bits, size, msg):
  7. if math.pow(2,bits) != size:
  8. print 'Error in argument: %s' % msg
  9. sys.exit(1)
  10. def mustbemultipleof(bignum, num, msg):
  11. if (int(float(bignum)/float(num)) != (int(bignum) / int(num))):
  12. print 'Error in argument: %s' % msg
  13. sys.exit(1)
  14. def convert(size):
  15. length = len(size)
  16. lastchar = size[length-1]
  17. if (lastchar == 'k') or (lastchar == 'K'):
  18. m = 1024
  19. nsize = int(size[0:length-1]) * m
  20. elif (lastchar == 'm') or (lastchar == 'M'):
  21. m = 1024*1024
  22. nsize = int(size[0:length-1]) * m
  23. elif (lastchar == 'g') or (lastchar == 'G'):
  24. m = 1024*1024*1024
  25. nsize = int(size[0:length-1]) * m
  26. else:
  27. nsize = int(size)
  28. return nsize
  29. #
  30. # main program
  31. #
  32. parser = OptionParser()
  33. parser.add_option('-A', '--addresses', default='-1',
  34. help='a set of comma-separated pages to access; -1 means randomly generate',
  35. action='store', type='string', dest='addresses')
  36. parser.add_option('-s', '--seed', default=0, help='the random seed', action='store', type='int', dest='seed')
  37. parser.add_option('-a', '--asize', default='16k', help='address space size (e.g., 16, 64k, 32m, 1g)', action='store', type='string', dest='asize')
  38. parser.add_option('-p', '--physmem', default='64k', help='physical memory size (e.g., 16, 64k, 32m, 1g)', action='store', type='string', dest='psize')
  39. parser.add_option('-P', '--pagesize', default='4k', help='page size (e.g., 4k, 8k, whatever)', action='store', type='string', dest='pagesize')
  40. parser.add_option('-n', '--numaddrs', default=5, help='number of virtual addresses to generate', action='store', type='int', dest='num')
  41. parser.add_option('-u', '--used', default=50, help='percent of virtual address space that is used', action='store', type='int', dest='used')
  42. parser.add_option('-v', help='verbose mode', action='store_true', default=False, dest='verbose')
  43. parser.add_option('-c', help='compute answers for me', action='store_true', default=False, dest='solve')
  44. (options, args) = parser.parse_args()
  45. print 'ARG seed', options.seed
  46. print 'ARG address space size', options.asize
  47. print 'ARG phys mem size', options.psize
  48. print 'ARG page size', options.pagesize
  49. print 'ARG verbose', options.verbose
  50. print 'ARG addresses', options.addresses
  51. print ''
  52. random.seed(options.seed)
  53. asize = convert(options.asize)
  54. psize = convert(options.psize)
  55. pagesize = convert(options.pagesize)
  56. addresses = str(options.addresses)
  57. if psize <= 1:
  58. print 'Error: must specify a non-zero physical memory size.'
  59. exit(1)
  60. if asize < 1:
  61. print 'Error: must specify a non-zero address-space size.'
  62. exit(1)
  63. if psize <= asize:
  64. print 'Error: physical memory size must be GREATER than address space size (for this simulation)'
  65. exit(1)
  66. if psize >= convert('1g') or asize >= convert('1g'):
  67. print 'Error: must use smaller sizes (less than 1 GB) for this simulation.'
  68. exit(1)
  69. mustbemultipleof(asize, pagesize, 'address space must be a multiple of the pagesize')
  70. mustbemultipleof(psize, pagesize, 'physical memory must be a multiple of the pagesize')
  71. # print some useful info, like the darn page table
  72. pages = psize / pagesize;
  73. import array
  74. used = array.array('i')
  75. pt = array.array('i')
  76. for i in range(0,pages):
  77. used.insert(i,0)
  78. vpages = asize / pagesize
  79. # now, assign some pages of the VA
  80. vabits = int(math.log(float(asize))/math.log(2.0))
  81. mustbepowerof2(vabits, asize, 'address space must be a power of 2')
  82. pagebits = int(math.log(float(pagesize))/math.log(2.0))
  83. mustbepowerof2(pagebits, pagesize, 'page size must be a power of 2')
  84. vpnbits = vabits - pagebits
  85. pagemask = (1 << pagebits) - 1
  86. # import ctypes
  87. # vpnmask = ctypes.c_uint32(~pagemask).value
  88. vpnmask = 0xFFFFFFFF & ~pagemask
  89. #if vpnmask2 != vpnmask:
  90. # print 'ERROR'
  91. # exit(1)
  92. # print 'va:%d page:%d vpn:%d -- %08x %08x' % (vabits, pagebits, vpnbits, vpnmask, pagemask)
  93. print ''
  94. print 'The format of the page table is simple:'
  95. print 'The high-order (left-most) bit is the VALID bit.'
  96. print ' If the bit is 1, the rest of the entry is the PFN.'
  97. print ' If the bit is 0, the page is not valid.'
  98. print 'Use verbose mode (-v) if you want to print the VPN # by'
  99. print 'each entry of the page table.'
  100. print ''
  101. print 'Page Table (from entry 0 down to the max size)'
  102. for v in range(0,vpages):
  103. done = 0
  104. while done == 0:
  105. if ((random.random() * 100.0) > (100.0 - float(options.used))):
  106. u = int(pages * random.random())
  107. if used[u] == 0:
  108. done = 1
  109. # print '%8d - %d' % (v, u)
  110. if options.verbose == True:
  111. print ' [%8d] ' % v,
  112. else:
  113. print ' ',
  114. print '0x%08x' % (0x80000000 | u)
  115. pt.insert(v,u)
  116. else:
  117. # print '%8d - not valid' % v
  118. if options.verbose == True:
  119. print ' [%8d] ' % v,
  120. else:
  121. print ' ',
  122. print '0x%08x' % 0
  123. pt.insert(v,-1)
  124. done = 1
  125. print ''
  126. #
  127. # now, need to generate virtual address trace
  128. #
  129. addrList = []
  130. if addresses == '-1':
  131. # need to generate addresses
  132. for i in range(0, options.num):
  133. n = int(asize * random.random())
  134. addrList.append(n)
  135. else:
  136. addrList = addresses.split(',')
  137. print 'Virtual Address Trace'
  138. for vStr in addrList:
  139. # vaddr = int(asize * random.random())
  140. vaddr = int(vStr)
  141. if options.solve == False:
  142. print ' VA 0x%08x (decimal: %8d) --> PA or invalid address?' % (vaddr, vaddr)
  143. else:
  144. paddr = 0
  145. # split vaddr into VPN | offset
  146. vpn = (vaddr & vpnmask) >> pagebits
  147. if pt[vpn] < 0:
  148. print ' VA 0x%08x (decimal: %8d) --> Invalid (VPN %d not valid)' % (vaddr, vaddr, vpn)
  149. else:
  150. pfn = pt[vpn]
  151. offset = vaddr & pagemask
  152. paddr = (pfn << pagebits) | offset
  153. print ' VA 0x%08x (decimal: %8d) --> %08x (decimal %8d) [VPN %d]' % (vaddr, vaddr, paddr, paddr, vpn)
  154. print ''
  155. if options.solve == False:
  156. print 'For each virtual address, write down the physical address it translates to'
  157. print 'OR write down that it is an out-of-bounds address (e.g., segfault).'
  158. print ''