diff --git a/myhdl/conversion/_analyze.py b/myhdl/conversion/_analyze.py index 2c139ec3..1371fb64 100644 --- a/myhdl/conversion/_analyze.py +++ b/myhdl/conversion/_analyze.py @@ -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 diff --git a/myhdl/conversion/_toVerilog.py b/myhdl/conversion/_toVerilog.py index 2e138999..49b50a4b 100644 --- a/myhdl/conversion/_toVerilog.py +++ b/myhdl/conversion/_toVerilog.py @@ -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)