diff --git a/myhdl/_Cosimulation.py b/myhdl/_Cosimulation.py index b5cebb2b..5a021aa0 100644 --- a/myhdl/_Cosimulation.py +++ b/myhdl/_Cosimulation.py @@ -48,7 +48,6 @@ class Cosimulation(object): """ Cosimulation class. """ def __init__(self, exe="", **kwargs): - """ Construct a cosimulation object. """ if _simulator._cosim: diff --git a/myhdl/_ShadowSignal.py b/myhdl/_ShadowSignal.py index b01163a6..e9bbd8e4 100644 --- a/myhdl/_ShadowSignal.py +++ b/myhdl/_ShadowSignal.py @@ -50,7 +50,6 @@ class _ShadowSignal(_Signal): raise AttributeError("ShadowSignals are readonly") - class _SliceSignal(_ShadowSignal): __slots__ = ('_sig', '_left', '_right') @@ -104,7 +103,6 @@ class _SliceSignal(_ShadowSignal): self._used = True self._sig._used = True - def toVerilog(self): if self._right is None: return "assign %s = %s[%s];" % (self._name, self._sig._name, self._left) @@ -118,7 +116,6 @@ class _SliceSignal(_ShadowSignal): return "%s <= %s(%s-1 downto %s);" % (self._name, self._sig._name, self._left, self._right) - class ConcatSignal(_ShadowSignal): __slots__ = ('_args', '_sigargs', '_initval') @@ -148,7 +145,7 @@ class ConcatSignal(_ShadowSignal): w = len(a) v = long(a, 2) else: - raise TypeError("ConcatSignal: inappropriate argument type: %s" \ + raise TypeError("ConcatSignal: inappropriate argument type: %s" % type(a)) nrbits += w val = val << w | v & (long(1) << w) - 1 @@ -209,12 +206,13 @@ class ConcatSignal(_ShadowSignal): else: lines.append("%s(%s) <= %s(0);" % (self._name, lo, a._name)) else: - lines.append("%s(%s) <= '%s';" % (self._name, lo, bin(ini[lo]))) + lines.append("%s(%s) <= '%s';" % (self._name, lo, bin(ini[lo]))) else: if isinstance(a, _Signal): lines.append("%s(%s-1 downto %s) <= %s;" % (self._name, hi, lo, a._name)) else: - lines.append('%s(%s-1 downto %s) <= "%s";' % (self._name, hi, lo, bin(ini[hi:lo], w))) + lines.append('%s(%s-1 downto %s) <= "%s";' % + (self._name, hi, lo, bin(ini[hi:lo], w))) hi = lo return "\n".join(lines) @@ -240,7 +238,8 @@ class ConcatSignal(_ShadowSignal): if isinstance(a, _Signal): lines.append("assign %s[%s-1:%s] = %s;" % (self._name, hi, lo, a._name)) else: - lines.append("assign %s[%s-1:%s] = 'b%s;" % (self._name, hi, lo, bin(ini[hi:lo], w))) + lines.append("assign %s[%s-1:%s] = 'b%s;" % + (self._name, hi, lo, bin(ini[hi:lo], w))) hi = lo return "\n".join(lines) @@ -301,7 +300,6 @@ class _TristateSignal(_ShadowSignal): self._next = res _siglist.append(self) - def toVerilog(self): lines = [] for d in self._drivers: @@ -317,7 +315,6 @@ class _TristateSignal(_ShadowSignal): return "\n".join(lines) - class _TristateDriver(_Signal): __slots__ = ('_sig',) diff --git a/myhdl/_Signal.py b/myhdl/_Signal.py index c2e999a7..061cca70 100644 --- a/myhdl/_Signal.py +++ b/myhdl/_Signal.py @@ -63,18 +63,25 @@ class _WaiterList(list): class _PosedgeWaiterList(_WaiterList): + def __init__(self, sig): self.sig = sig + def _toVerilog(self): return "posedge %s" % self.sig._name + def _toVHDL(self): return "rising_edge(%s)" % self.sig._name + class _NegedgeWaiterList(_WaiterList): + def __init__(self, sig): self.sig = sig + def _toVerilog(self): return "negedge %s" % self.sig._name + def _toVHDL(self): return "falling_edge(%s)" % self.sig._name @@ -83,11 +90,14 @@ def posedge(sig): """ Return a posedge trigger object """ return sig.posedge + def negedge(sig): """ Return a negedge trigger object """ return sig.negedge # signal factory function + + def Signal(val=None, delay=None): """ Return a new _Signal (default or delay 0) or DelayedSignal """ if delay is not None: @@ -97,6 +107,7 @@ def Signal(val=None, delay=None): else: return _Signal(val) + class _Signal(object): """ _Signal class. @@ -114,8 +125,7 @@ class _Signal(object): '_driven', '_read', '_name', '_used', '_inList', '_waiter', 'toVHDL', 'toVerilog', '_slicesigs', '_numeric' - ) - + ) def __init__(self, val=None): """ Construct a signal. @@ -211,8 +221,8 @@ class _Signal(object): # support for the 'next' attribute @property def next(self): -# if self._next is self._val: -# self._next = deepcopy(self._val) + # if self._next is self._val: + # self._next = deepcopy(self._val) _siglist.append(self) return self._next @@ -332,13 +342,11 @@ class _Signal(object): self._slicesigs.append(s) return s - ### operators for which delegation to current value is appropriate ### def __hash__(self): raise TypeError("Signals are unhashable") - def __bool__(self): return bool(self._val) @@ -361,6 +369,7 @@ class _Signal(object): return self._val + other._val else: return self._val + other + def __radd__(self, other): return other + self._val @@ -369,6 +378,7 @@ class _Signal(object): return self._val - other._val else: return self._val - other + def __rsub__(self, other): return other - self._val @@ -377,6 +387,7 @@ class _Signal(object): return self._val * other._val else: return self._val * other + def __rmul__(self, other): return other * self._val @@ -385,6 +396,7 @@ class _Signal(object): return self._val / other._val else: return self._val / other + def __rtruediv__(self, other): return other / self._val @@ -393,6 +405,7 @@ class _Signal(object): return self._val // other._val else: return self._val // other + def __rfloordiv__(self, other): return other // self._val @@ -401,6 +414,7 @@ class _Signal(object): return self._val % other._val else: return self._val % other + def __rmod__(self, other): return other % self._val @@ -411,6 +425,7 @@ class _Signal(object): return self._val ** other._val else: return self._val ** other + def __rpow__(self, other): return other ** self._val @@ -419,6 +434,7 @@ class _Signal(object): return self._val << other._val else: return self._val << other + def __rlshift__(self, other): return other << self._val @@ -427,6 +443,7 @@ class _Signal(object): return self._val >> other._val else: return self._val >> other + def __rrshift__(self, other): return other >> self._val @@ -435,6 +452,7 @@ class _Signal(object): return self._val & other._val else: return self._val & other + def __rand__(self, other): return other & self._val @@ -443,6 +461,7 @@ class _Signal(object): return self._val | other._val else: return self._val | other + def __ror__(self, other): return other | self._val @@ -451,6 +470,7 @@ class _Signal(object): return self._val ^ other._val else: return self._val ^ other + def __rxor__(self, other): return other ^ self._val @@ -486,22 +506,25 @@ class _Signal(object): def __index__(self): return int(self._val) - # comparisons def __eq__(self, other): return self.val == other + def __ne__(self, other): return self.val != other + def __lt__(self, other): return self.val < other + def __le__(self, other): return self.val <= other + def __gt__(self, other): return self.val > other + def __ge__(self, other): return self.val >= other - # method lookup delegation def __getattr__(self, attr): return getattr(self._val, attr) @@ -527,12 +550,10 @@ class _Signal(object): __ior__ = __iand__ = __ixor__ = __irshift__ = __ilshift__ = _augm __itruediv__ = __ifloordiv__ = _augm - # index and slice assignment not supported def __setitem__(self, key, val): raise TypeError("Signal object doesn't support item/slice assignment") - # continues assignment support def assign(self, sig): @@ -558,7 +579,7 @@ class _Signal(object): class _DelayedSignal(_Signal): __slots__ = ('_nextZ', '_delay', '_timeStamp', - ) + ) def __init__(self, val=None, delay=1): """ Construct a new DelayedSignal. @@ -609,10 +630,12 @@ class _DelayedSignal(_Signal): class _SignalWrap(object): + def __init__(self, sig, next, timeStamp): self.sig = sig self.next = next self.timeStamp = timeStamp + def apply(self): return self.sig._apply(self.next, self.timeStamp) diff --git a/myhdl/_Simulation.py b/myhdl/_Simulation.py index e7c68bf9..6dd8955f 100644 --- a/myhdl/_Simulation.py +++ b/myhdl/_Simulation.py @@ -39,6 +39,7 @@ from myhdl._block import _Block schedule = _futureEvents.append + class _error: pass _error.ArgType = "Inappriopriate argument type" @@ -46,6 +47,8 @@ _error.MultipleCosim = "Only a single cosimulator argument allowed" _error.DuplicatedArg = "Duplicated argument" # flatten Block objects out + + def _flatten(*args): arglist = [] for arg in args: @@ -60,6 +63,7 @@ def _flatten(*args): _error.MultipleSim = "Only a single Simulation instance is allowed" + class Simulation(object): """ Simulation class. @@ -89,7 +93,6 @@ class Simulation(object): del _futureEvents[:] del _siglist[:] - def _finalize(self): cosim = self._cosim if cosim: @@ -110,7 +113,6 @@ class Simulation(object): self._finalize() def run(self, duration=None, quiet=0): - """ Run the simulation for some duration. duration -- specified simulation duration (default: forever) diff --git a/myhdl/_Waiter.py b/myhdl/_Waiter.py index 812f80c7..81ed5991 100644 --- a/myhdl/_Waiter.py +++ b/myhdl/_Waiter.py @@ -227,7 +227,6 @@ def _inferWaiter(gen): return _Waiter(gen) - class _YieldVisitor(ast.NodeVisitor): def __init__(self, root): @@ -286,7 +285,5 @@ class _YieldVisitor(ast.NodeVisitor): node.kind = _kind.EDGE - # avoid problems with recursive imports from myhdl._instance import _Instantiator - diff --git a/myhdl/__init__.py b/myhdl/__init__.py index bc24a52f..e16869ed 100644 --- a/myhdl/__init__.py +++ b/myhdl/__init__.py @@ -59,50 +59,82 @@ class StopSimulation(Exception): """ Basic exception to stop a Simulation """ pass + class _SuspendSimulation(Exception): """ Basic exception to suspend a Simulation """ pass + class Error(Exception): + def __init__(self, kind, msg="", info=""): self.kind = kind self.msg = msg self.info = info + def __str__(self): s = "%s%s" % (self.info, self.kind) if self.msg: s += ": %s" % self.msg return s + class AlwaysError(Error): pass + + class AlwaysCombError(Error): pass + + class InstanceError(Error): pass + + class BlockError(Error): pass + + class BlockInstanceError(Error): pass + + class CosimulationError(Error): pass + + class ExtractHierarchyError(Error): pass + + class SimulationError(Error): pass + + class TraceSignalsError(Error): pass + + class ConversionError(Error): pass + + class ToVerilogError(ConversionError): pass + + class ToVHDLError(ConversionError): pass + class ConversionWarning(UserWarning): pass + + class ToVerilogWarning(ConversionWarning): pass + + class ToVHDLWarning(ConversionWarning): pass # warnings.filterwarnings('always', r".*", ToVerilogWarning) diff --git a/myhdl/_always.py b/myhdl/_always.py index c2327b51..4cd806e8 100644 --- a/myhdl/_always.py +++ b/myhdl/_always.py @@ -29,9 +29,10 @@ from myhdl._delay import delay from myhdl._Signal import _Signal from myhdl._Signal import _WaiterList from myhdl._Waiter import _Waiter, _SignalWaiter, _SignalTupleWaiter, \ - _DelayWaiter, _EdgeWaiter, _EdgeTupleWaiter + _DelayWaiter, _EdgeWaiter, _EdgeTupleWaiter from myhdl._instance import _Instantiator, _getCallInfo + class _error: pass _error.DecArgType = "decorator argument should be a Signal, edge, or delay" @@ -39,6 +40,7 @@ _error.ArgType = "decorated object should be a classic (non-generator) function" _error.NrOfArgs = "decorated function should not have arguments" _error.DecNrOfArgs = "decorator should have arguments" + def _getSigdict(sigs, symdict): """Lookup signals in caller namespace and return sigdict @@ -56,6 +58,7 @@ def _getSigdict(sigs, symdict): sigdict[n] = s return sigdict + def always(*args): callinfo = _getCallInfo() sigargs = [] @@ -71,6 +74,7 @@ def always(*args): elif not isinstance(arg, delay): raise AlwaysError(_error.DecArgType) sigdict = _getSigdict(sigargs, callinfo.symdict) + def _always_decorator(func): if not isinstance(func, FunctionType): raise AlwaysError(_error.ArgType) diff --git a/myhdl/_always_comb.py b/myhdl/_always_comb.py index 9621190b..8cdb7c48 100644 --- a/myhdl/_always_comb.py +++ b/myhdl/_always_comb.py @@ -28,6 +28,7 @@ from myhdl._util import _isGenFunc from myhdl._instance import _getCallInfo from myhdl._always import _Always + class _error: pass _error.ArgType = "always_comb argument should be a classic function" @@ -37,6 +38,7 @@ _error.SignalAsInout = "signal (%s) used as inout in always_comb function argume _error.EmbeddedFunction = "embedded functions in always_comb function argument not supported" _error.EmptySensitivityList = "sensitivity list is empty" + def always_comb(func): callinfo = _getCallInfo() if not isinstance(func, FunctionType): diff --git a/myhdl/_always_seq.py b/myhdl/_always_seq.py index a9ee23f2..0e525c27 100644 --- a/myhdl/_always_seq.py +++ b/myhdl/_always_seq.py @@ -32,6 +32,7 @@ from myhdl._instance import _getCallInfo # evacuate this later AlwaysSeqError = AlwaysError + class _error: pass _error.EdgeType = "first argument should be an edge" @@ -41,7 +42,9 @@ _error.NrOfArgs = "decorated function should not have arguments" _error.SigAugAssign = "signal assignment does not support augmented assignment" _error.EmbeddedFunction = "embedded functions in always_seq function not supported" + class ResetSignal(_Signal): + def __init__(self, val, active, async): """ Construct a ResetSignal. @@ -52,6 +55,7 @@ class ResetSignal(_Signal): self.active = bool(active) self.async = async + def always_seq(edge, reset): callinfo = _getCallInfo() sigargs = [] diff --git a/myhdl/_bin.py b/myhdl/_bin.py index 421cb8c2..1d5273bf 100644 --- a/myhdl/_bin.py +++ b/myhdl/_bin.py @@ -54,4 +54,3 @@ def bin(num, width=0): pad = '1' return (width - len(s)) * pad + s return s - diff --git a/myhdl/_block.py b/myhdl/_block.py index f1db161b..35cb5489 100644 --- a/myhdl/_block.py +++ b/myhdl/_block.py @@ -29,7 +29,7 @@ from myhdl import BlockError, BlockInstanceError, Cosimulation from myhdl._instance import _Instantiator from myhdl._util import _flatten from myhdl._extractHierarchy import (_MemInfo, _makeMemInfo, - _UserVerilogCode, _UserVhdlCode) + _UserVerilogCode, _UserVhdlCode) from myhdl._Signal import _Signal, _isListOfSigs @@ -38,12 +38,15 @@ class _error: _error.ArgType = "A block should return block or instantiator objects" _error.InstanceError = "%s: subblock %s should be encapsulated in a block decorator" + class _CallInfo(object): + def __init__(self, name, modctxt, symdict): self.name = name self.modctxt = modctxt self.symdict = symdict + def _getCallInfo(): """Get info on the caller of a BlockInstance. @@ -76,9 +79,11 @@ def _getCallInfo(): modctxt = isinstance(f_locals['self'], _Block) return _CallInfo(name, modctxt, symdict) + def block(func): srcfile = inspect.getsourcefile(func) srcline = inspect.getsourcelines(func)[0] + @wraps(func) def deco(*args, **kwargs): deco.calls += 1 @@ -86,6 +91,7 @@ def block(func): deco.calls = 0 return deco + class _Block(object): def __init__(self, func, deco, srcfile, srcline, *args, **kwargs): diff --git a/myhdl/_concat.py b/myhdl/_concat.py index 91c319e9..a9a7d74d 100644 --- a/myhdl/_concat.py +++ b/myhdl/_concat.py @@ -28,7 +28,6 @@ from myhdl._Signal import _Signal from myhdl._compat import long - def concat(base, *args): if isinstance(base, intbv): @@ -50,7 +49,7 @@ def concat(base, *args): basewidth = len(base) val = long(base, 2) else: - raise TypeError("concat: inappropriate first argument type: %s" \ + raise TypeError("concat: inappropriate first argument type: %s" % type(base)) width = 0 @@ -71,7 +70,7 @@ def concat(base, *args): w = len(arg) v = long(arg, 2) else: - raise TypeError("concat: inappropriate argument type: %s" \ + raise TypeError("concat: inappropriate argument type: %s" % type(arg)) if not w: raise TypeError("concat: arg on pos %d should have length" % (i + 1)) @@ -82,4 +81,3 @@ def concat(base, *args): return intbv(val, _nrbits=basewidth + width) else: return intbv(val) - diff --git a/myhdl/_delay.py b/myhdl/_delay.py index 69ba4e7f..a252f92a 100644 --- a/myhdl/_delay.py +++ b/myhdl/_delay.py @@ -24,6 +24,7 @@ from myhdl._compat import integer_types _errmsg = "arg of delay constructor should be a natural integeer" + class delay(object): """ Class to model delay in yield statements. """ diff --git a/myhdl/_enum.py b/myhdl/_enum.py index e56819d1..12547cf1 100644 --- a/myhdl/_enum.py +++ b/myhdl/_enum.py @@ -27,22 +27,27 @@ from myhdl._bin import bin from myhdl._Signal import _Signal from myhdl._compat import string_types + class EnumType(object): + def __init__(self): raise TypeError("class EnumType is only intended for type checking on subclasses") + class EnumItemType(object): + def __init__(self): raise TypeError("class EnumItemType is only intended for type checking on subclasses") supported_encodings = ("binary", "one_hot", "one_cold") + def enum(*names, **kwargs): # args = args encoding = kwargs.get('encoding', None) if encoding is not None and encoding not in supported_encodings: - raise ValueError("Unsupported enum encoding: %s\n Supported encodings: %s" % \ + raise ValueError("Unsupported enum encoding: %s\n Supported encodings: %s" % (encoding, supported_encodings)) if encoding in ("one_hot", "one_cold"): nrbits = len(names) @@ -130,8 +135,8 @@ def enum(*names, **kwargs): raise TypeError("Type mismatch in enum item comparison") return self is not other - class Enum(EnumType): + def __init__(self, names, codedict, nrbits, encoding): self.__dict__['_names'] = names self.__dict__['_nrbits'] = nrbits @@ -171,8 +176,3 @@ def enum(*names, **kwargs): return str return Enum(names, codedict, nrbits, encoding) - - - - - diff --git a/myhdl/_extractHierarchy.py b/myhdl/_extractHierarchy.py index bf580476..1aa76052 100644 --- a/myhdl/_extractHierarchy.py +++ b/myhdl/_extractHierarchy.py @@ -38,6 +38,7 @@ from myhdl._getcellvars import _getCellVars _profileFunc = None + class _error: pass _error.NoInstances = "No instances found" @@ -47,6 +48,7 @@ _error.InconsistentToplevel = "Inconsistent top level %s for %s - should be 1" class _Instance(object): __slots__ = ['level', 'obj', 'subs', 'sigdict', 'memdict', 'name'] + def __init__(self, level, obj, subs, sigdict, memdict): self.level = level self.obj = obj @@ -57,8 +59,10 @@ class _Instance(object): _memInfoMap = {} + class _MemInfo(object): __slots__ = ['mem', 'name', 'elObj', 'depth', '_used', '_driven', '_read'] + def __init__(self, mem): self.mem = mem self.name = None @@ -72,21 +76,25 @@ class _MemInfo(object): def _getMemInfo(mem): return _memInfoMap[id(mem)] + def _makeMemInfo(mem): key = id(mem) if key not in _memInfoMap: _memInfoMap[key] = _MemInfo(mem) return _memInfoMap[key] + def _isMem(mem): return id(mem) in _memInfoMap _userCodeMap = {'verilog': {}, 'vhdl': {} - } + } + class _UserCode(object): __slots__ = ['code', 'namespace', 'funcname', 'func', 'sourcefile', 'sourceline'] + def __init__(self, code, namespace, funcname, func, sourcefile, sourceline): self.code = code self.namespace = namespace @@ -110,26 +118,35 @@ class _UserCode(object): def _interpolate(self): return string.Template(self.code).substitute(self.namespace) + class _UserCodeDepr(_UserCode): + def _interpolate(self): return self.code % self.namespace + class _UserVerilogCode(_UserCode): + def raiseError(self, msg, info): raise ToVerilogError("Error in user defined Verilog code", msg, info) + class _UserVhdlCode(_UserCode): + def raiseError(self, msg, info): raise ToVHDLError("Error in user defined VHDL code", msg, info) + class _UserVerilogCodeDepr(_UserVerilogCode, _UserCodeDepr): pass + class _UserVhdlCodeDepr(_UserVhdlCode, _UserCodeDepr): pass class _UserVerilogInstance(_UserVerilogCode): + def __str__(self): args = inspect.getargspec(self.func)[0] s = "%s %s(" % (self.funcname, self.code) @@ -143,7 +160,9 @@ class _UserVerilogInstance(_UserVerilogCode): s += "\n);\n\n" return s + class _UserVhdlInstance(_UserVhdlCode): + def __str__(self): args = inspect.getargspec(self.func)[0] s = "%s: entity work.%s(MyHDL)\n" % (self.code, self.funcname) @@ -159,17 +178,16 @@ class _UserVhdlInstance(_UserVhdlCode): return s - def _addUserCode(specs, arg, funcname, func, frame): classMap = { - '__verilog__': _UserVerilogCodeDepr, - '__vhdl__': _UserVhdlCodeDepr, - 'verilog_code': _UserVerilogCode, - 'vhdl_code': _UserVhdlCode, - 'verilog_instance': _UserVerilogInstance, - 'vhdl_instance': _UserVhdlInstance, + '__verilog__': _UserVerilogCodeDepr, + '__vhdl__': _UserVhdlCodeDepr, + 'verilog_code': _UserVerilogCode, + 'vhdl_code': _UserVhdlCode, + 'verilog_instance': _UserVerilogInstance, + 'vhdl_instance': _UserVhdlInstance, - } + } namespace = frame.f_globals.copy() namespace.update(frame.f_locals) sourcefile = inspect.getsourcefile(frame) @@ -189,7 +207,8 @@ def _addUserCode(specs, arg, funcname, func, frame): if spec: assert id(arg) not in _userCodeMap[hdl] code = specs[spec] - _userCodeMap[hdl][id(arg)] = classMap[spec](code, namespace, funcname, func, sourcefile, sourceline) + _userCodeMap[hdl][id(arg)] = classMap[spec]( + code, namespace, funcname, func, sourcefile, sourceline) class _CallFuncVisitor(object): @@ -207,7 +226,6 @@ class _CallFuncVisitor(object): self.lineno = node.lineno - class _HierExtr(object): def __init__(self, name, dut, *args, **kwargs): @@ -216,10 +234,10 @@ class _HierExtr(object): _memInfoMap.clear() for hdl in _userCodeMap: _userCodeMap[hdl].clear() - self.skipNames = ('always_comb', 'instance', \ - 'always_seq', '_always_seq_decorator', \ - 'always', '_always_decorator', \ - 'instances', \ + self.skipNames = ('always_comb', 'instance', + 'always_seq', '_always_seq_decorator', + 'always', '_always_decorator', + 'instances', 'processes', 'posedge', 'negedge') self.skip = 0 self.hierarchy = hierarchy = [] @@ -260,7 +278,6 @@ class _HierExtr(object): names[id(soi)] = sni absnames[id(soi)] = "%s_%s_%s" % (tn, sn, i) - def extractor(self, frame, event, arg): if event == "call": @@ -324,8 +341,8 @@ class _HierExtr(object): # extract signals and memories # also keep track of whether they are used in generators # only include objects that are used in generators -# if not n in cellvars: -# continue + # if not n in cellvars: + # continue if isinstance(v, _Signal): sigdict[n] = v if n in cellvars: diff --git a/myhdl/_getHierarchy.py b/myhdl/_getHierarchy.py index e7f5debe..9d3523ae 100644 --- a/myhdl/_getHierarchy.py +++ b/myhdl/_getHierarchy.py @@ -26,7 +26,9 @@ from __future__ import absolute_import from myhdl._extractHierarchy import _Instance from myhdl._block import _Block + class _Hierarchy(object): + def __init__(self, name, modinst): self.top = modinst self.hierarchy = hierarchy = [] @@ -49,9 +51,11 @@ class _Hierarchy(object): # print (names) # print(absnames) + def _getHierarchy(name, modinst): - h = _Hierarchy(name, modinst) - return h + h = _Hierarchy(name, modinst) + return h + def _getHierarchyHelper(level, modinst, hierarchy): subs = [(s.name, s) for s in modinst.subs] diff --git a/myhdl/_getcellvars.py b/myhdl/_getcellvars.py index c157d97d..44ff1c8e 100644 --- a/myhdl/_getcellvars.py +++ b/myhdl/_getcellvars.py @@ -7,6 +7,7 @@ from myhdl._util import _flatten class Data(): pass + def _getCellVars(symdict, arg): gens = _flatten(arg) data = Data() @@ -16,7 +17,9 @@ def _getCellVars(symdict, arg): v.visit(gen.ast) return list(data.objset) + class _GetCellVars(ast.NodeVisitor): + def __init__(self, data): self.data = data self.data.objset = set() diff --git a/myhdl/_instance.py b/myhdl/_instance.py index 4215d3cf..9bd169ac 100644 --- a/myhdl/_instance.py +++ b/myhdl/_instance.py @@ -30,12 +30,15 @@ from myhdl._Waiter import _inferWaiter from myhdl._resolverefs import _AttrRefTransformer from myhdl._visitors import _SigNameVisitor + class _error: pass _error.NrOfArgs = "decorated generator function should not have arguments" _error.ArgType = "decorated object should be a generator function" + class _CallInfo(object): + def __init__(self, name, modctxt, symdict): self.name = name self.modctxt = modctxt @@ -77,6 +80,7 @@ def instance(genfunc): raise InstanceError(_error.NrOfArgs) return _Instantiator(genfunc, callinfo=callinfo) + class _Instantiator(object): def __init__(self, genfunc, callinfo): diff --git a/myhdl/_intbv.py b/myhdl/_intbv.py index 20a0852d..44059ef0 100644 --- a/myhdl/_intbv.py +++ b/myhdl/_intbv.py @@ -25,7 +25,6 @@ from myhdl._compat import long, integer_types, string_types, builtins from myhdl._bin import bin - class intbv(object): #__slots__ = ('_val', '_min', '_max', '_nrbits', '_handleBounds') @@ -87,7 +86,6 @@ class intbv(object): return False return max & max - 1 == 0 - # hash def __hash__(self): raise TypeError("intbv objects are unhashable") @@ -132,14 +130,14 @@ class intbv(object): j = 0 j = int(j) if j < 0: - raise ValueError("intbv[i:j] requires j >= 0\n" \ - " j == %s" % j) + raise ValueError("intbv[i:j] requires j >= 0\n" + " j == %s" % j) if i is None: # default return intbv(self._val >> j) i = int(i) if i <= j: - raise ValueError("intbv[i:j] requires i > j\n" \ - " i, j == %s, %s" % (i, j)) + raise ValueError("intbv[i:j] requires i > j\n" + " i, j == %s, %s" % (i, j)) res = intbv((self._val & (long(1) << i) - 1) >> j, _nrbits=i - j) return res else: @@ -147,8 +145,6 @@ class intbv(object): res = bool((self._val >> i) & 0x1) return res - - def __setitem__(self, key, val): # convert val to int to avoid confusion with intbv or Signals val = int(val) @@ -158,8 +154,8 @@ class intbv(object): j = 0 j = int(j) if j < 0: - raise ValueError("intbv[i:j] = v requires j >= 0\n" \ - " j == %s" % j) + raise ValueError("intbv[i:j] = v requires j >= 0\n" + " j == %s" % j) if i is None: # default q = self._val % (long(1) << j) self._val = val * (long(1) << j) + q @@ -167,12 +163,12 @@ class intbv(object): return i = int(i) if i <= j: - raise ValueError("intbv[i:j] = v requires i > j\n" \ - " i, j, v == %s, %s, %s" % (i, j, val)) + raise ValueError("intbv[i:j] = v requires i > j\n" + " i, j, v == %s, %s, %s" % (i, j, val)) lim = (long(1) << (i - j)) if val >= lim or val < -lim: - raise ValueError("intbv[i:j] = v abs(v) too large\n" \ - " i, j, v == %s, %s, %s" % (i, j, val)) + raise ValueError("intbv[i:j] = v abs(v) too large\n" + " i, j, v == %s, %s, %s" % (i, j, val)) mask = (lim - 1) << j self._val &= ~mask self._val |= (val << j) @@ -184,13 +180,11 @@ class intbv(object): elif val == 0: self._val &= ~(long(1) << i) else: - raise ValueError("intbv[i] = v requires v in (0, 1)\n" \ - " i == %s " % i) + raise ValueError("intbv[i] = v requires v in (0, 1)\n" + " i == %s " % i) self._handleBounds() - - # integer-like methods def __add__(self, other): @@ -198,6 +192,7 @@ class intbv(object): return self._val + other._val else: return self._val + other + def __radd__(self, other): return other + self._val @@ -206,6 +201,7 @@ class intbv(object): return self._val - other._val else: return self._val - other + def __rsub__(self, other): return other - self._val @@ -214,6 +210,7 @@ class intbv(object): return self._val * other._val else: return self._val * other + def __rmul__(self, other): return other * self._val @@ -222,6 +219,7 @@ class intbv(object): return self._val / other._val else: return self._val / other + def __rtruediv__(self, other): return other / self._val @@ -230,6 +228,7 @@ class intbv(object): return self._val // other._val else: return self._val // other + def __rfloordiv__(self, other): return other // self._val @@ -238,6 +237,7 @@ class intbv(object): return self._val % other._val else: return self._val % other + def __rmod__(self, other): return other % self._val @@ -248,6 +248,7 @@ class intbv(object): return self._val ** other._val else: return self._val ** other + def __rpow__(self, other): return other ** self._val @@ -256,6 +257,7 @@ class intbv(object): return intbv(long(self._val) << other._val) else: return intbv(long(self._val) << other) + def __rlshift__(self, other): return other << self._val @@ -264,6 +266,7 @@ class intbv(object): return intbv(self._val >> other._val) else: return intbv(self._val >> other) + def __rrshift__(self, other): return other >> self._val @@ -272,6 +275,7 @@ class intbv(object): return intbv(self._val & other._val) else: return intbv(self._val & other) + def __rand__(self, other): return intbv(other & self._val) @@ -280,6 +284,7 @@ class intbv(object): return intbv(self._val | other._val) else: return intbv(self._val | other) + def __ror__(self, other): return intbv(other | self._val) @@ -288,6 +293,7 @@ class intbv(object): return intbv(self._val ^ other._val) else: return intbv(self._val ^ other) + def __rxor__(self, other): return intbv(other ^ self._val) @@ -325,6 +331,7 @@ class intbv(object): def __idiv__(self, other): raise TypeError("intbv: Augmented classic division not supported") + def __itruediv__(self, other): raise TypeError("intbv: Augmented true division not supported") @@ -430,26 +437,31 @@ class intbv(object): return self._val == other._val else: return self._val == other + def __ne__(self, other): if isinstance(other, intbv): return self._val != other._val else: return self._val != other + def __lt__(self, other): if isinstance(other, intbv): return self._val < other._val else: return self._val < other + def __le__(self, other): if isinstance(other, intbv): return self._val <= other._val else: return self._val <= other + def __gt__(self, other): if isinstance(other, intbv): return self._val > other._val else: return self._val > other + def __ge__(self, other): if isinstance(other, intbv): return self._val >= other._val @@ -475,7 +487,6 @@ class intbv(object): def __repr__(self): return "intbv(" + repr(self._val) + ")" - def signed(self): ''' Return new intbv with the values interpreted as signed diff --git a/myhdl/_join.py b/myhdl/_join.py index f757ec85..cc5feef6 100644 --- a/myhdl/_join.py +++ b/myhdl/_join.py @@ -28,11 +28,10 @@ class join(object): """ Construct join object *args -- list of trigger object arguments. - + """ self._args = args def _generator(self): yield join(*self._args) - diff --git a/myhdl/_misc.py b/myhdl/_misc.py index 5f4062ab..36f42372 100644 --- a/myhdl/_misc.py +++ b/myhdl/_misc.py @@ -32,6 +32,7 @@ import inspect from myhdl._Cosimulation import Cosimulation from myhdl._instance import _Instantiator + def _isGenSeq(obj): if isinstance(obj, (Cosimulation, _Instantiator)): return True @@ -50,10 +51,11 @@ def instances(): d = inspect.getouterframes(f)[1][0].f_locals l = [] for v in d.values(): - if _isGenSeq(v): - l.append(v) + if _isGenSeq(v): + l.append(v) return l + def downrange(start, stop=0, step=1): """ Return a downward range. """ return range(start - 1, stop - 1, -step) diff --git a/myhdl/_modbv.py b/myhdl/_modbv.py index bd57bee5..8a85768c 100644 --- a/myhdl/_modbv.py +++ b/myhdl/_modbv.py @@ -23,6 +23,7 @@ from __future__ import absolute_import from ._intbv import intbv from ._compat import long + class modbv(intbv): __slots__ = [] @@ -35,7 +36,6 @@ class modbv(intbv): def __repr__(self): return "modbv(" + repr(self._val) + ")" - # indexing and slicing methods # dedicated for modbv to support "declaration by slicing" @@ -46,18 +46,17 @@ class modbv(intbv): j = 0 j = int(j) if j < 0: - raise ValueError("modbv[i:j] requires j >= 0\n" \ - " j == %s" % j) + raise ValueError("modbv[i:j] requires j >= 0\n" + " j == %s" % j) if i is None: # default return modbv(self._val >> j) i = int(i) if i <= j: - raise ValueError("modbv[i:j] requires i > j\n" \ - " i, j == %s, %s" % (i, j)) + raise ValueError("modbv[i:j] requires i > j\n" + " i, j == %s, %s" % (i, j)) res = modbv((self._val & (long(1) << i) - 1) >> j, _nrbits=i - j) return res else: i = int(key) res = bool((self._val >> i) & 0x1) return res - diff --git a/myhdl/_resolverefs.py b/myhdl/_resolverefs.py index 1d7986f1..2c97dd61 100644 --- a/myhdl/_resolverefs.py +++ b/myhdl/_resolverefs.py @@ -24,6 +24,7 @@ def _resolveRefs(symdict, arg): # TODO: Refactor this into two separate nodetransformers, since _resolveRefs # needs only the names, not the objects + def _suffixer(name, used_names): suffixed_names = (name + '_renamed{0}'.format(i) for i in itertools.count()) new_names = itertools.chain([name], suffixed_names) @@ -31,6 +32,7 @@ def _suffixer(name, used_names): class _AttrRefTransformer(ast.NodeTransformer): + def __init__(self, data): self.data = data self.data.objlist = [] diff --git a/myhdl/_simulator.py b/myhdl/_simulator.py index 779efa3c..9e3013c9 100644 --- a/myhdl/_simulator.py +++ b/myhdl/_simulator.py @@ -25,8 +25,6 @@ now -- function that returns the current simulation time """ - - _signals = [] _siglist = [] _futureEvents = [] @@ -35,6 +33,7 @@ _cosim = 0 _tracing = 0 _tf = None + def now(): """ Return the current simulation time """ return _time diff --git a/myhdl/_traceSignals.py b/myhdl/_traceSignals.py index bed895ca..66b17ecd 100644 --- a/myhdl/_traceSignals.py +++ b/myhdl/_traceSignals.py @@ -24,7 +24,6 @@ from __future__ import absolute_import from __future__ import print_function - import sys import time import os @@ -43,6 +42,7 @@ _tracing = 0 _profileFunc = None vcdpath = '' + class _error: pass _error.TopLevelName = "result of traceSignals call should be assigned to a top level name" @@ -110,7 +110,8 @@ class _TraceSignalsClass(object): if isinstance(dut, _Block): h = _getHierarchy(name, dut) else: - warnings.warn("\n traceSignals(): Deprecated usage: See http://dev.myhdl.org/meps/mep-114.html", stacklevel=2) + warnings.warn( + "\n traceSignals(): Deprecated usage: See http://dev.myhdl.org/meps/mep-114.html", stacklevel=2) h = _HierExtr(name, dut, *args, **kwargs) if self.filename is None: @@ -142,12 +143,14 @@ for i in range(33, 127): _codechars += chr(i) _mod = len(_codechars) + def _genNameCode(): n = 0 while 1: yield _namecode(n) n += 1 + def _namecode(n): q, r = divmod(n, _mod) code = _codechars[r] @@ -156,6 +159,7 @@ def _namecode(n): code = _codechars[r] + code return code + def _writeVcdHeader(f, timescale): print("$date", file=f) print(" %s" % time.asctime(), file=f) @@ -168,6 +172,7 @@ def _writeVcdHeader(f, timescale): print("$end", file=f) print(file=f) + def _getSval(s): if isinstance(s, _TristateSignal): sval = s._orival @@ -177,6 +182,7 @@ def _getSval(s): sval = s._val return sval + def _writeVcdSigs(f, hierarchy, tracelists): curlevel = 0 namegen = _genNameCode() diff --git a/myhdl/_tristate.py b/myhdl/_tristate.py index 5c095cf8..4aa3b305 100644 --- a/myhdl/_tristate.py +++ b/myhdl/_tristate.py @@ -4,11 +4,13 @@ import warnings from myhdl._Signal import _Signal, _DelayedSignal from myhdl._simulator import _siglist + class BusContentionWarning(UserWarning): pass warnings.filterwarnings('always', r".*", BusContentionWarning) + def Tristate(val, delay=None): """ Return a new Tristate(default or delay 0) or DelayedTristate """ if delay is not None: @@ -56,13 +58,13 @@ class _TristateDriver(_Signal): @_Signal.next.setter def next(self, val): - if isinstance(val, _Signal): + if isinstance(val, _Signal): val = val._val - if val is None: - self._next = None - else: - self._setNextVal(val) - _siglist.append(self._bus) + if val is None: + self._next = None + else: + self._setNextVal(val) + _siglist.append(self._bus) class _DelayedTristate(_DelayedSignal, _Tristate): diff --git a/myhdl/_visitors.py b/myhdl/_visitors.py index 82a79e4b..2e041245 100644 --- a/myhdl/_visitors.py +++ b/myhdl/_visitors.py @@ -5,6 +5,7 @@ from myhdl._Signal import _Signal, _isListOfSigs class _SigNameVisitor(ast.NodeVisitor): + def __init__(self, symdict): self.toplevel = 1 self.symdict = symdict @@ -31,7 +32,7 @@ class _SigNameVisitor(ast.NodeVisitor): def visit_If(self, node): if not node.orelse: if isinstance(node.test, ast.Name) and \ - node.test.id == '__debug__': + node.test.id == '__debug__': return # skip self.generic_visit(node) diff --git a/myhdl/conversion/_analyze.py b/myhdl/conversion/_analyze.py index 2c19045f..a5b88cec 100644 --- a/myhdl/conversion/_analyze.py +++ b/myhdl/conversion/_analyze.py @@ -55,11 +55,12 @@ builtinObjects = builtins.__dict__.values() _enumTypeSet = set() + def _makeName(n, prefixes, namedict): # trim empty prefixes prefixes = [p for p in prefixes if p] if len(prefixes) > 1: -# name = '_' + '_'.join(prefixes[1:]) + '_' + n + # name = '_' + '_'.join(prefixes[1:]) + '_' + n name = '_'.join(prefixes[1:]) + '_' + n else: name = n @@ -136,7 +137,6 @@ def _analyzeSigs(hierarchy, hdl='Verilog'): return siglist, memlist - def _analyzeGens(top, absnames): genlist = [] for g in top: @@ -238,13 +238,15 @@ class _FirstPassVisitor(ast.NodeVisitor, _ConversionMixin): def visit_ListComp(self, node): if len(node.generators) > 1: - self.raiseError(node, _error.NotSupported, "multiple for statements in list comprehension") + self.raiseError(node, _error.NotSupported, + "multiple for statements in list comprehension") if node.generators[0].ifs: self.raiseError(node, _error.NotSupported, "if statement in list comprehension") self.generic_visit(node) def visit_List(self, node): self.raiseError(node, _error.NotSupported, "list") + def visitSliceObj(self, node): self.raiseError(node, _error.NotSupported, "slice object") @@ -255,10 +257,10 @@ class _FirstPassVisitor(ast.NodeVisitor, _ConversionMixin): # Legacy try blocks def visit_TryExcept(self, node): self.raiseError(node, _error.NotSupported, "try-except statement") + def visit_TryFinally(self, node): self.raiseError(node, _error.NotSupported, "try-finally statement") - def visit_Assign(self, node): if len(node.targets) > 1: self.raiseError(node, _error.NotSupported, "multiple assignments") @@ -297,7 +299,7 @@ class _FirstPassVisitor(ast.NodeVisitor, _ConversionMixin): # put official docstrings aside for separate processing node.doc = None if node.body and isinstance(node.body[0], ast.Expr) and \ - isinstance(node.body[0].value, ast.Str): + isinstance(node.body[0].value, ast.Str): node.doc = node.body[0].value.s node.body = node.body[1:] self.visitList(node.body) @@ -306,8 +308,8 @@ class _FirstPassVisitor(ast.NodeVisitor, _ConversionMixin): """ Flatten if-then-else as in compiler package.""" if node: if len(node) == 1 and \ - isinstance(node[0], ast.If) and \ - node[0].body[0].col_offset == co: # ugly hack to detect separate else clause + isinstance(node[0], ast.If) and \ + node[0].body[0].col_offset == co: # ugly hack to detect separate else clause elifnode = node[0] tests.append((elifnode.test, elifnode.body)) self.flattenIf(elifnode.orelse, tests, else_, co) @@ -331,7 +333,6 @@ class _FirstPassVisitor(ast.NodeVisitor, _ConversionMixin): node.tests = tests node.else_ = else_ - def visit_Print(self, node): if node.dest is not None: self.raiseError(node, _error.NotSupported, "printing to a file with >> syntax") @@ -339,14 +340,12 @@ class _FirstPassVisitor(ast.NodeVisitor, _ConversionMixin): self.raiseError(node, _error.NotSupported, "printing without newline") - - - def getNrBits(obj): if hasattr(obj, '_nrbits'): return obj._nrbits return None + def hasType(obj, theType): if isinstance(obj, theType): return True @@ -357,10 +356,13 @@ def hasType(obj, theType): 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: @@ -368,20 +370,22 @@ class ReferenceStack(list): return False - class _Ram(object): __slots__ = ['elObj', 'depth'] class _Rom(object): __slots__ = ['rom'] + def __init__(self, rom): self.rom = rom re_str = re.compile(r"[^%]+") re_ConvSpec = re.compile(r"%(?P[-]?)(?P[0-9]*)(?P[sd])") + class ConvSpec(object): + def __init__(self, **kwargs): self.justified = "RIGHT" self.width = 0 @@ -395,6 +399,7 @@ class ConvSpec(object): defaultConvSpec = ConvSpec(**re_ConvSpec.match(r"%s").groupdict()) + def _getNritems(obj): """Return the number of items in an objects' type""" if isinstance(obj, _Signal): @@ -439,7 +444,8 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin): self.visit(n) for n in node.values: if not hasType(n.obj, bool): - self.raiseError(node, _error.NotSupported, "non-boolean argument in logical operator") + self.raiseError(node, _error.NotSupported, + "non-boolean argument in logical operator") node.obj = bool() def visit_UnaryOp(self, node): @@ -589,7 +595,8 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin): elif f is ord: node.obj = int(-1) if not (isinstance(node.args[0], ast.Str) and (len(node.args[0].s) == 1)): - self.raiseError(node, _error.NotSupported, "ord: expect string argument with length 1") + self.raiseError(node, _error.NotSupported, + "ord: expect string argument with length 1") elif f is delay: node.obj = delay(0) # suprize: identity comparison on unbound methods doesn't work in python 2.5?? @@ -807,8 +814,8 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin): node.obj = obj else: if n in ("__verilog__", "__vhdl__"): - self.raiseError(node, _error.NotSupported, - "%s in generator function" % n) + self.raiseError(node, _error.NotSupported, + "%s in generator function" % n) if n in self.globalRefs: self.raiseError(node, _error.UnboundLocal, n) self.refStack.add(n) @@ -1042,7 +1049,6 @@ class _AnalyzeBlockVisitor(_AnalyzeVisitor): if isinstance(v, _Signal): self.tree.sigdict[n] = v - def visit_FunctionDef(self, node): self.refStack.push() for n in node.body: @@ -1058,7 +1064,6 @@ class _AnalyzeBlockVisitor(_AnalyzeVisitor): self.tree.kind = _kind.INITIAL self.refStack.pop() - def visit_Module(self, node): self.generic_visit(node) for n in self.tree.outputs: @@ -1070,7 +1075,6 @@ class _AnalyzeBlockVisitor(_AnalyzeVisitor): s = self.tree.sigdict[n] s._markRead() - def visit_Return(self, node): # value should be None if node.value is None: @@ -1081,15 +1085,12 @@ class _AnalyzeBlockVisitor(_AnalyzeVisitor): self.raiseError(node, _error.NotSupported, "return value other than None") - - class _AnalyzeAlwaysCombVisitor(_AnalyzeBlockVisitor): def __init__(self, tree, senslist): _AnalyzeBlockVisitor.__init__(self, tree) self.tree.senslist = senslist - def visit_FunctionDef(self, node): self.refStack.push() for n in node.body: @@ -1112,9 +1113,6 @@ class _AnalyzeAlwaysCombVisitor(_AnalyzeBlockVisitor): self.tree.kind = _kind.ALWAYS_COMB self.refStack.pop() - - - def visit_Module(self, node): _AnalyzeBlockVisitor.visit_Module(self, node) if self.tree.kind == _kind.SIMPLE_ALWAYS_COMB: @@ -1135,7 +1133,6 @@ class _AnalyzeAlwaysSeqVisitor(_AnalyzeBlockVisitor): self.tree.sigregs = sigregs self.tree.varregs = varregs - def visit_FunctionDef(self, node): self.refStack.push() for n in node.body: @@ -1150,7 +1147,6 @@ class _AnalyzeAlwaysDecoVisitor(_AnalyzeBlockVisitor): _AnalyzeBlockVisitor.__init__(self, tree) self.tree.senslist = senslist - def visit_FunctionDef(self, node): self.refStack.push() for n in node.body: @@ -1159,7 +1155,6 @@ class _AnalyzeAlwaysDecoVisitor(_AnalyzeBlockVisitor): self.refStack.pop() - class _AnalyzeFuncVisitor(_AnalyzeVisitor): def __init__(self, tree, args, keywords): @@ -1169,7 +1164,6 @@ class _AnalyzeFuncVisitor(_AnalyzeVisitor): self.tree.hasReturn = False self.tree.returnObj = None - def visit_FunctionDef(self, node): self.refStack.push() argnames = _get_argnames(node) @@ -1199,8 +1193,6 @@ class _AnalyzeFuncVisitor(_AnalyzeVisitor): self.raiseError(node, _error.NotSupported, "pure function without return value") - - def visit_Return(self, node): self.kind = _kind.DECLARATION if node.value is not None: @@ -1233,6 +1225,8 @@ class _AnalyzeFuncVisitor(_AnalyzeVisitor): ismethod = inspect.ismethod # inspect doc is wrong: ismethod checks both bound and unbound methods + + def isboundmethod(m): return ismethod(m) and m.__self__ is not None @@ -1264,6 +1258,7 @@ def _analyzeTopFunc(func, *args, **kwargs): return v + class _AnalyzeTopFuncVisitor(_AnalyzeVisitor): def __init__(self, func, tree, *args, **kwargs): diff --git a/myhdl/conversion/_misc.py b/myhdl/conversion/_misc.py index 2e9ce48a..ebdea1e3 100644 --- a/myhdl/conversion/_misc.py +++ b/myhdl/conversion/_misc.py @@ -28,6 +28,7 @@ import ast from myhdl import ConversionError from myhdl._compat import PY2 + class _error(object): FirstArgType = "first argument should be a classic function" ArgType = "leaf cell type error" @@ -57,9 +58,9 @@ class _error(object): ExtraArguments = "Extra positional or named arguments are not supported" UnsupportedYield = "Unsupported yield statement" UnsupportedListComp = \ - "Unsupported list comprehension form: should be [intbv()[n:] for i in range(m)]" + "Unsupported list comprehension form: should be [intbv()[n:] for i in range(m)]" ListElementAssign = \ - "Can't assign to list element; use slice assignment to change its value" + "Can't assign to list element; use slice assignment to change its value" NotASignal = "Non-local object should be a Signal" UnsupportedType = "Object type is not supported in this context" InconsistentType = "Signal elements should have the same base type" @@ -75,11 +76,13 @@ class _error(object): class _access(object): INPUT, OUTPUT, INOUT, UNKNOWN = range(4) + class _kind(object): NORMAL, DECLARATION, ALWAYS, INITIAL, ALWAYS_DECO, \ - ALWAYS_COMB, SIMPLE_ALWAYS_COMB, ALWAYS_SEQ, \ - TASK, REG \ - = range(10) + ALWAYS_COMB, SIMPLE_ALWAYS_COMB, ALWAYS_SEQ, \ + TASK, REG \ + = range(10) + class _context(object): BOOLEAN, YIELD, PRINT, SIGNED, UNKNOWN = range(5) @@ -87,15 +90,15 @@ class _context(object): 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 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 getLineNo(self, node): lineno = 0 @@ -141,7 +144,7 @@ class _ConversionMixin(object): def raiseError(self, node, kind, msg=""): lineno = self.getLineNo(node) info = "in file %s, line %s:\n " % \ - (self.tree.sourcefile, self.tree.lineoffset + lineno) + (self.tree.sourcefile, self.tree.lineoffset + lineno) raise ConversionError(kind, msg, info) def require(self, node, test, msg=""): @@ -158,7 +161,6 @@ class _ConversionMixin(object): self.visit(n) - def _LabelGenerator(): i = 1 while 1: @@ -167,20 +169,28 @@ def _LabelGenerator(): _genLabel = _LabelGenerator() + class _Label(object): + def __init__(self, name): self.name = next(_genLabel) + '_' + name self.isActive = False + def __str__(self): return str(self.name) # this can be made more sophisticated to deal with existing suffixes # also, may require reset facility + + class _UniqueSuffixGenerator(object): + def __init__(self): self.i = 0 + def reset(self): self.i = 0 + def next(self): self.i += 1 return "_%s" % self.i @@ -199,6 +209,7 @@ def _isConstant(tree, symdict): return False return True + class _namesVisitor(ast.NodeVisitor): def __init__(self): @@ -207,6 +218,7 @@ class _namesVisitor(ast.NodeVisitor): def visit_Name(self, node): self.names.append(node.id) + def _get_argnames(node): if PY2: return [arg.id for arg in node.args.args] diff --git a/myhdl/conversion/_toVHDL.py b/myhdl/conversion/_toVHDL.py index c17d8004..a518232e 100644 --- a/myhdl/conversion/_toVHDL.py +++ b/myhdl/conversion/_toVHDL.py @@ -65,11 +65,13 @@ _converting = 0 _profileFunc = None _enumPortTypeSet = set() + def _checkArgs(arglist): for arg in arglist: if not isinstance(arg, (GeneratorType, _Instantiator, _UserVhdlCode)): raise ToVHDLError(_error.ArgType, arg) + def _flatten(*args): arglist = [] for arg in args: @@ -88,6 +90,7 @@ def _flatten(*args): arglist.append(arg) return arglist + def _makeDoc(doc, indent=''): if doc is None: return '' @@ -152,7 +155,8 @@ class _ToVHDLConvertor(object): finally: _converting = 0 else: - warnings.warn("\n toVHDL(): Deprecated usage: See http://dev.myhdl.org/meps/mep-114.html", stacklevel=2) + warnings.warn( + "\n toVHDL(): Deprecated usage: See http://dev.myhdl.org/meps/mep-114.html", stacklevel=2) try: h = _HierExtr(name, func, *args, **kwargs) finally: @@ -263,7 +267,6 @@ class _ToVHDLConvertor(object): self.architecture = "MyHDL" self.std_logic_ports = False - def _convert_filter(self, h, intf, siglist, memlist, genlist): # intended to be a entry point for other uses: # code checking, optimizations, etc @@ -278,6 +281,7 @@ myhdl_header = """\ -- Date: $date """ + def _writeFileHeader(f, fn): vars = dict(filename=fn, version=myhdl.__version__, @@ -306,6 +310,7 @@ def _writeCustomPackage(f, intf): portConversions = [] + def _writeModuleHeader(f, intf, needPck, lib, arch, useClauses, doc, stdLogicPorts): print("library IEEE;", file=f) print("use IEEE.std_logic_1164.all;", file=f) @@ -379,6 +384,7 @@ def _writeFuncDecls(f): return # print >> f, package + def _writeTypeDefs(f): f.write("\n") sortedList = list(_enumTypeSet) @@ -389,6 +395,7 @@ def _writeTypeDefs(f): constwires = [] + def _writeSigDecls(f, intf, siglist, memlist): del constwires[:] for s in siglist: @@ -433,13 +440,16 @@ def _writeSigDecls(f, intf, siglist, memlist): print("signal %s: %s;" % (m.name, t), file=f) print(file=f) + def _writeCompDecls(f, compDecls): if compDecls is not None: print(compDecls, file=f) + def _writeModuleFooter(f, arch): print("end architecture %s;" % arch, file=f) + def _getRangeString(s): if isinstance(s._val, EnumItemType): return '' @@ -451,6 +461,7 @@ def _getRangeString(s): else: raise AssertionError + def _getTypeString(s): if isinstance(s._val, EnumItemType): return s._val._type._name @@ -461,6 +472,7 @@ def _getTypeString(s): else: return 'unsigned' + def _convertGens(genlist, siglist, memlist, vfile): blockBuf = StringIO() funcBuf = StringIO() @@ -482,7 +494,8 @@ def _convertGens(genlist, siglist, memlist, vfile): Visitor = _ConvertAlwaysCombVisitor v = Visitor(tree, blockBuf, funcBuf) v.visit(tree) - vfile.write(funcBuf.getvalue()); funcBuf.close() + vfile.write(funcBuf.getvalue()) + funcBuf.close() print("begin", file=vfile) print(file=vfile) for st in portConversions: @@ -523,7 +536,8 @@ def _convertGens(genlist, siglist, memlist, vfile): if hasattr(s, 'toVHDL'): print(s.toVHDL(), file=vfile) print(file=vfile) - vfile.write(blockBuf.getvalue()); blockBuf.close() + vfile.write(blockBuf.getvalue()) + blockBuf.close() opmap = { @@ -654,8 +668,10 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin): tipe = obj._val._type._name else: tipe = vhd.toStr(constr) - if kind: kind += " " - if dir: dir += " " + if kind: + kind += " " + if dir: + dir += " " self.write("%s%s: %s%s%s" % (kind, name, dir, tipe, endchar)) def writeDeclarations(self): @@ -780,10 +796,10 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin): # Fix: restore python2 behavior by a shortcut: invert value of Num, inherit # vhdl type from UnaryOp node, and visit the modified operand if isinstance(node.op, ast.USub) and isinstance(node.operand, ast.Num): - node.operand.n = -node.operand.n - node.operand.vhd = node.vhd - self.visit(node.operand) - return + node.operand.n = -node.operand.n + node.operand.vhd = node.vhd + self.visit(node.operand) + return pre, suf = self.inferCast(node.vhd, node.vhdOri) self.write(pre) self.write("(") @@ -1094,7 +1110,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin): self.write("%s'(\"%s\")" % (typemark, node.s)) def visit_Continue(self, node, *args): - self.write("next;") + self.write("next;") def visit_Expr(self, node): expr = node.value @@ -1629,7 +1645,9 @@ class _ConvertAlwaysCombVisitor(_ConvertVisitor): for item in senslist: name = item._name.split('(', 1)[0] if not name in r: - r.append(name) # note that the list now contains names and not Signals, but we are interested in the strings anyway ... + # note that the list now contains names and not Signals, but we are + # interested in the strings anyway ... + r.append(name) return r self.writeDoc(node) @@ -1888,21 +1906,24 @@ class _ConvertTaskVisitor(_ConvertVisitor): self.writeline(2) - - # type inference class vhd_type(object): + def __init__(self, size=0): self.size = size + def __repr__(self): return "%s(%s)" % (type(self).__name__, self.size) + class vhd_string(vhd_type): pass + class vhd_enum(vhd_type): + def __init__(self, tipe): self._type = tipe @@ -1911,42 +1932,57 @@ class vhd_enum(vhd_type): class vhd_std_logic(vhd_type): + def __init__(self, size=0): vhd_type.__init__(self) self.size = 1 + def toStr(self, constr=True): return 'std_logic' + class vhd_boolean(vhd_type): + def __init__(self, size=0): vhd_type.__init__(self) self.size = 1 + def toStr(self, constr=True): return 'boolean' + class vhd_vector(vhd_type): + def __init__(self, size=0): vhd_type.__init__(self, size) + class vhd_unsigned(vhd_vector): + def toStr(self, constr=True): if constr: return "unsigned(%s downto 0)" % (self.size - 1) else: return "unsigned" + class vhd_signed(vhd_vector): + 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 vhd_nat(vhd_int): + def toStr(self, constr=True): return "natural" @@ -1954,6 +1990,7 @@ class vhd_nat(vhd_int): class _loopInt(int): pass + def maxType(o1, o2): s1 = s2 = 0 if isinstance(o1, vhd_type): @@ -1972,6 +2009,7 @@ def maxType(o1, o2): else: return None + def inferVhdlObj(obj): vhd = None if (isinstance(obj, _Signal) and obj._type is intbv) or \ @@ -1981,10 +2019,10 @@ def inferVhdlObj(obj): else: vhd = vhd_unsigned(size=len(obj)) elif (isinstance(obj, _Signal) and obj._type is bool) or \ - isinstance(obj, bool): + isinstance(obj, bool): vhd = vhd_std_logic() elif (isinstance(obj, _Signal) and isinstance(obj._val, EnumItemType)) or\ - isinstance(obj, EnumItemType): + isinstance(obj, EnumItemType): if isinstance(obj, _Signal): tipe = obj._val._type else: @@ -1998,6 +2036,7 @@ def inferVhdlObj(obj): # vhd = vhd_int() return vhd + def maybeNegative(vhd): if isinstance(vhd, vhd_signed): return True @@ -2005,6 +2044,7 @@ def maybeNegative(vhd): return True return False + class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin): def __init__(self, tree): @@ -2251,10 +2291,10 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin): node.vhd = copy(node.operand.vhd) if isinstance(node.op, ast.Not): # postpone this optimization until initial values are written -# if isinstance(node.operand.vhd, vhd_std_logic): -# node.vhd = vhd_std_logic() -# else: -# node.vhd = node.operand.vhd = vhd_boolean() + # if isinstance(node.operand.vhd, vhd_std_logic): + # node.vhd = vhd_std_logic() + # else: + # node.vhd = node.operand.vhd = vhd_boolean() node.vhd = node.operand.vhd = vhd_boolean() elif isinstance(node.op, ast.USub): if isinstance(node.vhd, vhd_unsigned): diff --git a/myhdl/conversion/_toVerilog.py b/myhdl/conversion/_toVerilog.py index f5922315..25c28d50 100644 --- a/myhdl/conversion/_toVerilog.py +++ b/myhdl/conversion/_toVerilog.py @@ -59,11 +59,13 @@ from myhdl._getHierarchy import _getHierarchy _converting = 0 _profileFunc = None + def _checkArgs(arglist): for arg in arglist: if not isinstance(arg, (GeneratorType, _Instantiator, _UserVerilogCode)): raise ToVerilogError(_error.ArgType, arg) + def _flatten(*args): arglist = [] for arg in args: @@ -148,7 +150,8 @@ class _ToVerilogConvertor(object): finally: _converting = 0 else: - warnings.warn("\n toVerilog(): Deprecated usage: See http://dev.myhdl.org/meps/mep-114.html", stacklevel=2) + warnings.warn( + "\n toVerilog(): Deprecated usage: See http://dev.myhdl.org/meps/mep-114.html", stacklevel=2) try: h = _HierExtr(name, func, *args, **kwargs) finally: @@ -205,8 +208,10 @@ class _ToVerilogConvertor(object): # build portmap for cosimulation portmap = {} for n, s in intf.argdict.items(): - if hasattr(s, 'driver'): portmap[n] = s.driver() - else: portmap[n] = s + if hasattr(s, 'driver'): + portmap[n] = s.driver() + else: + portmap[n] = s self.portmap = portmap ### clean-up properly ### @@ -232,7 +237,6 @@ class _ToVerilogConvertor(object): self.no_testbench = False self.trace = False - def _convert_filter(self, h, intf, siglist, memlist, genlist): # intended to be a entry point for other uses: # code checking, optimizations, etc @@ -247,6 +251,7 @@ myhdl_header = """\ // Date: $date """ + def _writeFileHeader(f, fn, ts): vars = dict(filename=fn, version=myhdl.__version__, @@ -419,6 +424,7 @@ def _getRangeString(s): else: raise AssertionError + def _getSignString(s): if s._min is not None and s._min < 0: return "signed " @@ -447,8 +453,10 @@ def _convertGens(genlist, vfile): Visitor = _ConvertAlwaysCombVisitor v = Visitor(tree, blockBuf, funcBuf) v.visit(tree) - vfile.write(funcBuf.getvalue()); funcBuf.close() - vfile.write(blockBuf.getvalue()); blockBuf.close() + vfile.write(funcBuf.getvalue()) + funcBuf.close() + vfile.write(blockBuf.getvalue()) + blockBuf.close() opmap = { @@ -485,7 +493,6 @@ nameconstant_map = { } - class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin): def __init__(self, tree, buf): @@ -501,7 +508,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin): def raiseError(self, node, kind, msg=""): lineno = self.getLineNo(node) info = "in file %s, line %s:\n " % \ - (self.tree.sourcefile, self.tree.lineoffset + lineno) + (self.tree.sourcefile, self.tree.lineoffset + lineno) raise ToVerilogError(kind, msg, info) def write(self, arg): @@ -543,7 +550,8 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin): return r def writeDeclaration(self, obj, name, dir): - if dir: dir = dir + ' ' + if dir: + dir = dir + ' ' if type(obj) is bool: self.write("%s%s" % (dir, name)) elif isinstance(obj, int): @@ -1177,8 +1185,8 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin): def accessIndex(self, node): addSignBit = isinstance(node.ctx, ast.Load) and \ - (not node.signed) and \ - (self.context == _context.SIGNED) + (not node.signed) and \ + (self.context == _context.SIGNED) if addSignBit: self.write("$signed({1'b0, ") self.context = None @@ -1287,7 +1295,6 @@ class _ConvertInitialVisitor(_ConvertVisitor): self.writeline(2) - class _ConvertAlwaysCombVisitor(_ConvertVisitor): def __init__(self, tree, blockBuf, funcBuf): @@ -1307,12 +1314,12 @@ class _ConvertAlwaysCombVisitor(_ConvertVisitor): self.writeline(2) - class _ConvertSimpleAlwaysCombVisitor(_ConvertVisitor): def __init__(self, tree, blockBuf, funcBuf): _ConvertVisitor.__init__(self, tree, blockBuf) self.funcBuf = funcBuf + def visit_Attribute(self, node): if isinstance(node.ctx, ast.Store): self.write("assign ") @@ -1443,8 +1450,6 @@ class _ConvertFunctionVisitor(_ConvertVisitor): self.write("disable %s;" % self.returnLabel) - - class _ConvertTaskVisitor(_ConvertVisitor): def __init__(self, tree, funcBuf): @@ -1486,6 +1491,7 @@ def _maybeNegative(obj): return True return False + class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin): def __init__(self, tree): @@ -1555,7 +1561,6 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin): return self.generic_visit(node) - def visit_Num(self, node): node.signed = False diff --git a/myhdl/conversion/_verify.py b/myhdl/conversion/_verify.py index 16623523..a4969bd9 100644 --- a/myhdl/conversion/_verify.py +++ b/myhdl/conversion/_verify.py @@ -46,7 +46,7 @@ registerSimulator( analyze="ghdl -a --std=08 --workdir=work pck_myhdl_%(version)s.vhd %(topname)s.vhd", elaborate="ghdl -e --std=08 --workdir=work %(unitname)s", simulate="ghdl -r --workdir=work %(unitname)s" - ) +) registerSimulator( name="nvc", @@ -54,7 +54,7 @@ registerSimulator( analyze="nvc --work=work_nvc -a pck_myhdl_%(version)s.vhd %(topname)s.vhd", elaborate="nvc --work=work_nvc -e %(topname)s", simulate="nvc --work=work_nvc -r %(topname)s" - ) +) registerSimulator( name="vlog", @@ -64,7 +64,7 @@ registerSimulator( skiplines=6, skipchars=2, ignore=("# **", "# //", "# run -all") - ) +) registerSimulator( name="vcom", @@ -74,7 +74,7 @@ registerSimulator( skiplines=6, skipchars=2, ignore=("# **", "# //", "# Time:", "# run -all") - ) +) registerSimulator( @@ -82,7 +82,7 @@ registerSimulator( hdl="Verilog", analyze="iverilog -o %(topname)s.o %(topname)s.v", simulate="vvp %(topname)s.o" - ) +) registerSimulator( name="cver", @@ -90,7 +90,7 @@ registerSimulator( analyze="cver -c -q %(topname)s.v", simulate="cver -q %(topname)s.v", skiplines=3 - ) +) class _VerificationClass(object): @@ -101,7 +101,6 @@ class _VerificationClass(object): self.simulator = None self._analyzeOnly = analyzeOnly - def __call__(self, func, *args, **kwargs): if not self.simulator: @@ -117,7 +116,8 @@ class _VerificationClass(object): elif isinstance(func, _Block): name = func.func.__name__ else: - warnings.warn("\n analyze()/verify(): Deprecated usage: See http://dev.myhdl.org/meps/mep-114.html", stacklevel=2) + warnings.warn( + "\n analyze()/verify(): Deprecated usage: See http://dev.myhdl.org/meps/mep-114.html", stacklevel=2) try: name = func.__name__ except: @@ -185,7 +185,6 @@ class _VerificationClass(object): print("No MyHDL simulation output - nothing to verify", file=sys.stderr) return 1 - if elaborate is not None: # print(elaborate) ret = subprocess.call(elaborate, shell=True) diff --git a/pylintrc b/pylintrc index 17f9b21c..e31aa453 100644 --- a/pylintrc +++ b/pylintrc @@ -164,7 +164,7 @@ bad-functions=map,filter,apply,input module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ # Regular expression which should only match correct module level names -const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ +const-rgx=(([a-zA-Z_][a-zA-Z0-9_]*)|(__.*__))$ # Regular expression which should only match correct class names class-rgx=[A-Z_][a-zA-Z0-9]+$