Commit ba1e2f36 authored by Alan Marchiori's avatar Alan Marchiori

initial commit

parents
This source diff could not be displayed because it is too large. You can view the blob instead.
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