From 3eaae1188b4c6086359a3dcce76d1f96e226b484 Mon Sep 17 00:00:00 2001 From: jand Date: Tue, 19 Sep 2006 15:39:10 +0000 Subject: [PATCH] removed old dirs --- myhdl/_toVHDL/__init__.py | 1 - myhdl/_toVHDL/_convert.py | 1691 ---------------------------------- myhdl/_toVerilog/__init__.py | 148 --- myhdl/_toVerilog/_analyze.py | 987 -------------------- myhdl/_toVerilog/_convert.py | 1078 ---------------------- 5 files changed, 3905 deletions(-) delete mode 100644 myhdl/_toVHDL/__init__.py delete mode 100644 myhdl/_toVHDL/_convert.py delete mode 100644 myhdl/_toVerilog/__init__.py delete mode 100644 myhdl/_toVerilog/_analyze.py delete mode 100644 myhdl/_toVerilog/_convert.py diff --git a/myhdl/_toVHDL/__init__.py b/myhdl/_toVHDL/__init__.py deleted file mode 100644 index 8d1c8b69..00000000 --- a/myhdl/_toVHDL/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/myhdl/_toVHDL/_convert.py b/myhdl/_toVHDL/_convert.py deleted file mode 100644 index 8d54dbb3..00000000 --- a/myhdl/_toVHDL/_convert.py +++ /dev/null @@ -1,1691 +0,0 @@ -# This file is part of the myhdl library, a Python package for using -# Python as a Hardware Description Language. -# -# Copyright (C) 2003 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 conversion module. - -""" - -__author__ = "Jan Decaluwe " -__revision__ = "$Revision: 811 $" -__date__ = "$Date: 2006-03-31 22:09:27 +0200 (Fri, 31 Mar 2006) $" - -import sys -import math -import traceback -import inspect -import compiler -from compiler import ast as astNode -from sets import Set -from types import GeneratorType, FunctionType, ClassType -from cStringIO import StringIO -import __builtin__ -import warnings - -import myhdl -from myhdl import * -from myhdl import ToVHDLError, ToVHDLWarning -from myhdl._extractHierarchy import _HierExtr, _isMem, _getMemInfo, \ - _UserDefinedVerilog, _userDefinedVerilogMap - -from myhdl._always_comb import _AlwaysComb -from myhdl._always import _Always -from myhdl._toVerilog import _error, _access, _kind,_context, \ - _ConversionMixin, _Label -from myhdl._toVerilog._analyze import _analyzeSigs, _analyzeGens, _analyzeTopFunc, \ - _Ram, _Rom -from myhdl._Signal import _WaiterList - -_converting = 0 -_profileFunc = None -_enumTypeList = [] - -def _checkArgs(arglist): - for arg in arglist: - if not type(arg) in (GeneratorType, _AlwaysComb, _Always, _UserDefinedVerilog): - raise ToVHDLError(_error.ArgType, arg) - -def _flatten(*args): - arglist = [] - for arg in args: - if id(arg) in _userDefinedVerilogMap: - arglist.append(_userDefinedVerilogMap[id(arg)]) - elif isinstance(arg, (list, tuple, Set)): - for item in arg: - arglist.extend(_flatten(item)) - else: - arglist.append(arg) - return arglist - - -class _ToVHDLConvertor(object): - - __slots__ = ("name", ) - - def __init__(self): - self.name = None - - def __call__(self, func, *args, **kwargs): - global _converting - if _converting: - return func(*args, **kwargs) # skip - else: - # clean start - sys.setprofile(None) - from myhdl import _traceSignals - if _traceSignals._tracing: - raise ToVHDLError("Cannot use toVerilog while tracing signals") - if not callable(func): - raise ToVHDLError(_error.FirstArgType, "got %s" % type(func)) - - _converting = 1 - if self.name is None: - name = func.func_name - else: - name = str(self.name) - try: - h = _HierExtr(name, func, *args, **kwargs) - finally: - _converting = 0 - - vpath = name + ".vhd" - vfile = open(vpath, 'w') - - siglist, memlist = _analyzeSigs(h.hierarchy) - arglist = _flatten(h.top) - # print h.top - _checkArgs(arglist) - genlist = _analyzeGens(arglist, h.absnames) - _annotateTypes(genlist) - intf = _analyzeTopFunc(func, *args, **kwargs) - intf.name = name - - _writeModuleHeader(vfile, intf) - _writeFuncDecls(vfile) - _writeSigDecls(vfile, intf, siglist, memlist) - _convertGens(genlist, vfile) - _writeModuleFooter(vfile) - - vfile.close() - # tbfile.close() - - # clean up signal names - for sig in siglist: - sig._name = None - sig._driven = False - sig._read = False - # clean up enum type names - for enumType in _enumTypeList: - enumType._clearDeclared() - - return h.top - - -toVHDL = _ToVHDLConvertor() - - -def _writeModuleHeader(f, intf): - print >> f, "library IEEE;" - print >> f, "use IEEE.std_logic_1164.all;" - print >> f, "use IEEE.numeric_std.all;" - print >> f, "use std.textio.all;" - print >> f - print >> f, "entity %s is" % intf.name - if intf.argnames: - f.write(" port (") - c = '' - for portname in intf.argnames: - s = intf.argdict[portname] - f.write("%s" % c) - c = ';' - if s._name is None: - raise ToVHDLError(_error.ShadowingSignal, portname) - # make sure signal name is equal to its port name - s._name = portname - r = _getRangeString(s) - p = _getTypeString(s) - if s._driven: - f.write("\n %s: out %s%s" % (portname, p, r)) - else: - f.write("\n %s: in %s%s" % (portname, p, r)) - f.write("\n );\n") - print >> f, "end entity %s;" % intf.name - print >> f - print >> f, "architecture MyHDL of %s is" % intf.name - print >> f - - -funcdecls = """\ -function to_std_logic (arg : boolean) return std_logic is begin - if arg then - return '1'; - else - return '0'; - end if; -end function to_std_logic; -""" - -def _writeFuncDecls(f): - print >> f, funcdecls - - - -def _writeSigDecls(f, intf, siglist, memlist): - constwires = [] - for s in siglist: - if s._name in intf.argnames: - continue - if isinstance(s._val, EnumItemType): - _declareEnumType(f, s) - r = _getRangeString(s) - p = _getTypeString(s) - if s._driven: - if not s._read: - warnings.warn("%s: %s" % (_error.UnusedSignal, s._name), - category=ToVHDLWarning - ) - # the following line implements initial value assignments - # print >> f, "%s %s%s = %s;" % (s._driven, r, s._name, int(s._val)) - print >> f, "signal %s: %s%s;" % (s._name, p, r) - elif s._read: - # the original exception - # raise ToVHDLError(_error.UndrivenSignal, s._name) - # changed to a warning and a continuous assignment to a wire - warnings.warn("%s: %s" % (_error.UndrivenSignal, s._name), - category=ToVHDLWarning - ) - constwires.append(s) - print >> f, "wire %s%s;" % (r, s._name) - for m in memlist: - if not m.decl: - continue - r = _getRangeString(m.elObj) - print >> f, "reg %s%s [0:%s-1];" % (r, m.name, m.depth) - for s in constwires: - print >> f, "%s <= %s;" % (s._name, int(s._val)) - print >> f - - -def _writeModuleFooter(f): - print >> f, "end architecture MyHDL;" - - -def _declareEnumType(f, s): - enumType = s._val._type - if enumType._isDeclared(): - return - else: - print >> f, enumType._toVHDL(s._name) - enumType._setDeclared() - _enumTypeList.append(enumType) - - -def _getRangeString(s): - if isinstance(s._val, EnumItemType): - return '' - elif s._type is bool: - return '' - elif s._nrbits is not None: - nrbits = s._nrbits - return "(%s downto 0)" % (nrbits-1) - else: - raise AssertionError - - -def _getTypeString(s): - if isinstance(s._val, EnumItemType): - return s._val._type._name - elif s._type is bool: - return "std_logic" - if s._min is not None and s._min < 0: - return "signed " - else: - return 'unsigned' - - -def _convertGens(genlist, vfile): - blockBuf = StringIO() - funcBuf = StringIO() - for ast in genlist: - if isinstance(ast, _UserDefinedVerilog): - blockBuf.write(str(ast)) - continue - if ast.kind == _kind.ALWAYS: - Visitor = _ConvertAlwaysVisitor - elif ast.kind == _kind.INITIAL: - Visitor = _ConvertInitialVisitor - elif ast.kind == _kind.SIMPLE_ALWAYS_COMB: - Visitor = _ConvertSimpleAlwaysCombVisitor - elif ast.kind == _kind.ALWAYS_DECO: - Visitor = _ConvertAlwaysDecoVisitor - else: # ALWAYS_COMB - Visitor = _ConvertAlwaysCombVisitor - v = Visitor(ast, blockBuf, funcBuf) - compiler.walk(ast, v) - # print >> vfile - vfile.write(funcBuf.getvalue()); funcBuf.close() - print >> vfile, "begin" - print >> vfile - vfile.write(blockBuf.getvalue()); blockBuf.close() - -class _ConvertVisitor(_ConversionMixin): - - def __init__(self, ast, buf): - self.ast = ast - self.buf = buf - self.returnLabel = ast.name - self.ind = '' - self.isSigAss = False - self.labelStack = [] - - def write(self, arg): - self.buf.write("%s" % arg) - - def writeline(self, nr=1): - for i in range(nr): - self.buf.write("\n%s" % self.ind) - - def writeIntSize(self, n): - # write size for large integers (beyond 32 bits signed) - # with some safety margin - if n >= 2**30: - size = int(math.ceil(math.log(n+1,2))) + 1 # sign bit! - self.write("%s'sd" % size) - - def writeDeclaration(self, obj, name, kind="", dir="", endchar=";", constr=True): - if isinstance(obj, EnumItemType): - enumType = obj._type - if not enumType._isDeclared(): - self.write(enumType._toVHDL('XXX')) - self.writeline() - enumType._setDeclared() - _enumTypeList.append(enumType) - tipe = obj._type._name - elif isinstance(obj, _Ram): - tipe = "reg [%s-1:0] %s [0:%s-1]" % (obj.elObj._nrbits, name, obj.depth) - else: - vhd = inferVhdlObj(obj) - tipe = vhd.toStr(constr) - if kind: kind += " " - if dir: dir += " " - self.write("%s%s: %s%s%s" % (kind, name, dir, tipe, endchar)) - - -## def writeDeclaration(self, obj, name, dir, endchar=";"): -## if dir: dir = dir + ' ' -## if type(obj) is bool: -## self.write("%s%s: std_logic" % (dir, name)) -## elif isinstance(obj, EnumItemType): -## self.write("%s%s: %s" % (dir, name, obj._type._name)) -## elif isinstance(obj, int): -## if dir == "input ": -## self.write("input %s;" % name) -## self.writeline() -## self.write("variable %s: integer" % name) -## elif isinstance(obj, _Ram): -## self.write("reg [%s-1:0] %s [0:%s-1]" % (obj.elObj._nrbits, name, obj.depth)) -## elif hasattr(obj, '_nrbits'): -## s = "unsigned" -## if isinstance(obj, (intbv, Signal)): -## if obj._min is not None and obj._min < 0: -## s = "signed " -## if dir == "in ": -## self.write("%s: %s %s(%s-1 downto 0)" % (name, dir, s, obj._nrbits)) -## else: -## self.write("%s%s: %s(%s-1 downto 0)" % (dir, name, s, obj._nrbits)) -## else: -## raise AssertionError("var %s has unexpected type %s" % (name, type(obj))) -## # initialize regs -## # if dir == 'reg ' and not isinstance(obj, _Ram): -## # disable for cver -## if False: -## if isinstance(obj, EnumItemType): -## inival = obj._toVHDL() -## else: -## inival = int(obj) -## self.write(" = %s;" % inival) -## else: -## self.write(endchar) - - def writeDeclarations(self): - if self.ast.hasPrint: - self.writeline() - self.write("variable L: line;") - for name, obj in self.ast.vardict.items(): - if isinstance(obj, _loopInt): - continue # hack for loop vars - self.writeline() - self.writeDeclaration(obj, name, kind="variable") - - def indent(self): - self.ind += ' ' * 4 - - def dedent(self): - self.ind = self.ind[:-4] - - def binaryOp(self, node, op=None): - pre, suf = "", "" - prel, sufl = "", "" - prer, sufr = "", "" - if isinstance(node.vhd, vhd_type): - ts = node.vhd.size - if isinstance(node.left.vhd, vhd_int) and isinstance(node.right.vhd, vhd_int): - if isinstance(node.vhd, vhd_unsigned): - pre, suf = "to_unsigned(", ", %s)" % node.vhd.size - elif isinstance(node.vhd, vhd_signed): - pre, suf = "to_signed(", ", %s)" % node.vhd.size - elif isinstance(node.vhd, vhd_int): - pass - else: - raise NotImplementedError - elif isinstance(node.left.vhd, vhd_unsigned) and isinstance(node.right.vhd, vhd_int): - if op == '*': - ns = 2 * node.left.vhd.size - else: - ns = node.left.vhd.size - ds = ts - ns - if isinstance(node.vhd, vhd_unsigned): - if ds > 0: - prel, sufl = "resize(", ", %s)" % node.vhd.size - elif ds < 0: - pre, suf = "resize(", ", %s)" % node.vhd.size - else: - assert NotImplementedError - elif isinstance(node.left.vhd, vhd_unsigned) and isinstance(node.right.vhd, vhd_unsigned): - if op == '*': - ns = node.left.vhd.size + node.right.vhd.size - else: - ns = max(node.left.vhd.size, node.right.vhd.size) - ds = ts - ns - if isinstance(node.vhd, vhd_unsigned): - if ds > 0: - prel, sufl = "resize(", ", %s)" % ts - elif ds < 0: - pre, suf = "resize(", ", %s)" % ts - else: - assertNotImplementedError - - context = None - self.write(pre) - self.write("(") - self.write(prel) - self.visit(node.left, context) - self.write(sufl) - self.write(" %s " % op) - self.write(prer) - self.visit(node.right, context) - self.write(sufr) - self.write(")") - self.write(suf) - def visitAdd(self, node, *args): - self.binaryOp(node, '+') - def visitFloorDiv(self, node, *args): - self.binaryOp(node, '/') - def visitMod(self, node, context=None, *args): - if context == _context.PRINT: - self.visit(node.left, _context.PRINT) - self.write(", ") - self.visit(node.right, _context.PRINT) - else: - self.binaryOp(node, 'mod') - def visitMul(self, node, *args): - self.binaryOp(node, '*') - def visitPower(self, node, *args): - self.binaryOp(node, '**') - def visitSub(self, node, *args): - self.binaryOp(node, "-") - - - def shiftOp(self, node, op=None): - pre, suf = "", "" - prel, sufl = "", "" - prer, sufr = "", "" - if isinstance(node.vhd, vhd_type): - ts = node.vhd.size - if isinstance(node.left.vhd, vhd_int): - if isinstance(node.vhd, vhd_unsigned): - pre, suf = "to_unsigned(", ", %s)" % ts - elif isinstance(node.vhd, vhd_signed): - pre, suf = "to_signed(", ", %s)" % ts - else: - raise NotImplementedError - elif isinstance(node.left.vhd, vhd_unsigned): - ns = node.left.vhd.size - ds = ts - ns - if isinstance(node.vhd, vhd_unsigned): - if ds > 0: - prel, sufl = "resize(", ", %s)" % ts - elif ds < 0: - pre, suf = "resize(", ", %s)" % ts - else: - raise NotImplementedError - else: - assert NotImplementedError - self.write(pre) - self.write("%s(" % op) - self.write(prel) - self.visit(node.left) - self.write(sufl) - self.write(", ") - self.write(prer) - self.visit(node.right) - self.write(sufr) - self.write(")") - self.write(suf) - - - - - def visitLeftShift(self, node, *args): - self.shiftOp(node, "shift_left") - def visitRightShift(self, node, *args): - self.shiftOp(node, "shift_right") - - def checkOpWithNegIntbv(self, node, op): - if op in ("+", "-", "*", "&&", "||", "!"): - return - if isinstance(node, astNode.Name): - o = node.obj - if isinstance(o, (Signal, intbv)) and o.min is not None and o.min < 0: - self.raiseError(node, _error.NotSupported, - "negative intbv with operator %s" % op) - - def multiBoolOp(self, node, op): - for n in node.nodes: - self.checkOpWithNegIntbv(n, op) - if isinstance(node.vhd, vhd_std_logic): - self.write("to_std_logic") - self.write("(") - self.visit(node.nodes[0]) - for n in node.nodes[1:]: - self.write(" %s " % op) - self.visit(n) - self.write(")") - def visitAnd(self, node, *args): - self.multiBoolOp(node, 'and') - def visitOr(self, node, *args): - self.multiBoolOp(node, 'or') - - def multiBitOp(self, node, op): - for n in node.nodes: - self.checkOpWithNegIntbv(n, op) - self.write("(") - self.visit(node.nodes[0]) - for n in node.nodes[1:]: - self.write(" %s " % op) - self.visit(n) - self.write(")") - def visitBitand(self, node, *args): - self.multiBitOp(node, 'and') - def visitBitor(self, node, *args): - self.multiBitOp(node, 'or') - def visitBitxor(self, node, *args): - self.multiBitOp(node, 'xor') - - def unaryOp(self, node, op, context): - self.checkOpWithNegIntbv(node.expr, op) - self.write("(%s" % op) - self.visit(node.expr, context) - self.write(")") - def visitInvert(self, node, context=None, *args): - self.unaryOp(node, 'not ', context) - def visitUnaryAdd(self, node, context=None, *args): - self.unaryOp(node, '+', context) - def visitUnarySub(self, node, context=None, *args): - self.unaryOp(node, '-', context) - def visitNot(self, node, context=None): - self.checkOpWithNegIntbv(node.expr, 'not ') - if isinstance(node.vhd, vhd_std_logic): - self.write("to_std_logic") - self.write("(not ") - self.visit(node.expr, context) - self.write(")") - - - - def visitAssAttr(self, node, *args): - assert node.attrname == 'next' - self.isSigAss = True - self.visit(node.expr) - node.obj = self.getObj(node.expr) - def visitAssert(self, node, *args): - # XXX - pass - - def visitAssign(self, node, *args): - assert len(node.nodes) == 1 - lhs = node.nodes[0] - rhs = node.expr - # shortcut for expansion of ROM in case statement - if isinstance(node.expr, astNode.Subscript) and \ - isinstance(node.expr.expr.obj, _Rom): - rom = node.expr.expr.obj.rom - self.write("case ") - self.visit(node.expr.subs[0]) - self.write(" is") - self.indent() - size = lhs.vhd.size - for i, n in enumerate(rom): - self.writeline() - if i == len(rom)-1: - self.write("when others => ") - else: - self.write("when %s => " % i) - self.visit(lhs) - if self.isSigAss: - self.write(' <= ') - self.isSigAss = False - else: - self.write(' := ') - if isinstance(lhs.vhd, vhd_std_logic): - self.write("'%s';" % n) - elif isinstance(lhs.vhd, vhd_int): - self.write("%s;" % n) - else: - self.write('"%s";' % bin(n, size)) - self.dedent() - self.writeline() - self.write("end case;") - return - # default behavior - convOpen, convClose = "", "" -## if isinstance(lhs.vhd, vhd_unsigned): -## if isinstance(rhs.vhd, vhd_unsigned) and \ -## (lhs.vhd.size == rhs.vhd.size): -## pass -## else: -## convOpen, convClose = "to_unsigned(", ", %s)" % lhs.vhd.size -## rhs.vhd = vhd_int() -## elif isinstance(lhs.vhd, vhd_signed): -## if isinstance(rhs.vhd, vhd_signed) and \ -## (lhs.vhd.size == rhs.vhd.size): -## pass -## else: -## convOpen, convClose = "to_signed(", ", %s)" % lhs.vhd.size -## rhs.vhd = vhd_int() -## elif isinstance(lhs.vhd, vhd_std_logic): -## rhs.vhd = vhd_std_logic() - if isinstance(lhs.vhd, vhd_type): - rhs.vhd = lhs.vhd - self.visit(node.nodes[0]) - if self.isSigAss: - self.write(' <= ') - self.isSigAss = False - else: - self.write(' := ') - self.write(convOpen) - # node.expr.target = obj = self.getObj(node.nodes[0]) - self.visit(node.expr) - self.write(convClose) - self.write(';') - - def visitAssName(self, node, *args): - self.write(node.name) - - def visitAugAssign(self, node, *args): - opmap = {"+=" : "+", - "-=" : "-", - "*=" : "*", - "//=" : "/", - "%=" : "%", - "**=" : "**", - "|=" : "|", - ">>=" : ">>>", - "<<=" : "<<", - "&=" : "&", - "^=" : "^" - } - if node.op not in opmap: - self.raiseError(node, _error.NotSupported, - "augmented assignment %s" % node.op) - op = opmap[node.op] - # XXX apparently no signed context required for augmented assigns - self.visit(node.node) - self.write(" := ") - self.visit(node.node) - self.write(" %s " % op) - self.visit(node.expr) - self.write(";") - - def visitBreak(self, node, *args): - # self.write("disable %s;" % self.labelStack[-2]) - self.write("exit;") - - def visitCallFunc(self, node, *args): - fn = node.node - assert isinstance(fn, astNode.Name) - f = self.getObj(fn) - opening, closing = '(', ')' - sep = ", " - if f is bool: - self.write("(") - arg = node.args[0] - self.visit(arg) - if isinstance(arg, vhd_std_logic): - test = "'0'" - else: - test = "0" - self.write(" /= %s)" % test) - # self.write(" ? 1'b1 : 1'b0)") - return - elif f is len: - val = self.getVal(node) - self.require(node, val is not None, "cannot calculate len") - self.write(`val`) - return - elif f in (int, long): - opening, closing = '', '' - elif f is intbv: - pre, post = "", "" - if isinstance(node.vhd, vhd_unsigned): - pre, post = "to_unsigned(", ", %s)" % node.vhd.size - elif isinstance(node.vhd, vhd_signed): - pre, post = "to_signed(", ", %s)" % node.vhd.size - self.write(pre) - self.visit(node.args[0]) - self.write(post) - return - elif type(f) is ClassType and issubclass(f, Exception): - self.write(f.__name__) - elif f in (posedge, negedge): - opening, closing = ' ', '' - self.write(f.__name__) - elif f is delay: - self.visit(node.args[0]) - self.write(" ns") - return - elif f is concat: - sep = " & " - elif hasattr(node, 'ast'): - self.write(node.ast.name) - else: - self.write(f.__name__) - if node.args: - self.write(opening) - self.visit(node.args[0], *args) - for arg in node.args[1:]: - self.write(sep) - self.visit(arg, *args) - self.write(closing) - if hasattr(node, 'ast'): - if node.ast.kind == _kind.TASK: - Visitor = _ConvertTaskVisitor - else: - Visitor = _ConvertFunctionVisitor - v = Visitor(node.ast, self.funcBuf) - compiler.walk(node.ast, v) - - def visitCompare(self, node, *args): - context = None - if node.signed: - context = _context.SIGNED - if isinstance(node.vhd, vhd_std_logic): - self.write("to_std_logic") - self.write("(") - self.visit(node.expr, context) - op, code = node.ops[0] - if op == "==": - op = "=" - elif op == "!=": - op = "/=" - self.write(" %s " % op) - self.visit(code, context) - self.write(")") - - def visitConst(self, node, context=None, *args): - if context == _context.PRINT: - self.write('"%s"' % node.value) - else: - if isinstance(node.vhd, vhd_std_logic): - self.write("'%s'" % node.value) -## elif target._type is intbv: -## self.write('"%s"' % bin(node.value, len(target))) - elif isinstance(node.vhd, vhd_boolean): - self.write("%s" % bool(node.value)) - elif isinstance(node.vhd, (vhd_unsigned, vhd_signed)): - self.write('"%s"' % bin(node.value, node.vhd.size)) - else: - self.write(node.value) - - def visitContinue(self, node, *args): - # self.write("next %s;" % self.labelStack[-1]) - self.write("next;") - - def visitDiscard(self, node, *args): - expr = node.expr - self.visit(expr) - # ugly hack to detect an orphan "task" call - if isinstance(expr, astNode.CallFunc) and hasattr(expr, 'ast'): - self.write(';') - - def visitFor(self, node, *args): - self.labelStack.append(node.breakLabel) - self.labelStack.append(node.loopLabel) - var = node.assign.name - cf = node.list - 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") - args = cf.args - assert len(args) <= 3 - if f is range: - cmp = '<' - op = 'to' - oneoff = '' - if len(args) == 1: - start, stop, step = None, args[0], None - elif len(args) == 2: - start, stop, step = args[0], args[1], None - else: - start, stop, step = args - else: # downrange - cmp = '>=' - op = 'downto' - oneoff ='-1' - if len(args) == 1: - start, stop, step = args[0], None, None - elif len(args) == 2: - start, stop, step = args[0], args[1], None - else: - start, stop, step = args - assert step is None - ## if node.breakLabel.isActive: -## self.write("begin: %s" % node.breakLabel) -## self.writeline() -## if node.loopLabel.isActive: -## self.write("%s: " % node.loopLabel) - self.write("for %s in " % var) - if start is None: - self.write("0") - else: - self.visit(start) - if f is downrange: - self.write("-1") - self.write(" %s " % op) - if stop is None: - self.write("0") - else: - self.visit(stop) - if f is range: - self.write("-1") - self.write(" loop") - self.indent() - self.visit(node.body) - self.dedent() - self.writeline() - self.write("end loop;") -## if node.breakLabel.isActive: -## self.writeline() -## self.write("end") - self.labelStack.pop() - self.labelStack.pop() - - def visitFunction(self, node, *args): - raise AssertionError("To be implemented in subclass") - - def visitGetattr(self, node, *args): - assert isinstance(node.expr, astNode.Name) - assert node.expr.name in self.ast.symdict - obj = self.ast.symdict[node.expr.name] - if isinstance(obj, Signal): - if node.attrname == 'next': - self.isSigAss = True - self.visit(node.expr) - elif node.attrname == 'posedge': - self.write("rising_edge(") - self.visit(node.expr) - self.write(")") - elif node.attrname == 'negedge': - self.write("falling_edge(") - self.visit(node.expr) - self.write(")") - else: - assert False - elif isinstance(obj, EnumType): - assert hasattr(obj, node.attrname) - e = getattr(obj, node.attrname) - self.write(e._toVHDL()) - - def visitIf(self, node, *args): - if node.ignore: - return - if node.isCase: - self.mapToCase(node, *args) - else: - self.mapToIf(node, *args) - - def mapToCase(self, node, *args): - var = node.caseVar - self.write("case ") - self.visit(var) - self.write(" is") - self.indent() - for test, suite in node.tests: - self.writeline() - item = test.ops[0][1].obj - self.write("when ") - self.write(item._toVHDL()) - self.write(" =>") - self.indent() - self.visit(suite) - self.dedent() - if node.else_: - self.writeline() - self.write("when others =>") - self.indent() - self.visit(node.else_) - self.dedent() - self.dedent() - self.writeline() - self.write("end case;") - - def mapToIf(self, node, *args): - first = True - for test, suite in node.tests: - if first: - ifstring = "if " - first = False - else: - ifstring = "elsif " - self.writeline() - self.write(ifstring) - self.visit(test, _context.BOOLEAN) - self.write(" then") - self.indent() - self.visit(suite) - self.dedent() - if node.else_: - self.writeline() - edges = self.getEdge(node.else_) - if edges is not None: - edgeTests = [e._toVHDL() for e in edges] - self.write("elsif ") - self.write("or ".join(edgeTests)) - self.write(" then") - else: - self.write("else") - self.indent() - self.visit(node.else_) - self.dedent() - self.writeline() - self.write("end if;") - - def visitKeyword(self, node, *args): - self.visit(node.expr) - - def visitModule(self, node, *args): - for stmt in node.node.nodes: - self.visit(stmt) - - def visitName(self, node, context=None, *args): - n = node.name - if n == 'False': - if isinstance(node.vhd, vhd_std_logic): - s = "'0'" - else: - s = "False" - elif n == 'True': - if isinstance(node.vhd, vhd_std_logic): - s = "'1'" - else: - s = "True" - elif n in self.ast.vardict: - s = n - obj = self.ast.vardict[n] - vhd = inferVhdlObj(obj) - if isinstance(vhd, vhd_unsigned): - if isinstance(node.vhd, vhd_int): - s = "to_integer(%s)" % n - elif isinstance(node.vhd, vhd_unsigned): - if vhd.size != node.vhd.size: - s = "resize(%s, %s)" % (n, node.vhd.size) - else: - raise NotImplementedError - - - elif isinstance(vhd, vhd_std_logic) and isinstance(node.vhd, vhd_boolean): - s = "(%s = '1')" % n - elif isinstance(vhd, vhd_int): - if isinstance(node.vhd, vhd_unsigned): - s = "to_unsigned(%s, %s)" % (n, node.vhd.size) - elif isinstance(node.vhd, vhd_signed): - s = "to_signed(%s, %s)" % (n, node.vhd.size) - - elif n in self.ast.argnames: - assert n in self.ast.symdict - obj = self.ast.symdict[n] - vhd = inferVhdlObj(obj) - if isinstance(vhd, vhd_std_logic) and isinstance(node.vhd, vhd_boolean): - s = "(%s = '1')" % n - else: - s = n - elif n in self.ast.symdict: - obj = self.ast.symdict[n] - s = n - if isinstance(obj, bool): - s = "'%s'" % int(obj) - elif isinstance(obj, (int, long)): - if isinstance(node.vhd, vhd_int): - s = "%s" % int(obj) - elif isinstance(node.vhd, vhd_std_logic): - s = "'%s'" % int(obj) - else: - s = '"%s"' % bin(obj, node.vhd.size) - elif isinstance(obj, Signal): - if context == _context.PRINT: - if obj._type is intbv: - s = "write(L, to_integer(%s))" % str(obj) - elif obj._type is bool: - s = "write(L, to_bit(%s))" % str(obj) - else: - typename = "UNDEF" - if isinstance(obj._val, EnumItemType): - typename = obj._val._type._name - s = "write(L, %s'image(%s))" % (typename, str(obj)) - else: - vhd = inferVhdlObj(obj) - n = s = str(obj) - if isinstance(vhd, vhd_unsigned): - if isinstance(node.vhd, vhd_int): - s = "to_integer(%s)" % n - elif isinstance(node.vhd, vhd_unsigned): - if vhd.size != node.vhd.size: - s = "resize(%s, %s)" % (n, node.vhd.size) - else: - raise NotImplementedError - - - elif isinstance(vhd, vhd_std_logic) and isinstance(node.vhd, vhd_boolean): - s = "(%s = '1')" % n - elif isinstance(vhd, vhd_int): - if isinstance(node.vhd, (vhd_unsigned, vhd_signed)): - s = "to_unsigned(%s, %s)" % (n, node.vhd.size) - elif isinstance(node.vhd, vhd_signed): - s = "to_signed(%s, %s)" % (n, node.vhd.size) - else: - raise NotImplementedError - else: - s = str(obj) - elif _isMem(obj): - m = _getMemInfo(obj) - assert m.name - if not m.decl: - self.raiseError(node, _error.ListElementNotUnique, m.name) - s = m.name - elif isinstance(obj, EnumItemType): - s = obj._toVHDL() - elif type(obj) is ClassType and issubclass(obj, Exception): - s = n - else: - self.raiseError(node, _error.UnsupportedType, "%s, %s" % (n, type(obj))) - else: - raise AssertionError("name ref: %s" % n) - self.write(s) - - def visitPass(self, node, *args): - self.write("null;") - - def handlePrint(self, node): - assert len(node.nodes) == 1 - s = node.nodes[0] - self.visit(s, _context.PRINT) - self.write(';') - self.writeline() - self.write("writeline(output, L);") - - - def visitPrint(self, node, *args): - self.handlePrint(node) - - def visitPrintnl(self, node, *args): - self.handlePrint(node) - - def visitRaise(self, node, *args): -# pass - self.write('assert False report "End of Simulation" severity Failure;') -## self.write('$display("') -## self.visit(node.expr1) -## self.write('");') -## self.writeline() -## self.write("$finish;") - - def visitReturn(self, node, *args): - self.write("disable %s;" % self.returnLabel) - - def visitSlice(self, node, context=None, *args): - if isinstance(node.expr, astNode.CallFunc) and \ - node.expr.node.obj is intbv: - c = self.getVal(node) - pre, post = "", "" - if isinstance(node.vhd, vhd_unsigned): - print "YES" - pre, post = "to_unsigned(", ", %s)" % node.vhd.size - elif isinstance(node.vhd, vhd_signed): - pre, post = "to_signed(", ", %s)" % node.vhd.size - self.write(pre) - self.write("%s" % c._val) - self.write(post) - return - self.visit(node.expr) - # special shortcut case for [:] slice - if node.lower is None and node.upper is None: - return - self.write("(") - if node.lower is None: - self.write("%s" % node.obj._nrbits) - else: - self.visit(node.lower) - self.write("-1 downto ") - if node.upper is None: - self.write("0") - else: - self.visit(node.upper) - self.write(")") - - def visitStmt(self, node, *args): - for stmt in node.nodes: - self.writeline() - self.visit(stmt) - # ugly hack to detect an orphan "task" call - if isinstance(stmt, astNode.CallFunc) and hasattr(stmt, 'ast'): - self.write(';') - - def visitSubscript(self, node, context=None, *args): - addSignBit = (node.flags == 'OP_APPLY') and (context == _context.SIGNED) - if addSignBit: - self.write("$signed({1'b0, ") - self.visit(node.expr) - self.write("(") - assert len(node.subs) == 1 - self.visit(node.subs[0]) - self.write(")") - if addSignBit: - self.write("})") - - def visitTuple(self, node, context=None, *args): - assert context != None - sep = ", " - tpl = node.nodes - self.visit(tpl[0]) - for elt in tpl[1:]: - self.write(sep) - self.visit(elt) - - def visitWhile(self, node, *args): - self.labelStack.append(node.breakLabel) - self.labelStack.append(node.loopLabel) - self.write("while ") - self.visit(node.test) - self.write(" loop") - self.indent() - self.visit(node.body) - self.dedent() - self.writeline() - self.write("end loop") - self.write(";") - self.labelStack.pop() - self.labelStack.pop() - - def visitYield(self, node, *args): - self.write("wait ") - yieldObj = self.getObj(node.value) - if isinstance(yieldObj, delay): - self.write("for ") - elif isinstance(yieldObj, _WaiterList): - self.write("until ") - else: - self.write("on ") - self.visit(node.value, _context.YIELD) - self.write(";") - - def manageEdges(self, ifnode, senslist): - """ Helper method to convert MyHDL style template into VHDL style""" - first = senslist[0] - if isinstance(first, _WaiterList): - bt = _WaiterList - elif isinstance(first, Signal): - bt = Signal - elif isinstance(first, delay): - bt = delay - assert bt - for e in senslist: - if not isinstance(e, bt): - self.raiseError(node, "base type error in sensitivity list") - if len(senslist) >= 2 and bt == _WaiterList: - # ifnode = node.code.nodes[0] - assert isinstance(ifnode, astNode.If) - asyncEdges = [] - for test, suite in ifnode.tests: - e = self.getEdge(test) - if e is None: - self.raiseError(ifnode, "no edge test") - asyncEdges.append(e) - if ifnode.else_ is None: - self.raiseError(ifnode, "no else test") - edges = [] - for s in senslist: - for e in asyncEdges: - if s is e: - break - else: - edges.append(s) - ifnode.else_.edge = edges - senslist = [s.sig for s in senslist] - return senslist - - -class _ConvertAlwaysVisitor(_ConvertVisitor): - - def __init__(self, ast, blockBuf, funcBuf): - _ConvertVisitor.__init__(self, ast, blockBuf) - self.funcBuf = funcBuf - - def visitFunction(self, node, *args): - w = node.code.nodes[-1] - assert isinstance(w.body.nodes[0], astNode.Yield) - sl = w.body.nodes[0].value - senslist = w.body.nodes[0].senslist - senslist = self.manageEdges(w.body.nodes[1], senslist) - singleEdge = (len(senslist) == 1) and isinstance(senslist[0], _WaiterList) - self.write("%s: process (" % self.ast.name) - if singleEdge: - self.write(senslist[0].sig) - else: - for e in senslist[:-1]: - self.write(e) - self.write(', ') - self.write(senslist[-1]) - self.write(") is") - self.indent() - self.writeDeclarations() - self.dedent() - self.writeline() - self.write("begin") - self.indent() - if singleEdge: - self.writeline() - self.write("if %s then" % senslist[0]._toVHDL()) - self.indent() - assert isinstance(w.body, astNode.Stmt) - for stmt in w.body.nodes[1:]: - self.writeline() - self.visit(stmt) - self.dedent() - if singleEdge: - self.writeline() - self.write("end if;") - self.dedent() - self.writeline() - self.write("end process %s;" % self.ast.name) - self.writeline(2) - - -class _ConvertInitialVisitor(_ConvertVisitor): - - def __init__(self, ast, blockBuf, funcBuf): - _ConvertVisitor.__init__(self, ast, blockBuf) - self.funcBuf = funcBuf - - def visitFunction(self, node, *args): - self.write("%s: process is" % self.ast.name) - self.indent() - self.writeDeclarations() - self.dedent() - self.writeline() - self.write("begin") - self.indent() - self.visit(node.code) - self.writeline() - self.write("wait;") - self.dedent() - self.writeline() - self.write("end process %s;" % self.ast.name) - self.writeline(2) - - -class _ConvertAlwaysCombVisitor(_ConvertVisitor): - - def __init__(self, ast, blockBuf, funcBuf): - _ConvertVisitor.__init__(self, ast, blockBuf) - self.funcBuf = funcBuf - - def visitFunction(self, node, *args): - senslist = self.ast.senslist - self.write("%s: process (" % self.ast.name) - for e in senslist[:-1]: - self.write(e) - self.write(', ') - self.write(senslist[-1]) - self.write(") is") - self.indent() - self.writeDeclarations() - self.dedent() - self.writeline() - self.write("begin") - self.indent() - self.visit(node.code) - self.dedent() - self.writeline() - self.write("end process %s;" % self.ast.name) - self.writeline(2) - - -class _ConvertSimpleAlwaysCombVisitor(_ConvertVisitor): - - def __init__(self, ast, blockBuf, funcBuf): - _ConvertVisitor.__init__(self, ast, blockBuf) - self.funcBuf = funcBuf - - def visitAssAttr(self, node, *args): - self.write("assign ") - self.visit(node.expr) - - def visitFunction(self, node, *args): - self.visit(node.code) - self.writeline(2) - - - -class _ConvertAlwaysDecoVisitor(_ConvertVisitor): - - def __init__(self, ast, blockBuf, funcBuf): - _ConvertVisitor.__init__(self, ast, blockBuf) - self.funcBuf = funcBuf - - def visitFunction(self, node, *args): - assert self.ast.senslist - senslist = self.ast.senslist - senslist = self.manageEdges(node.code.nodes[0], senslist) -## first = senslist[0] -## if isinstance(first, _WaiterList): -## bt = _WaiterList -## elif isinstance(first, Signal): -## bt = Signal -## elif isinstance(first, delay): -## bt = delay -## assert bt -## for e in senslist: -## if not isinstance(e, bt): -## self.raiseError(node, "base type error in sensitivity list") -## if len(senslist) >= 2 and bt == _WaiterList: -## ifnode = node.code.nodes[0] -## assert isinstance(ifnode, astNode.If) -## asyncEdges = [] -## for test, suite in ifnode.tests: -## e = self.getEdge(test) -## if e is None: -## self.raiseError(node, "no edge test") -## asyncEdges.append(e) -## if ifnode.else_ is None: -## self.raiseError(node, "no else test") -## edges = [] -## for s in senslist: -## for e in asyncEdges: -## if s is e: -## break -## else: -## edges.append(s) -## ifnode.else_.edge = edges -## senslist = [s.sig for s in senslist] - singleEdge = (len(senslist) == 1) and isinstance(senslist[0], _WaiterList) - self.write("%s: process (" % self.ast.name) - if singleEdge: - self.write(senslist[0].sig) - else: - for e in senslist[:-1]: - self.write(e) - self.write(', ') - self.write(senslist[-1]) - self.indent() - self.writeDeclarations() - self.dedent() - self.write(") is") - self.writeline() - self.write("begin") - self.indent() - if singleEdge: - self.writeline() - self.write("if %s then" % senslist[0]._toVHDL()) - self.indent() - self.visit(node.code) - self.dedent() - if singleEdge: - self.writeline() - self.write("end if;") - self.dedent() - self.writeline() - self.write("end process %s;" % self.ast.name) - self.writeline(2) - - -class _ConvertFunctionVisitor(_ConvertVisitor): - - def __init__(self, ast, funcBuf): - _ConvertVisitor.__init__(self, ast, funcBuf) - self.returnObj = ast.returnObj - self.returnLabel = _Label("RETURN") - - def writeOutputDeclaration(self): - self.write(self.ast.vhd.toStr(constr=False)) - - def writeInputDeclarations(self): - endchar = "" - for name in self.ast.argnames: - self.write(endchar) - enchar = ";" - obj = self.ast.symdict[name] - self.writeline() - self.writeDeclaration(obj, name, dir="in", constr=False, endchar="") - - def visitFunction(self, node, *args): - self.write("function %s(" % self.ast.name) - self.indent() - self.writeInputDeclarations() - self.writeline() - self.write(") return ") - self.writeOutputDeclaration() - self.write(" is") - self.writeDeclarations() - self.dedent() - self.writeline() - self.write("begin") - self.indent() - self.visit(node.code) - self.dedent() - self.writeline() - self.write("end function %s;" % self.ast.name) - self.writeline(2) - - def visitReturn(self, node, *args): - self.write("return ") - self.visit(node.value) - self.write(";") - - -class _ConvertTaskVisitor(_ConvertVisitor): - - def __init__(self, ast, funcBuf): - _ConvertVisitor.__init__(self, ast, funcBuf) - self.returnLabel = _Label("RETURN") - - def writeInterfaceDeclarations(self): - endchar = "" - for name in self.ast.argnames: - self.write(endchar) - endchar = ";" - obj = self.ast.symdict[name] - output = name in self.ast.outputs - input = name in self.ast.inputs - inout = input and output - dir = (inout and "inout") or (output and "out") or "in" - self.writeline() - self.writeDeclaration(obj, name, dir=dir, constr=False, endchar="") - - def visitFunction(self, node, *args): - self.write("procedure %s" % self.ast.name) - if self.ast.argnames: - self.write("(") - self.indent() - self.writeInterfaceDeclarations() - self.write(") ") - self.write("is") - self.writeDeclarations() - self.dedent() - self.writeline() - self.write("begin") - self.indent() - t = node.code.nodes[0].tests[0][0] - self.visit(node.code) - self.dedent() - self.writeline() - self.write("end procedure %s;" % self.ast.name) - self.writeline(2) - - -class vhd_type(object): - def __init__(self, size=0): - self.size = size - -class vhd_std_logic(vhd_type): - def __init__(self, size=0): - self.size = 1 - def toStr(self, constr=True): - return 'std_logic' - -class vhd_boolean(vhd_type): - def __init__(self, size=0): - self.size = 1 - def toStr(self, constr=True): - return 'boolean' - -class vhd_unsigned(vhd_type): - def toStr(self, constr=True): - if constr: - return "unsigned(%s downto 0)" % (self.size-1) - else: - return "unsigned" - -class vhd_signed(vhd_type): - def toStr(self, constr=True): - if constr: - return "signed(%s downto 0)" % (self.size-1) - else: - return "signed" - -class vhd_int(vhd_type): - def toStr(self, constr=True): - return "integer" - -class _loopInt(int): - pass - -def maxType(o1, o2): - s1 = s2 = 0 - if isinstance(o1, vhd_type): - s1 = o1.size - if isinstance(o2, vhd_type): - s2 = o2.size - s = max(s1, s2) - if isinstance(o1, vhd_signed) or isinstance(o2, vhd_signed): - return vhd_signed(s) - elif isinstance(o1, vhd_unsigned) or isinstance(o2, vhd_unsigned): - return vhd_unsigned(s) - elif isinstance(o1, vhd_std_logic) or isinstance(o2, vhd_std_logic): - return vhd_std_logic() - elif isinstance(o1, vhd_int) or isinstance(o2, vhd_int): - return vhd_int() - else: - return None - -def inferVhdlObj(obj): - vhd = None - if (isinstance(obj, Signal) and obj._type is intbv) or \ - isinstance(obj, intbv): - if obj.min < 0: - vhd = vhd_signed(len(obj)) - else: - vhd = vhd_unsigned(len(obj)) - elif (isinstance(obj, Signal) and obj._type is bool) or \ - isinstance(obj, bool): - vhd = vhd_std_logic() - elif isinstance(obj, (int, long)): - vhd = vhd_int() - return vhd - - -class _AnnotateTypesVisitor(_ConversionMixin): - - def __init__(self, ast): - self.ast = ast - - def visitAssAttr(self, node): - self.visit(node.expr) - node.vhd = node.expr.vhd - - def visitCallFunc(self, node, *args): - fn = node.node - assert isinstance(fn, astNode.Name) - f = self.getObj(fn) - node.vhd = inferVhdlObj(node.obj) - self.visitChildNodes(node) - if f is concat: - s = 0 - for a in node.args: - s += a.vhd.size - node.vhd = vhd_unsigned(s) - elif f is int: - node.vhd = vhd_int() - node.args[0].vhd = vhd_int() - elif f is intbv: - node.vhd = vhd_int() - elif f is len: - node.vhd = vhd_int() - elif hasattr(node, 'ast'): - v = _AnnotateTypesVisitor(node.ast) - compiler.walk(node.ast, v) - node.vhd = node.ast.vhd = inferVhdlObj(node.ast.returnObj) - - def visitCompare(self, node): - node.vhd = vhd_boolean() - self.visitChildNodes(node) - expr = node.expr - op, code = node.ops[0] - o = maxType(expr.vhd, code.vhd) - if isinstance(o, vhd_std_logic): - expr.vhd = code.vhd = o - - def visitConst(self, node): - node.vhd = vhd_int() - - def visitFor(self, node): - self.visitChildNodes(node) - var = node.assign.name - # make it possible to detect loop variable - self.ast.vardict[var] = _loopInt() - - def visitGetattr(self, node): - self.visitChildNodes(node) - node.vhd = node.expr.vhd - - def visitName(self, node): - node.vhd = inferVhdlObj(node.obj) - - # visitAssName = visitName - def visitAssName(self, node): - node.obj = self.ast.vardict[node.name] - self.visitName(node) - - - def binaryOp(self, node, op=None): - self.visit(node.left) - self.visit(node.right) - r = node.right.vhd - l = node.left.vhd - if op in ('+', '-', '%'): - s = max(l.size, r.size) - elif op in ('*',): - s = l.size + r.size - if isinstance(r, vhd_int) and isinstance(l, vhd_int): - node.vhd = vhd_int() - elif isinstance(r, (vhd_signed, vhd_int)) and isinstance(l, (vhd_signed, vhd_int)): - node.vhd = vhd_signed(max(l.size, r.size)) - elif isinstance(r, (vhd_unsigned, vhd_int)) and isinstance(l, (vhd_unsigned, vhd_int)): - node.vhd = vhd_unsigned(max(l.size, r.size)) - else: - node.vhd = vhd_int() - - def visitAdd(self, node): - self.binaryOp(node, op='+') - def visitSub(self, node): - self.binaryOp(node, op='-') - def visitMod(self, node): - self.binaryOp(node, op='%') - def visitMul(self, node): - self.binaryOp(node, op='+') - - - def multiBitOp(self, node): - self.visitChildNodes(node) - o = None - for n in node.nodes: - o = maxType(o, n.vhd) - for n in node.nodes: - n.vhd = o - node.vhd = o - visitBitand = visitBitor = visitBitxor = multiBitOp - - def multiBoolOp(self, node): - self.visitChildNodes(node) - for n in node.nodes: - n.vhd = vhd_boolean() - node.vhd = vhd_boolean() - visitAnd = visitOr = multiBoolOp - - def visitNot(self, node): - self.visit(node.expr) - node.vhd = node.expr.vhd = vhd_boolean() - - def visitIf(self, node): - self.visitChildNodes(node) - for test, suite in node.tests: - test.vhd = vhd_boolean() - - def shift(self, node): - self.visitChildNodes(node) - node.vhd = node.left.vhd - node.right.vhd = vhd_int() - visitRightShift = visitLeftShift = shift - - def visitSlice(self, node): - self.visitChildNodes(node) - lower = 0 - t = vhd_unsigned - if hasattr(node.expr, 'vhd'): - lower = node.expr.vhd.size - t = type(node.expr.vhd) - if node.lower: - lower = self.getVal(node.lower) - upper = 0 - if node.upper: - upper = self.getVal(node.upper) - node.vhd = t(lower-upper) - - def visitSubscript(self, node): - self.visitChildNodes(node) - node.vhd = vhd_std_logic() - - def unaryOp(self, node): - self.visit(node.expr) - node.vhd = node.expr.vhd - - visitUnaryAdd = visitUnarySub = unaryOp - - def visitWhile(self, node): - self.visitChildNodes(node) - node.test.vhd = vhd_boolean() - - - - -def _annotateTypes(genlist): - for ast in genlist: - v = _AnnotateTypesVisitor(ast) - compiler.walk(ast, v) - - - diff --git a/myhdl/_toVerilog/__init__.py b/myhdl/_toVerilog/__init__.py deleted file mode 100644 index 6c502440..00000000 --- a/myhdl/_toVerilog/__init__.py +++ /dev/null @@ -1,148 +0,0 @@ -# This file is part of the myhdl library, a Python package for using -# Python as a Hardware Description Language. -# -# Copyright (C) 2003 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 package. - -""" - -__author__ = "Jan Decaluwe " -__revision__ = "$Revision$" -__date__ = "$Date$" - -import inspect -from compiler import ast as astNode - -import myhdl -from myhdl import * -from myhdl import ConversionError -from myhdl._util import _flatten -from myhdl._unparse import _unparse - -class _error: - pass -_error.FirstArgType = "first argument should be a classic function" -_error.ArgType = "leaf cell type error" -_error.NotSupported = "Not supported" -_error.TopLevelName = "Result of toVerilog call should be assigned to a top level name" -_error.SigMultipleDriven = "Signal has multiple drivers" -_error.UndefinedBitWidth = "Signal has undefined bit width" -_error.UndrivenSignal = "Signal is not driven" -_error.UnusedSignal = "Signal is driven but not used" -_error.Requirement = "Requirement violation" -_error.UnboundLocal = "Local variable may be referenced before assignment" -_error.TypeMismatch = "Type mismatch with earlier assignment" -_error.NrBitsMismatch = "Nr of bits mismatch with earlier assignment" -_error.IntbvBitWidth = "intbv should have bit width" -_error.IntbvSign = "intbv's that can have negative values are not yet supported" -_error.TypeInfer = "Can't infer variable type" -_error.ReturnTypeMismatch = "Return type mismatch" -_error.ReturnNrBitsMismatch = "Returned nr of bits mismatch" -_error.ReturnIntbvBitWidth = "Returned intbv instance should have bit width" -_error.ReturnTypeInfer = "Can't infer return type" -_error.ShadowingSignal = "Port is shadowed by internal signal" -_error.FreeVarTypeError = "Free variable should be a Signal or an int" -_error.ExtraArguments = "Extra positional or named arguments are not supported" -_error.UnsupportedYield = "Unsupported yield statement" -_error.UnsupportedListComp = \ - "Unsupported list comprehension form: should be [intbv()[n:] for i in range(m)]" -_error.ListElementAssign = \ - "Can't assign to list element; use slice assignment to change its value" -_error.NotASignal = "Non-local object should be a Signal" -_error.UnsupportedType = "Object type is not supported in this context" -_error.InconsistentType = "Signal elements should have the same base type" -_error.InconsistentBitWidth = "Signal elements should have the same bit width" -_error.ListElementNotUnique = "List contains Signals that are not unique to it" - - -_access = enum("INPUT", "OUTPUT", "INOUT", "UNKNOWN") -_kind = enum("NORMAL", "DECLARATION", "ALWAYS", "INITIAL", "ALWAYS_COMB", "SIMPLE_ALWAYS_COMB", "ALWAYS_DECO", "TASK", "REG") -_context = enum("BOOLEAN", "YIELD", "PRINT" ,"SIGNED", "UNKNOWN") - - -class _ConversionMixin(object): - - def getLineNo(self, node): - lineno = node.lineno - if lineno is None: - for n in node.getChildNodes(): - if n.lineno is not None: - lineno = n.lineno - break - lineno = lineno or 0 - return lineno - - def getObj(self, node): - if hasattr(node, 'obj'): - return node.obj - return None - - def getTarget(self, node): - if hasattr(node, 'target'): - return node.target - return None - - def getKind(self, node): - if hasattr(node, 'kind'): - return node.kind - return None - - def getEdge(self, node): - if hasattr(node, 'edge'): - return node.edge - return None - - def getValue(self, node): - if hasattr(node, 'value'): - return node.value - return None - - def getVal(self, node): - val = eval(_unparse(node), self.ast.symdict) - return val - - def raiseError(self, node, kind, msg=""): - lineno = self.getLineNo(node) - info = "in file %s, line %s:\n " % \ - (self.ast.sourcefile, self.ast.lineoffset+lineno) - raise ConversionError(kind, msg, info) - - def require(self, node, test, msg=""): - assert isinstance(node, astNode.Node) - if not test: - self.raiseError(node, _error.Requirement, msg) - - def visitChildNodes(self, node, *args): - for n in node.getChildNodes(): - self.visit(n, *args) - - -def _LabelGenerator(): - i = 1 - while 1: - yield "MYHDL%s" % i - i += 1 - -_genLabel = _LabelGenerator() - -class _Label(object): - def __init__(self, name): - self.name = _genLabel.next() + '_' + name - self.isActive = False - def __str__(self): - return str(self.name) diff --git a/myhdl/_toVerilog/_analyze.py b/myhdl/_toVerilog/_analyze.py deleted file mode 100644 index fb25857f..00000000 --- a/myhdl/_toVerilog/_analyze.py +++ /dev/null @@ -1,987 +0,0 @@ -# This file is part of the myhdl library, a Python package for using -# Python as a Hardware Description Language. -# -# Copyright (C) 2003 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. - -""" - -__author__ = "Jan Decaluwe " -__revision__ = "$Revision$" -__date__ = "$Date$" - -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 __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._toVerilog import _error, _access, _kind, _context, \ - _ConversionMixin, _Label -from myhdl._extractHierarchy import _isMem, _UserDefinedVerilog -from myhdl._Signal import _WaiterList - -myhdlObjects = myhdl.__dict__.values() -builtinObjects = __builtin__.__dict__.values() - - -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): - curlevel = 0 - siglist = [] - memlist = [] - prefixes = [] - - 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; such a list - # is not declared and references to it in a generator will be flagged as an error - for m in memlist: - for s in m.mem: - if s._name is not None: - m.decl = False - break - if not m.decl: - continue - for i, s in enumerate(m.mem): - s._name = "%s[%s]" % (m.name, i) - 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, _UserDefinedVerilog): - 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): - 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: - f = g.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) - - visitPrint = visitPrintnl - - -def isTupleOfInts(obj): - if not isinstance(obj, tuple): - return False - for e in obj: - if not isinstance(e, (int, long)): - return False - return True - -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 _isNegative(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 _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() - 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() - node.signed = node.expr.signed - def visitUnaryAdd(self, node, *args): - self.visit(node.expr) - node.obj = int() - node.signed = node.expr.signed - def visitUnarySub(self, node, *args): - self.visit(node.expr) - node.obj = int() - 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 - 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 == "__verilog__": - self.raiseError(node, _error.NotSupported, - "__verilog__ in generator function") - # 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 len: - node.obj = int() # XXX - elif f is bool: - node.obj = bool() - elif f is int: - node.obj = int() -## elif f in (posedge , negedge): -## node.obj = _EdgeDetector() - elif f is delay: - node.obj = delay(0) - 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): - 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() - self.visit(node.list) - 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) - assert isinstance(node.expr, astNode.Name) - assert node.expr.name in self.ast.symdict - node.obj = None - node.signed = False - obj = self.ast.symdict[node.expr.name] - if isinstance(obj, Signal): - if node.attrname == 'posedge': - node.obj = obj.posedge - elif node.attrname == 'negedge': - node.obj = obj.negedge - elif node.attrname == 'val': - node.obj = obj.val - elif isinstance(obj, EnumType): - assert hasattr(obj, node.attrname) - node.obj = getattr(obj, 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 - 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() - 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 = _isNegative(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 - 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): - node.signed = False - 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 isinstance(node.expr.obj, _Rom): - node.obj = int() - elif isinstance(node.expr.obj, intbv): - node.obj = bool() - else: - node.obj = bool() # XXX default - - 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 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.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) - else: - if not isinstance(n.obj, (Signal, _WaiterList, delay)): - self.raiseError(node, _error.UnsupportedYield) - senslist = [n.obj] - 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] - - diff --git a/myhdl/_toVerilog/_convert.py b/myhdl/_toVerilog/_convert.py deleted file mode 100644 index fa946944..00000000 --- a/myhdl/_toVerilog/_convert.py +++ /dev/null @@ -1,1078 +0,0 @@ -# This file is part of the myhdl library, a Python package for using -# Python as a Hardware Description Language. -# -# Copyright (C) 2003 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 conversion module. - -""" - -__author__ = "Jan Decaluwe " -__revision__ = "$Revision$" -__date__ = "$Date$" - -import sys -import math -import traceback -import inspect -import compiler -from compiler import ast as astNode -from sets import Set -from types import GeneratorType, FunctionType, ClassType -from cStringIO import StringIO -import __builtin__ -import warnings - -import myhdl -from myhdl import * -from myhdl import ToVerilogError, ToVerilogWarning -from myhdl._extractHierarchy import _HierExtr, _isMem, _getMemInfo, \ - _UserDefinedVerilog, _userDefinedVerilogMap - -from myhdl._always_comb import _AlwaysComb -from myhdl._always import _Always -from myhdl._toVerilog import _error, _access, _kind,_context, \ - _ConversionMixin, _Label -from myhdl._toVerilog._analyze import _analyzeSigs, _analyzeGens, _analyzeTopFunc, \ - _Ram, _Rom - -_converting = 0 -_profileFunc = None - -def _checkArgs(arglist): - for arg in arglist: - if not type(arg) in (GeneratorType, _AlwaysComb, _Always, _UserDefinedVerilog): - raise ToVerilogError(_error.ArgType, arg) - -def _flatten(*args): - arglist = [] - for arg in args: - if id(arg) in _userDefinedVerilogMap: - arglist.append(_userDefinedVerilogMap[id(arg)]) - elif isinstance(arg, (list, tuple, Set)): - for item in arg: - arglist.extend(_flatten(item)) - else: - arglist.append(arg) - return arglist - - -class _ToVerilogConvertor(object): - - __slots__ = ("name", ) - - def __init__(self): - self.name = None - - def __call__(self, func, *args, **kwargs): - global _converting - if _converting: - return func(*args, **kwargs) # skip - else: - # clean start - sys.setprofile(None) - from myhdl import _traceSignals - if _traceSignals._tracing: - raise ToVerilogError("Cannot use toVerilog while tracing signals") - if not callable(func): - raise ToVerilogError(_error.FirstArgType, "got %s" % type(func)) - - _converting = 1 - if self.name is None: - name = func.func_name - else: - name = str(self.name) - try: - h = _HierExtr(name, func, *args, **kwargs) - finally: - _converting = 0 - - vpath = name + ".v" - vfile = open(vpath, 'w') - tbpath = "tb_" + vpath - tbfile = open(tbpath, 'w') - - siglist, memlist = _analyzeSigs(h.hierarchy) - arglist = _flatten(h.top) - # print h.top - _checkArgs(arglist) - genlist = _analyzeGens(arglist, h.absnames) - intf = _analyzeTopFunc(func, *args, **kwargs) - intf.name = name - - _writeModuleHeader(vfile, intf) - _writeSigDecls(vfile, intf, siglist, memlist) - _convertGens(genlist, vfile) - _writeModuleFooter(vfile) - _writeTestBench(tbfile, intf) - - vfile.close() - tbfile.close() - - # clean up signal names - for sig in siglist: - sig._name = None - sig._driven = False - sig._read = False - - return h.top - - -toVerilog = _ToVerilogConvertor() - - -def _writeModuleHeader(f, intf): - print >> f, "module %s (" % intf.name - b = StringIO() - for portname in intf.argnames: - print >> b, " %s," % portname - print >> f, b.getvalue()[:-2] - b.close() - print >> f, ");" - print >> f - for portname in intf.argnames: - s = intf.argdict[portname] - if s._name is None: - raise ToVerilogError(_error.ShadowingSignal, portname) - # make sure signal name is equal to its port name - s._name = portname - r = _getRangeString(s) - p = _getSignString(s) - if s._driven: - print >> f, "output %s%s%s;" % (p, r, portname) - if s._driven == 'reg': - print >> f, "reg %s%s%s;" % (p, r, portname) - else: - print >> f, "wire %s%s%s;" % (p, r, portname) - else: - print >> f, "input %s%s%s;" % (p, r, portname) - print >> f - - -def _writeSigDecls(f, intf, siglist, memlist): - constwires = [] - for s in siglist: - if s._name in intf.argnames: - continue - r = _getRangeString(s) - p = _getSignString(s) - if s._driven: - if not s._read: - warnings.warn("%s: %s" % (_error.UnusedSignal, s._name), - category=ToVerilogWarning - ) - # the following line implements initial value assignments - # print >> f, "%s %s%s = %s;" % (s._driven, r, s._name, int(s._val)) - print >> f, "%s %s%s%s;" % (s._driven, p, r, s._name) - elif s._read: - # the original exception - # raise ToVerilogError(_error.UndrivenSignal, s._name) - # changed to a warning and a continuous assignment to a wire - warnings.warn("%s: %s" % (_error.UndrivenSignal, s._name), - category=ToVerilogWarning - ) - constwires.append(s) - print >> f, "wire %s%s;" % (r, s._name) - print >> f - for m in memlist: - if not m.decl: - continue - r = _getRangeString(m.elObj) - print >> f, "reg %s%s [0:%s-1];" % (r, m.name, m.depth) - print >> f - for s in constwires: - print >> f, "assign %s = %s;" % (s._name, int(s._val)) - - -def _writeModuleFooter(f): - print >> f, "endmodule" - - -def _writeTestBench(f, intf): - print >> f, "module tb_%s;" % intf.name - print >> f - fr = StringIO() - to = StringIO() - pm = StringIO() - for portname in intf.argnames: - s = intf.argdict[portname] - r = _getRangeString(s) - if s._driven: - print >> f, "wire %s%s;" % (r, portname) - print >> to, " %s," % portname - else: - print >> f, "reg %s%s;" % (r, portname) - print >> fr, " %s," % portname - print >> pm, " %s," % portname - print >> f - print >> f, "initial begin" - if fr.getvalue(): - print >> f, " $from_myhdl(" - print >> f, fr.getvalue()[:-2] - print >> f, " );" - if to.getvalue(): - print >> f, " $to_myhdl(" - print >> f, to.getvalue()[:-2] - print >> f, " );" - print >> f, "end" - print >> f - print >> f, "%s dut(" % intf.name - print >> f, pm.getvalue()[:-2] - print >> f, ");" - print >> f - print >> f, "endmodule" - - -def _getRangeString(s): - if s._type is bool: - return '' - elif s._nrbits is not None: - nrbits = s._nrbits - return "[%s:0] " % (nrbits-1) - else: - raise AssertionError - -def _getSignString(s): - if s._min is not None and s._min < 0: - return "signed " - else: - return '' - - -def _convertGens(genlist, vfile): - blockBuf = StringIO() - funcBuf = StringIO() - for ast in genlist: - if isinstance(ast, _UserDefinedVerilog): - blockBuf.write(str(ast)) - continue - if ast.kind == _kind.ALWAYS: - Visitor = _ConvertAlwaysVisitor - elif ast.kind == _kind.INITIAL: - Visitor = _ConvertInitialVisitor - elif ast.kind == _kind.SIMPLE_ALWAYS_COMB: - Visitor = _ConvertSimpleAlwaysCombVisitor - elif ast.kind == _kind.ALWAYS_DECO: - Visitor = _ConvertAlwaysDecoVisitor - else: # ALWAYS_COMB - Visitor = _ConvertAlwaysCombVisitor - v = Visitor(ast, blockBuf, funcBuf) - compiler.walk(ast, v) - vfile.write(funcBuf.getvalue()); funcBuf.close() - vfile.write(blockBuf.getvalue()); blockBuf.close() - -class _ConvertVisitor(_ConversionMixin): - - def __init__(self, ast, buf): - self.ast = ast - self.buf = buf - self.returnLabel = ast.name - self.ind = '' - self.isSigAss = False - self.labelStack = [] - - def raiseError(self, node, kind, msg=""): - lineno = self.getLineNo(node) - info = "in file %s, line %s:\n " % \ - (self.ast.sourcefile, self.ast.lineoffset+lineno) - raise ToVerilogError(kind, msg, info) - - def write(self, arg): - self.buf.write("%s" % arg) - - def writeline(self, nr=1): - for i in range(nr): - self.buf.write("\n%s" % self.ind) - - def writeIntSize(self, n): - # write size for large integers (beyond 32 bits signed) - # with some safety margin - if n >= 2**30: - size = int(math.ceil(math.log(n+1,2))) + 1 # sign bit! - self.write("%s'sd" % size) - - def writeDeclaration(self, obj, name, dir): - if dir: dir = dir + ' ' - if type(obj) is bool: - self.write("%s%s" % (dir, name)) - elif isinstance(obj, int): - if dir == "input ": - self.write("input %s;" % name) - self.writeline() - self.write("integer %s" % name) - elif isinstance(obj, _Ram): - self.write("reg [%s-1:0] %s [0:%s-1]" % (obj.elObj._nrbits, name, obj.depth)) - elif hasattr(obj, '_nrbits'): - s = "" - if isinstance(obj, (intbv, Signal)): - if obj._min is not None and obj._min < 0: - s = "signed " - self.write("%s%s[%s-1:0] %s" % (dir, s, obj._nrbits, name)) - else: - raise AssertionError("var %s has unexpected type %s" % (name, type(obj))) - # initialize regs - # if dir == 'reg ' and not isinstance(obj, _Ram): - # disable for cver - if False: - if isinstance(obj, EnumItemType): - inival = obj._toVerilog() - else: - inival = int(obj) - self.write(" = %s;" % inival) - else: - self.write(";") - - - def writeDeclarations(self): - for name, obj in self.ast.vardict.items(): - self.writeline() - self.writeDeclaration(obj, name, "reg") - - def indent(self): - self.ind += ' ' * 4 - - def dedent(self): - self.ind = self.ind[:-4] - - def binaryOp(self, node, op=None): - context = None - if node.signed: - context = _context.SIGNED - self.write("(") - self.visit(node.left, context) - self.write(" %s " % op) - self.visit(node.right, context) - self.write(")") - def visitAdd(self, node, *args): - self.binaryOp(node, '+') - def visitFloorDiv(self, node, *args): - self.binaryOp(node, '/') - def visitLeftShift(self, node, *args): - self.binaryOp(node, '<<') - def visitMod(self, node, context=None, *args): - if context == _context.PRINT: - self.visit(node.left, _context.PRINT) - self.write(", ") - self.visit(node.right, _context.PRINT) - else: - self.binaryOp(node, '%') - def visitMul(self, node, *args): - self.binaryOp(node, '*') - def visitPower(self, node, *args): - self.binaryOp(node, '**') - def visitSub(self, node, *args): - self.binaryOp(node, "-") - def visitRightShift(self, node, *args): - # Additional cast to signed of the full expression - # this is apparently required by cver - not sure if it - # is actually required by standard Verilog. - # It shouldn't hurt however. - if node.signed: - self.write("$signed") - self.binaryOp(node, '>>>') - - def checkOpWithNegIntbv(self, node, op): - if op in ("+", "-", "*", "&&", "||", "!"): - return - if isinstance(node, astNode.Name): - o = node.obj - if isinstance(o, (Signal, intbv)) and o.min is not None and o.min < 0: - self.raiseError(node, _error.NotSupported, - "negative intbv with operator %s" % op) - - def multiOp(self, node, op): - for n in node.nodes: - self.checkOpWithNegIntbv(n, op) - self.write("(") - self.visit(node.nodes[0]) - for n in node.nodes[1:]: - self.write(" %s " % op) - self.visit(n) - self.write(")") - def visitAnd(self, node, *args): - self.multiOp(node, '&&') - def visitBitand(self, node, *args): - self.multiOp(node, '&') - def visitBitor(self, node, *args): - self.multiOp(node, '|') - def visitBitxor(self, node, *args): - self.multiOp(node, '^') - def visitOr(self, node, *args): - self.multiOp(node, '||') - - def unaryOp(self, node, op, context): - self.checkOpWithNegIntbv(node.expr, op) - self.write("(%s" % op) - self.visit(node.expr, context) - self.write(")") - def visitInvert(self, node, context=None, *args): - self.unaryOp(node, '~', context) - def visitNot(self, node, context=None, *args): - self.unaryOp(node, '!', context) - def visitUnaryAdd(self, node, context=None, *args): - self.unaryOp(node, '+', context) - def visitUnarySub(self, node, context=None, *args): - self.unaryOp(node, '-', context) - - def visitAssAttr(self, node, *args): - assert node.attrname == 'next' - self.isSigAss = True - self.visit(node.expr) - - def visitAssert(self, node, *args): - # XXX - pass - - def visitAssign(self, node, *args): - assert len(node.nodes) == 1 - # shortcut for expansion of ROM in case statement - if isinstance(node.expr, astNode.Subscript) and \ - isinstance(node.expr.expr.obj, _Rom): - rom = node.expr.expr.obj.rom - self.write("// synthesis parallel_case full_case") - self.writeline() - self.write("case (") - self.visit(node.expr.subs[0]) - self.write(")") - self.indent() - for i, n in enumerate(rom): - self.writeline() - if i == len(rom)-1: - self.write("default: ") - else: - self.write("%s: " % i) - self.visit(node.nodes[0]) - if self.isSigAss: - self.write(' <= ') - self.isSigAss = False - else: - self.write(' = ') - self.writeIntSize(n) - self.write("%s;" % n) - self.dedent() - self.writeline() - self.write("endcase") - return - # default behavior - self.visit(node.nodes[0]) - if self.isSigAss: - self.write(' <= ') - self.isSigAss = False - else: - self.write(' = ') - self.visit(node.expr) - self.write(';') - - def visitAssName(self, node, *args): - self.write(node.name) - - def visitAugAssign(self, node, *args): - opmap = {"+=" : "+", - "-=" : "-", - "*=" : "*", - "//=" : "/", - "%=" : "%", - "**=" : "**", - "|=" : "|", - ">>=" : ">>>", - "<<=" : "<<", - "&=" : "&", - "^=" : "^" - } - if node.op not in opmap: - self.raiseError(node, _error.NotSupported, - "augmented assignment %s" % node.op) - op = opmap[node.op] - # XXX apparently no signed context required for augmented assigns - self.visit(node.node) - self.write(" = ") - self.visit(node.node) - self.write(" %s " % op) - self.visit(node.expr) - self.write(";") - - def visitBreak(self, node, *args): - self.write("disable %s;" % self.labelStack[-2]) - - def visitCallFunc(self, node, *args): - fn = node.node - assert isinstance(fn, astNode.Name) - f = self.getObj(fn) - opening, closing = '(', ')' - if f is bool: - self.write("(") - self.visit(node.args[0]) - self.write(" != 0)") - # self.write(" ? 1'b1 : 1'b0)") - return - elif f is len: - val = self.getVal(node) - self.require(node, val is not None, "cannot calculate len") - self.write(`val`) - return - elif f in (int, long): - opening, closing = '', '' - elif f is intbv: - self.visit(node.args[0]) - return - elif type(f) is ClassType and issubclass(f, Exception): - self.write(f.__name__) - elif f in (posedge, negedge): - opening, closing = ' ', '' - self.write(f.__name__) - elif f is concat: - opening, closing = '{', '}' - elif hasattr(node, 'ast'): - self.write(node.ast.name) - else: - self.write(f.__name__) - if node.args: - self.write(opening) - self.visit(node.args[0]) - for arg in node.args[1:]: - self.write(", ") - self.visit(arg) - self.write(closing) - if hasattr(node, 'ast'): - if node.ast.kind == _kind.TASK: - Visitor = _ConvertTaskVisitor - else: - Visitor = _ConvertFunctionVisitor - v = Visitor(node.ast, self.funcBuf) - compiler.walk(node.ast, v) - - def visitCompare(self, node, *args): - context = None - if node.signed: - context = _context.SIGNED - self.write("(") - self.visit(node.expr, context) - op, code = node.ops[0] - self.write(" %s " % op) - self.visit(code, context) - self.write(")") - - def visitConst(self, node, context=None, *args): - if context == _context.PRINT: - self.write('"%s"' % node.value) - else: - self.write(node.value) - - def visitContinue(self, node, *args): - self.write("disable %s;" % self.labelStack[-1]) - - def visitDiscard(self, node, *args): - expr = node.expr - self.visit(expr) - # ugly hack to detect an orphan "task" call - if isinstance(expr, astNode.CallFunc) and hasattr(expr, 'ast'): - self.write(';') - - def visitFor(self, node, *args): - self.labelStack.append(node.breakLabel) - self.labelStack.append(node.loopLabel) - var = node.assign.name - cf = node.list - 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") - args = cf.args - assert len(args) <= 3 - if f is range: - cmp = '<' - op = '+' - oneoff = '' - if len(args) == 1: - start, stop, step = None, args[0], None - elif len(args) == 2: - start, stop, step = args[0], args[1], None - else: - start, stop, step = args - else: # downrange - cmp = '>=' - op = '-' - oneoff ='-1' - if len(args) == 1: - start, stop, step = args[0], None, None - elif len(args) == 2: - start, stop, step = args[0], args[1], None - else: - start, stop, step = args - if node.breakLabel.isActive: - self.write("begin: %s" % node.breakLabel) - self.writeline() - self.write("for (%s=" % var) - if start is None: - self.write("0") - else: - self.visit(start) - self.write("%s; %s%s" % (oneoff, var, cmp)) - if stop is None: - self.write("0") - else: - self.visit(stop) - self.write("; %s=%s%s" % (var, var, op)) - if step is None: - self.write("1") - else: - self.visit(step) - self.write(") begin") - if node.loopLabel.isActive: - self.write(": %s" % node.loopLabel) - self.indent() - self.visit(node.body) - self.dedent() - self.writeline() - self.write("end") - if node.breakLabel.isActive: - self.writeline() - self.write("end") - self.labelStack.pop() - self.labelStack.pop() - - def visitFunction(self, node, *args): - raise AssertionError("To be implemented in subclass") - - def visitGetattr(self, node, *args): - assert isinstance(node.expr, astNode.Name) - assert node.expr.name in self.ast.symdict - obj = self.ast.symdict[node.expr.name] - if isinstance(obj, Signal): - if node.attrname == 'next': - self.isSigAss = True - elif node.attrname in ('posedge', 'negedge'): - self.write(node.attrname) - self.write(' ') - self.visit(node.expr) - elif isinstance(obj, EnumType): - assert hasattr(obj, node.attrname) - e = getattr(obj, node.attrname) - self.write(e._toVerilog()) - - def visitIf(self, node, *args): - if node.ignore: - return - if node.isCase: - self.mapToCase(node, *args) - else: - self.mapToIf(node, *args) - - def mapToCase(self, node, *args): - var = node.caseVar - self.write("// synthesis parallel_case") - if node.isFullCase: - self.write(" full_case") - self.writeline() - self.write("casez (") - self.visit(var) - self.write(")") - self.indent() - for test, suite in node.tests: - self.writeline() - item = test.ops[0][1].obj - self.write(item._toVerilog(dontcare=True)) - self.write(": begin") - self.indent() - self.visit(suite) - self.dedent() - self.writeline() - self.write("end") - if node.else_: - self.writeline() - self.write("default: begin") - self.indent() - self.visit(node.else_) - self.dedent() - self.writeline() - self.write("end") - self.dedent() - self.writeline() - self.write("endcase") - - def mapToIf(self, node, *args): - first = True - for test, suite in node.tests: - if first: - ifstring = "if (" - first = False - else: - ifstring = "else if (" - self.writeline() - self.write(ifstring) - self.visit(test) - self.write(") begin") - self.indent() - self.visit(suite) - self.dedent() - self.writeline() - self.write("end") - if node.else_: - self.writeline() - self.write("else begin") - self.indent() - self.visit(node.else_) - self.dedent() - self.writeline() - self.write("end") - - def visitKeyword(self, node, *args): - self.visit(node.expr) - - def visitModule(self, node, *args): - for stmt in node.node.nodes: - self.visit(stmt) - - def visitName(self, node, context=None, *args): - addSignBit = False - isMixedExpr = (not node.signed) and (context == _context.SIGNED) - n = node.name - if n == 'False': - s = "0" - elif n == 'True': - s = "1" - elif n in self.ast.vardict: - addSignBit = isMixedExpr - s = n - elif n in self.ast.argnames: - assert n in self.ast.symdict - addSignBit = isMixedExpr - s = n - elif n in self.ast.symdict: - obj = self.ast.symdict[n] - if isinstance(obj, bool): - s = "%s" % int(obj) - elif isinstance(obj, (int, long)): - self.writeIntSize(obj) - s = str(obj) - elif isinstance(obj, Signal): - addSignBit = isMixedExpr - s = str(obj) - elif _isMem(obj): - m = _getMemInfo(obj) - assert m.name - if not m.decl: - self.raiseError(node, _error.ListElementNotUnique, m.name) - s = m.name - elif isinstance(obj, EnumItemType): - s = obj._toVerilog() - elif type(obj) is ClassType and issubclass(obj, Exception): - s = n - else: - self.raiseError(node, _error.UnsupportedType, "%s, %s" % (n, type(obj))) - else: - raise AssertionError("name ref: %s" % n) - if addSignBit: - self.write("$signed({1'b0, ") - self.write(s) - if addSignBit: - self.write("})") - - def visitPass(self, node, *args): - self.write("// pass") - - def handlePrint(self, node): - self.write('$display(') - s = node.nodes[0] - self.visit(s, _context.PRINT) - for s in node.nodes[1:]: - self.write(', , ') - self.visit(s, _context.PRINT) - self.write(');') - - def visitPrint(self, node, *args): - self.handlePrint(node) - - def visitPrintnl(self, node, *args): - self.handlePrint(node) - - def visitRaise(self, node, *args): - self.write('$display("') - self.visit(node.expr1) - self.write('");') - self.writeline() - self.write("$finish;") - - def visitReturn(self, node, *args): - self.write("disable %s;" % self.returnLabel) - - def visitSlice(self, node, context=None, *args): - if isinstance(node.expr, astNode.CallFunc) and \ - node.expr.node.obj is intbv: - c = self.getVal(node) - self.write("%s'h" % c._nrbits) - self.write("%x" % c._val) - return - addSignBit = (node.flags == 'OP_APPLY') and (context == _context.SIGNED) - if addSignBit: - self.write("$signed({1'b0, ") - self.visit(node.expr) - # special shortcut case for [:] slice - if node.lower is None and node.upper is None: - return - self.write("[") - if node.lower is None: - self.write("%s" % node.obj._nrbits) - else: - self.visit(node.lower) - self.write("-1:") - if node.upper is None: - self.write("0") - else: - self.visit(node.upper) - self.write("]") - if addSignBit: - self.write("})") - - def visitStmt(self, node, *args): - for stmt in node.nodes: - self.writeline() - self.visit(stmt) - # ugly hack to detect an orphan "task" call - if isinstance(stmt, astNode.CallFunc) and hasattr(stmt, 'ast'): - self.write(';') - - def visitSubscript(self, node, context=None, *args): - addSignBit = (node.flags == 'OP_APPLY') and (context == _context.SIGNED) - if addSignBit: - self.write("$signed({1'b0, ") - self.visit(node.expr) - self.write("[") - assert len(node.subs) == 1 - self.visit(node.subs[0]) - self.write("]") - if addSignBit: - self.write("})") - - def visitTuple(self, node, context=None, *args): - assert context != None - if context == _context.PRINT: - sep = ", " - else: - sep = " or " - tpl = node.nodes - self.visit(tpl[0]) - for elt in tpl[1:]: - self.write(sep) - self.visit(elt) - - def visitWhile(self, node, *args): - self.labelStack.append(node.breakLabel) - self.labelStack.append(node.loopLabel) - if node.breakLabel.isActive: - self.write("begin: %s" % node.breakLabel) - self.writeline() - self.write("while (") - self.visit(node.test) - self.write(") begin") - if node.loopLabel.isActive: - self.write(": %s" % node.loopLabel) - self.indent() - self.visit(node.body) - self.dedent() - self.writeline() - self.write("end") - if node.breakLabel.isActive: - self.writeline() - self.write("end") - self.labelStack.pop() - self.labelStack.pop() - - def visitYield(self, node, *args): - self.write("@ (") - self.visit(node.value, _context.YIELD) - self.write(");") - - -class _ConvertAlwaysVisitor(_ConvertVisitor): - - def __init__(self, ast, blockBuf, funcBuf): - _ConvertVisitor.__init__(self, ast, blockBuf) - self.funcBuf = funcBuf - - def visitFunction(self, node, *args): - w = node.code.nodes[-1] - assert isinstance(w.body.nodes[0], astNode.Yield) - sl = w.body.nodes[0].value - self.write("always @(") - self.visit(sl, _context.YIELD) - self.write(") begin: %s" % self.ast.name) - self.indent() - self.writeDeclarations() - assert isinstance(w.body, astNode.Stmt) - for stmt in w.body.nodes[1:]: - self.writeline() - self.visit(stmt) - self.dedent() - self.writeline() - self.write("end") - self.writeline(2) - - -class _ConvertInitialVisitor(_ConvertVisitor): - - def __init__(self, ast, blockBuf, funcBuf): - _ConvertVisitor.__init__(self, ast, blockBuf) - self.funcBuf = funcBuf - - def visitFunction(self, node, *args): - self.write("initial begin: %s" % self.ast.name) - self.indent() - self.writeDeclarations() - self.visit(node.code) - self.dedent() - self.writeline() - self.write("end") - self.writeline(2) - - -class _ConvertAlwaysCombVisitor(_ConvertVisitor): - - def __init__(self, ast, blockBuf, funcBuf): - _ConvertVisitor.__init__(self, ast, blockBuf) - self.funcBuf = funcBuf - - def visitFunction(self, node, *args): - self.write("always @(") - assert self.ast.senslist - for s in self.ast.senslist[:-1]: - self.write(s._name) - self.write(', ') - self.write(self.ast.senslist[-1]._name) - self.write(") begin: %s" % self.ast.name) - self.indent() - self.writeDeclarations() - self.visit(node.code) - self.dedent() - self.writeline() - self.write("end") - self.writeline(2) - - -class _ConvertSimpleAlwaysCombVisitor(_ConvertVisitor): - - def __init__(self, ast, blockBuf, funcBuf): - _ConvertVisitor.__init__(self, ast, blockBuf) - self.funcBuf = funcBuf - - def visitAssAttr(self, node, *args): - self.write("assign ") - self.visit(node.expr) - - def visitFunction(self, node, *args): - self.visit(node.code) - self.writeline(2) - - - -class _ConvertAlwaysDecoVisitor(_ConvertVisitor): - - def __init__(self, ast, blockBuf, funcBuf): - _ConvertVisitor.__init__(self, ast, blockBuf) - self.funcBuf = funcBuf - - def visitFunction(self, node, *args): - self.write("always @(") - assert self.ast.senslist - for e in self.ast.senslist[:-1]: - self.write(e._toVerilog()) - self.write(' or ') - self.write(self.ast.senslist[-1]._toVerilog()) - self.write(") begin: %s" % self.ast.name) - self.indent() - self.writeDeclarations() - self.visit(node.code) - self.dedent() - self.writeline() - self.write("end") - self.writeline(2) - - -class _ConvertFunctionVisitor(_ConvertVisitor): - - def __init__(self, ast, funcBuf): - _ConvertVisitor.__init__(self, ast, funcBuf) - self.returnObj = ast.returnObj - self.returnLabel = _Label("RETURN") - - def writeOutputDeclaration(self): - obj = self.ast.returnObj - self.writeDeclaration(obj, self.ast.name, dir='') - - def writeInputDeclarations(self): - for name in self.ast.argnames: - obj = self.ast.symdict[name] - self.writeline() - self.writeDeclaration(obj, name, "input") - - def visitFunction(self, node, *args): - self.write("function ") - self.writeOutputDeclaration() - self.indent() - self.writeInputDeclarations() - self.writeDeclarations() - self.dedent() - self.writeline() - self.write("begin: %s" % self.returnLabel) - self.indent() - self.visit(node.code) - self.dedent() - self.writeline() - self.write("end") - self.writeline() - self.write("endfunction") - self.writeline(2) - - def visitReturn(self, node, *args): - self.write("%s = " % self.ast.name) - self.visit(node.value) - self.write(";") - self.writeline() - self.write("disable %s;" % self.returnLabel) - - -class _ConvertTaskVisitor(_ConvertVisitor): - - def __init__(self, ast, funcBuf): - _ConvertVisitor.__init__(self, ast, funcBuf) - self.returnLabel = _Label("RETURN") - - def writeInterfaceDeclarations(self): - for name in self.ast.argnames: - obj = self.ast.symdict[name] - output = name in self.ast.outputs - input = name in self.ast.inputs - inout = input and output - dir = (inout and "inout") or (output and "output") or "input" - self.writeline() - self.writeDeclaration(obj, name, dir) - - def visitFunction(self, node, *args): - self.write("task %s;" % self.ast.name) - self.indent() - self.writeInterfaceDeclarations() - self.writeDeclarations() - self.dedent() - self.writeline() - self.write("begin: %s" % self.returnLabel) - self.indent() - self.visit(node.code) - self.dedent() - self.writeline() - self.write("end") - self.writeline() - self.write("endtask") - self.writeline(2)