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

Major refactoring of type inference for toVerilog

Put the code in _toVerilog instead of _analyze

--HG--
branch : 0.8-dev
This commit is contained in:
Jan Decaluwe 2012-08-28 17:23:17 +02:00
parent 951d0d53ae
commit 1006dbe564
3 changed files with 148 additions and 270 deletions

View File

@ -25,23 +25,19 @@
import inspect import inspect
# import compiler # import compiler
# from compiler import ast as astNode # from compiler import ast as astNode
from types import GeneratorType, FunctionType, ClassType, MethodType from types import FunctionType, MethodType
from cStringIO import StringIO
import re import re
import warnings
import ast import ast
import __builtin__ import __builtin__
import myhdl import myhdl
from myhdl import * from myhdl import *
from myhdl import ConversionError from myhdl import ConversionError
from myhdl._unparse import _unparse
from myhdl._cell_deref import _cell_deref from myhdl._cell_deref import _cell_deref
from myhdl._always_comb import _AlwaysComb from myhdl._always_comb import _AlwaysComb
from myhdl._always_seq import _AlwaysSeq from myhdl._always_seq import _AlwaysSeq
from myhdl._always import _Always from myhdl._always import _Always
from myhdl._delay import delay from myhdl.conversion._misc import (_error, _access, _kind,
from myhdl.conversion._misc import (_error, _access, _kind, _context,
_ConversionMixin, _Label, _genUniqueSuffix) _ConversionMixin, _Label, _genUniqueSuffix)
from myhdl._extractHierarchy import _isMem, _getMemInfo, _UserCode from myhdl._extractHierarchy import _isMem, _getMemInfo, _UserCode
from myhdl._Signal import _Signal, _WaiterList from myhdl._Signal import _Signal, _WaiterList
@ -376,14 +372,6 @@ class _Rom(object):
def __init__(self, rom): def __init__(self, rom):
self.rom = rom self.rom = rom
def _maybeNegative(obj):
if hasattr(obj, '_min') and (obj._min is not None) and (obj._min < 0):
return True
if isinstance(obj, (int, long)) and obj < 0:
return True
return False
re_str = re.compile(r"[^%]+") re_str = re.compile(r"[^%]+")
re_ConvSpec = re.compile(r"%(?P<justified>[-]?)(?P<width>[0-9]*)(?P<conv>[sd])") re_ConvSpec = re.compile(r"%(?P<justified>[-]?)(?P<width>[0-9]*)(?P<conv>[sd])")
@ -435,13 +423,10 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
self.access = _access.INPUT self.access = _access.INPUT
self.kind = _kind.NORMAL self.kind = _kind.NORMAL
def visit_BinOp(self, node): def visit_BinOp(self, node):
self.visit(node.left) self.visit(node.left)
self.visit(node.right) self.visit(node.right)
node.obj = int(-1) node.obj = int(-1)
node.signed = node.left.signed or node.right.signed
def visit_BoolOp(self, node): def visit_BoolOp(self, node):
for n in node.values: for n in node.values:
@ -450,23 +435,17 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
if not hasType(n.obj, bool): if not hasType(n.obj, bool):
self.raiseError(node, _error.NotSupported, "non-boolean argument in logical operator") self.raiseError(node, _error.NotSupported, "non-boolean argument in logical operator")
node.obj = bool() node.obj = bool()
node.signed = False
def visit_UnaryOp(self, node): def visit_UnaryOp(self, node):
self.visit(node.operand) self.visit(node.operand)
op = node.op op = node.op
node.obj = node.operand.obj node.obj = node.operand.obj
node.signed = node.operand.signed
if isinstance(op, ast.Not): if isinstance(op, ast.Not):
node.obj = bool() node.obj = bool()
elif isinstance(op, ast.UAdd): elif isinstance(op, ast.UAdd):
node.obj = int(-1) node.obj = int(-1)
elif isinstance(op, ast.USub): elif isinstance(op, ast.USub):
node.obj = int(-1) node.obj = int(-1)
if isinstance(node.operand, ast.Num):
node.signed = True
def visit_Attribute(self, node): def visit_Attribute(self, node):
if isinstance(node.ctx, ast.Store): if isinstance(node.ctx, ast.Store):
@ -481,7 +460,6 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
if not obj._init._hasFullRange(): if not obj._init._hasFullRange():
self.raiseError(node, _error.ModbvRange, n) self.raiseError(node, _error.ModbvRange, n)
def setAttr(self, node): def setAttr(self, node):
if node.attr != 'next': if node.attr != 'next':
self.raiseError(node, _error.NotSupported, "attribute assignment") self.raiseError(node, _error.NotSupported, "attribute assignment")
@ -493,7 +471,6 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
def getAttr(self, node): def getAttr(self, node):
self.visit(node.value) self.visit(node.value)
node.obj = None node.obj = None
node.signed = False
if isinstance(node.value, ast.Name): if isinstance(node.value, ast.Name):
n = node.value.id n = node.value.id
if (n not in self.tree.vardict) and (n not in self.tree.symdict): if (n not in self.tree.vardict) and (n not in self.tree.symdict):
@ -523,8 +500,6 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
if node.obj is None: # attribute lookup failed if node.obj is None: # attribute lookup failed
self.raiseError(node, _error.UnsupportedAttribute, node.attr) self.raiseError(node, _error.UnsupportedAttribute, node.attr)
def visit_Assign(self, node): def visit_Assign(self, node):
target, value = node.targets[0], node.value target, value = node.targets[0], node.value
self.access = _access.OUTPUT self.access = _access.OUTPUT
@ -544,8 +519,6 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
if isinstance(obj, intbv): if isinstance(obj, intbv):
if len(obj) == 0: if len(obj) == 0:
self.raiseError(node, _error.IntbvBitWidth, n) self.raiseError(node, _error.IntbvBitWidth, n)
if obj._min < 0:
_signed = True
if isinstance(obj, modbv): if isinstance(obj, modbv):
if not obj._hasFullRange(): if not obj._hasFullRange():
self.raiseError(node, _error.ModbvRange, n) self.raiseError(node, _error.ModbvRange, n)
@ -564,23 +537,15 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
else: else:
self.visit(value) self.visit(value)
def visit_AugAssign(self, node): def visit_AugAssign(self, node):
self.access = _access.INOUT self.access = _access.INOUT
self.visit(node.target) self.visit(node.target)
self.access = _access.INPUT self.access = _access.INPUT
self.visit(node.value) self.visit(node.value)
def visit_Break(self, node): def visit_Break(self, node):
self.labelStack[-2].isActive = True self.labelStack[-2].isActive = True
def visit_Call(self, node): def visit_Call(self, node):
self.visit(node.func) self.visit(node.func)
self.access = _access.UNKNOWN self.access = _access.UNKNOWN
@ -592,7 +557,6 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
argsAreInputs = True argsAreInputs = True
f = self.getObj(node.func) f = self.getObj(node.func)
node.obj = None node.obj = None
node.signed = False
if type(f) is type and issubclass(f, intbv): if type(f) is type and issubclass(f, intbv):
node.obj = self.getVal(node) node.obj = self.getVal(node)
elif f is concat: elif f is concat:
@ -610,7 +574,6 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
### suprize: identity comparison on unbound methods doesn't work in python 2.5?? ### suprize: identity comparison on unbound methods doesn't work in python 2.5??
elif f == intbv.signed: elif f == intbv.signed:
node.obj = int(-1) node.obj = int(-1)
node.signed = True
elif f in myhdlObjects: elif f in myhdlObjects:
pass pass
elif f in builtinObjects: elif f in builtinObjects:
@ -665,17 +628,10 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
for arg in node.args: for arg in node.args:
self.visit(arg) self.visit(arg)
def visit_Compare(self, node): def visit_Compare(self, node):
node.obj = bool() node.obj = bool()
node.signed = False
#for n in ast.iter_child_nodes(node):
for n in [node.left] + node.comparators: for n in [node.left] + node.comparators:
self.visit(n) self.visit(n)
if n.signed:
node.signed = True
op, arg = node.ops[0], node.comparators[0] op, arg = node.ops[0], node.comparators[0]
## node.expr.target = self.getObj(arg) ## node.expr.target = self.getObj(arg)
## arg.target = self.getObj(node.expr) ## arg.target = self.getObj(node.expr)
@ -698,10 +654,7 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
elif v == 1: elif v == 1:
node.edge = sig.posedge node.edge = sig.posedge
def visit_Num(self, node): def visit_Num(self, node):
node.signed = False
n = node.n n = node.n
# assign to value attribute for backwards compatibility # assign to value attribute for backwards compatibility
node.value = n node.value = n
@ -713,15 +666,11 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
node.obj = None node.obj = None
def visit_Str(self, node): def visit_Str(self, node):
node.signed = False
node.obj = node.s node.obj = node.s
def visit_Continue(self, node): def visit_Continue(self, node):
self.labelStack[-1].isActive = True self.labelStack[-1].isActive = True
def visit_For(self, node): def visit_For(self, node):
node.breakLabel = _Label("BREAK") node.breakLabel = _Label("BREAK")
node.loopLabel = _Label("LOOP") node.loopLabel = _Label("LOOP")
@ -745,11 +694,9 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
self.labelStack.pop() self.labelStack.pop()
self.labelStack.pop() self.labelStack.pop()
def visit_FunctionDef(self, node): def visit_FunctionDef(self, node):
raise AssertionError("subclass must implement this") raise AssertionError("subclass must implement this")
def visit_If(self, node): def visit_If(self, node):
if node.ignore: if node.ignore:
return return
@ -789,8 +736,6 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
if (len(choices) == _getNritems(var1.obj)) or node.else_: if (len(choices) == _getNritems(var1.obj)) or node.else_:
node.isFullCase = True node.isFullCase = True
def visit_ListComp(self, node): def visit_ListComp(self, node):
mem = node.obj = _Ram() mem = node.obj = _Ram()
self.kind = _kind.DECLARATION self.kind = _kind.DECLARATION
@ -808,8 +753,6 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
self.raiseError(node, _error.UnsupportedListComp) self.raiseError(node, _error.UnsupportedListComp)
mem.depth = cf.args[0].obj mem.depth = cf.args[0].obj
def visit_Name(self, node): def visit_Name(self, node):
if isinstance(node.ctx, ast.Store): if isinstance(node.ctx, ast.Store):
self.setName(node) self.setName(node)
@ -843,7 +786,6 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
def getName(self, node): def getName(self, node):
n = node.id n = node.id
node.obj = None node.obj = None
if n not in self.refStack: if n not in self.refStack:
if n in self.tree.vardict: if n in self.tree.vardict:
self.raiseError(node, _error.UnboundLocal, n) self.raiseError(node, _error.UnboundLocal, n)
@ -901,19 +843,10 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
node.obj = __builtin__.__dict__[n] node.obj = __builtin__.__dict__[n]
else: else:
pass pass
node.signed = _maybeNegative(node.obj)
## node.target = node.obj
def visit_Return(self, node): def visit_Return(self, node):
self.raiseError(node, _error.NotSupported, "return statement") self.raiseError(node, _error.NotSupported, "return statement")
def visit_Print(self, node): def visit_Print(self, node):
self.tree.hasPrint = True self.tree.hasPrint = True
f = [] f = []
@ -969,8 +902,6 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
self.raiseError(node, _error.FormatString, "too many arguments") self.raiseError(node, _error.FormatString, "too many arguments")
self.generic_visit(node) self.generic_visit(node)
def visit_Subscript(self, node): def visit_Subscript(self, node):
if isinstance(node.slice, ast.Slice): if isinstance(node.slice, ast.Slice):
self.accessSlice(node) self.accessSlice(node)
@ -978,7 +909,6 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
self.accessIndex(node) self.accessIndex(node)
def accessSlice(self, node): def accessSlice(self, node):
node.signed = False
self.visit(node.value) self.visit(node.value)
node.obj = self.getObj(node.value) node.obj = self.getObj(node.value)
self.access = _access.INPUT self.access = _access.INPUT
@ -1014,15 +944,10 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
node.obj = bool() node.obj = bool()
else: else:
node.obj = bool() # XXX default node.obj = bool() # XXX default
node.signed = _maybeNegative(node.obj)
def visit_Tuple(self, node): def visit_Tuple(self, node):
node.signed = False
self.generic_visit(node) self.generic_visit(node)
def visit_While(self, node): def visit_While(self, node):
node.breakLabel = _Label("BREAK") node.breakLabel = _Label("BREAK")
node.loopLabel = _Label("LOOP") node.loopLabel = _Label("LOOP")
@ -1046,7 +971,6 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
self.labelStack.pop() self.labelStack.pop()
self.labelStack.pop() self.labelStack.pop()
def visit_Yield(self, node, *args): def visit_Yield(self, node, *args):
self.tree.hasYield += 1 self.tree.hasYield += 1
n = node.value n = node.value
@ -1066,8 +990,6 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
node.senslist = senslist node.senslist = senslist
class _AnalyzeBlockVisitor(_AnalyzeVisitor): class _AnalyzeBlockVisitor(_AnalyzeVisitor):
def __init__(self, tree): def __init__(self, tree):

View File

@ -1,7 +1,7 @@
# This file is part of the myhdl library, a Python package for using # This file is part of the myhdl library, a Python package for using
# Python as a Hardware Description Language. # Python as a Hardware Description Language.
# #
# Copyright (C) 2003-2009 Jan Decaluwe # Copyright (C) 2003-2012 Jan Decaluwe
# #
# The myhdl library is free software; you can redistribute it and/or # The myhdl library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License as # modify it under the terms of the GNU Lesser General Public License as
@ -86,8 +86,6 @@ def _makeDoc(doc, indent=''):
return doc return doc
class _ToVHDLConvertor(object): class _ToVHDLConvertor(object):
__slots__ = ("name", __slots__ = ("name",
@ -220,7 +218,6 @@ def _writeFileHeader(f, fn):
print >> f print >> f
def _writeCustomPackage(f, intf): def _writeCustomPackage(f, intf):
print >> f print >> f
print >> f, "package pck_%s is" % intf.name print >> f, "package pck_%s is" % intf.name
@ -343,10 +340,6 @@ def _writeCompDecls(f, compDecls):
def _writeModuleFooter(f, arch): def _writeModuleFooter(f, arch):
print >> f, "end architecture %s;" % arch print >> f, "end architecture %s;" % arch
def _getRangeString(s): def _getRangeString(s):
if isinstance(s._val, EnumItemType): if isinstance(s._val, EnumItemType):
return '' return ''
@ -358,7 +351,6 @@ def _getRangeString(s):
else: else:
raise AssertionError raise AssertionError
def _getTypeString(s): def _getTypeString(s):
if isinstance(s._val, EnumItemType): if isinstance(s._val, EnumItemType):
return s._val._type._name return s._val._type._name
@ -369,7 +361,6 @@ def _getTypeString(s):
else: else:
return 'unsigned' return 'unsigned'
def _convertGens(genlist, siglist, memlist, vfile): def _convertGens(genlist, siglist, memlist, vfile):
blockBuf = StringIO() blockBuf = StringIO()
funcBuf = StringIO() funcBuf = StringIO()
@ -463,7 +454,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.labelStack = [] self.labelStack = []
self.context = None self.context = None
def write(self, arg): def write(self, arg):
self.buf.write("%s" % arg) self.buf.write("%s" % arg)
@ -487,7 +477,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
def BitRepr(self, item, var): def BitRepr(self, item, var):
return '"%s"' % bin(item, len(var)) return '"%s"' % bin(item, len(var))
def inferCast(self, vhd, ori): def inferCast(self, vhd, ori):
pre, suf = "", "" pre, suf = "", ""
if isinstance(vhd, vhd_int): if isinstance(vhd, vhd_int):
@ -529,7 +518,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
return pre, suf return pre, suf
def writeIntSize(self, n): def writeIntSize(self, n):
# write size for large integers (beyond 32 bits signed) # write size for large integers (beyond 32 bits signed)
# with some safety margin # with some safety margin
@ -555,7 +543,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
if dir: dir += " " if dir: dir += " "
self.write("%s%s: %s%s%s" % (kind, name, dir, tipe, endchar)) self.write("%s%s: %s%s%s" % (kind, name, dir, tipe, endchar))
def writeDeclarations(self): def writeDeclarations(self):
if self.tree.hasPrint: if self.tree.hasPrint:
self.writeline() self.writeline()
@ -572,7 +559,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
def dedent(self): def dedent(self):
self.ind = self.ind[:-4] self.ind = self.ind[:-4]
def visit_BinOp(self, node): def visit_BinOp(self, node):
if isinstance(node.op, (ast.LShift, ast.RShift)): if isinstance(node.op, (ast.LShift, ast.RShift)):
self.shiftOp(node) self.shiftOp(node)
@ -585,8 +571,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
else: else:
self.BinOp(node) self.BinOp(node)
def inferBinaryOpCast(self, node, left, right, op): def inferBinaryOpCast(self, node, left, right, op):
ns, os = node.vhd.size, node.vhdOri.size ns, os = node.vhd.size, node.vhdOri.size
ds = ns - os ds = ns - os
@ -628,7 +612,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
pre, suf = "(", ")" pre, suf = "(", ")"
return pre, suf return pre, suf
def BinOp(self, node): def BinOp(self, node):
pre, suf = self.inferBinaryOpCast(node, node.left, node.right, node.op) pre, suf = self.inferBinaryOpCast(node, node.left, node.right, node.op)
self.write(pre) self.write(pre)
@ -637,7 +620,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(node.right) self.visit(node.right)
self.write(suf) self.write(suf)
def inferShiftOpCast(self, node, left, right, op): def inferShiftOpCast(self, node, left, right, op):
ns, os = node.vhd.size, node.vhdOri.size ns, os = node.vhd.size, node.vhdOri.size
ds = ns - os ds = ns - os
@ -648,7 +630,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
pre, suf = self.inferCast(node.vhd, node.vhdOri) pre, suf = self.inferCast(node.vhd, node.vhdOri)
return pre, suf return pre, suf
def shiftOp(self, node): def shiftOp(self, node):
pre, suf = self.inferShiftOpCast(node, node.left, node.right, node.op) pre, suf = self.inferShiftOpCast(node, node.left, node.right, node.op)
self.write(pre) self.write(pre)
@ -659,8 +640,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(")") self.write(")")
self.write(suf) self.write(suf)
def BitOp(self, node): def BitOp(self, node):
pre, suf = self.inferCast(node.vhd, node.vhdOri) pre, suf = self.inferCast(node.vhd, node.vhdOri)
self.write(pre) self.write(pre)
@ -671,7 +650,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(")") self.write(")")
self.write(suf) self.write(suf)
def visit_BoolOp(self, node): def visit_BoolOp(self, node):
if isinstance(node.vhd, vhd_std_logic): if isinstance(node.vhd, vhd_std_logic):
self.write("stdl") self.write("stdl")
@ -682,7 +660,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(n) self.visit(n)
self.write(")") self.write(")")
def visit_UnaryOp(self, node): def visit_UnaryOp(self, node):
pre, suf = self.inferCast(node.vhd, node.vhdOri) pre, suf = self.inferCast(node.vhd, node.vhdOri)
self.write(pre) self.write(pre)
@ -692,21 +669,18 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(")") self.write(")")
self.write(suf) self.write(suf)
def visit_Attribute(self, node): def visit_Attribute(self, node):
if isinstance(node.ctx, ast.Store): if isinstance(node.ctx, ast.Store):
self.setAttr(node) self.setAttr(node)
else: else:
self.getAttr(node) self.getAttr(node)
def setAttr(self, node): def setAttr(self, node):
assert node.attr == 'next' assert node.attr == 'next'
self.isSigAss = True self.isSigAss = True
self.visit(node.value) self.visit(node.value)
node.obj = self.getObj(node.value) node.obj = self.getObj(node.value)
def getAttr(self, node): def getAttr(self, node):
assert isinstance(node.value, ast.Name), node.value assert isinstance(node.value, ast.Name), node.value
n = node.value.id n = node.value.id
@ -741,7 +715,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
e = getattr(obj, node.attr) e = getattr(obj, node.attr)
self.write(e._toVHDL()) self.write(e._toVHDL())
def visit_Assert(self, node): def visit_Assert(self, node):
# XXX # XXX
self.write("assert ") self.write("assert ")
@ -753,7 +726,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write("severity error;") self.write("severity error;")
self.dedent() self.dedent()
def visit_Assign(self, node): def visit_Assign(self, node):
lhs = node.targets[0] lhs = node.targets[0]
rhs = node.value rhs = node.value
@ -808,9 +780,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(convClose) self.write(convClose)
self.write(';') self.write(';')
def visit_AugAssign(self, node): def visit_AugAssign(self, node):
op = opmap[type(node.op)]
# XXX apparently no signed context required for augmented assigns # XXX apparently no signed context required for augmented assigns
left, op, right = node.target, node.op, node.value left, op, right = node.target, node.op, node.value
isFunc = False isFunc = False
@ -836,12 +806,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(suf) self.write(suf)
self.write(";") self.write(";")
def visit_Break(self, node): def visit_Break(self, node):
self.write("exit;") self.write("exit;")
def visit_Call(self, node): def visit_Call(self, node):
fn = node.func fn = node.func
# assert isinstance(fn, astNode.Name) # assert isinstance(fn, astNode.Name)
@ -930,8 +897,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
v = Visitor(node.tree, self.funcBuf) v = Visitor(node.tree, self.funcBuf)
v.visit(node.tree) v.visit(node.tree)
def visit_Compare(self, node): def visit_Compare(self, node):
n = node.vhd n = node.vhd
ns = node.vhd.size ns = node.vhd.size
@ -949,7 +914,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(right) self.visit(right)
self.write(suf) self.write(suf)
def visit_Num(self, node): def visit_Num(self, node):
n = node.n n = node.n
if isinstance(node.vhd, vhd_std_logic): if isinstance(node.vhd, vhd_std_logic):
@ -968,11 +932,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
def visit_Str(self, node): def visit_Str(self, node):
self.write("string'(\"%s\")" % node.s) self.write("string'(\"%s\")" % node.s)
def visit_Continue(self, node, *args): def visit_Continue(self, node, *args):
self.write("next;") self.write("next;")
def visit_Expr(self, node): def visit_Expr(self, node):
expr = node.value expr = node.value
# docstrings on unofficial places # docstrings on unofficial places
@ -988,7 +950,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
if isinstance(expr, ast.Call) and hasattr(expr, 'tree'): if isinstance(expr, ast.Call) and hasattr(expr, 'tree'):
self.write(';') self.write(';')
def visit_IfExp(self, node): def visit_IfExp(self, node):
pre, suf = self.inferCast(node.vhd, node.body.vhdOri) pre, suf = self.inferCast(node.vhd, node.body.vhdOri)
self.write(pre) self.write(pre)
@ -1063,11 +1024,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.labelStack.pop() self.labelStack.pop()
self.labelStack.pop() self.labelStack.pop()
def visit_FunctionDef(self, node): def visit_FunctionDef(self, node):
raise AssertionError("To be implemented in subclass") raise AssertionError("To be implemented in subclass")
def visit_If(self, node): def visit_If(self, node):
if node.ignore: if node.ignore:
return return
@ -1077,7 +1036,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
else: else:
self.mapToIf(node) self.mapToIf(node)
def mapToCase(self, node): def mapToCase(self, node):
var = node.caseVar var = node.caseVar
obj = self.getObj(var) obj = self.getObj(var)
@ -1114,7 +1072,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.writeline() self.writeline()
self.write("end case;") self.write("end case;")
def mapToIf(self, node): def mapToIf(self, node):
first = True first = True
for test, suite in node.tests: for test, suite in node.tests:
@ -1146,16 +1103,13 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.writeline() self.writeline()
self.write("end if;") self.write("end if;")
def visit_ListComp(self, node): def visit_ListComp(self, node):
pass # do nothing pass # do nothing
def visit_Module(self, node): def visit_Module(self, node):
for stmt in node.body: for stmt in node.body:
self.visit(stmt) self.visit(stmt)
def visit_Name(self, node): def visit_Name(self, node):
if isinstance(node.ctx, ast.Store): if isinstance(node.ctx, ast.Store):
self.setName(node) self.setName(node)
@ -1226,12 +1180,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
raise AssertionError("name ref: %s" % n) raise AssertionError("name ref: %s" % n)
self.write(s) self.write(s)
def visit_Pass(self, node): def visit_Pass(self, node):
self.write("null;") self.write("null;")
def visit_Print(self, node): def visit_Print(self, node):
argnr = 0 argnr = 0
for s in node.format: for s in node.format:
@ -1262,13 +1213,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.writeline() self.writeline()
self.write("writeline(output, L);") self.write("writeline(output, L);")
def visit_Raise(self, node): def visit_Raise(self, node):
self.write('assert False report "End of Simulation" severity Failure;') self.write('assert False report "End of Simulation" severity Failure;')
# def visitReturn(self, node, *args):
# self.write("disable %s;" % self.returnLabel)
def visit_Return(self, node): def visit_Return(self, node):
pass pass
@ -1278,7 +1225,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
else: else:
self.accessIndex(node) self.accessIndex(node)
def accessSlice(self, node): def accessSlice(self, node):
if isinstance(node.value, ast.Call) and \ if isinstance(node.value, ast.Call) and \
node.value.func.obj is intbv and \ node.value.func.obj is intbv and \
@ -1335,7 +1281,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(")") self.write(")")
self.write(suf) self.write(suf)
def visit_stmt(self, body): def visit_stmt(self, body):
for stmt in body: for stmt in body:
self.writeline() self.writeline()
@ -1344,7 +1289,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
if isinstance(stmt, ast.Call) and hasattr(stmt, 'tree'): if isinstance(stmt, ast.Call) and hasattr(stmt, 'tree'):
self.write(';') self.write(';')
def visit_Tuple(self, node): def visit_Tuple(self, node):
assert self.context != None assert self.context != None
sep = ", " sep = ", "
@ -1354,7 +1298,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(sep) self.write(sep)
self.visit(elt) self.visit(elt)
def visit_While(self, node): def visit_While(self, node):
self.labelStack.append(node.breakLabel) self.labelStack.append(node.breakLabel)
self.labelStack.append(node.loopLabel) self.labelStack.append(node.loopLabel)
@ -1370,7 +1313,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.labelStack.pop() self.labelStack.pop()
self.labelStack.pop() self.labelStack.pop()
def visit_Yield(self, node): def visit_Yield(self, node):
self.write("wait ") self.write("wait ")
yieldObj = self.getObj(node.value) yieldObj = self.getObj(node.value)
@ -1385,8 +1327,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.context = _context.UNKNOWN self.context = _context.UNKNOWN
self.write(";") self.write(";")
def manageEdges(self, ifnode, senslist): def manageEdges(self, ifnode, senslist):
""" Helper method to convert MyHDL style template into VHDL style""" """ Helper method to convert MyHDL style template into VHDL style"""
first = senslist[0] first = senslist[0]
@ -1424,14 +1364,12 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
return senslist return senslist
class _ConvertAlwaysVisitor(_ConvertVisitor): class _ConvertAlwaysVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf): def __init__(self, tree, blockBuf, funcBuf):
_ConvertVisitor.__init__(self, tree, blockBuf) _ConvertVisitor.__init__(self, tree, blockBuf)
self.funcBuf = funcBuf self.funcBuf = funcBuf
def visit_FunctionDef(self, node): def visit_FunctionDef(self, node):
self.writeDoc(node) self.writeDoc(node)
w = node.body[-1] w = node.body[-1]
@ -1475,15 +1413,12 @@ class _ConvertAlwaysVisitor(_ConvertVisitor):
self.writeline(2) self.writeline(2)
class _ConvertInitialVisitor(_ConvertVisitor): class _ConvertInitialVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf): def __init__(self, tree, blockBuf, funcBuf):
_ConvertVisitor.__init__(self, tree, blockBuf) _ConvertVisitor.__init__(self, tree, blockBuf)
self.funcBuf = funcBuf self.funcBuf = funcBuf
def visit_FunctionDef(self, node): def visit_FunctionDef(self, node):
self.writeDoc(node) self.writeDoc(node)
self.write("%s: process is" % self.tree.name) self.write("%s: process is" % self.tree.name)
@ -1502,8 +1437,6 @@ class _ConvertInitialVisitor(_ConvertVisitor):
self.writeline(2) self.writeline(2)
class _ConvertAlwaysCombVisitor(_ConvertVisitor): class _ConvertAlwaysCombVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf): def __init__(self, tree, blockBuf, funcBuf):
@ -1532,7 +1465,6 @@ class _ConvertAlwaysCombVisitor(_ConvertVisitor):
self.writeline(2) self.writeline(2)
class _ConvertSimpleAlwaysCombVisitor(_ConvertVisitor): class _ConvertSimpleAlwaysCombVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf): def __init__(self, tree, blockBuf, funcBuf):
@ -1668,8 +1600,6 @@ class _ConvertAlwaysSeqVisitor(_ConvertVisitor):
self.writeline(2) self.writeline(2)
class _ConvertFunctionVisitor(_ConvertVisitor): class _ConvertFunctionVisitor(_ConvertVisitor):
def __init__(self, tree, funcBuf): def __init__(self, tree, funcBuf):
@ -1689,7 +1619,6 @@ class _ConvertFunctionVisitor(_ConvertVisitor):
self.writeline() self.writeline()
self.writeDeclaration(obj, name, dir="in", constr=False, endchar="") self.writeDeclaration(obj, name, dir="in", constr=False, endchar="")
def visit_FunctionDef(self, node): def visit_FunctionDef(self, node):
self.write("function %s(" % self.tree.name) self.write("function %s(" % self.tree.name)
self.indent() self.indent()
@ -1709,16 +1638,12 @@ class _ConvertFunctionVisitor(_ConvertVisitor):
self.write("end function %s;" % self.tree.name) self.write("end function %s;" % self.tree.name)
self.writeline(2) self.writeline(2)
def visit_Return(self, node): def visit_Return(self, node):
self.write("return ") self.write("return ")
self.visit(node.value) self.visit(node.value)
self.write(";") self.write(";")
class _ConvertTaskVisitor(_ConvertVisitor): class _ConvertTaskVisitor(_ConvertVisitor):
def __init__(self, tree, funcBuf): def __init__(self, tree, funcBuf):
@ -1738,8 +1663,6 @@ class _ConvertTaskVisitor(_ConvertVisitor):
self.writeline() self.writeline()
self.writeDeclaration(obj, name, dir=dir, constr=False, endchar="") self.writeDeclaration(obj, name, dir=dir, constr=False, endchar="")
def visit_FunctionDef(self, node): def visit_FunctionDef(self, node):
self.write("procedure %s" % self.tree.name) self.write("procedure %s" % self.tree.name)
if self.tree.argnames: if self.tree.argnames:
@ -1764,6 +1687,7 @@ class _ConvertTaskVisitor(_ConvertVisitor):
# type inference # type inference
class vhd_type(object): class vhd_type(object):
def __init__(self, size=0): def __init__(self, size=0):
self.size = size self.size = size
@ -1871,7 +1795,6 @@ def maybeNegative(vhd):
return True return True
return False return False
class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin): class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
def __init__(self, tree): def __init__(self, tree):
@ -1882,19 +1805,15 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
for stmt in node.body: for stmt in node.body:
self.visit(stmt) self.visit(stmt)
def visit_Attribute(self, node): def visit_Attribute(self, node):
self.generic_visit(node) self.generic_visit(node)
node.vhd = copy(node.value.vhd) node.vhd = copy(node.value.vhd)
node.vhdOri = copy(node.vhd) node.vhdOri = copy(node.vhd)
def visit_Assert(self, node): def visit_Assert(self, node):
self.visit(node.test) self.visit(node.test)
node.test.vhd = vhd_boolean() node.test.vhd = vhd_boolean()
def visit_AugAssign(self, node): def visit_AugAssign(self, node):
self.visit(node.target) self.visit(node.target)
self.visit(node.value) self.visit(node.value)
@ -1909,7 +1828,6 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
self.inferBinOpType(node) self.inferBinOpType(node)
node.vhd = copy(node.target.vhd) node.vhd = copy(node.target.vhd)
def visit_Call(self, node): def visit_Call(self, node):
fn = node.func fn = node.func
# assert isinstance(fn, astNode.Name) # assert isinstance(fn, astNode.Name)
@ -1941,8 +1859,6 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
node.vhd = node.tree.vhd = inferVhdlObj(node.tree.returnObj) node.vhd = node.tree.vhd = inferVhdlObj(node.tree.returnObj)
node.vhdOri = copy(node.vhd) node.vhdOri = copy(node.vhd)
def visit_Compare(self, node): def visit_Compare(self, node):
node.vhd = vhd_boolean() node.vhd = vhd_boolean()
self.generic_visit(node) self.generic_visit(node)
@ -1955,7 +1871,6 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
right.vhd = vhd_signed(right.vhd.size + 1) right.vhd = vhd_signed(right.vhd.size + 1)
node.vhdOri = copy(node.vhd) node.vhdOri = copy(node.vhd)
def visit_Str(self, node): def visit_Str(self, node):
node.vhd = vhd_string() node.vhd = vhd_string()
node.vhdOri = copy(node.vhd) node.vhdOri = copy(node.vhd)
@ -1967,21 +1882,18 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
node.vhd = vhd_nat() node.vhd = vhd_nat()
node.vhdOri = copy(node.vhd) node.vhdOri = copy(node.vhd)
def visit_For(self, node): def visit_For(self, node):
var = node.target.id var = node.target.id
# make it possible to detect loop variable # make it possible to detect loop variable
self.tree.vardict[var] = _loopInt(-1) self.tree.vardict[var] = _loopInt(-1)
self.generic_visit(node) self.generic_visit(node)
def visit_Name(self, node): def visit_Name(self, node):
if isinstance(node.ctx, ast.Store): if isinstance(node.ctx, ast.Store):
node.obj = self.tree.vardict[node.id] node.obj = self.tree.vardict[node.id]
node.vhd = inferVhdlObj(node.obj) node.vhd = inferVhdlObj(node.obj)
node.vhdOri = copy(node.vhd) node.vhdOri = copy(node.vhd)
def visit_BinOp(self, node): def visit_BinOp(self, node):
self.generic_visit(node) self.generic_visit(node)
if isinstance(node.op, (ast.LShift, ast.RShift)): if isinstance(node.op, (ast.LShift, ast.RShift)):
@ -1998,7 +1910,6 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
node.right.vhd = vhd_nat() node.right.vhd = vhd_nat()
node.vhdOri = copy(node.vhd) node.vhdOri = copy(node.vhd)
def inferBitOpType(self, node): def inferBitOpType(self, node):
obj = maxType(node.left.vhd, node.right.vhd) obj = maxType(node.left.vhd, node.right.vhd)
node.vhd = node.left.vhd = node.right.vhd = obj node.vhd = node.left.vhd = node.right.vhd = obj
@ -2051,7 +1962,6 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
node.vhd = vhd_int() node.vhd = vhd_int()
node.vhdOri = copy(node.vhd) node.vhdOri = copy(node.vhd)
def visit_BoolOp(self, node): def visit_BoolOp(self, node):
self.generic_visit(node) self.generic_visit(node)
for n in node.values: for n in node.values:
@ -2059,7 +1969,6 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
node.vhd = vhd_boolean() node.vhd = vhd_boolean()
node.vhdOri = copy(node.vhd) node.vhdOri = copy(node.vhd)
def visit_If(self, node): def visit_If(self, node):
if node.ignore: if node.ignore:
return return
@ -2071,18 +1980,15 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
self.generic_visit(node) self.generic_visit(node)
node.test.vhd = vhd_boolean() node.test.vhd = vhd_boolean()
def visit_ListComp(self, node): def visit_ListComp(self, node):
pass # do nothing pass # do nothing
def visit_Subscript(self, node): def visit_Subscript(self, node):
if isinstance(node.slice, ast.Slice): if isinstance(node.slice, ast.Slice):
self.accessSlice(node) self.accessSlice(node)
else: else:
self.accessIndex(node) self.accessIndex(node)
def accessSlice(self, node): def accessSlice(self, node):
self.generic_visit(node) self.generic_visit(node)
lower = node.value.vhd.size lower = node.value.vhd.size
@ -2101,7 +2007,6 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
node.vhd = vhd_unsigned(lower-upper) node.vhd = vhd_unsigned(lower-upper)
node.vhdOri = copy(node.vhd) node.vhdOri = copy(node.vhd)
def accessIndex(self, node): def accessIndex(self, node):
self.generic_visit(node) self.generic_visit(node)
node.vhd = vhd_std_logic() # XXX default node.vhd = vhd_std_logic() # XXX default
@ -2118,8 +2023,6 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
node.vhd = vhd_std_logic() node.vhd = vhd_std_logic()
node.vhdOri = copy(node.vhd) node.vhdOri = copy(node.vhd)
def visit_UnaryOp(self, node): def visit_UnaryOp(self, node):
self.visit(node.operand) self.visit(node.operand)
node.vhd = copy(node.operand.vhd) node.vhd = copy(node.operand.vhd)
@ -2137,14 +2040,11 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
node.vhd = vhd_int() node.vhd = vhd_int()
node.vhdOri = copy(node.vhd) node.vhdOri = copy(node.vhd)
def visit_While(self, node): def visit_While(self, node):
self.generic_visit(node) self.generic_visit(node)
node.test.vhd = vhd_boolean() node.test.vhd = vhd_boolean()
def _annotateTypes(genlist): def _annotateTypes(genlist):
for tree in genlist: for tree in genlist:
if isinstance(tree, _UserVhdlCode): if isinstance(tree, _UserVhdlCode):

View File

@ -1,7 +1,7 @@
# This file is part of the myhdl library, a Python package for using # This file is part of the myhdl library, a Python package for using
# Python as a Hardware Description Language. # Python as a Hardware Description Language.
# #
# Copyright (C) 2003-2008 Jan Decaluwe # Copyright (C) 2003-2012 Jan Decaluwe
# #
# The myhdl library is free software; you can redistribute it and/or # The myhdl library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License as # modify it under the terms of the GNU Lesser General Public License as
@ -23,19 +23,14 @@
import sys import sys
import os
import math import math
import traceback
import inspect import inspect
from datetime import datetime from datetime import datetime
import compiler
# from compiler import ast as astNode
import ast import ast
import string import string
from types import GeneratorType, FunctionType, ClassType, TypeType, StringType from types import GeneratorType, ClassType, TypeType
from cStringIO import StringIO from cStringIO import StringIO
import __builtin__
import warnings import warnings
import myhdl import myhdl
@ -45,12 +40,11 @@ from myhdl._extractHierarchy import (_HierExtr, _isMem, _getMemInfo,
_UserVerilogCode, _userCodeMap) _UserVerilogCode, _userCodeMap)
from myhdl._instance import _Instantiator from myhdl._instance import _Instantiator
from myhdl.conversion._misc import (_error, _access, _kind, _context, from myhdl.conversion._misc import (_error, _kind, _context,
_ConversionMixin, _Label, _genUniqueSuffix, _isConstant) _ConversionMixin, _Label, _genUniqueSuffix, _isConstant)
from myhdl.conversion._analyze import (_analyzeSigs, _analyzeGens, _analyzeTopFunc, from myhdl.conversion._analyze import (_analyzeSigs, _analyzeGens, _analyzeTopFunc,
_Ram, _Rom) _Ram, _Rom)
from myhdl._Signal import _Signal from myhdl._Signal import _Signal
from myhdl._ShadowSignal import _SliceSignal
_converting = 0 _converting = 0
_profileFunc = None _profileFunc = None
@ -139,6 +133,7 @@ class _ToVerilogConvertor(object):
# print h.top # print h.top
_checkArgs(arglist) _checkArgs(arglist)
genlist = _analyzeGens(arglist, h.absnames) genlist = _analyzeGens(arglist, h.absnames)
_annotateTypes(genlist)
intf = _analyzeTopFunc(func, *args, **kwargs) intf = _analyzeTopFunc(func, *args, **kwargs)
intf.name = name intf.name = name
doc = _makeDoc(inspect.getdoc(func)) doc = _makeDoc(inspect.getdoc(func))
@ -496,7 +491,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
else: else:
self.write(";") self.write(";")
def writeDeclarations(self): def writeDeclarations(self):
for name, obj in self.tree.vardict.items(): for name, obj in self.tree.vardict.items():
self.writeline() self.writeline()
@ -521,8 +515,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(senslist[-1]._toVerilog()) self.write(senslist[-1]._toVerilog())
self.write(")") self.write(")")
def visit_BinOp(self, node): def visit_BinOp(self, node):
if isinstance(node.op, ast.Mod) and self.context == _context.PRINT: if isinstance(node.op, ast.Mod) and self.context == _context.PRINT:
self.visit(node.left) self.visit(node.left)
@ -546,9 +538,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(")") self.write(")")
self.context = None self.context = None
def checkOpWithNegIntbv(self, node, op): def checkOpWithNegIntbv(self, node, op):
if op in ("+", "-", "*", "~", "&&", "||", "!"): if op in ("+", "-", "*", "~", "&&", "||", "!"):
return return
@ -558,9 +547,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.raiseError(node, _error.NotSupported, self.raiseError(node, _error.NotSupported,
"negative intbv with operator %s" % op) "negative intbv with operator %s" % op)
def visit_BoolOp(self, node): def visit_BoolOp(self, node):
self.write("(") self.write("(")
self.visit(node.values[0]) self.visit(node.values[0])
@ -569,14 +555,11 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(n) self.visit(n)
self.write(")") self.write(")")
def visit_UnaryOp(self, node): def visit_UnaryOp(self, node):
self.write("(%s" % opmap[type(node.op)]) self.write("(%s" % opmap[type(node.op)])
self.visit(node.operand) self.visit(node.operand)
self.write(")") self.write(")")
def visit_Attribute(self, node): def visit_Attribute(self, node):
if isinstance(node.ctx, ast.Store): if isinstance(node.ctx, ast.Store):
self.setAttr(node) self.setAttr(node)
@ -615,8 +598,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
e = getattr(obj, node.attr) e = getattr(obj, node.attr)
self.write(e._toVerilog()) self.write(e._toVerilog())
def visit_Assert(self, node): def visit_Assert(self, node):
self.write("if (") self.write("if (")
self.visit(node.test) self.visit(node.test)
@ -630,8 +611,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.writeline() self.writeline()
self.write("end") self.write("end")
def visit_Assign(self, node): def visit_Assign(self, node):
# shortcut for expansion of ROM in case statement # shortcut for expansion of ROM in case statement
if isinstance(node.value, ast.Subscript) and \ if isinstance(node.value, ast.Subscript) and \
@ -675,8 +654,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(node.value) self.visit(node.value)
self.write(';') self.write(';')
def visit_AugAssign(self, node, *args): def visit_AugAssign(self, node, *args):
# XXX apparently no signed context required for augmented assigns # XXX apparently no signed context required for augmented assigns
self.visit(node.target) self.visit(node.target)
@ -686,12 +663,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(node.value) self.visit(node.value)
self.write(";") self.write(";")
def visit_Break(self, node,): def visit_Break(self, node,):
self.write("disable %s;" % self.labelStack[-2]) self.write("disable %s;" % self.labelStack[-2])
def visit_Call(self, node): def visit_Call(self, node):
self.context = None self.context = None
fn = node.func fn = node.func
@ -764,7 +738,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
v = Visitor(node.tree, self.funcBuf) v = Visitor(node.tree, self.funcBuf)
v.visit(node.tree) v.visit(node.tree)
def visit_Compare(self, node): def visit_Compare(self, node):
self.context = None self.context = None
if node.signed: if node.signed:
@ -776,8 +749,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(")") self.write(")")
self.context = None self.context = None
def visit_Num(self, node): def visit_Num(self, node):
if self.context == _context.PRINT: if self.context == _context.PRINT:
self.write('"%s"' % node.n) self.write('"%s"' % node.n)
@ -793,12 +764,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
else: else:
self.write(s) self.write(s)
def visit_Continue(self, node): def visit_Continue(self, node):
self.write("disable %s;" % self.labelStack[-1]) self.write("disable %s;" % self.labelStack[-1])
def visit_Expr(self, node): def visit_Expr(self, node):
expr = node.value expr = node.value
# docstrings on unofficial places # docstrings on unofficial places
@ -814,7 +782,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
if isinstance(expr, ast.Call) and hasattr(expr, 'tree'): if isinstance(expr, ast.Call) and hasattr(expr, 'tree'):
self.write(';') self.write(';')
def visit_IfExp(self, node): def visit_IfExp(self, node):
self.visit(node.test) self.visit(node.test)
self.write(' ? ') self.write(' ? ')
@ -822,7 +789,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(' : ') self.write(' : ')
self.visit(node.orelse) self.visit(node.orelse)
def visit_For(self, node): def visit_For(self, node):
self.labelStack.append(node.breakLabel) self.labelStack.append(node.breakLabel)
self.labelStack.append(node.loopLabel) self.labelStack.append(node.loopLabel)
@ -885,11 +851,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.labelStack.pop() self.labelStack.pop()
self.labelStack.pop() self.labelStack.pop()
def visit_FunctionDef(self, node): def visit_FunctionDef(self, node):
raise AssertionError("To be implemented in subclass") raise AssertionError("To be implemented in subclass")
def visit_If(self, node): def visit_If(self, node):
if node.ignore: if node.ignore:
return return
@ -963,7 +927,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.writeline() self.writeline()
self.write("end") self.write("end")
def visitKeyword(self, node, *args): def visitKeyword(self, node, *args):
self.visit(node.expr) self.visit(node.expr)
@ -1027,11 +990,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
if addSignBit: if addSignBit:
self.write("})") self.write("})")
def visit_Pass(self, node): def visit_Pass(self, node):
self.write("// pass") self.write("// pass")
def visit_Print(self, node): def visit_Print(self, node):
argnr = 0 argnr = 0
for s in node.format: for s in node.format:
@ -1079,16 +1040,12 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.writeline() self.writeline()
self.write('$write("\\n");') self.write('$write("\\n");')
def visit_Raise(self, node): def visit_Raise(self, node):
self.write("$finish;") self.write("$finish;")
def visit_Return(self, node): def visit_Return(self, node):
self.write("disable %s;" % self.returnLabel) self.write("disable %s;" % self.returnLabel)
def visit_Subscript(self, node): def visit_Subscript(self, node):
if isinstance(node.slice, ast.Slice): if isinstance(node.slice, ast.Slice):
self.accessSlice(node) self.accessSlice(node)
@ -1126,7 +1083,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
if addSignBit: if addSignBit:
self.write("})") self.write("})")
def accessIndex(self, node): def accessIndex(self, node):
addSignBit = isinstance(node.ctx, ast.Load) and \ addSignBit = isinstance(node.ctx, ast.Load) and \
(not node.signed) and \ (not node.signed) and \
@ -1142,7 +1098,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
if addSignBit: if addSignBit:
self.write("})") self.write("})")
def visit_stmt(self, body): def visit_stmt(self, body):
for stmt in body: for stmt in body:
self.writeline() self.writeline()
@ -1151,7 +1106,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
if isinstance(stmt, ast.Call) and hasattr(stmt, 'tree'): if isinstance(stmt, ast.Call) and hasattr(stmt, 'tree'):
self.write(';') self.write(';')
def visit_Tuple(self, node): def visit_Tuple(self, node):
assert self.context != None assert self.context != None
sep = ", " sep = ", "
@ -1161,8 +1115,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(sep) self.write(sep)
self.visit(elt) self.visit(elt)
def visit_While(self, node): def visit_While(self, node):
self.labelStack.append(node.breakLabel) self.labelStack.append(node.breakLabel)
self.labelStack.append(node.loopLabel) self.labelStack.append(node.loopLabel)
@ -1185,8 +1137,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.labelStack.pop() self.labelStack.pop()
self.labelStack.pop() self.labelStack.pop()
def visit_Yield(self, node): def visit_Yield(self, node):
yieldObj = self.getObj(node.value) yieldObj = self.getObj(node.value)
assert node.senslist assert node.senslist
@ -1202,10 +1152,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(";") self.write(";")
class _ConvertAlwaysVisitor(_ConvertVisitor): class _ConvertAlwaysVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf): def __init__(self, tree, blockBuf, funcBuf):
@ -1250,7 +1196,6 @@ class _ConvertInitialVisitor(_ConvertVisitor):
class _ConvertAlwaysCombVisitor(_ConvertVisitor): class _ConvertAlwaysCombVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf): def __init__(self, tree, blockBuf, funcBuf):
@ -1259,7 +1204,6 @@ class _ConvertAlwaysCombVisitor(_ConvertVisitor):
self.okSigAss = False self.okSigAss = False
self.funcBuf = funcBuf self.funcBuf = funcBuf
def visit_FunctionDef(self, node): def visit_FunctionDef(self, node):
self.writeDoc(node) self.writeDoc(node)
self.writeAlwaysHeader() self.writeAlwaysHeader()
@ -1272,14 +1216,11 @@ class _ConvertAlwaysCombVisitor(_ConvertVisitor):
class _ConvertSimpleAlwaysCombVisitor(_ConvertVisitor): class _ConvertSimpleAlwaysCombVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf): def __init__(self, tree, blockBuf, funcBuf):
_ConvertVisitor.__init__(self, tree, blockBuf) _ConvertVisitor.__init__(self, tree, blockBuf)
self.funcBuf = funcBuf self.funcBuf = funcBuf
def visit_Attribute(self, node): def visit_Attribute(self, node):
if isinstance(node.ctx, ast.Store): if isinstance(node.ctx, ast.Store):
self.write("assign ") self.write("assign ")
@ -1287,7 +1228,6 @@ class _ConvertSimpleAlwaysCombVisitor(_ConvertVisitor):
else: else:
self.getAttr(node) self.getAttr(node)
def visit_FunctionDef(self, node): def visit_FunctionDef(self, node):
self.writeDoc(node) self.writeDoc(node)
self.visit_stmt(node.body) self.visit_stmt(node.body)
@ -1300,7 +1240,6 @@ class _ConvertAlwaysDecoVisitor(_ConvertVisitor):
_ConvertVisitor.__init__(self, tree, blockBuf) _ConvertVisitor.__init__(self, tree, blockBuf)
self.funcBuf = funcBuf self.funcBuf = funcBuf
def visit_FunctionDef(self, node): def visit_FunctionDef(self, node):
self.writeDoc(node) self.writeDoc(node)
self.writeAlwaysHeader() self.writeAlwaysHeader()
@ -1360,8 +1299,6 @@ class _ConvertAlwaysSeqVisitor(_ConvertVisitor):
self.writeline(2) self.writeline(2)
class _ConvertFunctionVisitor(_ConvertVisitor): class _ConvertFunctionVisitor(_ConvertVisitor):
def __init__(self, tree, funcBuf): def __init__(self, tree, funcBuf):
@ -1379,7 +1316,6 @@ class _ConvertFunctionVisitor(_ConvertVisitor):
self.writeline() self.writeline()
self.writeDeclaration(obj, name, "input") self.writeDeclaration(obj, name, "input")
def visit_FunctionDef(self, node): def visit_FunctionDef(self, node):
self.write("function ") self.write("function ")
self.writeOutputDeclaration() self.writeOutputDeclaration()
@ -1398,7 +1334,6 @@ class _ConvertFunctionVisitor(_ConvertVisitor):
self.write("endfunction") self.write("endfunction")
self.writeline(2) self.writeline(2)
def visit_Return(self, node): def visit_Return(self, node):
self.write("%s = " % self.tree.name) self.write("%s = " % self.tree.name)
self.visit(node.value) self.visit(node.value)
@ -1425,7 +1360,6 @@ class _ConvertTaskVisitor(_ConvertVisitor):
self.writeline() self.writeline()
self.writeDeclaration(obj, name, dir) self.writeDeclaration(obj, name, dir)
def visit_FunctionDef(self, node): def visit_FunctionDef(self, node):
self.write("task %s;" % self.tree.name) self.write("task %s;" % self.tree.name)
self.indent() self.indent()
@ -1442,3 +1376,125 @@ class _ConvertTaskVisitor(_ConvertVisitor):
self.writeline() self.writeline()
self.write("endtask") self.write("endtask")
self.writeline(2) self.writeline(2)
def _maybeNegative(obj):
if hasattr(obj, '_min') and (obj._min is not None) and (obj._min < 0):
return True
if isinstance(obj, (int, long)) and obj < 0:
return True
return False
class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
def __init__(self, tree):
self.tree = tree
def visit_FunctionDef(self, node):
# don't visit arguments and decorators
for stmt in node.body:
self.visit(stmt)
def visit_BinOp(self, node):
self.visit(node.left)
self.visit(node.right)
node.signed = node.left.signed or node.right.signed
def visit_BoolOp(self, node):
for n in node.values:
self.visit(n)
node.signed = False
def visit_UnaryOp(self, node):
self.visit(node.operand)
node.signed = node.operand.signed
if isinstance(node.op, ast.USub):
node.obj = int(-1)
if isinstance(node.operand, ast.Num):
node.signed = True
def visit_Attribute(self, node):
if isinstance(node.ctx, ast.Store):
self.setAttr(node)
else:
self.getAttr(node)
def setAttr(self, node):
self.visit(node.value)
def getAttr(self, node):
node.signed = False
self.visit(node.value)
def visit_Call(self, node):
self.generic_visit(node)
f = self.getObj(node.func)
node.signed = False
### suprize: identity comparison on unbound methods doesn't work in python 2.5??
if f == intbv.signed:
node.signed = True
elif hasattr(node, 'tree'):
v = _AnnotateTypesVisitor(node.tree)
v.visit(node.tree)
node.signed = _maybeNegative(node.tree.returnObj)
def visit_Compare(self, node):
node.signed = False
#for n in ast.iter_child_nodes(node):
for n in [node.left] + node.comparators:
self.visit(n)
if n.signed:
node.signed = True
def visit_If(self, node):
if node.ignore:
return
self.generic_visit(node)
def visit_Num(self, node):
node.signed = False
def visit_Str(self, node):
node.signed = False
def visit_Name(self, node):
if isinstance(node.ctx, ast.Store):
self.setName(node)
else:
self.getName(node)
def setName(self, node):
pass
def getName(self, node):
node.signed = _maybeNegative(node.obj)
def visit_Subscript(self, node):
if isinstance(node.slice, ast.Slice):
self.accessSlice(node)
else:
self.accessIndex(node)
def accessSlice(self, node):
node.signed = False
self.generic_visit(node)
def accessIndex(self, node):
node.signed = _maybeNegative(node.obj)
self.generic_visit(node)
def visit_Tuple(self, node):
node.signed = False
self.generic_visit(node)
def _annotateTypes(genlist):
for tree in genlist:
if isinstance(tree, _UserVerilogCode):
continue
v = _AnnotateTypesVisitor(tree)
v.visit(tree)