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

View File

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

View File

@ -1,7 +1,7 @@
# This file is part of the myhdl library, a Python package for using
# 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
# modify it under the terms of the GNU Lesser General Public License as
@ -23,19 +23,14 @@
import sys
import os
import math
import traceback
import inspect
from datetime import datetime
import compiler
# from compiler import ast as astNode
import ast
import string
from types import GeneratorType, FunctionType, ClassType, TypeType, StringType
from types import GeneratorType, ClassType, TypeType
from cStringIO import StringIO
import __builtin__
import warnings
import myhdl
@ -45,12 +40,11 @@ from myhdl._extractHierarchy import (_HierExtr, _isMem, _getMemInfo,
_UserVerilogCode, _userCodeMap)
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)
from myhdl.conversion._analyze import (_analyzeSigs, _analyzeGens, _analyzeTopFunc,
_Ram, _Rom)
from myhdl._Signal import _Signal
from myhdl._ShadowSignal import _SliceSignal
_converting = 0
_profileFunc = None
@ -139,6 +133,7 @@ class _ToVerilogConvertor(object):
# print h.top
_checkArgs(arglist)
genlist = _analyzeGens(arglist, h.absnames)
_annotateTypes(genlist)
intf = _analyzeTopFunc(func, *args, **kwargs)
intf.name = name
doc = _makeDoc(inspect.getdoc(func))
@ -496,7 +491,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
else:
self.write(";")
def writeDeclarations(self):
for name, obj in self.tree.vardict.items():
self.writeline()
@ -521,8 +515,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(senslist[-1]._toVerilog())
self.write(")")
def visit_BinOp(self, node):
if isinstance(node.op, ast.Mod) and self.context == _context.PRINT:
self.visit(node.left)
@ -546,9 +538,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(")")
self.context = None
def checkOpWithNegIntbv(self, node, op):
if op in ("+", "-", "*", "~", "&&", "||", "!"):
return
@ -558,9 +547,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.raiseError(node, _error.NotSupported,
"negative intbv with operator %s" % op)
def visit_BoolOp(self, node):
self.write("(")
self.visit(node.values[0])
@ -569,14 +555,11 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(n)
self.write(")")
def visit_UnaryOp(self, node):
self.write("(%s" % opmap[type(node.op)])
self.visit(node.operand)
self.write(")")
def visit_Attribute(self, node):
if isinstance(node.ctx, ast.Store):
self.setAttr(node)
@ -615,8 +598,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
e = getattr(obj, node.attr)
self.write(e._toVerilog())
def visit_Assert(self, node):
self.write("if (")
self.visit(node.test)
@ -630,8 +611,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.writeline()
self.write("end")
def visit_Assign(self, node):
# shortcut for expansion of ROM in case statement
if isinstance(node.value, ast.Subscript) and \
@ -675,8 +654,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(node.value)
self.write(';')
def visit_AugAssign(self, node, *args):
# XXX apparently no signed context required for augmented assigns
self.visit(node.target)
@ -686,12 +663,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(node.value)
self.write(";")
def visit_Break(self, node,):
self.write("disable %s;" % self.labelStack[-2])
def visit_Call(self, node):
self.context = None
fn = node.func
@ -764,7 +738,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
v = Visitor(node.tree, self.funcBuf)
v.visit(node.tree)
def visit_Compare(self, node):
self.context = None
if node.signed:
@ -776,8 +749,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(")")
self.context = None
def visit_Num(self, node):
if self.context == _context.PRINT:
self.write('"%s"' % node.n)
@ -793,12 +764,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
else:
self.write(s)
def visit_Continue(self, node):
self.write("disable %s;" % self.labelStack[-1])
def visit_Expr(self, node):
expr = node.value
# docstrings on unofficial places
@ -813,8 +781,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
# ugly hack to detect an orphan "task" call
if isinstance(expr, ast.Call) and hasattr(expr, 'tree'):
self.write(';')
def visit_IfExp(self, node):
self.visit(node.test)
self.write(' ? ')
@ -822,7 +789,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(' : ')
self.visit(node.orelse)
def visit_For(self, node):
self.labelStack.append(node.breakLabel)
self.labelStack.append(node.loopLabel)
@ -885,11 +851,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.labelStack.pop()
self.labelStack.pop()
def visit_FunctionDef(self, node):
raise AssertionError("To be implemented in subclass")
def visit_If(self, node):
if node.ignore:
return
@ -963,7 +927,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.writeline()
self.write("end")
def visitKeyword(self, node, *args):
self.visit(node.expr)
@ -1027,11 +990,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
if addSignBit:
self.write("})")
def visit_Pass(self, node):
self.write("// pass")
def visit_Print(self, node):
argnr = 0
for s in node.format:
@ -1078,17 +1039,13 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.context = _context.UNKNOWN
self.writeline()
self.write('$write("\\n");')
def visit_Raise(self, node):
self.write("$finish;")
def visit_Return(self, node):
self.write("disable %s;" % self.returnLabel)
def visit_Subscript(self, node):
if isinstance(node.slice, ast.Slice):
self.accessSlice(node)
@ -1126,7 +1083,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
if addSignBit:
self.write("})")
def accessIndex(self, node):
addSignBit = isinstance(node.ctx, ast.Load) and \
(not node.signed) and \
@ -1142,7 +1098,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
if addSignBit:
self.write("})")
def visit_stmt(self, body):
for stmt in body:
self.writeline()
@ -1151,7 +1106,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
if isinstance(stmt, ast.Call) and hasattr(stmt, 'tree'):
self.write(';')
def visit_Tuple(self, node):
assert self.context != None
sep = ", "
@ -1161,8 +1115,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(sep)
self.visit(elt)
def visit_While(self, node):
self.labelStack.append(node.breakLabel)
self.labelStack.append(node.loopLabel)
@ -1185,8 +1137,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.labelStack.pop()
self.labelStack.pop()
def visit_Yield(self, node):
yieldObj = self.getObj(node.value)
assert node.senslist
@ -1201,10 +1151,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.writeSensitivityList(senslist)
self.write(";")
class _ConvertAlwaysVisitor(_ConvertVisitor):
@ -1250,7 +1196,6 @@ class _ConvertInitialVisitor(_ConvertVisitor):
class _ConvertAlwaysCombVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf):
@ -1259,7 +1204,6 @@ class _ConvertAlwaysCombVisitor(_ConvertVisitor):
self.okSigAss = False
self.funcBuf = funcBuf
def visit_FunctionDef(self, node):
self.writeDoc(node)
self.writeAlwaysHeader()
@ -1271,15 +1215,12 @@ class _ConvertAlwaysCombVisitor(_ConvertVisitor):
self.writeline(2)
class _ConvertSimpleAlwaysCombVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf):
_ConvertVisitor.__init__(self, tree, blockBuf)
self.funcBuf = funcBuf
def visit_Attribute(self, node):
if isinstance(node.ctx, ast.Store):
self.write("assign ")
@ -1287,7 +1228,6 @@ class _ConvertSimpleAlwaysCombVisitor(_ConvertVisitor):
else:
self.getAttr(node)
def visit_FunctionDef(self, node):
self.writeDoc(node)
self.visit_stmt(node.body)
@ -1300,7 +1240,6 @@ class _ConvertAlwaysDecoVisitor(_ConvertVisitor):
_ConvertVisitor.__init__(self, tree, blockBuf)
self.funcBuf = funcBuf
def visit_FunctionDef(self, node):
self.writeDoc(node)
self.writeAlwaysHeader()
@ -1359,8 +1298,6 @@ class _ConvertAlwaysSeqVisitor(_ConvertVisitor):
self.write("end")
self.writeline(2)
class _ConvertFunctionVisitor(_ConvertVisitor):
@ -1379,7 +1316,6 @@ class _ConvertFunctionVisitor(_ConvertVisitor):
self.writeline()
self.writeDeclaration(obj, name, "input")
def visit_FunctionDef(self, node):
self.write("function ")
self.writeOutputDeclaration()
@ -1398,7 +1334,6 @@ class _ConvertFunctionVisitor(_ConvertVisitor):
self.write("endfunction")
self.writeline(2)
def visit_Return(self, node):
self.write("%s = " % self.tree.name)
self.visit(node.value)
@ -1407,7 +1342,7 @@ class _ConvertFunctionVisitor(_ConvertVisitor):
self.write("disable %s;" % self.returnLabel)
class _ConvertTaskVisitor(_ConvertVisitor):
@ -1425,7 +1360,6 @@ class _ConvertTaskVisitor(_ConvertVisitor):
self.writeline()
self.writeDeclaration(obj, name, dir)
def visit_FunctionDef(self, node):
self.write("task %s;" % self.tree.name)
self.indent()
@ -1442,3 +1376,125 @@ class _ConvertTaskVisitor(_ConvertVisitor):
self.writeline()
self.write("endtask")
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)