1
0
mirror of https://github.com/myhdl/myhdl.git synced 2025-01-24 21:52:56 +08:00

UNSTABLE - replace compiler by ast for conversion

Tests in conversion/general for Verilog work.
This commit is contained in:
Jan Decaluwe 2009-05-02 22:51:08 +02:00
parent c962b8542e
commit e6ba8d4ec1
2 changed files with 135 additions and 72 deletions

View File

@ -139,7 +139,6 @@ def _analyzeGens(top, absnames):
s = inspect.getsource(f)
s = _dedent(s)
tree = ast.parse(s)
#print ast.dump(tree)
tree.sourcefile = inspect.getsourcefile(f)
tree.lineoffset = inspect.getsourcelines(f)[1]-1
tree.symdict = f.func_globals.copy()
@ -166,7 +165,6 @@ def _analyzeGens(top, absnames):
s = inspect.getsource(f)
s = _dedent(s)
tree = ast.parse(s)
# print ast.dump(tree)
tree.sourcefile = inspect.getsourcefile(f)
tree.lineoffset = inspect.getsourcelines(f)[1]-1
tree.symdict = f.f_globals.copy()
@ -279,7 +277,8 @@ class _FirstPassVisitor(ast.NodeVisitor, _ConversionMixin):
self.raiseError(node, _error.NotSupported, "embedded function definition")
self.toplevel = False
node.argnames = [arg.id for arg in node.args.args]
self.generic_visit(node)
# don't visit decorator lists - they can support more than other calls
self.visitList(node.body)
def flattenIf(self, node, tests):
""" Flatten if-then-else as in compiler package."""
@ -485,7 +484,7 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
node.signed = node.operand.signed
if isinstance(op, ast.Not):
node.obj = bool()
elif isintance(op, ast.UAdd):
elif isinstance(op, ast.UAdd):
node.obj = int(-1)
elif isinstance(op, ast.USub):
node.obj = int(-1)
@ -545,16 +544,16 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
if node.attr != 'next':
self.raiseError(node, _error.NotSupported, "attribute assignment")
self.tree.kind = _kind.TASK
self.access = _access.OUTPUT
# self.access = _access.OUTPUT
self.visit(node.value)
self.access = _access.INPUT
# self.access = _access.INPUT
def getAttr(self, node):
self.visit(node.value)
node.obj = None
node.signed = False
if isinstance(node.value, astNode.Name):
n = node.value.name
if isinstance(node.value, ast.Name):
n = node.value.id
if (n not in self.tree.vardict) and (n not in self.tree.symdict):
raise AssertionError("attribute target: %s" % n)
obj = node.value.obj
@ -869,11 +868,12 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
def visit_Compare(self, node):
node.obj = bool()
node.signed = False
for n in ast.iter_field_nodes(node):
#for n in ast.iter_child_nodes(node):
for n in [node.left] + node.comparators:
self.visit(n)
if n.signed:
node.signed = True
op, arg = ops[0], compartors[0]
op, arg = node.ops[0], node.comparators[0]
## node.expr.target = self.getObj(arg)
## arg.target = self.getObj(node.expr)
# detect specialized case for the test
@ -1029,11 +1029,11 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
for test, suite in node.tests:
self.visit(test)
self.refStack.push()
self.visit(suite)
self.visitList(suite)
self.refStack.pop()
if node.else_:
self.refStack.push()
self.visit(node.else_)
self.visitList(node.else_)
self.refStack.pop()
# check whether the if can be mapped to a (parallel) case
node.isCase = node.isFullCase = False
@ -1164,14 +1164,28 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
self.getName(node)
def setName(self, node):
# XXX INOUT access in Store context, unlike with compiler
# XXX check whether ast context is correct
n = node.id
if n in ("__verilog__", "__vhdl__"):
self.raiseError(node, _error.NotSupported,
"%s in generator function" % n)
# XXX ?
if n in self.globalRefs:
self.raiseError(node, _error.UnboundLocal, n)
self.refStack.add(n)
if self.access == _access.INOUT: # augmented assign
if n in self.tree.sigdict:
sig = self.tree.sigdict[n]
if isinstance(sig, Signal):
self.raiseError(node, _error.NotSupported, "Augmented signal assignment")
if n in self.tree.vardict:
obj = self.tree.vardict[n]
# upgrade bool to int for augmented assignments
if isinstance(obj, bool):
obj = int(0)
self.tree.vardict[n] = obj
node.obj = obj
else:
if n in ("__verilog__", "__vhdl__"):
self.raiseError(node, _error.NotSupported,
"%s in generator function" % n)
if n in self.globalRefs:
self.raiseError(node, _error.UnboundLocal, n)
self.refStack.add(n)
def getName(self, node):
n = node.id
@ -1201,7 +1215,7 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
self.raiseError(node, _error.NotSupported, "Augmented signal assignment")
if n in self.tree.vardict:
obj = self.tree.vardict[n]
if self.access == _access.INOUT:
if self.access == _access.INOUT: # probably dead code
# upgrade bool to int for augmented assignments
if isinstance(obj, bool):
obj = int(0)
@ -1302,7 +1316,7 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
a.extend(n.right.elts)
else:
a.append(n.right)
s = n.left.value
s = n.left.s
while s:
if not s:
break
@ -1417,7 +1431,7 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
self.access = _access.INPUT
self.visit(node.slice.value)
if isinstance(node.value.obj, _Ram):
if node.flags == 'OP_ASSIGN':
if isinstance(node.ctx, ast.Store):
self.raiseError(node, _error.ListElementAssign)
else:
node.obj = node.value.obj.elObj

View File

@ -333,6 +333,12 @@ opmap = {
ast.Not : '!',
ast.UAdd : '+',
ast.USub : '-',
ast.Eq : '==',
ast.Gt : '>',
ast.GtE : '>=',
ast.Lt : '<',
ast.LtE : '<=',
ast.NotEq : '!=',
}
@ -528,7 +534,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write("(")
self.visit(node.values[0])
for n in node.nodes[1:]:
self.write(" %s " % opmap[node.op])
self.write(" %s " % opmap[type(node.op)])
self.visit(n)
self.write(")")
@ -551,7 +557,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
def visit_UnaryOp(self, node):
self.write("(%s" % opmap[node.op])
self.write("(%s" % opmap[type(node.op)])
self.visit(node.operand)
self.write(")")
@ -562,12 +568,71 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
# self.isSigAss = True
# self.visit(node.expr)
# def visitGetattr(self, node, *args):
# assert isinstance(node.expr, astNode.Name)
# n = node.expr.name
# if n in self.tree.symdict:
# obj = self.tree.symdict[n]
# elif n in self.tree.vardict:
# obj = self.tree.vardict[n]
# else:
# raise AssertionError("object not found")
# if isinstance(obj, Signal):
# if node.attrname == 'next':
# self.isSigAss = True
# self.visit(node.expr)
# elif node.attrname in ('posedge', 'negedge'):
# self.write(node.attrname)
# self.write(' ')
# self.visit(node.expr)
# elif node.attrname == 'val':
# self.visit(node.expr)
# if isinstance(obj, (Signal, intbv)):
# if node.attrname in ('min', 'max'):
# self.write("%s" % node.obj)
# if isinstance(obj, EnumType):
# assert hasattr(obj, node.attrname)
# e = getattr(obj, node.attrname)
# self.write(e._toVerilog())
def visit_Attribute(self, node):
if isinstance(node.ctx, ast.Store):
assert node.attr == 'next'
self.isSigAss = True
self.visit(node.value)
self.setAttr(node)
else:
self.getAttr(node)
def setAttr(self, node):
assert node.attr == 'next'
self.isSigAss = True
self.visit(node.value)
def getAttr(self, node):
assert isinstance(node.value, ast.Name)
n = node.value.id
if n in self.tree.symdict:
obj = self.tree.symdict[n]
elif n in self.tree.vardict:
obj = self.tree.vardict[n]
else:
raise AssertionError("object not found")
if isinstance(obj, Signal):
if node.attr == 'next':
self.isSigAss = True
self.visit(node.value)
elif node.attr in ('posedge', 'negedge'):
self.write(node.attr)
self.write(' ')
self.visit(node.value)
elif node.attr == 'val':
self.visit(node.value)
if isinstance(obj, (Signal, intbv)):
if node.attr in ('min', 'max'):
self.write("%s" % node.obj)
if isinstance(obj, EnumType):
assert hasattr(obj, node.attr)
e = getattr(obj, node.attr)
self.write(e._toVerilog())
# def visitAssert(self, node, *args):
@ -803,6 +868,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
def visit_Call(self, node):
self.context = None
fn = node.func
# assert isinstance(fn, astNode.Name)
f = self.getObj(fn)
@ -839,10 +905,10 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
elif f == intbv.signed: # note equality comparison
# comes from a getattr
opening, closing = '', ''
if not fn.expr.signed:
if not fn.value.signed:
opening, closing = "$signed(", ")"
self.write(opening)
self.visit(fn.expr)
self.visit(fn.value)
self.write(closing)
elif type(f) in (ClassType, TypeType) and issubclass(f, Exception):
self.write(f.__name__)
@ -874,16 +940,27 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
v.visit(node.tree)
def visitCompare(self, node, *args):
context = None
# def visitCompare(self, node, *args):
# context = None
# if node.signed:
# context = _context.SIGNED
# self.write("(")
# self.visit(node.expr, context)
# op, code = node.ops[0]
# self.write(" %s " % op)
# self.visit(code, context)
# self.write(")")
def visit_Compare(self, node):
self.context = None
if node.signed:
context = _context.SIGNED
self.context = _context.SIGNED
self.write("(")
self.visit(node.expr, context)
op, code = node.ops[0]
self.write(" %s " % op)
self.visit(code, context)
self.visit(node.left)
self.write(" %s " % opmap[type(node.ops[0])])
self.visit(node.comparators[0])
self.write(")")
self.context = None
@ -1072,33 +1149,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
def visitGetattr(self, node, *args):
assert isinstance(node.expr, astNode.Name)
n = node.expr.name
if n in self.tree.symdict:
obj = self.tree.symdict[n]
elif n in self.tree.vardict:
obj = self.tree.vardict[n]
else:
raise AssertionError("object not found")
if isinstance(obj, Signal):
if node.attrname == 'next':
self.isSigAss = True
self.visit(node.expr)
elif node.attrname in ('posedge', 'negedge'):
self.write(node.attrname)
self.write(' ')
self.visit(node.expr)
elif node.attrname == 'val':
self.visit(node.expr)
if isinstance(obj, (Signal, intbv)):
if node.attrname in ('min', 'max'):
self.write("%s" % node.obj)
if isinstance(obj, EnumType):
assert hasattr(obj, node.attrname)
e = getattr(obj, node.attrname)
self.write(e._toVerilog())
# def visitIf(self, node, *args):
@ -1133,7 +1183,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(item._toVerilog(dontcare=True))
self.write(": begin")
self.indent()
self.visit(suite)
self.visit_stmt(suite)
self.dedent()
self.writeline()
self.write("end")
@ -1141,7 +1191,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.writeline()
self.write("default: begin")
self.indent()
self.visit(node.else_)
self.visit_stmt(node.else_)
self.dedent()
self.writeline()
self.write("end")
@ -1162,7 +1212,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(test)
self.write(") begin")
self.indent()
self.visit(suite)
self.visit_stmt(suite)
self.dedent()
self.writeline()
self.write("end")
@ -1170,7 +1220,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.writeline()
self.write("else begin")
self.indent()
self.visit(node.else_)
self.visit_stmt(node.else_)
self.dedent()
self.writeline()
self.write("end")
@ -1364,7 +1414,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
if isinstance(s, str):
self.write('$write("%s");' % s)
else:
a = node.values[argnr]
a = node.args[argnr]
argnr += 1
obj = a.obj
fs = "%0d"
@ -1549,7 +1599,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
# self.visit(elt)
def visitTuple(self, node):
def visit_Tuple(self, node):
assert self.context != None
sep = ", "
tpl = node.elts
@ -1747,7 +1797,7 @@ class _ConvertSimpleAlwaysCombVisitor(_ConvertVisitor):
# self.visit(node.expr)
def visit_Attribute(self, node):
if isintance(node.ctx, ast.Store):
if isinstance(node.ctx, ast.Store):
self.write("assign ")
self.visit(node.value)
else:
@ -1758,8 +1808,7 @@ class _ConvertSimpleAlwaysCombVisitor(_ConvertVisitor):
# self.writeline(2)
def visit_FunctionDef(self, node):
for stmt in node.body:
self.visit(node.body)
self.visit_stmt(node.body)
self.writeline(2)