Commit ba1e2f36 authored by Alan Marchiori's avatar Alan Marchiori

initial commit

parents
This diff is collapsed.
class global_pht:
def __init__(self, num_history_bits = 3):
self.num_bits = num_history_bits
self.num_index = 2**self.num_bits
self.shift_register = self.num_index - 1
self.bin_fmt = "{{:0{}b}}".format(self.num_bits)
self.counters = [ 'T' for i in range (self.num_index)]
def predict(self, pc, target, outcome, verbose, learn = True):
result = self.counters[self.shift_register]
if verbose and learn:
print ("predicting PC = 0x{:x}, branch history = ".format(pc) + \
self.bin_fmt.format(self.shift_register) + \
" outcome = {}".format(outcome))
tag = {True: '<===',
False: ''}
msg = {False: {True: "", False: ""},
True: {True: " (correct)",
False: " (MISSPREDICT)"}}
for i in range (self.num_index):
print ("PHT[" + self.bin_fmt.format(i) + "] = {} {}{}".format(self.counters[i],
tag[i == self.shift_register],
msg[i == self.shift_register][result == outcome]))
if learn:
self.counters[self.shift_register] = outcome
self.shift_register = ((self.shift_register << 1) & (self.num_index - 1))
if outcome == 'T':
self.shift_register |= 1
return result
\ No newline at end of file
from twolevel import correlation_register
from local import saturating_counter
class hybrid_correlating_predictor():
def __init__(self, global_history_bits = 2, local_pc_bits = 3):
self.global_indexes = 2**global_history_bits
self.local_indexes = 2**local_pc_bits
self.bin_fmt = "{{:0{}b}}".format(global_history_bits)
def predict(self, pc, target, outcome, verbose):
"""TODO: complete this"""
return "T"
\ No newline at end of file
import math
class saturating_counter():
pred = ['N', 'N', 'T', 'T']
def __init__(self):
self.value = 3
def increment(self):
if self.value < 3:
self.value += 1
def decrement(self):
if self.value > 0:
self.value -= 1
def predict(self):
return saturating_counter.pred[self.value]
def __str__(self):
return "{:02b} ({})".format(self.value, saturating_counter.pred[self.value])
class local_bht:
def __init__(self, num_index_bits = 3):
self.num_index = 2**num_index_bits
self.counters = [saturating_counter() for i in range(self.num_index)]
# compute the correct number of significant digits
self.bin_fmt ="{{:{}d}}".format(math.ceil(math.log10(self.num_index)))
def predict(self, pc, target, outcome, verbose):
i = (pc//4) % self.num_index
result = self.counters[i].predict()
if verbose:
print ("predict PC = {:x}, index = {:d}, outcome = {}".format(pc, i, outcome))
tag = {True: '<===',
False: ''}
msg = {False: {True: "", False: ""},
True: {True: " (correct)",
False: " (MISSPREDICT)"}}
for x in range (self.num_index):
print ("BHT[" + self.bin_fmt.format(x) + "] = {} {}{}".format(self.counters[x],
tag[i == x],
msg[i == x][result == outcome]))
if outcome == 'T':
self.counters[i].increment()
else:
self.counters[i].decrement()
return result
\ No newline at end of file
from static import static_predictor
from local import local_bht
from global_pred import global_pht # global is a reserved word, cannot use as module name
from twolevel import twolevel_predictor
from hybrid_correlating import hybrid_correlating_predictor
from tournament import tournament_predictor
def predict(lines, verbose = False, predictor = static_predictor()):
"""Input is a generator which yields triples: (PC, branch target, [T]aken / [N]ot taken
"""
stats = {True:0,
False:0}
msg = {True: '',
False: '*MISSPREDICT*'}
for pc, target, outcome in lines:
#if verbose:
# print()
# print ("-"*30)
prd = predictor.predict(pc, target, outcome, verbose)
if verbose:
print ("0x{:x} --> 0x{:x}: pred = {} actual = {} {}".format(pc,
target,
prd,
outcome,
msg[prd == outcome]))
#if verbose:
# print ("+"*30)
stats[prd == outcome] += + 1
print ("Correct: {}, misspredict: {}, Accuracy: {:4.2f}%".format(stats[True],
stats[False],
100*stats[True]/(sum(stats.values()))))
if __name__ == "__main__":
branches = """0x31c1e011c8 0x31c1e011b0 T
0x31c1e011c2 0x31c1e011f0 N
0x31c1e011c8 0x31c1e011b0 T
0x31c1e011c2 0x31c1e011f0 N
0x31c1e011c8 0x31c1e011b0 T
0x31c1e011c2 0x31c1e011f0 N
0x31c1e011c8 0x31c1e011b0 T
0x31c1e011c2 0x31c1e011f0 N
0x31c1e011c8 0x31c1e011b0 N
0x31c1e011d4 0x31c1e014d0 N
0x31c1e011ee 0x31c1e011c4 T
0x31c1e011c8 0x31c1e011b0 N
0x31c1e011d4 0x31c1e014d0 N
0x31c1e011ee 0x31c1e011c4 T
0x31c1e011c8 0x31c1e011b0 T
0x31c1e011c2 0x31c1e011f0 N
0x31c1e011c8 0x31c1e011b0 N
0x31c1e011d4 0x31c1e014d0 N
0x31c1e011ee 0x31c1e011c4 T
0x31c1e011c8 0x31c1e011b0 N
0x31c1e011d4 0x31c1e014d0 N
0x31c1e011ee 0x31c1e011c4 T
0x31c1e011c8 0x31c1e011b0 N"""
def parts_to_ints(parts):
return ( int(parts[0],16), int(parts[1],16), parts[2] )
# use this line if you want to read from a file.
#lines = open('brtrace.out').readlines()
lines = branches.split('\n')
verb = True
# which predictor or predictors you want to run...
predictors = 'static'
if 'static' in predictors:
for predictor, string in ( (static_predictor(), 'Static'), ):
s = (x.strip().split(' ') for x in lines)
s = (parts_to_ints(x) for x in s)
print (string, ': ')
predict (s, verb, predictor)
print ("="*60)
if 'local' in predictors:
#for predictor, string in (
#(local_bht(i), '2-bit local BHT n={:2d}'.format(i)) for i in range (1, 4) ):
for predictor, string in ((local_bht(3), '2-bit local BHT with {} entries'.format(2**3)),):
s = (x.strip().split(' ') for x in lines)
s = (parts_to_ints(x) for x in s)
print (string, ': ')
predict (s, verb, predictor)
print ("="*60)
if 'global' in predictors:
#for predictor, string in (
# (global_pht(i), 'Global PHT n={:2d}'.format(i)) for i in range (1, 4) ):
for predictor, string in ( (global_pht(3), 'Global PHT with {} entries'.format(2**3)), ):
s = (x.strip().split(' ') for x in lines)
s = (parts_to_ints(x) for x in s)
print (string, ': ')
predict (s, verb, predictor)
print ("="*60)
if 'twolevel' in predictors:
for predictor, string in ( (twolevel_predictor(3,3), 'Two-level with {} entries and {} counters'.format(8,8)), ):
s = (x.strip().split(' ') for x in lines)
s = (parts_to_ints(x) for x in s)
print (string, ': ')
predict (s, verb, predictor)
print ("="*60)
if 'hybrid_correlating' in predictors:
for predictor, string in ( (hybrid_correlating_predictor(2,3),
'Hybrid correlating with global {} bit shift register and {} BHT counters'.format(2,2**3)), ):
s = (x.strip().split(' ') for x in lines)
s = (parts_to_ints(x) for x in s)
print (string, ': ')
predict (s, verb, predictor)
print ("="*60)
if 'tournament' in predictors:
for predictor, string in ( (tournament_predictor(3, 3, 3),
'tournament predictor {} entry bht and {} bit shift register'.format(8,8)), ):
s = (x.strip().split(' ') for x in lines)
s = (parts_to_ints(x) for x in s)
print (string, ': ')
predict (s, verb, predictor)
print ("="*60)
\ No newline at end of file
class static_predictor:
def __init__(self):
pass
def predict(self, pc, target, outcome, verbose):
if target > pc:
return 'N' # target is after PC, --> FORWARD branch
else:
return 'T' # backwards branch
\ No newline at end of file
from twolevel import correlation_register
from global_pred import global_pht
from local import local_bht
class tournament_predictor:
def __init__(self, local_bits, global_bits, meta_bits):
self.local = local_bht(local_bits)
self.glob = global_pht(global_bits)
# TODO
# still need a predictor to predict which to use??
def predict(self, pc, target, outcome, verbose):
result = self.local.predict(pc, target, outcome, verbose)
result += self.glob.predict(pc, target, outcome, verbose)
# TODO
# we have a string with the result of both predictors, what to do with it?
return "T"
\ No newline at end of file
from local import saturating_counter
class correlation_register():
def __init__(self, bits=3):
self.bits = bits
self.mask = 2**self.bits - 1
self.value = self.mask
self.binfmt = "{{:0{:d}b}}".format(len(bin(self.mask)[2:])) # chop leading 0b prefix
def learn(self, outcome):
self.value = (self.value << 1) & (self.mask)
if outcome == 'T':
self.value |= 1
def __str__(self):
return self.binfmt.format(self.value)
class twolevel_predictor():
def __init__(self, correlation_bits=3, pht_bits = 3):
self.corr_bits = correlation_bits
self.pht_bits = pht_bits
self.corr_indexes = 2**self.corr_bits
self.pht_indexes = 2**self.pht_bits
def predict(self, pc, target, outcome, verbose):
# TODO
# finish me.
return "T"
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment