OpenCores
URL https://opencores.org/ocsvn/wb_lcd/wb_lcd/trunk

Subversion Repositories wb_lcd

[/] [wb_lcd/] [trunk/] [myhdl/] [wb_lcd_workspace_ramless/] [workspace/] [.metadata/] [.plugins/] [org.eclipse.core.resources/] [.history/] [3f/] [d0f7494f1e2d001e1d938226a9f3d8bc] - Rev 2

Compare with Previous | Blame | View Log

#  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
#
#  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
#  published by the Free Software Foundation; either version 2.1 of the
#  License, or (at your option) any later version.
#
#  This library is distributed in the hope that it will be useful, but
#  WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#  Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public
#  License along with this library; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

""" myhdl toVerilog analysis module.

"""


import inspect
import compiler
from compiler import ast as astNode
from sets import Set
from types import GeneratorType, FunctionType, ClassType, MethodType
from cStringIO import StringIO
import re
import warnings
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 import _Always
from myhdl._delay import delay
from myhdl.conversion._misc import (_error, _access, _kind, _context,
                                    _ConversionMixin, _Label, _genUniqueSuffix)
from myhdl._extractHierarchy import _isMem, _UserCode
from myhdl._Signal import _WaiterList
from myhdl._util import _isTupleOfInts

myhdlObjects = myhdl.__dict__.values()
builtinObjects = __builtin__.__dict__.values()

_enumTypeSet = set()


def _makeName(n, prefixes):
    if len(prefixes) > 1:
#        name = '_' + '_'.join(prefixes[1:]) + '_' + n
        name = '_'.join(prefixes[1:]) + '_' + n
    else:
        name = n
    if '[' in name or ']' in name:
        name = "\\" + name + ' '
##     print prefixes
##     print name
    return name
                    
def _analyzeSigs(hierarchy, hdl='Verilog'):
    curlevel = 0
    siglist = []
    memlist = []
    prefixes = []
    open, close = '[', ']'
    if hdl == 'VHDL':
        open, close = '(', ')'
    
    for inst in hierarchy:
        level = inst.level
        name = inst.name
        sigdict = inst.sigdict
        memdict = inst.memdict
        delta = curlevel - level
        curlevel = level
        assert(delta >= -1)
        if delta == -1:
            prefixes.append(name)
        else:
            prefixes = prefixes[:curlevel-1]
            prefixes.append(name)
        assert prefixes[-1] == name
        for n, s in sigdict.items():
            if s._name is not None:
                continue
            s._name = _makeName(n, prefixes)
            if not s._nrbits:
                raise ConversionError(_error.UndefinedBitWidth, s._name)
            siglist.append(s)
        # list of signals
        for n, m in memdict.items():
            if m.name is not None:
                continue
            m.name = _makeName(n, prefixes)
            memlist.append(m)

    # handle the case where a named signal appears in a list also by giving
    # priority to the list and marking the signals as unused
    for m in memlist:
        if not m._used:
            continue
        m._driven = 'reg'
        for i, s in enumerate(m.mem):
            s._name = "%s%s%s%s" % (m.name, open, i, close)
            s._used = False
            if s._inList:
                raise ConversionError(_error.SignalInMultipleLists, s._name)
            s._inList = True
            if not s._nrbits:
                raise ConversionError(_error.UndefinedBitWidth, s._name)
            if type(s.val) != type(m.elObj.val):
                raise ConversionError(_error.InconsistentType, s._name)
            if s._nrbits != m.elObj._nrbits:
                raise ConversionError(_error.InconsistentBitWidth, s._name)
            
    return siglist, memlist

        

def _analyzeGens(top, absnames):
    genlist = []
    for g in top:
        if isinstance(g, _UserCode):
            ast = g
        elif isinstance(g, (_AlwaysComb, _Always)):
            f = g.func
            s = inspect.getsource(f)
            # remove decorators
            s = re.sub(r"@.*", "", s)
            s = s.lstrip()
            ast = compiler.parse(s)
            # print ast
            ast.sourcefile = inspect.getsourcefile(f)
            ast.lineoffset = inspect.getsourcelines(f)[1]-1
            ast.symdict = f.func_globals.copy()
            ast.callstack = []
            # handle free variables
            if f.func_code.co_freevars:
                for n, c in zip(f.func_code.co_freevars, f.func_closure):
                    obj = _cell_deref(c)
                    if isinstance(g, _AlwaysComb):
                        print type(obj)
                        assert isinstance(obj, (int, long, Signal)) or \
                               _isMem(obj) or _isTupleOfInts(obj)
                    ast.symdict[n] = obj
            ast.name = absnames.get(id(g), str(_Label("BLOCK"))).upper()
            v = _NotSupportedVisitor(ast)
            compiler.walk(ast, v)
            if isinstance(g, _AlwaysComb):
                v = _AnalyzeAlwaysCombVisitor(ast, g.senslist)
            else:
                v = _AnalyzeAlwaysDecoVisitor(ast, g.senslist)
            compiler.walk(ast, v)
        else: # @instance
            f = g.gen.gi_frame
            s = inspect.getsource(f)
            # remove decorators
            s = re.sub(r"@.*", "", s)
            s = s.lstrip()
            ast = compiler.parse(s)
            # print ast
            ast.sourcefile = inspect.getsourcefile(f)
            ast.lineoffset = inspect.getsourcelines(f)[1]-1
            ast.symdict = f.f_globals.copy()
            ast.symdict.update(f.f_locals)
            ast.callstack = []
            ast.name = absnames.get(id(g), str(_Label("BLOCK"))).upper()
            v = _NotSupportedVisitor(ast)
            compiler.walk(ast, v)
            v = _AnalyzeBlockVisitor(ast)
            compiler.walk(ast, v)
        genlist.append(ast)
    return genlist


class _NotSupportedVisitor(_ConversionMixin):
    
    def __init__(self, ast):
        self.ast = ast
        self.toplevel = True
        
    def visitAssList(self, node, *args):
        self.raiseError(node, _error.NotSupported, "list assignment")
    def visitAssTuple(self, node, *args):
        self.raiseError(node, _error.NotSupported, "tuple assignment")
    def visitBackquote(self, node, *args):
        self.raiseError(node, _error.NotSupported, "backquote")
    def visitClass(self, node, *args):
        self.raiseError(node, _error.NotSupported, "class statement")
    def visitDict(self, node, *args):
        self.raiseError(node, _error.NotSupported, "dictionary")
    def visitDiv(self, node, *args):
        self.raiseError(node, _error.NotSupported, "true division - consider '//'")
    def visitEllipsis(self, node, *args):
        self.raiseError(node, _error.NotSupported, "ellipsis")
    def visitExec(self, node, *args):
        self.raiseError(node, _error.NotSupported, "exec statement")
    def visitExpression(self, node, *args):
        self.raiseError(node, _error.NotSupported, "Expression node")
    def visitFrom(self, node, *args):
        self.raiseError(node, _error.NotSupported, "from statement")
    def visitGlobal(self, node, *args):
        self.raiseError(node, _error.NotSupported, "global statement")
    def visitImport(self, node, *args):
        self.raiseError(node, _error.NotSupported, "import statement")
    def visitLambda(self, node, *args):
        self.raiseError(node, _error.NotSupported, "lambda statement")
    def visitListComp(self, node, *args):
        if len(node.quals) > 1:
            self.raiseError(node, _error.NotSupported, "multiple for statements in list comprehension")
        self.visitChildNodes(node)
    def visitListCompIf(self, node, *args):
        self.raiseError(node, _error.NotSupported, "if statement in list comprehension")
    def visitList(self, node, *args):
        self.raiseError(node, _error.NotSupported, "list")
    def visitSliceObj(self, node):
        self.raiseError(node, _error.NotSupported, "slice object")
    def visitTryExcept(self, node, *args):
        self.raiseError(node, _error.NotSupported, "try-except statement")
    def visitTryFinally(self, node, *args):
        self.raiseError(node, _error.NotSupported, "try-finally statement")

    def visitAnd(self, node):
        self.visitChildNodes(node)
            
    def visitOr(self, node):
        self.visitChildNodes(node)
        
    def visitAssign(self, node, *args):
        if len(node.nodes) > 1:
            self.raiseError(node, _error.NotSupported, "multiple assignments")
        self.visit(node.nodes[0], *args)
        self.visit(node.expr, *args)
        
    def visitCallFunc(self, node):
        if node.star_args:
            self.raiseError(node, _error.NotSupported, "extra positional arguments")
        if node.dstar_args:
            self.raiseError(node, _error.NotSupported, "extra named arguments")
        # f = eval(_unparse(node.node), self.ast.symdict)
        self.visitChildNodes(node)
                
    def visitCompare(self, node, *args):
        if len(node.ops) != 1:
            self.raiseError(node, _error.NotSupported, "chained comparison")
        self.visitChildNodes(node, *args)
        
    def visitFunction(self, node, *args):
        if node.flags != 0: # check flags
            self.raiseError(node, _error.NotSupported, "extra positional or named arguments")
        if not self.toplevel:
            self.raiseError(node, _error.NotSupported, "embedded function definition")
        self.toplevel = False
        self.visitChildNodes(node, *args)
        
    def visitIf(self, node, *args):
        node.ignore = False
        if len(node.tests) == 1 and not node.else_:
            test = node.tests[0][0]
            if isinstance(test, compiler.ast.Name):
                if test.name == '__debug__':
                    node.ignore = True
                    return # skip
        for test, suite in node.tests:
            self.visit(test)
            self.visit(suite)
        if node.else_:
            self.visit(node.else_)
        
    def visitPrintnl(self, node, *args):
        if node.dest is not None:
            self.raiseError(node, _error.NotSupported, "printing to a file with >> syntax")
        self.visitChildNodes(node, *args)

    def visitPrint(self, node, *args):
        self.raiseError(node, _error.NotSupported, "printing without newline")
        
    # visitPrint = visitPrintnl



def getNrBits(obj):
    if hasattr(obj, '_nrbits'):
        return obj._nrbits
    return None

def hasType(obj, theType):
    if isinstance(obj, theType):
        return True
    if isinstance(obj, Signal):
        if isinstance(obj._val, theType):
            return True
    return False


class ReferenceStack(list):
    def push(self):
        self.append(Set())
    def add(self, item):
        self[-1].add(item)
    def __contains__(self, item):
        for s in self:
            if item in s:
                return True
        return False

# auxiliary types to aid type checking
## class _EdgeDetector(object):
##     pass

class _Ram(object):
    __slots__ = ['elObj', 'depth']


class _Rom(object):
    __slots__ = ['rom']
    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])")

class ConvSpec(object):
    def __init__(self, **kwargs):
        self.justified = "RIGHT"
        self.width = 0
        self.conv = str
        if kwargs['justified'] == '-':
            self.justified = "LEFT"
        if kwargs['width']:
            self.width = int(kwargs['width'])
        if kwargs['conv'] == 'd':
            self.conv = int

defaultConvSpec = ConvSpec(**re_ConvSpec.match(r"%s").groupdict())
        

class _AnalyzeVisitor(_ConversionMixin):
    
    def __init__(self, ast):
        ast.sigdict = {}
        ast.vardict = {}
        ast.inputs = Set()
        ast.outputs = Set()
        ast.argnames = []
        ast.kind = None
        ast.hasYield = 0
        ast.hasRom = False
        ast.hasPrint = False
        self.ast = ast
        self.labelStack = []
        self.refStack = ReferenceStack()
        self.globalRefs = Set()


    def binaryOp(self, node, *args):
        self.visit(node.left)
        self.visit(node.right)
        node.obj = int(-1)
        node.signed = node.left.signed or node.right.signed
    visitAdd = binaryOp
    visitFloorDiv = binaryOp
    visitLeftShift = binaryOp
    visitMul = binaryOp
    visitPower = binaryOp
    visitMod = binaryOp
    visitRightShift = binaryOp
    visitSub = binaryOp
    
    def multiBitOp(self, node, *args):
        node.signed = False
        for n in node.nodes:
            self.visit(n)
            if n.signed:
                node.signed = True
        node.obj = None
        for n in node.nodes:
            if node.obj is None:
                node.obj = n.obj
            elif isinstance(node.obj, type(n.obj)):
                node.obj = n.obj
    def visitBitand(self, node, *args):
        self.multiBitOp(node, *args)
    def visitBitor(self, node, *args):
        self.multiBitOp(node, *args)
    def visitBitxor(self, node, *args):
        self.multiBitOp(node, *args)
    def multiLogicalOp(self, node, *args):
        for n in node.nodes:
            self.visit(n, *args)
        for n in node.nodes:
            if not hasType(n.obj, bool):
                self.raiseError(node, _error.NotSupported, "non-boolean argument in logical operator")
        node.obj = bool()
    def visitAnd(self, node, *args):
        self.multiLogicalOp(node, *args)
    def visitOr(self, node, *args):
        self.multiLogicalOp(node, *args)

    # unaryOp's
    def visitInvert(self, node, *args):
        self.visit(node.expr)
        node.obj = node.expr.obj
        node.signed = node.expr.signed
    def visitNot(self, node, *args):
        self.visit(node.expr)
        node.obj = bool()
        print(node.expr)
        node.signed = node.expr.signed
    def visitUnaryAdd(self, node, *args):
        self.visit(node.expr)
        node.obj = int(-1)
        node.signed = node.expr.signed
    def visitUnarySub(self, node, *args):
        self.visit(node.expr)
        node.obj = int(-1)
        node.signed = node.expr.signed
        if isinstance(node.expr, astNode.Const):
            node.signed = True
        
    def visitAssAttr(self, node, access=_access.OUTPUT, *args):
        if node.attrname != 'next':
            self.raiseError(node, _error.NotSupported, "attribute assignment")
        self.ast.kind = _kind.TASK
        self.visit(node.expr, _access.OUTPUT)
        
    def visitAssign(self, node, access=_access.OUTPUT, *args):
        target, expr = node.nodes[0], node.expr
        self.visit(target, _access.OUTPUT)
        if isinstance(target, astNode.AssName):
            self.visit(expr, _access.INPUT, _kind.DECLARATION)
            node.kind = _kind.DECLARATION
            n = target.name
            if n in self.ast.sigdict:
                self.raiseError(node, _error.ShadowingVar)
            obj = self.getObj(expr)
            if obj is None:
                self.raiseError(node, _error.TypeInfer, n)
            if isinstance(obj, intbv):
                if len(obj) == 0:
                    self.raiseError(node, _error.IntbvBitWidth, n)
##                 if obj._min < 0:
##                     self.raiseError(node, _error.IntbvSign, n)
                    if obj._min < 0:
                        _signed = True
            if n in self.ast.vardict:
                curObj = self.ast.vardict[n]
                if isinstance(obj, type(curObj)):
                    pass
                elif isinstance(curObj, type(obj)):
                     self.ast.vardict[n] = obj
                else:
                    self.raiseError(node, _error.TypeMismatch, n)
                if getNrBits(obj) != getNrBits(curObj):
                    self.raiseError(node, _error.NrBitsMismatch, n)
            else:
                self.ast.vardict[n] = obj
        else:
            self.visit(expr, _access.INPUT)

    def visitAssName(self, node, *args):
        n = node.name
        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)
        
    def visitAugAssign(self, node, access=_access.INPUT, *args):
        self.visit(node.node, _access.INOUT)
        self.visit(node.expr, _access.INPUT)

    def visitBreak(self, node, *args):
        self.labelStack[-2].isActive = True

    def visitCallFunc(self, node, *args):
        self.visit(node.node)
        for arg in node.args:
            self.visit(arg, _access.UNKNOWN)
        argsAreInputs = True
        f = self.getObj(node.node)
        node.obj = None
        node.signed = False
        if type(f) is type and issubclass(f, intbv):
            node.obj = self.getVal(node)
        elif f is concat:
            node.obj = self.getVal(node)
        elif f is len:
            node.obj = int(0) # XXX
        elif f is bool:
            node.obj = bool()
        elif f in (int, long, ord):
            node.obj = int(-1)
##         elif f in (posedge , negedge):
##             node.obj = _EdgeDetector()
        elif f is delay:
            node.obj = delay(0)
        ### 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:
            pass
        elif type(f) is FunctionType:
            argsAreInputs = False
            s = inspect.getsource(f)
            s = s.lstrip()
            ast = compiler.parse(s)
            # print ast
            fname = f.__name__
            ast.name = _Label(fname)
            ast.sourcefile = inspect.getsourcefile(f)
            ast.lineoffset = inspect.getsourcelines(f)[1]-1
            ast.symdict = f.func_globals.copy()
            if fname in self.ast.callstack:
                self.raiseError(node, _error.NotSupported, "Recursive call")
            ast.callstack = self.ast.callstack[:]
            ast.callstack.append(fname)
            # handle free variables
            if f.func_code.co_freevars:
                for n, c in zip(f.func_code.co_freevars, f.func_closure):
                    obj = _cell_deref(c)
                    if not  isinstance(obj, (int, long, Signal)):
                        self.raiseError(node, _error.FreeVarTypeError, n)
                    ast.symdict[n] = obj
            v = _NotSupportedVisitor(ast)
            compiler.walk(ast, v)
            v = _AnalyzeFuncVisitor(ast, node.args)
            compiler.walk(ast, v)
            node.obj = ast.returnObj
            node.ast = ast
            for i, arg in enumerate(node.args):
                if isinstance(arg, astNode.Keyword):
                    n = arg.name
                else: # Name
                    n = ast.argnames[i]
                if n in ast.outputs:
                    self.visit(arg, _access.OUTPUT)
                if n in ast.inputs:
                    self.visit(arg, _access.INPUT)
        elif type(f) is MethodType:
            self.raiseError(node,_error.NotSupported, "method call: '%s'" % f.__name__)
        else:
            raise AssertionError("Unexpected callable")
        if argsAreInputs:
            for arg in node.args:
                self.visit(arg, _access.INPUT)
            
    def visitCompare(self, node, *args):
        node.obj = bool()
        node.signed = False
        for n in node.getChildNodes():
            self.visit(n, *args)
            if n.signed:
                node.signed = True
        op, arg = node.ops[0]
##         node.expr.target = self.getObj(arg)
##         arg.target = self.getObj(node.expr)
        # detect specialized case for the test
        if op == '==' and isinstance(node.expr, astNode.Name):
            n = node.expr.name
            # check wether it can be a case
            if isinstance(arg.obj, EnumItemType):
                node.case = (node.expr, arg.obj)
            # check whether it can be part of an edge check
            elif n in self.ast.sigdict:
                sig = self.ast.sigdict[n]
                v = self.getValue(arg)
                if v is not None:
                    if v == 0:
                        node.edge = sig.negedge
                    elif v == 1:
                        node.edge = sig.posedge
                        

    def visitConst(self, node, *args):
        node.signed = False
        if node.value in (0, 1):
            node.obj = bool(node.value)
        elif isinstance(node.value, (int, str)):
            node.obj = node.value
        else:
            node.obj = None
            
    def visitContinue(self, node, *args):
        self.labelStack[-1].isActive = True
            
    def visitFor(self, node, *args):
        node.breakLabel = _Label("BREAK")
        node.loopLabel = _Label("LOOP")
        self.labelStack.append(node.breakLabel)
        self.labelStack.append(node.loopLabel)
        self.refStack.push()
        self.visit(node.assign)
        var = node.assign.name
        self.ast.vardict[var] = int(-1)
        
        cf = node.list
        self.visit(cf)
        self.require(node, isinstance(cf, astNode.CallFunc), "Expected (down)range call")
        f = self.getObj(cf.node)
        self.require(node, f in (range, downrange), "Expected (down)range call")
        
        self.visit(node.body, *args)
        self.refStack.pop()
        self.require(node, node.else_ is None, "for-else not supported")
        self.labelStack.pop()
        self.labelStack.pop()

    def visitFunction(self, node, *args):
        raise AssertionError("subclass must implement this")
           
    def visitGetattr(self, node, *args):
        self.visit(node.expr, *args)
        node.obj = None
        node.signed = False
        if isinstance(node.expr, astNode.Name):
            n = node.expr.name
            if (n not in self.ast.vardict) and (n not in self.ast.symdict):
                raise AssertionError("attribute target: %s" % n)
        obj = node.expr.obj
        if isinstance(obj, Signal):
            if node.attrname == 'posedge':
                node.obj = obj.posedge
            elif node.attrname == 'negedge':
                node.obj = obj.negedge
            elif node.attrname in ('val', 'next'):
                node.obj = obj.val
        if isinstance(obj, (intbv, Signal)):
            if node.attrname == 'min':
                node.obj = obj.min
            elif node.attrname == 'max':
                node.obj = obj.max
            elif node.attrname == 'signed':
                node.obj = intbv.signed
        if isinstance(obj, EnumType):
            print("Object:" + `obj`)
            print("Name:" + `node.attrname`)
            assert hasattr(obj, node.attrname)
            node.obj = getattr(obj, node.attrname)
            if obj not in _enumTypeSet:
                _enumTypeSet.add(obj)
                suf = _genUniqueSuffix.next()
                obj._setName(n+suf)
        if node.obj is None: # attribute lookup failed
            self.raiseError(node, _error.UnsupportedAttribute, node.attrname)
            
            
            
    def visitIf(self, node, *args):
        if node.ignore:
            return
        for test, suite in node.tests:
            self.visit(test, *args)
            self.refStack.push()
            self.visit(suite, *args)
            self.refStack.pop()
        if node.else_:
            self.refStack.push()
            self.visit(node.else_, *args)
            self.refStack.pop()
        # check whether the if can be mapped to a (parallel) case
        node.isCase = node.isFullCase = False
        test1 = node.tests[0][0]
        if not hasattr(test1, 'case'):
            return
        var1, item1 = test1.case
        # don't infer a case if there's no elsif test
        if not node.tests[1:]:
            return
        choices = Set()
        choices.add(item1._index)
        for test, suite in node.tests[1:]:
            if not hasattr(test, 'case'):
                return
            var, item = test.case
            if var.name != var1.name or type(item) is not type(item1):
                return
            if item._index in choices:
                return
            choices.add(item._index)
        node.isCase = True
        node.caseVar = var1
        if (len(choices) == item1._nritems) or (node.else_ is not None):
            node.isFullCase = True
            
    def visitListComp(self, node, *args):
        mem = node.obj = _Ram()
        self.visit(node.expr, _access.INPUT, _kind.DECLARATION)
        mem.elObj = self.getObj(node.expr)
        if not isinstance(mem.elObj, intbv) or not len(mem.elObj) > 0:
            self.raiseError(node, _error.UnsupportedListComp)
        cf = node.quals[0].list
        self.visit(cf)
        if not isinstance(cf, astNode.CallFunc):
            self.raiseError(node, _error.UnsupportedListComp)
        f = self.getObj(cf.node)
        if f is not range or len(cf.args) != 1:
            self.raiseError(node, _error.UnsupportedListComp)
        mem.depth = cf.args[0].obj

    def visitName(self, node, access=_access.INPUT, *args):
        n = node.name
        node.obj = None
        if n not in self.refStack:
            if n in self.ast.vardict:
                self.raiseError(node, _error.UnboundLocal, n)
            self.globalRefs.add(n)
        if n in self.ast.sigdict:
            node.obj = sig = self.ast.sigdict[n]
            if not isinstance(sig, Signal):
                # print "not a signal: %s" % n
                pass 
            else:
                if sig._type is bool:
                    node.edge = sig.posedge
            if access == _access.INPUT:
                self.ast.inputs.add(n)
            elif access == _access.OUTPUT:
                self.ast.kind = _kind.TASK
                if n in self.ast.outputs:
                    node.kind = _kind.REG
                self.ast.outputs.add(n)
            elif access == _access.UNKNOWN:
                pass
            else: 
                raise AssertionError
        if n in self.ast.vardict:
            obj = self.ast.vardict[n]
            if access == _access.INOUT:
                # upgrade bool to int for augmented assignments
                if isinstance(obj, bool):
                    obj = int(0)
                    self.ast.vardict[n] = obj
            node.obj = obj
        elif n in self.ast.symdict:
            node.obj = self.ast.symdict[n]
            if _isTupleOfInts(node.obj):
                node.obj = _Rom(node.obj)
                self.ast.hasRom = True
            elif isinstance(node.obj, int):
                node.value = node.obj
        elif n in __builtin__.__dict__:
            node.obj = __builtin__.__dict__[n]
        else:
            pass
        node.signed = _maybeNegative(node.obj)
##         node.target = node.obj

    def visitReturn(self, node, *args):
        self.raiseError(node, _error.NotSupported, "return statement")
        
    def visitPrintnl(self, node, *args):
        self.ast.hasPrint = True
        f = []
        nr = 0
        a = []
        for n in node.nodes:
            if isinstance(n, astNode.Mod) and \
               (isinstance(n.left, astNode.Const) and isinstance(n.left.value, str)):
                if isinstance(n.right, astNode.Tuple):
                    a.extend(n.right.nodes)
                else:
                    a.append(n.right)
                s = n.left.value
                while s:
                    if not s:
                        break
                    if s[:2] == "%%":
                        f.append("%")
                        s = s[2:]
                        continue
                    m = re_ConvSpec.match(s)
                    if m:
                        c = ConvSpec(**m.groupdict())
                        if c.justified != "RIGHT":
                            self.raiseError(node,_error.UnsupportedFormatString,
                                            "format justification specification: %s" %s)
                        if c.width != 0:
                            self.raiseError(node,_error.UnsupportedFormatString,
                                            "format width specification: %s" %s)
                        f.append(c)
                        s = s[m.end():]
                        nr += 1
                        continue
                    m = re_str.match(s)
                    if m:
                        f.append(s[:m.end()])
                        s = s[m.end():]
                        continue
                    self.raiseError(node, _error.UnsupportedFormatString, "%s" % s)
            else:
                f.append(defaultConvSpec)
                a.append(n)
                nr += 1
            f.append(" ")
        # remove last single space if it exists
        if f:
            f.pop()
        node.format = f
        node.args = a
        if len(node.args) < nr:
            self.raiseError(node, _error.FormatString, "not enough arguments")
        if len(node.args) > nr:
            self.raiseError(node, _error.FormatString, "too many arguments")
        self.visitChildNodes(node, *args)
        
    visitPrint = visitPrintnl
            
    def visitSlice(self, node, access=_access.INPUT, kind=_kind.NORMAL, *args):
        node.signed = False
        self.visit(node.expr, access)
        node.obj = self.getObj(node.expr)
        if node.lower:
            self.visit(node.lower, _access.INPUT)
        if node.upper:
            self.visit(node.upper, _access.INPUT)
        if isinstance(node.obj , intbv):
            if kind == _kind.DECLARATION:
                self.require(node.lower, "Expected leftmost index")
                leftind = self.getVal(node.lower)
                if node.upper:
                    rightind = self.getVal(node.upper)
                else:
                    rightind = 0
                node.obj = node.obj[leftind:rightind]
            
 
    def visitSubscript(self, node, access=_access.INPUT, *args):
        self.visit(node.expr, access)
        assert len(node.subs) == 1
        self.visit(node.subs[0], _access.INPUT)
        if isinstance(node.expr.obj, _Ram):
            if node.flags == 'OP_ASSIGN':
                self.raiseError(node, _error.ListElementAssign)
            else:
                node.obj = node.expr.obj.elObj
        elif _isMem(node.expr.obj):
            node.obj = node.expr.obj[0]
        elif isinstance(node.expr.obj, _Rom):
            node.obj = int(-1)
        elif isinstance(node.expr.obj, intbv):
            node.obj = bool()
        else:
            node.obj = bool() # XXX default
        node.signed = _maybeNegative(node.obj)

    def visitTuple(self, node, *args):
        node.signed = False
        self.visitChildNodes(node, *args)

    def visitWhile(self, node, *args):
        node.breakLabel = _Label("BREAK")
        node.loopLabel = _Label("LOOP")
        self.labelStack.append(node.breakLabel)
        self.labelStack.append(node.loopLabel)
        self.visit(node.test, *args)
        self.refStack.push()
        self.visit(node.body, *args)
        self.refStack.pop()
        y = node.body.nodes[0]
        if isinstance(y, astNode.Discard):
            y = y.expr
        if node.test.obj == True and \
           isinstance(y, astNode.Yield) and \
           not self.ast.hasYield > 1 and \
           not isinstance(self.getObj(y.value), delay):
            node.kind = _kind.ALWAYS
            self.ast.senslist = y.senslist
        self.require(node, node.else_ is None, "while-else not supported")
        self.labelStack.pop()
        self.labelStack.pop()

    def visitYield(self, node, *args):
        self.ast.hasYield += 1
        n = node.value
        self.visit(n)
        senslist = []
        if isinstance(n, astNode.Tuple):
            for n in n.nodes:
                if not isinstance(n.obj, (Signal, _WaiterList)):
                    self.raiseError(node, _error.UnsupportedYield)
                senslist.append(n.obj)
        elif isinstance(n.obj, (Signal, _WaiterList, delay)):
            senslist = [n.obj]
        elif _isMem(n.obj):
            senslist = n.obj
        else:
            self.raiseError(node, _error.UnsupportedYield)
        node.senslist = senslist

##     def visitModule(self, node, *args):
##         self.visit(node.node)
##         for n in self.ast.inputs:
##             s = self.ast.sigdict[n]
##             s._read = True
        
        

class _AnalyzeBlockVisitor(_AnalyzeVisitor):
    
    def __init__(self, ast):
        _AnalyzeVisitor.__init__(self, ast)
        for n, v in self.ast.symdict.items():
            if isinstance(v, Signal):
                self.ast.sigdict[n] = v
        
    def visitFunction(self, node, *args):
        self.refStack.push()
        self.visit(node.code)
        self.ast.kind = _kind.ALWAYS
        for n in node.code.nodes[:-1]:
            if not self.getKind(n) == _kind.DECLARATION:
                self.ast.kind = _kind.INITIAL
                break
        if self.ast.kind == _kind.ALWAYS:
            w = node.code.nodes[-1]
            if not self.getKind(w) == _kind.ALWAYS:
                self.ast.kind = _kind.INITIAL
        self.refStack.pop()
                
    def visitModule(self, node, *args):
        self.visit(node.node)
        for n in self.ast.outputs:
            s = self.ast.sigdict[n]
            if s._driven:
                self.raiseError(node, _error.SigMultipleDriven, n)
            s._driven = "reg"
        for n in self.ast.inputs:
            s = self.ast.sigdict[n]
            s._read = True
            
    def visitReturn(self, node, *args):
        ### value should be None
        if isinstance(node.value, astNode.Const) and node.value.value is None:
            obj = None
        elif isinstance(node.value, astNode.Name) and node.value.name == 'None':
            obj = None
        else:
            self.raiseError(node, _error.NotSupported, "return value other than None")
     

class _AnalyzeAlwaysCombVisitor(_AnalyzeBlockVisitor):
    
    def __init__(self, ast, senslist):
        _AnalyzeBlockVisitor.__init__(self, ast)
        self.ast.senslist = senslist

    def visitFunction(self, node, *args):
          self.refStack.push()
          self.visit(node.code)
          self.ast.kind = _kind.SIMPLE_ALWAYS_COMB
          for n in node.code.nodes:
              if isinstance(n, astNode.Assign) and \
                 isinstance(n.nodes[0], astNode.AssAttr) and \
                 self.getKind(n.nodes[0].expr) != _kind.REG:
                  pass
              else:
                  self.ast.kind = _kind.ALWAYS_COMB
                  return
          # rom access is expanded into a case statement
          if self.ast.hasRom:
              self.ast.kind = _kind.ALWAYS_COMB
          self.refStack.pop()

    def visitModule(self, node, *args):
        _AnalyzeBlockVisitor.visitModule(self, node, *args)
        if self.ast.kind == _kind.SIMPLE_ALWAYS_COMB:
            for n in self.ast.outputs:
                s = self.ast.sigdict[n]
                s._driven = "wire"
                

class _AnalyzeAlwaysDecoVisitor(_AnalyzeBlockVisitor):
    
    def __init__(self, ast, senslist):
        _AnalyzeBlockVisitor.__init__(self, ast)
        self.ast.senslist = senslist

    def visitFunction(self, node, *args):
          self.refStack.push()
          self.visit(node.code)
          self.ast.kind = _kind.ALWAYS_DECO
          self.refStack.pop()
         
            

class _AnalyzeFuncVisitor(_AnalyzeVisitor):
    
    def __init__(self, ast, args):
        _AnalyzeVisitor.__init__(self, ast)
        self.args = args
        self.ast.hasReturn = False
        self.ast.returnObj = None

    def visitFunction(self, node, *args):
        self.refStack.push()
        argnames = node.argnames
        for i, arg in enumerate(self.args):
            if isinstance(arg, astNode.Keyword):
                n = arg.name
                self.ast.symdict[n] = self.getObj(arg.expr)
            else: # Name
                n = argnames[i]
                self.ast.symdict[n] = self.getObj(arg)
            self.ast.argnames.append(n)
        for n, v in self.ast.symdict.items():
            if isinstance(v, (Signal, intbv)):
                self.ast.sigdict[n] = v
        self.visit(node.code)
        self.refStack.pop()
        if self.ast.hasYield:
            self.raiseError(node, _error.NotSupported,
                            "call to a generator function")
        if self.ast.kind == _kind.TASK:
            if self.ast.returnObj is not None:
                self.raiseError(node, _error.NotSupported,
                                "function with side effects and return value")
        else:
            if self.ast.returnObj is None:
                self.raiseError(node, _error.NotSupported,
                                "pure function without return value")
        
        
    def visitReturn(self, node, *args):
        self.visit(node.value, _access.INPUT, _kind.DECLARATION, *args)
        if isinstance(node.value, astNode.Const) and node.value.value is None:
            obj = None
        elif isinstance(node.value, astNode.Name) and node.value.name == 'None':
            obj = None
        elif node.value.obj is not None:
            obj = node.value.obj
        else:
            self.raiseError(node, _error.ReturnTypeInfer)
        if isinstance(obj, intbv) and len(obj) == 0:
            self.raiseError(node, _error.ReturnIntbvBitWidth)
        if self.ast.hasReturn:
            returnObj = self.ast.returnObj
            if isinstance(obj, type(returnObj)):
                pass
            elif isinstance(returnObj, type(obj)):
                self.ast.returnObj = obj
            else:
                self.raiseError(node, _error.ReturnTypeMismatch)
            if getNrBits(obj) != getNrBits(returnObj):
                self.raiseError(node, _error.ReturnNrBitsMismatch)
        else:
            self.ast.returnObj = obj
            self.ast.hasReturn = True

       
def _analyzeTopFunc(func, *args, **kwargs):
    s = inspect.getsource(func)
    s = s.lstrip()
    ast = compiler.parse(s)
    v = _AnalyzeTopFuncVisitor(*args, **kwargs)
    compiler.walk(ast, v)
    return v
      
    
class _AnalyzeTopFuncVisitor(object):

    def __init__(self, *args, **kwargs):
        self.args = args
        self.kwargs = kwargs
        self.name = None
        self.argdict = {}
    
    def visitFunction(self, node):
        self.name = node.name
        argnames = node.argnames
        i=-1
        for i, arg in enumerate(self.args):
            if isinstance(arg, Signal):
                n = argnames[i]
                self.argdict[n] = arg
        for n in argnames[i+1:]:
            if n in self.kwargs:
                arg = self.kwargs[n]
                if isinstance(arg, Signal):
                    self.argdict[n] = arg
        self.argnames = [n for n in argnames if n in self.argdict]


Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.