mirror of
https://github.com/myhdl/myhdl.git
synced 2025-01-24 21:52:56 +08:00
map to case
This commit is contained in:
parent
ebfa3be920
commit
4e4451a4d4
@ -35,9 +35,9 @@ def enum(*args, **kwargs):
|
|||||||
encoding = kwargs.get('encoding', 'binary')
|
encoding = kwargs.get('encoding', 'binary')
|
||||||
argdict = {}
|
argdict = {}
|
||||||
codedict = {}
|
codedict = {}
|
||||||
if encoding == 'binary':
|
if encoding == "binary":
|
||||||
nrbits = len(bin(len(args)))
|
nrbits = len(bin(len(args)))
|
||||||
elif encoding in ('one_hot', 'one_cold'):
|
elif encoding in ("one_hot", "one_cold"):
|
||||||
nrbits = len(args)
|
nrbits = len(args)
|
||||||
else:
|
else:
|
||||||
raise ValueError("Unsupported enum encoding: %s \n Supported encodings:" + \
|
raise ValueError("Unsupported enum encoding: %s \n Supported encodings:" + \
|
||||||
@ -50,9 +50,9 @@ def enum(*args, **kwargs):
|
|||||||
if codedict.has_key(arg):
|
if codedict.has_key(arg):
|
||||||
raise ValueError("enum literals should be unique")
|
raise ValueError("enum literals should be unique")
|
||||||
argdict[i] = arg
|
argdict[i] = arg
|
||||||
if encoding == 'binary':
|
if encoding == "binary":
|
||||||
code = bin(i, nrbits)
|
code = bin(i, nrbits)
|
||||||
elif encoding == 'one_hot':
|
elif encoding == "one_hot":
|
||||||
code = bin(1<<i, nrbits)
|
code = bin(1<<i, nrbits)
|
||||||
else: # one_cold
|
else: # one_cold
|
||||||
code = bin(~(1<<i), nrbits)
|
code = bin(~(1<<i), nrbits)
|
||||||
@ -66,11 +66,20 @@ def enum(*args, **kwargs):
|
|||||||
self._index = index
|
self._index = index
|
||||||
self._val = codedict[arg]
|
self._val = codedict[arg]
|
||||||
self._nrbits = nrbits
|
self._nrbits = nrbits
|
||||||
|
self._nritems = len(args)
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return argdict[self._index]
|
return argdict[self._index]
|
||||||
def __hex__(self):
|
def __hex__(self):
|
||||||
return hex(int(self._val, 2))
|
return hex(int(self._val, 2))
|
||||||
__str__ = __repr__
|
__str__ = __repr__
|
||||||
|
def _toVerilog(self, dontcare=False):
|
||||||
|
val = self._val
|
||||||
|
if dontcare:
|
||||||
|
if encoding == "one_hot":
|
||||||
|
val = val.replace('0', '?')
|
||||||
|
elif encoding == "one_cold":
|
||||||
|
val = val.replace('1', '?')
|
||||||
|
return "%d'b%s" % (self._nrbits, val)
|
||||||
|
|
||||||
class Enum(object):
|
class Enum(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -98,6 +98,7 @@ def _analyzeGens(top, genNames):
|
|||||||
s = inspect.getsource(f)
|
s = inspect.getsource(f)
|
||||||
s = s.lstrip()
|
s = s.lstrip()
|
||||||
ast = compiler.parse(s)
|
ast = compiler.parse(s)
|
||||||
|
print ast
|
||||||
ast.sourcefile = inspect.getsourcefile(f)
|
ast.sourcefile = inspect.getsourcefile(f)
|
||||||
ast.lineoffset = inspect.getsourcelines(f)[1]-1
|
ast.lineoffset = inspect.getsourcelines(f)[1]-1
|
||||||
ast.symdict = f.f_globals.copy()
|
ast.symdict = f.f_globals.copy()
|
||||||
@ -377,6 +378,12 @@ class _AnalyzeVisitor(_ToVerilogMixin):
|
|||||||
|
|
||||||
def visitCompare(self, node, *args):
|
def visitCompare(self, node, *args):
|
||||||
node.obj = bool()
|
node.obj = bool()
|
||||||
|
self.visitChildNodes(node)
|
||||||
|
op, arg = node.ops[0]
|
||||||
|
if op == '==':
|
||||||
|
if isinstance(node.expr, astNode.Name) and \
|
||||||
|
str(type(arg.obj)) == "<class 'myhdl._enum.EnumItem'>":
|
||||||
|
node.case = (node.expr.name, arg.obj)
|
||||||
|
|
||||||
def visitConst(self, node, *args):
|
def visitConst(self, node, *args):
|
||||||
if isinstance(node.value, int):
|
if isinstance(node.value, int):
|
||||||
@ -425,6 +432,27 @@ class _AnalyzeVisitor(_ToVerilogMixin):
|
|||||||
self.refStack.push()
|
self.refStack.push()
|
||||||
self.visit(node.else_, *args)
|
self.visit(node.else_, *args)
|
||||||
self.refStack.pop()
|
self.refStack.pop()
|
||||||
|
# check whether the if can be mapped to a (parallel) case
|
||||||
|
node.isCase = node.isFullCase = False
|
||||||
|
test1 = node.tests[0][0]
|
||||||
|
if not hasattr(test1, 'case'):
|
||||||
|
return
|
||||||
|
name1, item1 = test1.case
|
||||||
|
choices = Set()
|
||||||
|
choices.add(item1._index)
|
||||||
|
for test, suite in node.tests[1:]:
|
||||||
|
if not hasattr(test, 'case'):
|
||||||
|
return
|
||||||
|
name, item = test.case
|
||||||
|
if name != name1 or type(item) is not type(item1):
|
||||||
|
return
|
||||||
|
if item._index in choices:
|
||||||
|
return
|
||||||
|
choices.add(item._index)
|
||||||
|
node.isCase = True
|
||||||
|
node.caseVar = name1
|
||||||
|
if (len(choices) == item1._nritems) or (node.else_ is not None):
|
||||||
|
node.isFullCase = True
|
||||||
|
|
||||||
def visitName(self, node, access=_access.INPUT, *args):
|
def visitName(self, node, access=_access.INPUT, *args):
|
||||||
n = node.name
|
n = node.name
|
||||||
|
@ -478,9 +478,45 @@ class _ConvertVisitor(_ToVerilogMixin):
|
|||||||
elif str(type(obj)) == "<class 'myhdl._enum.Enum'>":
|
elif str(type(obj)) == "<class 'myhdl._enum.Enum'>":
|
||||||
assert hasattr(obj, node.attrname)
|
assert hasattr(obj, node.attrname)
|
||||||
e = getattr(obj, node.attrname)
|
e = getattr(obj, node.attrname)
|
||||||
self.write("%d'b%s" % (obj._nrbits, e._val))
|
self.write(e._toVerilog())
|
||||||
|
|
||||||
def visitIf(self, node, *args):
|
def visitIf(self, node, *args):
|
||||||
|
if node.isCase:
|
||||||
|
self.mapToCase(node, *args)
|
||||||
|
else:
|
||||||
|
self.mapToIf(node, *args)
|
||||||
|
|
||||||
|
def mapToCase(self, node, *args):
|
||||||
|
var = node.caseVar
|
||||||
|
self.write("// synthesis parallel_case")
|
||||||
|
if node.isFullCase:
|
||||||
|
self.write(" full_case")
|
||||||
|
self.writeline()
|
||||||
|
self.write("casez (%s)" % var)
|
||||||
|
self.indent()
|
||||||
|
for test, suite in node.tests:
|
||||||
|
self.writeline()
|
||||||
|
item = test.ops[0][1].obj
|
||||||
|
self.write(item._toVerilog(dontcare=True))
|
||||||
|
self.write(": begin")
|
||||||
|
self.indent()
|
||||||
|
self.visit(suite)
|
||||||
|
self.dedent()
|
||||||
|
self.writeline()
|
||||||
|
self.write("end")
|
||||||
|
if node.else_:
|
||||||
|
self.writeline()
|
||||||
|
self.write("default: begin")
|
||||||
|
self.indent()
|
||||||
|
self.visit(node.else_)
|
||||||
|
self.dedent()
|
||||||
|
self.writeline()
|
||||||
|
self.write("end")
|
||||||
|
self.dedent()
|
||||||
|
self.writeline()
|
||||||
|
self.write("endcase")
|
||||||
|
|
||||||
|
def mapToIf(self, node, *args):
|
||||||
first = True
|
first = True
|
||||||
for test, suite in node.tests:
|
for test, suite in node.tests:
|
||||||
if first:
|
if first:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user