|
|
@ -0,0 +1,208 @@ |
|
|
|
#! /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 '' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|