209 lines
7.5 KiB
Python
209 lines
7.5 KiB
Python
|
#! /usr/bin/env python
|
||
|
|
||
|
import sys
|
||
|
from optparse import OptionParser
|
||
|
import random
|
||
|
import math
|
||
|
|
||
|
def hfunc(index):
|
||
|
if index == -1:
|
||
|
return 'MISS'
|
||
|
else:
|
||
|
return 'HIT '
|
||
|
|
||
|
def vfunc(victim):
|
||
|
if victim == -1:
|
||
|
return '-'
|
||
|
else:
|
||
|
return str(victim)
|
||
|
|
||
|
#
|
||
|
# 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('-p', '--policy', default='FIFO', help='replacement policy: FIFO, LRU, OPT, CLOCK', action='store', type='string', dest='policy')
|
||
|
parser.add_option('-b', '--clockbits', default=1, help='for CLOCK policy, how many clock bits to use', action='store', type='int', dest='clockbits')
|
||
|
parser.add_option('-f', '--pageframesize', default='3', help='size of the physical page frame, in pages', action='store', type='string', dest='pageframesize')
|
||
|
parser.add_option('-s', '--seed', default='0', help='random number seed', action='store', type='string', dest='seed')
|
||
|
parser.add_option('-N', '--notrace', default=False, help='do not print out a detailed trace', action='store_true', dest='notrace')
|
||
|
parser.add_option('-c', '--compute', default=False, help='compute answers for me', action='store_true', dest='solve')
|
||
|
|
||
|
(options, args) = parser.parse_args()
|
||
|
|
||
|
print 'ARG addresses', options.addresses
|
||
|
print 'ARG policy', options.policy
|
||
|
print 'ARG clockbits', options.clockbits
|
||
|
print 'ARG pageframesize', options.pageframesize
|
||
|
print 'ARG seed', options.seed
|
||
|
print 'ARG notrace', options.notrace
|
||
|
print ''
|
||
|
|
||
|
addresses = str(options.addresses)
|
||
|
pageframesize = int(options.pageframesize)
|
||
|
seed = int(options.seed)
|
||
|
policy = str(options.policy)
|
||
|
notrace = options.notrace
|
||
|
clockbits = int(options.clockbits)
|
||
|
|
||
|
random.seed(seed)
|
||
|
|
||
|
addrList = []
|
||
|
addrList = addresses.split(',')
|
||
|
|
||
|
if options.solve == False:
|
||
|
print 'Assuming a replacement policy of %s, and a physical page frame of size %d pages,' % (policy, pageframesize)
|
||
|
print 'figure out whether each of the following page references hit or miss'
|
||
|
|
||
|
for n in addrList:
|
||
|
print 'Access: %d Hit/Miss? State of Memory?' % int(n)
|
||
|
print ''
|
||
|
|
||
|
else:
|
||
|
if notrace == False:
|
||
|
print 'Solving...\n'
|
||
|
|
||
|
# init memory structure
|
||
|
count = 0
|
||
|
memory = []
|
||
|
hits = 0
|
||
|
miss = 0
|
||
|
|
||
|
if policy == 'FIFO':
|
||
|
leftStr = 'FirstIn'
|
||
|
riteStr = 'Lastin '
|
||
|
elif policy == 'LRU':
|
||
|
leftStr = 'LRU'
|
||
|
riteStr = 'MRU'
|
||
|
elif policy == 'OPT' or policy == 'CLOCK':
|
||
|
leftStr = 'Left '
|
||
|
riteStr = 'Right'
|
||
|
else:
|
||
|
print 'Policy %s is not yet implemented' % policy
|
||
|
exit(1)
|
||
|
|
||
|
# track reference bits for clock
|
||
|
ref = {}
|
||
|
|
||
|
cdebug = False
|
||
|
|
||
|
# need to generate addresses
|
||
|
addrIndex = 0
|
||
|
for nStr in addrList:
|
||
|
# first, lookup
|
||
|
n = int(nStr)
|
||
|
try:
|
||
|
idx = memory.index(n)
|
||
|
hits = hits + 1
|
||
|
if policy == 'LRU' :
|
||
|
update = memory.remove(n)
|
||
|
memory.append(n) # puts it on MRU side
|
||
|
except:
|
||
|
idx = -1
|
||
|
miss = miss + 1
|
||
|
|
||
|
victim = -1
|
||
|
if idx == -1:
|
||
|
# miss, replace?
|
||
|
# print 'BUG count, pageframesize:', count, pageframesize
|
||
|
if count == pageframesize:
|
||
|
# must replace
|
||
|
if policy == 'FIFO' or policy == 'LRU':
|
||
|
victim = memory.pop(0)
|
||
|
elif policy == 'CLOCK':
|
||
|
if cdebug:
|
||
|
print 'REFERENCE TO PAGE', n
|
||
|
print 'MEMORY ', memory
|
||
|
print 'REF (b)', ref
|
||
|
# hack: for now, do random
|
||
|
# victim = memory.pop(int(random.random() * count))
|
||
|
victim = -1
|
||
|
while victim == -1:
|
||
|
page = memory[int(random.random() * count)]
|
||
|
if cdebug:
|
||
|
print ' scan page:', page, ref[page]
|
||
|
if ref[page] >= 1:
|
||
|
ref[page] -= 1
|
||
|
else:
|
||
|
# this is our victim
|
||
|
victim = page
|
||
|
memory.remove(page)
|
||
|
break
|
||
|
|
||
|
# remove old page's ref count
|
||
|
if page in memory:
|
||
|
assert('BROKEN')
|
||
|
del ref[victim]
|
||
|
if cdebug:
|
||
|
print 'VICTIM', page
|
||
|
print 'LEN', len(memory)
|
||
|
print 'MEM', memory
|
||
|
print 'REF (a)', ref
|
||
|
|
||
|
elif policy == 'OPT':
|
||
|
maxReplace = -1
|
||
|
replaceIdx = -1
|
||
|
replacePage = -1
|
||
|
# print 'OPT: access %d, memory %s' % (n, memory)
|
||
|
# print 'OPT: replace from FUTURE (%s)' % addrList[addrIndex+1:]
|
||
|
for pageIndex in range(0,count):
|
||
|
page = memory[pageIndex]
|
||
|
# now, have page 'page' at index 'pageIndex' in memory
|
||
|
whenReferenced = len(addrList)
|
||
|
# whenReferenced tells us when, in the future, this was referenced
|
||
|
for futureIdx in range(addrIndex+1,len(addrList)):
|
||
|
futurePage = int(addrList[futureIdx])
|
||
|
if page == futurePage:
|
||
|
whenReferenced = futureIdx
|
||
|
break
|
||
|
# print 'OPT: page %d is referenced at %d' % (page, whenReferenced)
|
||
|
if whenReferenced >= maxReplace:
|
||
|
# print 'OPT: ??? updating maxReplace (%d %d %d)' % (replaceIdx, replacePage, maxReplace)
|
||
|
replaceIdx = pageIndex
|
||
|
replacePage = page
|
||
|
maxReplace = whenReferenced
|
||
|
# print 'OPT: --> updating maxReplace (%d %d %d)' % (replaceIdx, replacePage, maxReplace)
|
||
|
victim = memory.pop(replaceIdx)
|
||
|
# print 'OPT: replacing page %d (idx:%d) because I saw it in future at %d' % (victim, replaceIdx, whenReferenced)
|
||
|
else:
|
||
|
# miss, but no replacement needed (page frame not full)
|
||
|
victim = -1
|
||
|
count = count + 1
|
||
|
|
||
|
# now add to memory
|
||
|
memory.append(n)
|
||
|
if cdebug:
|
||
|
print 'LEN (a)', len(memory)
|
||
|
if victim != -1:
|
||
|
assert(victim not in memory)
|
||
|
|
||
|
# after miss processing, update reference bit
|
||
|
if n not in ref:
|
||
|
ref[n] = 1
|
||
|
else:
|
||
|
ref[n] += 1
|
||
|
if ref[n] > clockbits:
|
||
|
ref[n] = clockbits
|
||
|
|
||
|
if cdebug:
|
||
|
print 'REF (a)', ref
|
||
|
|
||
|
if notrace == False:
|
||
|
print 'Access: %d %s %s -> %12s <- %s Replaced:%s [Hits:%d Misses:%d]' % (n, hfunc(idx), leftStr, memory, riteStr, vfunc(victim), hits, miss)
|
||
|
addrIndex = addrIndex + 1
|
||
|
|
||
|
print ''
|
||
|
print 'FINALSTATS hits %d misses %d hitrate %.2f' % (hits, miss, (100.0*float(hits))/(float(hits)+float(miss)))
|
||
|
print ''
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|