OK, here's my object. Basically, you set up a truth table with the
input and output pins, then you can add values to it usings
dictionaries of the form { 'pin name': 0 or 1......} to represent each
state. The point here is more to deduce the boolean functions of a
table from data observed from black box boolean functions, very useful
for my job in semiconductors. Keep in mind that I wasn't exactly
trained in software, so my code is usually a little rough and brute
force, which keeps it from being less elegant, but easy to understand.
Anyway, if you have any questions, feel free to ask.
class TruthTable(object):
def __init__(self,iinputs= [], ioutputs=[]):
self.ttab = {}
self.inpindex = {}
self.vcount = 0
if iinputs and ioutputs:
self.vcount = 2 ** len(iinputs)
i = 1
for input in iinputs:
self.inpindex[input] = i
i = i * 2
for output in ioutputs:
self.ttab[output] = [ None ] * self.vcount
def reducetable(self):
newinputs = []
onegone = False
for ipin in self.inpindex.keys():
iused = False
for opin in self.ttab.keys():
iused = iused or self.findtransitions(ipin, opin)
if iused:
newinputs.append(ipin)
else:
onegone = True
if not onegone:
return None
i = 1
newindex = {}
newttab = {}
newcount = 2 ** len(newinputs)
for ipin in newinputs:
newindex[ipin] = i
i = i * 2
for opin in self.ttab.keys():
newttab[opin] = [None] * newcount
for i in range(newcount):
curristate = {}
for ipin, bplace in newindex.items():
curristate[ipin] = ( i & bplace ) / bplace
for j in range(self.vcount):
oldstate = self.vec2output(j)
matched = True
for ipin in curristate:
matched = matched and curristate[ipin] ==
oldstate[ipin]
if matched:
for opin in newttab:
newttab[opin]
= oldstate[opin]
self.ttab = newttab
self.inpindex = newindex
self.vcount = newcount
def addvalues(self, ttentry):
index = 0
foundall = True
for ipin in self.inpindex:
if ipin not in ttentry:
raise KeyError, 'Pin %s not in %s' % (ipin, ttentry)
else:
index = index + ttentry[ipin] * self.inpindex[ipin]
for pin, value in ttentry.items():
if pin in self.ttab:
self.ttab[pin][index] = value
def deloutput(self, outname):
if self.ttab.has_key(outname):
del self.ttab[outname]
def vec2output(self, vec):
outent = {}
for input, binplace in self.inpindex.items():
outent[input] = ( vec & binplace) / binplace
for output, outvals in self.ttab.items():
outent[output] = outvals[vec]
return outent
def getvalue(self, inpstate, opin):
if opin not in self.ttab:
raise IndexError, 'Incorrect output pin %s used in
getvalue.' % opin
stindex = 0
for ipin in self.inpindex:
if ipin not in inpstate:
raise KeyError, 'Pin %s cannot be found in inpstate
%s' % (ipin, inpstate)
stindex = stindex + self.inpindex[ipin] * inpstate[ipin]
return self.ttab[opin][stindex]
def __str__(self):
outs = ''
allpins = self.inpindex.keys() + self.ttab.keys()
maxname = 0
for pin in allpins:
if len(pin) > maxname:
maxname = len(pin)
if maxname < 5:
maxname = 5
indicies = self.inpindex.values()
indicies.sort()
indicies.reverse()
indtoinp = {}
inputs = []
for input, index in self.inpindex.items():
indtoinp[index] = input
for i in indicies:
outs = outs + '%s ' % stringfill(indtoinp, maxname)
inputs.append(indtoinp)
outs = outs + '| '
outputs = self.ttab.keys()
outputs.sort()
for out in outputs:
outs = outs + '%s ' % stringfill(out, maxname)
outs = outs + '\n'
for i in range(self.vcount):
currvec = self.vec2output(i)
for inp in inputs:
outs = outs + '%s ' % stringfill(str(currvec[inp]),
maxname)
outs = outs + '| '
for out in outputs:
outs = outs + '%s ' % stringfill(str(currvec[out]),
maxname)
outs = outs + '\n'
return outs
def findtransitions(self, ipin, opin):
indicies = range(self.vcount)
binplace = self.inpindex[ipin]
zerobits = filter(lambda x: x & binplace == 0, indicies)
possibles = map(lambda x: ( x, x + binplace ), zerobits)
foundtrans = []
for lowbit, highbit in possibles:
ovec = self.ttab[opin]
if (ovec[lowbit] != ovec[highbit] and ovec[lowbit] in
[0,1] and
ovec[highbit] in [0,1]):
foundtrans.append( (lowbit, highbit) )
foundtrans = map(lambda x: ( self.vec2output(x[0]),
self.vec2output(x[1]) ),
foundtrans)
return foundtrans
def getoutfunc2(self, opin, notxwhens = []):
if opin not in self.ttab:
return '',''
relpins = []
for ipin in self.inpindex.keys():
tranpairs = self.alltransitions(ipin)
for lowst, highst in tranpairs:
if lowst[opin] != highst[opin] and ipin not in
relpins:
relpins.append(ipin)
if relpins == []:
return '',''
outhighs = []
outx = []
allone = True
for vec in range(self.vcount):
pvec = self.vec2output(vec)
if pvec[opin] in [1, 'X']:
saveout = pvec[opin]
for pin in pvec.keys():
a = pin in self.ttab
b = pin not in relpins
if a or b:
del pvec[pin]
if len(pvec) > 0:
allone = False
if saveout == 1 and pvec not in outhighs:
outhighs.append(pvec)
if saveout == 'X' and pvec not in outx:
outx.append(pvec)
outfunc = ''
xfunc = ''
if allone:
return '1',''
for cwhen in outhighs:
pstring = WhenString(cwhen)
if outfunc == '':
outfunc = '(%s)' % pstring
else:
outfunc = '%s|(%s)' % (outfunc, pstring)
if notxwhens:
print 'finding badxwhens'
badxwhens = []
for cwhen in outx:
for subwhen in notxwhens:
if DictIn(cwhen,subwhen):
badxwhens.append(cwhen)
break
for bwhen in badxwhens:
outx.remove(bwhen)
for cwhen in outx:
pstring = WhenString(cwhen)
if xfunc == '':
xfunc = '(%s)' % pstring
else:
xfunc = '%s|(%s)' % (xfunc, pstring)
return outfunc, xfunc
def alltransitions(self, ipin):
indicies = range(self.vcount)
binplace = self.inpindex[ipin]
zerobits = filter(lambda x: x & binplace == 0, indicies)
possibles = map(lambda x: ( x, x + binplace ), zerobits)
foundtrans = []
foundtrans = map(lambda x: ( self.vec2output(x[0]),
self.vec2output(x[1]) ),
possibles)
return foundtrans
def getinputs(self):
return self.inpindex.keys()
def getoutputs(self):
return self.ttab.keys()
def __len__(self):
return self.vcount
Oh, and a function called WhenString is also called, here's that:
def WhenString(statein):
pstring = ''
pinlist = statein.keys()
pinlist.sort()
for pin in pinlist:
if pstring != '':
pstring = '%s&' % pstring
if statein[pin] == 0:
pstring = '%s!' % pstring
if statein[pin] in [0, 1]:
pstring = '%s%s' % (pstring, pin)
if pstring and pstring[-1] in ['&', '!']:
pstring = pstring[:-1]
return pstring
I took out some comments and a couple of differential specific
functions to clear things up, and it's a little cluttered up with code
to check for 'X' states, but that's it. Let me know what you think.