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

MEP107(Conversion of attribute signal containers) support

--HG--
branch : 0.9-dev
This commit is contained in:
Keerthan Jaic 2013-08-07 17:49:09 -04:00
commit 409c07ee87
13 changed files with 732 additions and 304 deletions

View File

@ -30,4 +30,4 @@ old_conversion/
work/
work_vlog/
work_vcom/
*egg-info/

View File

@ -0,0 +1,54 @@
.. currentmodule:: myhdl
.. _new09:
***********************
What's new in MyHDL 0.9
***********************
:Author:
Interfaces
===========
Rationale
---------
Complex designs often have many signals (ports) that
are passed to different levels of hierarchy. Typically
many of the signals can logically be grouped together.
Grouping the signals into an *interface* simplifies the
code, improves efficiency, and reduces errors.
Previous versions supported /interfaces/ for modeling
and for conversion if the **attributes** were locally
referenced in a MyHDL module. The proposed solution
will convert an example like the following:
def complex_mult(clock,reset,a,b,c):
@always_seq(clock.posedge,reset=reset)
def rtl_mult():
c.real.next = (a.real*b.real) - (a.imag*b.imag)
c.imag.next = (a.real*b.imag) + (a.imag*b.real)
return rtl_mult
Solution
--------
The proposed solution is to create uniques names for
attributes which are type Signal and used by a module.
The converter will create a unique name by using the
name of the parent and the name of the attribute along
with the name of the MyHDL module instance (if applicable).
Conversion
----------
See also
--------
For additional information see the original proposal `mep-107`_.
.. _mep-107: http://http://myhdl.org/doku.php/meps:mep-107

View File

@ -31,6 +31,7 @@ from myhdl._util import _isGenFunc, _dedent
from myhdl._cell_deref import _cell_deref
from myhdl._Waiter import _Waiter, _SignalWaiter, _SignalTupleWaiter
from myhdl._instance import _Instantiator
from myhdl._resolverefs import _AttrRefTransformer
class _error:
pass
@ -40,7 +41,7 @@ _error.Scope = "always_comb argument should be a local function"
_error.SignalAsInout = "signal (%s) used as inout in always_comb function argument"
_error.EmbeddedFunction = "embedded functions in always_comb function argument not supported"
_error.EmptySensitivityList= "sensitivity list is empty"
def always_comb(func):
if not isinstance( func, FunctionType):
raise AlwaysCombError(_error.ArgType)
@ -63,7 +64,7 @@ def always_comb(func):
raise NameError(n)
c = _AlwaysComb(func, symdict)
return c
INPUT, OUTPUT, INOUT = range(3)
@ -115,7 +116,7 @@ class _SigNameVisitor(ast.NodeVisitor):
raise AlwaysCombError(_error.SignalAsInout % id)
else:
raise AssertionError("bug in always_comb")
def visit_Assign(self, node):
self.context = OUTPUT
for n in node.targets:
@ -136,7 +137,7 @@ class _SigNameVisitor(ast.NodeVisitor):
self.visit(node.target)
self.context = INPUT
self.visit(node.value)
def visit_ClassDef(self, node):
pass # skip
@ -146,7 +147,7 @@ class _SigNameVisitor(ast.NodeVisitor):
def visit_Print(self, node):
pass # skip
class _AlwaysComb(_Instantiator):
@ -186,7 +187,9 @@ class _AlwaysComb(_Instantiator):
s = _dedent(s)
tree = ast.parse(s)
# print ast.dump(tree)
v = _SigNameVisitor(symdict)
v = _AttrRefTransformer(self)
v.visit(tree)
v = _SigNameVisitor(self.symdict)
v.visit(tree)
self.inputs = v.inputs
self.outputs = v.outputs
@ -217,7 +220,7 @@ class _AlwaysComb(_Instantiator):
while 1:
func()
yield senslist

View File

@ -32,6 +32,7 @@ from myhdl._delay import delay
from myhdl._Signal import _Signal, _WaiterList,_isListOfSigs
from myhdl._Waiter import _Waiter, _EdgeWaiter, _EdgeTupleWaiter
from myhdl._instance import _Instantiator
from myhdl._resolverefs import _AttrRefTransformer
# evacuate this later
AlwaysSeqError = AlwaysError
@ -48,14 +49,14 @@ _error.EmbeddedFunction = "embedded functions in always_seq function not support
class ResetSignal(_Signal):
def __init__(self, val, active, async):
""" Construct a ResetSignal.
This is to be used in conjunction with the always_seq decorator,
as the reset argument.
"""
_Signal.__init__(self, bool(val))
self.active = bool(active)
self.async = async
def always_seq(edge, reset):
@ -78,7 +79,7 @@ def always_seq(edge, reset):
raise AlwaysSeqError(_error.NrOfArgs)
return _AlwaysSeq(func, edge, reset)
return _always_seq_decorator
class _AlwaysSeq(_Instantiator):
@ -125,7 +126,9 @@ class _AlwaysSeq(_Instantiator):
s = _dedent(s)
tree = ast.parse(s)
# print ast.dump(tree)
v = _SigNameVisitor(symdict)
v = _AttrRefTransformer(self)
v.visit(tree)
v = _SigNameVisitor(self.symdict)
v.visit(tree)
sigregs = self.sigregs = []
varregs = self.varregs = []
@ -139,7 +142,7 @@ class _AlwaysSeq(_Instantiator):
assert _isListOfSigs(reg)
for e in reg:
sigregs.append(e)
def reset_sigs(self):
for s in self.sigregs:
@ -223,7 +226,7 @@ class _SigNameVisitor(ast.NodeVisitor):
raise AlwaysSeqError(_error.SigAugAssign % id)
else:
raise AssertionError("bug in always_seq")
def visit_Assign(self, node):
self.context = OUTPUT
for n in node.targets:
@ -244,7 +247,7 @@ class _SigNameVisitor(ast.NodeVisitor):
self.visit(node.target)
self.context = INPUT
self.visit(node.value)
def visit_ClassDef(self, node):
pass # skip
@ -254,8 +257,8 @@ class _SigNameVisitor(ast.NodeVisitor):
def visit_Print(self, node):
pass # skip

21
myhdl/_convutils.py Normal file
View File

@ -0,0 +1,21 @@
import inspect
import ast
from myhdl._util import _dedent
def _makeAST(f):
s = inspect.getsource(f)
s = _dedent(s)
tree = ast.parse(s)
tree.sourcefile = inspect.getsourcefile(f)
tree.lineoffset = inspect.getsourcelines(f)[1]-1
return tree
def _genfunc(gen):
from myhdl._always_comb import _AlwaysComb
from myhdl._always_seq import _AlwaysSeq
from myhdl._always import _Always
if isinstance(gen, (_AlwaysComb, _AlwaysSeq, _Always)):
func = gen.func
else:
func = gen.genfunc
return func

View File

@ -32,12 +32,14 @@ import linecache
from myhdl import ExtractHierarchyError, ToVerilogError, ToVHDLError
from myhdl._Signal import _Signal, _isListOfSigs
from myhdl._util import _isGenFunc
from myhdl._util import _isGenFunc, _flatten
from myhdl._misc import _isGenSeq
from myhdl._resolverefs import _resolveRefs
from myhdl._convutils import _genfunc
_profileFunc = None
class _error:
pass
_error.NoInstances = "No instances found"
@ -46,8 +48,8 @@ _error.InconsistentToplevel = "Inconsistent top level %s for %s - should be 1"
class _Instance(object):
__slots__ = ['level', 'obj', 'subs', 'sigdict', 'memdict', 'name', 'func', 'argdict']
def __init__(self, level, obj, subs, sigdict, memdict, func, argdict):
__slots__ = ['level', 'obj', 'subs', 'sigdict', 'memdict', 'name', 'func', 'argdict', 'objdict']
def __init__(self, level, obj, subs, sigdict, memdict, func, argdict, objdict=None):
self.level = level
self.obj = obj
self.subs = subs
@ -55,7 +57,9 @@ class _Instance(object):
self.memdict = memdict
self.func = func
self.argdict = argdict
if objdict:
self.objdict = objdict
_memInfoMap = {}
@ -79,7 +83,7 @@ def _makeMemInfo(mem):
if key not in _memInfoMap:
_memInfoMap[key] = _MemInfo(mem)
return _memInfoMap[key]
def _isMem(mem):
return id(mem) in _memInfoMap
@ -108,10 +112,10 @@ class _UserCode(object):
self.raiseError(msg, info)
code = "\n%s\n" % code
return code
def _interpolate(self):
return string.Template(self.code).substitute(self.namespace)
class _UserCodeDepr(_UserCode):
def _interpolate(self):
return self.code % self.namespace
@ -119,18 +123,18 @@ class _UserCodeDepr(_UserCode):
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]
@ -159,8 +163,8 @@ class _UserVhdlInstance(_UserVhdlCode):
s += "\n %s=>%s" % (arg, signame)
s += "\n );\n\n"
return s
def _addUserCode(specs, arg, funcname, func, frame):
classMap = {
@ -170,7 +174,7 @@ def _addUserCode(specs, arg, funcname, func, frame):
'vhdl_code' :_UserVhdlCode,
'verilog_instance' : _UserVerilogInstance,
'vhdl_instance' :_UserVhdlInstance,
}
namespace = frame.f_globals.copy()
namespace.update(frame.f_locals)
@ -192,13 +196,13 @@ def _addUserCode(specs, arg, funcname, func, frame):
assert id(arg) not in _userCodeMap[hdl]
code = specs[spec]
_userCodeMap[hdl][id(arg)] = classMap[spec](code, namespace, funcname, func, sourcefile, sourceline)
class _CallFuncVisitor(object):
def __init__(self):
self.linemap = {}
def visitAssign(self, node):
if isinstance(node.expr, ast.CallFunc):
self.lineno = None
@ -207,13 +211,13 @@ class _CallFuncVisitor(object):
def visitName(self, node):
self.lineno = node.lineno
class _HierExtr(object):
def __init__(self, name, dut, *args, **kwargs):
global _profileFunc
_memInfoMap.clear()
for hdl in _userCodeMap:
@ -262,28 +266,28 @@ 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":
funcname = frame.f_code.co_name
# skip certain functions
if funcname in self.skipNames:
self.skip +=1
if not self.skip:
self.level += 1
elif event == "return":
funcname = frame.f_code.co_name
func = frame.f_globals.get(funcname)
func = frame.f_globals.get(funcname)
if func is None:
# Didn't find a func in the global space, try the local "self"
# argument and see if it has a method called *funcname*
obj = frame.f_locals.get('self')
if hasattr(obj, funcname):
func = getattr(obj, funcname)
func = getattr(obj, funcname)
if not self.skip:
isGenSeq = _isGenSeq(arg)
if isGenSeq:
@ -298,65 +302,71 @@ class _HierExtr(object):
spec = "%s_instance" % hdl
if func and hasattr(func, spec) and getattr(func, spec):
specs[spec] = getattr(func, spec)
if specs:
if specs:
_addUserCode(specs, arg, funcname, func, frame)
# building hierarchy only makes sense if there are generators
if isGenSeq and arg:
sigdict = {}
memdict = {}
argdict = {}
argdict = {}
if func:
arglist = inspect.getargspec(func).args
arglist = inspect.getargspec(func).args
else:
arglist = []
cellvars = frame.f_code.co_cellvars
for dict in (frame.f_globals, frame.f_locals):
for n, v in dict.items():
# extract signals and memories
# also keep track of whether they are used in generators
# only include objects that are used in generators
symdict = frame.f_globals.copy()
symdict.update(frame.f_locals)
cellvars = []
cellvars.extend(frame.f_code.co_cellvars)
#All nested functions will be in co_consts
if func:
local_gens = []
consts = func.func_code.co_consts
for item in _flatten(arg):
genfunc = _genfunc(item)
if genfunc.func_code in consts:
local_gens.append(item)
if local_gens:
objlist = _resolveRefs(symdict, local_gens)
cellvars.extend(objlist)
#for dict in (frame.f_globals, frame.f_locals):
for n, v in symdict.items():
# 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 isinstance(v, _Signal):
sigdict[n] = v
if n in cellvars:
v._markUsed()
if _isListOfSigs(v):
m = _makeMemInfo(v)
memdict[n] = m
if n in cellvars:
m._used = True
# save any other variable in argdict
if (n in arglist) and (n not in sigdict) and (n not in memdict):
argdict[n] = v
if isinstance(v, _Signal):
sigdict[n] = v
if n in cellvars:
v._markUsed()
if _isListOfSigs(v):
m = _makeMemInfo(v)
memdict[n] = m
if n in cellvars:
m._used = True
# save any other variable in argdict
if (n in arglist) and (n not in sigdict) and (n not in memdict):
argdict[n] = v
subs = []
for n, sub in frame.f_locals.items():
for elt in _inferArgs(arg):
if elt is sub:
subs.append((n, sub))
inst = _Instance(self.level, arg, subs, sigdict, memdict, func, argdict)
self.hierarchy.append(inst)
self.level -= 1
if funcname in self.skipNames:
self.skip -= 1
def _inferArgs(arg):
c = [arg]
if isinstance(arg, (tuple, list)):
c += list(arg)
return c

74
myhdl/_resolverefs.py Normal file
View File

@ -0,0 +1,74 @@
import ast
from myhdl._convutils import _makeAST, _genfunc
from myhdl._util import _flatten
from myhdl._enum import EnumType
from myhdl._Signal import SignalType
class Data():
pass
def _resolveRefs(symdict, arg):
gens = _flatten(arg)
data = Data()
data.symdict = symdict
v = _AttrRefTransformer(data)
for gen in gens:
func = _genfunc(gen)
tree = _makeAST(func)
v.visit(tree)
return data.objlist
#TODO: Refactor this into two separate nodetransformers, since _resolveRefs
#needs only the names, not the objects
class _AttrRefTransformer(ast.NodeTransformer):
def __init__(self, data):
self.data = data
self.data.objlist = []
self.myhdl_types = (EnumType, SignalType)
#optionally store a list of signals of every object resolved, for
#inferring the interface at the top level
if hasattr(data, 'objsiglist'):
self.storesigs = True
else:
self.storesigs = False
def visit_Attribute(self, node):
self.generic_visit(node)
#Don't handle subscripts for now.
if not isinstance(node.value, ast.Name):
return node
obj = self.data.symdict[node.value.id]
#Don't handle enums, handle signals as long as it a new attribute
if isinstance(obj, EnumType):
return node
elif isinstance(obj, SignalType):
if hasattr(SignalType, node.attr):
return node
attrobj = getattr(obj, node.attr)
if self.storesigs and isinstance(attrobj, SignalType):
self.data.objsiglist[id(obj)].append(attrobj)
new_name = node.value.id+'.'+node.attr
if new_name not in self.data.symdict:
self.data.symdict[new_name] = attrobj
self.data.objlist.append(new_name)
else:
pass
#assert self.data.symdict[new_name] == attrobj
new_node = ast.Name(id=new_name, ctx=node.value.ctx)
return ast.copy_location(new_node, node)
def visit_FunctionDef(self, node):
nodes = _flatten(node.body, node.args)
for n in nodes:
self.visit(n)
return node

View File

@ -27,6 +27,7 @@ import inspect
from types import FunctionType, MethodType
import re
import ast
from collections import defaultdict
import __builtin__
import myhdl
@ -42,6 +43,7 @@ from myhdl._extractHierarchy import _isMem, _getMemInfo, _UserCode
from myhdl._Signal import _Signal, _WaiterList
from myhdl._ShadowSignal import _ShadowSignal, _SliceSignal
from myhdl._util import _isTupleOfInts, _dedent
from myhdl._resolverefs import _AttrRefTransformer
myhdlObjects = myhdl.__dict__.values()
builtinObjects = __builtin__.__dict__.values()
@ -49,6 +51,7 @@ builtinObjects = __builtin__.__dict__.values()
_enumTypeSet = set()
_constDict = {}
_extConstDict = {}
_objsiglist = defaultdict(list)
def _makeName(n, prefixes):
@ -72,16 +75,17 @@ def _makeAST(f):
tree.sourcefile = inspect.getsourcefile(f)
tree.lineoffset = inspect.getsourcelines(f)[1]-1
return tree
def _analyzeSigs(hierarchy, hdl='Verilog'):
curlevel = 0
siglist = []
memlist = []
prefixes = []
open, close = '[', ']'
if hdl == 'VHDL':
open, close = '(', ')'
for inst in hierarchy:
level = inst.level
name = inst.name
@ -91,8 +95,8 @@ def _analyzeSigs(hierarchy, hdl='Verilog'):
curlevel = level
assert(delta >= -1)
if delta > -1: # same or higher level
prefixes = prefixes[:curlevel-1]
# skip processing and prefixing in context without signals
prefixes = prefixes[:curlevel-1]
# skip processing and prefixing in context without signals
if not (sigdict or memdict):
prefixes.append("")
continue
@ -100,6 +104,10 @@ def _analyzeSigs(hierarchy, hdl='Verilog'):
for n, s in sigdict.items():
if s._name is not None:
continue
if '.' in n:
n = n.replace('.', '_')
while n in sigdict:
n = n + '_'
if isinstance(s, _SliceSignal):
continue
s._name = _makeName(n, prefixes)
@ -133,10 +141,10 @@ def _analyzeSigs(hierarchy, hdl='Verilog'):
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 = []
@ -153,26 +161,30 @@ def _analyzeGens(top, absnames):
tree.lineoffset = inspect.getsourcelines(f)[1]-1
tree.symdict = f.func_globals.copy()
tree.callstack = []
tree.objsiglist = _objsiglist
# handle free variables
tree.nonlocaldict = {}
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):
if not ( isinstance(obj, (int, long, EnumType,_Signal)) or \
_isMem(obj) or _isTupleOfInts(obj)
):
info = "File %s, line %s: " % (tree.sourcefile, tree.lineoffset)
print type(obj)
raise ConversionError(_error.UnsupportedType, n, info)
tree.symdict[n] = obj
# currently, only intbv as automatic nonlocals (until Python 3.0)
if isinstance(obj, intbv):
tree.nonlocaldict[n] = obj
tree.name = absnames.get(id(g), str(_Label("BLOCK"))).upper()
v = _AttrRefTransformer(tree)
v.visit(tree)
v = _FirstPassVisitor(tree)
v.visit(tree)
if isinstance(g, _AlwaysComb):
objs = [tree.symdict[objname] for objname in tree.objlist]
for obj in objs:
if not ( isinstance(obj, (int, long, EnumType,_Signal)) or \
_isMem(obj) or _isTupleOfInts(obj)
):
info = "File %s, line %s: " % (tree.sourcefile, tree.lineoffset)
print type(obj)
raise ConversionError(_error.UnsupportedType, n, info)
v = _AnalyzeAlwaysCombVisitor(tree, g.senslist)
elif isinstance(g, _AlwaysSeq):
v = _AnalyzeAlwaysSeqVisitor(tree, g.senslist, g.reset, g.sigregs, g.varregs)
@ -192,6 +204,8 @@ def _analyzeGens(top, absnames):
tree.nonlocaldict = {}
tree.callstack = []
tree.name = absnames.get(id(g), str(_Label("BLOCK"))).upper()
v = _AttrRefTransformer(tree)
v.visit(tree)
v = _FirstPassVisitor(tree)
v.visit(tree)
v = _AnalyzeBlockVisitor(tree)
@ -203,15 +217,15 @@ def _analyzeGens(top, absnames):
class _FirstPassVisitor(ast.NodeVisitor, _ConversionMixin):
"""First pass visitor.
Prune unsupported contructs, and add some useful attributes.
"""
def __init__(self, tree):
self.tree = tree
self.toplevel = True
def visit_Tuple(self, node):
if isinstance(node.ctx, ast.Store):
self.raiseError(node, _error.NotSupported, "tuple assignment")
@ -266,13 +280,13 @@ class _FirstPassVisitor(ast.NodeVisitor, _ConversionMixin):
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")
self.visit(node.targets[0])
self.visit(node.value)
def visit_Call(self, node):
if node.starargs:
self.raiseError(node, _error.NotSupported, "extra positional arguments")
@ -280,12 +294,12 @@ class _FirstPassVisitor(ast.NodeVisitor, _ConversionMixin):
self.raiseError(node, _error.NotSupported, "extra named arguments")
# f = eval(_unparse(node.node), self.tree.symdict)
self.generic_visit(node)
def visit_Compare(self, node):
if len(node.ops) != 1:
self.raiseError(node, _error.NotSupported, "chained comparison")
self.generic_visit(node)
def visit_FunctionDef(self, node):
if node.args.vararg or node.args.kwarg:
self.raiseError(node, _error.NotSupported, "extra positional or named arguments")
@ -301,7 +315,7 @@ class _FirstPassVisitor(ast.NodeVisitor, _ConversionMixin):
node.doc = node.body[0].value.s
node.body = node.body[1:]
self.visitList(node.body)
def flattenIf(self, node, tests, else_, co):
""" Flatten if-then-else as in compiler package."""
if node:
@ -323,7 +337,7 @@ class _FirstPassVisitor(ast.NodeVisitor, _ConversionMixin):
node.ignore = True
return # skip
self.generic_visit(node)
# add fields that match old compiler package
tests = [(node.test, node.body)]
else_ = []
@ -337,7 +351,7 @@ class _FirstPassVisitor(ast.NodeVisitor, _ConversionMixin):
self.raiseError(node, _error.NotSupported, "printing to a file with >> syntax")
if not node.nl:
self.raiseError(node, _error.NotSupported, "printing without newline")
@ -405,10 +419,10 @@ def _getNritems(obj):
return len(obj._type)
else:
raise TypeError("Unexpected type")
class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
def __init__(self, tree):
tree.sigdict = {}
tree.vardict = {}
@ -441,7 +455,7 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
if not hasType(n.obj, bool):
self.raiseError(node, _error.NotSupported, "non-boolean argument in logical operator")
node.obj = bool()
def visit_UnaryOp(self, node):
self.visit(node.operand)
op = node.op
@ -465,7 +479,7 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
if isinstance(obj, _Signal) and isinstance(obj._init, modbv):
if not obj._init._hasFullRange():
self.raiseError(node, _error.ModbvRange, n)
def setAttr(self, node):
if node.attr != 'next':
self.raiseError(node, _error.NotSupported, "attribute assignment")
@ -505,7 +519,7 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
obj._setName(n+suf)
if node.obj is None: # attribute lookup failed
self.raiseError(node, _error.UnsupportedAttribute, node.attr)
def visit_Assign(self, node):
target, value = node.targets[0], node.value
self.access = _access.OUTPUT
@ -557,7 +571,7 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
def visit_Break(self, node):
self.labelStack[-2].isActive = True
def visit_Call(self, node):
self.visit(node.func)
self.access = _access.UNKNOWN
@ -655,7 +669,7 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
if isinstance(val, bool):
val = int(val) # cast bool to int first
if isinstance(val, (EnumItemType, int, long)):
node.case = (node.left, val)
node.case = (node.left, val)
# check whether it can be part of an edge check
n = node.left.id
if n in self.tree.sigdict:
@ -680,7 +694,7 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
def visit_Str(self, node):
node.obj = node.s
def visit_Continue(self, node):
self.labelStack[-1].isActive = True
@ -693,20 +707,20 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(node.target)
var = node.target.id
self.tree.vardict[var] = int(-1)
cf = node.iter
self.visit(cf)
self.require(node, isinstance(cf, ast.Call), "Expected (down)range call")
f = self.getObj(cf.func)
self.require(node, f in (range, downrange), "Expected (down)range call")
for stmt in node.body:
self.visit(stmt)
self.refStack.pop()
self.require(node, not node.orelse, "for-else not supported")
self.labelStack.pop()
self.labelStack.pop()
def visit_FunctionDef(self, node):
raise AssertionError("subclass must implement this")
@ -816,7 +830,7 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
sig._driven = 'wire'
if not isinstance(sig, _Signal):
# print "not a signal: %s" % n
pass
pass
else:
if sig._type is bool:
node.edge = sig.posedge
@ -835,7 +849,7 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
self.tree.outputs.add(n)
elif self.access == _access.UNKNOWN:
pass
else:
else:
self.raiseError(node, _error.NotSupported, "Augmented signal assignment")
if n in self.tree.vardict:
obj = self.tree.vardict[n]
@ -887,7 +901,7 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
node.obj = __builtin__.__dict__[n]
else:
self.raiseError(node, _error.UnboundLocal, n)
def visit_Return(self, node):
self.raiseError(node, _error.NotSupported, "return statement")
@ -945,7 +959,7 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
if len(node.args) > nr:
self.raiseError(node, _error.FormatString, "too many arguments")
self.generic_visit(node)
def visit_Subscript(self, node):
if isinstance(node.slice, ast.Slice):
self.accessSlice(node)
@ -970,7 +984,7 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
else:
rightind = 0
node.obj = node.obj[leftind:rightind]
def accessIndex(self, node):
self.visit(node.value)
self.access = _access.INPUT
@ -1033,15 +1047,15 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
self.raiseError(node, _error.UnsupportedYield)
node.senslist = senslist
class _AnalyzeBlockVisitor(_AnalyzeVisitor):
def __init__(self, tree):
_AnalyzeVisitor.__init__(self, tree)
for n, v in self.tree.symdict.items():
if isinstance(v, _Signal):
self.tree.sigdict[n] = v
def visit_FunctionDef(self, node):
self.refStack.push()
@ -1058,7 +1072,7 @@ 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:
@ -1069,8 +1083,8 @@ class _AnalyzeBlockVisitor(_AnalyzeVisitor):
for n in self.tree.inputs:
s = self.tree.sigdict[n]
s._markRead()
def visit_Return(self, node):
### value should be None
if node.value is None:
@ -1084,7 +1098,7 @@ class _AnalyzeBlockVisitor(_AnalyzeVisitor):
class _AnalyzeAlwaysCombVisitor(_AnalyzeBlockVisitor):
def __init__(self, tree, senslist):
_AnalyzeBlockVisitor.__init__(self, tree)
self.tree.senslist = senslist
@ -1124,10 +1138,10 @@ class _AnalyzeAlwaysCombVisitor(_AnalyzeBlockVisitor):
for n in self.tree.outmems:
m = _getMemInfo(self.tree.symdict[n])
m._driven = "wire"
class _AnalyzeAlwaysSeqVisitor(_AnalyzeBlockVisitor):
def __init__(self, tree, senslist, reset, sigregs, varregs):
_AnalyzeBlockVisitor.__init__(self, tree)
self.tree.senslist = senslist
@ -1135,22 +1149,22 @@ class _AnalyzeAlwaysSeqVisitor(_AnalyzeBlockVisitor):
self.tree.sigregs = sigregs
self.tree.varregs = varregs
def visit_FunctionDef(self, node):
self.refStack.push()
for n in node.body:
self.visit(n)
self.tree.kind = _kind.ALWAYS_SEQ
self.refStack.pop()
class _AnalyzeAlwaysDecoVisitor(_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:
@ -1158,10 +1172,10 @@ class _AnalyzeAlwaysDecoVisitor(_AnalyzeBlockVisitor):
self.tree.kind = _kind.ALWAYS_DECO
self.refStack.pop()
class _AnalyzeFuncVisitor(_AnalyzeVisitor):
def __init__(self, tree, args, keywords):
_AnalyzeVisitor.__init__(self, tree)
self.args = args
@ -1169,7 +1183,7 @@ class _AnalyzeFuncVisitor(_AnalyzeVisitor):
self.tree.hasReturn = False
self.tree.returnObj = None
def visit_FunctionDef(self, node):
self.refStack.push()
argnames = [arg.id for arg in node.args.args]
@ -1236,10 +1250,23 @@ ismethod = inspect.ismethod
def isboundmethod(m):
return ismethod(m) and m.__self__ is not None
def _analyzeTopFunc(func, *args, **kwargs):
def _analyzeTopFunc(top_inst, func, *args, **kwargs):
tree = _makeAST(func)
v = _AnalyzeTopFuncVisitor(func, tree, *args, **kwargs)
v.visit(tree)
objs = (obj for obj in v.fullargdict.values() if not isinstance(obj, _Signal))
#create ports for any signal in the top instance if it was buried in an
#object passed as in argument
#TODO: This will not work for nested objects in the top level
for obj in objs:
if id(obj) in _objsiglist:
for sig in _objsiglist[id(obj)]:
v.argdict[sig._name] = sig
v.argnames.append(sig._name)
return v
class _AnalyzeTopFuncVisitor(_AnalyzeVisitor):
@ -1250,30 +1277,34 @@ class _AnalyzeTopFuncVisitor(_AnalyzeVisitor):
self.args = args
self.kwargs = kwargs
self.name = None
self.fullargdict = {}
self.argdict = {}
self.argnames = []
def visit_FunctionDef(self, node):
self.name = node.name
argnames = [arg.id for arg in node.args.args]
self.argnames = [arg.id for arg in node.args.args]
if isboundmethod(self.func):
if not argnames[0] == 'self':
if not self.argnames[0] == 'self':
self.raiseError(node, _error.NotSupported,
"first method argument name other than 'self'")
# skip self
argnames = argnames[1:]
self.argnames = self.argnames[1:]
i=-1
for i, arg in enumerate(self.args):
n = argnames[i]
n = self.argnames[i]
self.fullargdict[n] = arg
if isinstance(arg, _Signal):
self.argdict[n] = arg
self.argdict[n] = arg
if _isMem(arg):
self.raiseError(node, _error.ListAsPort, n)
for n in argnames[i+1:]:
for n in self.argnames[i+1:]:
if n in self.kwargs:
arg = self.kwargs[n]
self.fullargdict[n] = arg
if isinstance(arg, _Signal):
self.argdict[n] = arg
if _isMem(arg):
self.raiseError(node, _error.ListAsPort, n)
self.argnames = [n for n in argnames if n in self.argdict]
self.argnames = [n for n in self.argnames if n in self.argdict]

View File

@ -60,7 +60,7 @@ 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:
@ -72,7 +72,7 @@ def _flatten(*args):
else:
arglist.append(arg)
return arglist
def _makeDoc(doc, indent=''):
if doc is None:
return ''
@ -150,15 +150,16 @@ class _ToVHDLConvertor(object):
_constDict.clear()
_extConstDict.clear()
siglist, memlist = _analyzeSigs(h.hierarchy, hdl='VHDL')
arglist = _flatten(h.top)
# print h.top
_checkArgs(arglist)
genlist = _analyzeGens(arglist, h.absnames)
siglist, memlist = _analyzeSigs(h.hierarchy, hdl='VHDL')
# print h.top
_annotateTypes(genlist)
### infer interface
intf = _analyzeTopFunc(func, *args, **kwargs)
top_inst = h.hierarchy[0]
intf = _analyzeTopFunc(top_inst, func, *args, **kwargs)
intf.name = name
# sanity checks on interface
for portname in intf.argnames:
@ -175,14 +176,14 @@ class _ToVHDLConvertor(object):
_enumPortTypeSet.add(obj)
doc = _makeDoc(inspect.getdoc(func))
needPck = len(_enumPortTypeSet) > 0
lib = self.library
arch = self.architecture
numeric = self.numeric_ports
self._convert_filter(h, intf, siglist, memlist, genlist)
if pfile:
_writeFileHeader(pfile, ppath)
print >> pfile, _package
@ -207,7 +208,7 @@ class _ToVHDLConvertor(object):
self._cleanup(siglist)
return h.top
def _cleanup(self, siglist):
# clean up signal names
for sig in siglist:
@ -215,7 +216,7 @@ class _ToVHDLConvertor(object):
# sig._name = None
# sig._driven = False
# sig._read = False
# clean up attributes
self.name = None
self.component_declarations = None
@ -224,13 +225,13 @@ class _ToVHDLConvertor(object):
self.no_myhdl_package = False
self.architecture = "MyHDL"
self.numeric_ports = True
def _convert_filter(self, h, intf, siglist, memlist, genlist):
# intended to be a entry point for other uses:
# intended to be a entry point for other uses:
# code checking, optimizations, etc
pass
toVHDL = _ToVHDLConvertor()
@ -241,7 +242,7 @@ myhdl_header = """\
"""
def _writeFileHeader(f, fn):
vars = dict(filename=fn,
vars = dict(filename=fn,
version=myhdl.__version__,
date=datetime.today().ctime()
)
@ -404,8 +405,8 @@ def _writeCompDecls(f, compDecls):
print >> f, compDecls
def _writeModuleFooter(f, arch):
print >> f, "end architecture %s;" % arch
print >> f, "end architecture %s;" % arch
def _getRangeString(s):
if isinstance(s._val, EnumItemType):
return ''
@ -416,7 +417,7 @@ def _getRangeString(s):
if ls:
msb = ls + '-1'
else:
msb = s._nrbits-1
msb = s._nrbits-1
return "(%s downto 0)" % msb
else:
raise AssertionError
@ -513,10 +514,10 @@ opmap = {
ast.And : 'and',
ast.Or : 'or',
}
class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
def __init__(self, tree, buf):
self.tree = tree
self.buf = buf
@ -526,30 +527,30 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.isLhs = False
self.labelStack = []
self.context = None
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 writeDoc(self, node):
assert hasattr(node, 'doc')
doc = _makeDoc(node.doc, self.ind)
self.write(doc)
self.writeline()
def IntRepr(self, obj):
self.writeline()
def IntRepr(self, obj):
if obj >= 0:
s = "%s" % int(obj)
else:
s = "(- %s)" % abs(int(obj))
return s
def BitRepr(self, item, var):
return '"%s"' % bin(item, len(var))
def inferCast(self, vhd, ori):
pre, suf = "", ""
if isinstance(vhd, vhd_int):
@ -584,13 +585,13 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
pre, suf = "bool(", ")"
elif isinstance(vhd, vhd_std_logic):
if not isinstance(ori, vhd_std_logic):
pre, suf = "stdl(", ")"
pre, suf = "stdl(", ")"
elif isinstance(vhd, vhd_string):
if isinstance(ori, vhd_enum):
pre, suf = "%s'image(" % ori._type._name, ")"
return pre, suf
def writeIntSize(self, n):
# write size for large integers (beyond 32 bits signed)
# with some safety margin
@ -615,7 +616,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
if kind: kind += " "
if dir: dir += " "
self.write("%s%s: %s%s%s" % (kind, name, dir, tipe, endchar))
def writeDeclarations(self):
if self.tree.hasPrint:
self.writeline()
@ -625,7 +626,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
continue # hack for loop vars
self.writeline()
self.writeDeclaration(obj, name, kind="variable")
def indent(self):
self.ind += ' ' * 4
@ -643,7 +644,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(node.right)
else:
self.BinOp(node)
def inferBinaryOpCast(self, node, left, right, op):
ns, os = node.vhd.size, node.vhdOri.size
ds = ns - os
@ -671,7 +672,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
if isinstance(op, (ast.Add, ast.Sub, ast.Mod, ast.FloorDiv)):
left.vhd.size = ns
node.vhdOri.size = ns
elif isinstance(op, ast.Mult):
elif isinstance(op, ast.Mult):
left.vhd.size += ds
node.vhdOri.size = 2 * left.vhd.size
else:
@ -681,14 +682,14 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
right.vhd.size = ns
node.vhdOri.size = ns
elif isinstance(op, ast.Mult):
node.vhdOri.size = 2 * right.vhd.size
node.vhdOri.size = 2 * right.vhd.size
else:
raise AssertionError("unexpected op %s" % op)
pre, suf = self.inferCast(node.vhd, node.vhdOri)
if pre == "":
pre, suf = "(", ")"
return pre, suf
def BinOp(self, node):
pre, suf = self.inferBinaryOpCast(node, node.left, node.right, node.op)
self.write(pre)
@ -696,7 +697,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(" %s " % opmap[type(node.op)])
self.visit(node.right)
self.write(suf)
def inferShiftOpCast(self, node, left, right, op):
ns, os = node.vhd.size, node.vhdOri.size
ds = ns - os
@ -706,7 +707,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
node.vhdOri.size = ns
pre, suf = self.inferCast(node.vhd, node.vhdOri)
return pre, suf
def shiftOp(self, node):
pre, suf = self.inferShiftOpCast(node, node.left, node.right, node.op)
self.write(pre)
@ -716,7 +717,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(node.right)
self.write(")")
self.write(suf)
def BitOp(self, node):
pre, suf = self.inferCast(node.vhd, node.vhdOri)
self.write(pre)
@ -726,7 +727,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(node.right)
self.write(")")
self.write(suf)
def visit_BoolOp(self, node):
if isinstance(node.vhd, vhd_std_logic):
self.write("stdl")
@ -736,7 +737,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(" %s " % opmap[type(node.op)])
self.visit(n)
self.write(")")
def visit_UnaryOp(self, node):
pre, suf = self.inferCast(node.vhd, node.vhdOri)
self.write(pre)
@ -745,7 +746,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(node.operand)
self.write(")")
self.write(suf)
def visit_Attribute(self, node):
if isinstance(node.ctx, ast.Store):
self.setAttr(node)
@ -893,7 +894,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(")")
self.write(suf)
self.write(";")
def visit_Break(self, node):
self.write("exit;")
@ -1012,12 +1013,12 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
# self.write('"%s"' % bin(n, node.vhd.size))
elif isinstance(node.vhd, vhd_unsigned):
if abs(n) < 2**31:
self.write("to_unsigned(%s, %s)" % (n, node.vhd.size))
self.write("to_unsigned(%s, %s)" % (n, node.vhd.size))
else:
self.write('unsigned\'("%s")' % bin(n, node.vhd.size))
elif isinstance(node.vhd, vhd_signed):
if abs(n) < 2**31:
self.write("to_signed(%s, %s)" % (n, node.vhd.size))
self.write("to_signed(%s, %s)" % (n, node.vhd.size))
else:
self.write('signed\'("%s")' % bin(n, node.vhd.size))
else:
@ -1026,7 +1027,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(n)
if n < 0:
self.write(")")
def visit_Str(self, node):
typemark = 'string'
if isinstance(node.vhd, vhd_unsigned):
@ -1050,7 +1051,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
# ugly hack to detect an orphan "task" call
if isinstance(expr, ast.Call) and hasattr(expr, 'tree'):
self.write(';')
def visit_IfExp(self, node):
pre, suf = self.inferCast(node.vhd, node.body.vhdOri)
self.write(pre)
@ -1123,7 +1124,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
## self.write("end")
self.labelStack.pop()
self.labelStack.pop()
def visit_FunctionDef(self, node):
raise AssertionError("To be implemented in subclass")
@ -1155,7 +1156,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
if (i == len(node.tests)-1) and not node.else_:
self.write("when others")
comment = " -- %s" % itemRepr
else:
else:
self.write("when ")
self.write(itemRepr)
self.write(" =>%s" % comment)
@ -1202,13 +1203,13 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.dedent()
self.writeline()
self.write("end if;")
def visit_ListComp(self, node):
pass # do nothing
def visit_Module(self, node):
for stmt in node.body:
self.visit(stmt)
self.visit(stmt)
def visit_Name(self, node):
if isinstance(node.ctx, ast.Store):
@ -1239,7 +1240,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
ori = inferVhdlObj(obj)
pre, suf = self.inferCast(node.vhd, ori)
s = "%s%s%s" % (pre, s, suf)
elif n in self.tree.argnames:
assert n in self.tree.symdict
obj = self.tree.symdict[n]
@ -1262,9 +1263,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
elif isinstance(node.vhd, vhd_std_logic):
s = "stdl(%s)" % n
elif isinstance(node.vhd, vhd_unsigned):
s = "to_unsigned(%s, %s)" % (n, node.vhd.size)
s = "to_unsigned(%s, %s)" % (n, node.vhd.size)
elif isinstance(node.vhd, vhd_signed):
s = "to_signed(%s, %s)" % (n, node.vhd.size)
s = "to_signed(%s, %s)" % (n, node.vhd.size)
else:
if isinstance(node.vhd, vhd_int):
s = self.IntRepr(obj)
@ -1272,12 +1273,12 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
s = "'%s'" % int(obj)
elif isinstance(node.vhd, vhd_unsigned):
if abs(obj) < 2** 31:
s = "to_unsigned(%s, %s)" % (n, node.vhd.size)
s = "to_unsigned(%s, %s)" % (n, node.vhd.size)
else:
s = 'unsigned\'("%s")' % bin(obj, node.vhd.size)
elif isinstance(node.vhd, vhd_signed):
if abs(obj) < 2** 31:
s = "to_signed(%s, %s)" % (n, node.vhd.size)
s = "to_signed(%s, %s)" % (n, node.vhd.size)
else:
s = 'signed\'("%s")' % bin(obj, node.vhd.size)
elif isinstance(obj, _Signal):
@ -1308,7 +1309,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
def visit_Pass(self, node):
self.write("null;")
def visit_Print(self, node):
argnr = 0
for s in node.format:
@ -1341,7 +1342,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
def visit_Raise(self, node):
self.write('assert False report "End of Simulation" severity Failure;')
def visit_Return(self, node):
pass
@ -1489,9 +1490,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
senslist = [s.sig for s in senslist]
return senslist
class _ConvertAlwaysVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf):
_ConvertVisitor.__init__(self, tree, blockBuf)
self.funcBuf = funcBuf
@ -1538,9 +1539,9 @@ class _ConvertAlwaysVisitor(_ConvertVisitor):
self.write("end process %s;" % self.tree.name)
self.writeline(2)
class _ConvertInitialVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf):
_ConvertVisitor.__init__(self, tree, blockBuf)
self.funcBuf = funcBuf
@ -1564,7 +1565,7 @@ class _ConvertInitialVisitor(_ConvertVisitor):
class _ConvertAlwaysCombVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf):
_ConvertVisitor.__init__(self, tree, blockBuf)
self.funcBuf = funcBuf
@ -1590,9 +1591,9 @@ class _ConvertAlwaysCombVisitor(_ConvertVisitor):
self.write("end process %s;" % self.tree.name)
self.writeline(2)
class _ConvertSimpleAlwaysCombVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf):
_ConvertVisitor.__init__(self, tree, blockBuf)
self.funcBuf = funcBuf
@ -1614,7 +1615,7 @@ class _ConvertSimpleAlwaysCombVisitor(_ConvertVisitor):
class _ConvertAlwaysDecoVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf):
_ConvertVisitor.__init__(self, tree, blockBuf)
self.funcBuf = funcBuf
@ -1653,8 +1654,8 @@ class _ConvertAlwaysDecoVisitor(_ConvertVisitor):
self.writeline()
self.write("end process %s;" % self.tree.name)
self.writeline(2)
def _convertInitVal(reg, init):
pre, suf = '', ''
if isinstance(reg, _Signal):
@ -1678,10 +1679,10 @@ def _convertInitVal(reg, init):
assert isinstance(init, EnumItemType)
v = init._toVHDL()
return v
class _ConvertAlwaysSeqVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf):
_ConvertVisitor.__init__(self, tree, blockBuf)
self.funcBuf = funcBuf
@ -1743,9 +1744,9 @@ class _ConvertAlwaysSeqVisitor(_ConvertVisitor):
self.write("end process %s;" % self.tree.name)
self.writeline(2)
class _ConvertFunctionVisitor(_ConvertVisitor):
def __init__(self, tree, funcBuf):
_ConvertVisitor.__init__(self, tree, funcBuf)
self.returnObj = tree.returnObj
@ -1762,7 +1763,7 @@ class _ConvertFunctionVisitor(_ConvertVisitor):
obj = self.tree.symdict[name]
self.writeline()
self.writeDeclaration(obj, name, dir="in", constr=False, endchar="")
def visit_FunctionDef(self, node):
self.write("function %s(" % self.tree.name)
self.indent()
@ -1787,9 +1788,9 @@ class _ConvertFunctionVisitor(_ConvertVisitor):
self.visit(node.value)
self.write(";")
class _ConvertTaskVisitor(_ConvertVisitor):
def __init__(self, tree, funcBuf):
_ConvertVisitor.__init__(self, tree, funcBuf)
self.returnLabel = _Label("RETURN")
@ -1806,7 +1807,7 @@ class _ConvertTaskVisitor(_ConvertVisitor):
dir = (inout and "inout") or (output and "out") or "in"
self.writeline()
self.writeDeclaration(obj, name, dir=dir, constr=False, endchar="")
def visit_FunctionDef(self, node):
self.write("procedure %s" % self.tree.name)
if self.tree.argnames:
@ -1844,14 +1845,14 @@ class vhd_string(vhd_type):
class vhd_enum(vhd_type):
def __init__(self, tipe):
self._type = tipe
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)
@ -1863,7 +1864,7 @@ class vhd_vector(vhd_type):
def __init__(self, size=0, lenStr=False):
vhd_type.__init__(self, size)
self.lenStr = lenStr
class vhd_unsigned(vhd_vector):
def toStr(self, constr=True):
if constr:
@ -1874,7 +1875,7 @@ class vhd_unsigned(vhd_vector):
return "unsigned(%s downto 0)" % (self.size-1)
else:
return "unsigned"
class vhd_signed(vhd_vector):
def toStr(self, constr=True):
if constr:
@ -1885,7 +1886,7 @@ class vhd_signed(vhd_vector):
return "signed(%s downto 0)" % (self.size-1)
else:
return "signed"
class vhd_int(vhd_type):
def toStr(self, constr=True):
return "integer"
@ -1893,7 +1894,7 @@ class vhd_int(vhd_type):
class vhd_nat(vhd_int):
def toStr(self, constr=True):
return "natural"
class _loopInt(int):
pass
@ -1915,7 +1916,7 @@ def maxType(o1, o2):
return vhd_int()
else:
return None
def inferVhdlObj(obj):
vhd = None
if (isinstance(obj, _Signal) and obj._type is intbv) or \
@ -1934,7 +1935,7 @@ def inferVhdlObj(obj):
tipe = obj._val._type
else:
tipe = obj._type
vhd = vhd_enum(tipe)
vhd = vhd_enum(tipe)
elif isinstance(obj, (int, long)):
if obj >= 0:
vhd = vhd_nat()
@ -1949,7 +1950,7 @@ def maybeNegative(vhd):
if isinstance(vhd, vhd_int) and not isinstance(vhd, vhd_nat):
return True
return False
class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
def __init__(self, tree):
@ -1976,7 +1977,7 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
node.value.vhd = copy(node.target.vhd)
node.vhdOri = copy(node.target.vhd)
elif isinstance(node.op, (ast.RShift, ast.LShift)):
node.value.vhd = vhd_int()
node.value.vhd = vhd_int()
node.vhdOri = copy(node.target.vhd)
else:
node.left, node.right = node.target, node.value
@ -2044,7 +2045,7 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
# make it possible to detect loop variable
self.tree.vardict[var] = _loopInt(-1)
self.generic_visit(node)
def visit_Name(self, node):
if node.id in self.tree.vardict:
node.obj = self.tree.vardict[node.id]
@ -2083,7 +2084,7 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
if isinstance(left.vhd, vhd_unsigned) and maybeNegative(right.vhd):
left.vhd = vhd_signed(left.vhd.size + 1)
l, r = left.vhd, right.vhd
ls, rs = l.size, r.size
ls, rs = l.size, r.size
if isinstance(r, vhd_vector) and isinstance(l, vhd_vector):
if isinstance(op, (ast.Add, ast.Sub)):
s = max(ls, rs)
@ -2132,7 +2133,7 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
self.generic_visit(node)
for test, suite in node.tests:
test.vhd = vhd_boolean()
def visit_IfExp(self, node):
self.generic_visit(node)
node.test.vhd = vhd_boolean()
@ -2196,7 +2197,7 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
elif isinstance(node.vhd, vhd_nat):
node.vhd = vhd_int()
node.vhdOri = copy(node.vhd)
def visit_While(self, node):
self.generic_visit(node)
node.test.vhd = vhd_boolean()
@ -2211,7 +2212,7 @@ def _annotateTypes(genlist):

View File

@ -40,12 +40,12 @@ from myhdl._extractHierarchy import (_HierExtr, _isMem, _getMemInfo,
_UserVerilogCode, _userCodeMap)
from myhdl._instance import _Instantiator
from myhdl.conversion._misc import (_error, _kind, _context,
from myhdl.conversion._misc import (_error, _kind, _context,
_ConversionMixin, _Label, _genUniqueSuffix, _isConstant)
from myhdl.conversion._analyze import (_analyzeSigs, _analyzeGens, _analyzeTopFunc,
from myhdl.conversion._analyze import (_analyzeSigs, _analyzeGens, _analyzeTopFunc,
_Ram, _Rom)
from myhdl._Signal import _Signal
_converting = 0
_profileFunc = None
@ -53,7 +53,7 @@ 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:
@ -79,10 +79,10 @@ def _makeDoc(doc, indent=''):
class _ToVerilogConvertor(object):
__slots__ = ("name",
"timescale",
__slots__ = ("name",
"timescale",
"standard",
"prefer_blocking_assignments",
"prefer_blocking_assignments",
"radix",
"header",
"no_myhdl_header",
@ -124,20 +124,20 @@ class _ToVerilogConvertor(object):
vpath = name + ".v"
vfile = open(vpath, 'w')
### initialize properly ###
_genUniqueSuffix.reset()
siglist, memlist = _analyzeSigs(h.hierarchy)
arglist = _flatten(h.top)
# print h.top
_checkArgs(arglist)
genlist = _analyzeGens(arglist, h.absnames)
siglist, memlist = _analyzeSigs(h.hierarchy)
_annotateTypes(genlist)
intf = _analyzeTopFunc(func, *args, **kwargs)
intf.name = name
top_inst = h.hierarchy[0]
intf = _analyzeTopFunc(top_inst, func, *args, **kwargs)
doc = _makeDoc(inspect.getdoc(func))
self._convert_filter(h, intf, siglist, memlist, genlist)
_writeFileHeader(vfile, vpath, self.timescale)
@ -157,9 +157,9 @@ class _ToVerilogConvertor(object):
### clean-up properly ###
self._cleanup(siglist)
return h.top
def _cleanup(self, siglist):
# clean up signal names
for sig in siglist:
@ -167,7 +167,7 @@ class _ToVerilogConvertor(object):
# sig._name = None
# sig._driven = False
# sig._read = False
# clean up attributes
self.name = None
self.standard = '2001'
@ -176,13 +176,13 @@ class _ToVerilogConvertor(object):
self.header = ""
self.no_myhdl_header = False
self.no_testbench = False
def _convert_filter(self, h, intf, siglist, memlist, genlist):
# intended to be a entry point for other uses:
# intended to be a entry point for other uses:
# code checking, optimizations, etc
pass
toVerilog = _ToVerilogConvertor()
@ -193,7 +193,7 @@ myhdl_header = """\
"""
def _writeFileHeader(f, fn, ts):
vars = dict(filename=fn,
vars = dict(filename=fn,
version=myhdl.__version__,
date=datetime.today().ctime()
)
@ -290,7 +290,7 @@ def _writeSigDecls(f, intf, siglist, memlist):
p = _getSignString(m.elObj)
k = 'wire'
if m._driven:
k = m._driven
k = m._driven
print >> f, "%s %s%s%s [0:%s-1];" % (k, p, r, m.name, m.depth)
print >> f
for s in constwires:
@ -309,7 +309,7 @@ def _writeSigDecls(f, intf, siglist, memlist):
def _writeModuleFooter(f):
print >> f, "endmodule"
def _writeTestBench(f, intf):
print >> f, "module tb_%s;" % intf.name
@ -336,7 +336,7 @@ def _writeTestBench(f, intf):
if to.getvalue():
print >> f, " $to_myhdl("
print >> f, to.getvalue()[:-2]
print >> f, " );"
print >> f, " );"
print >> f, "end"
print >> f
print >> f, "%s dut(" % intf.name
@ -378,7 +378,7 @@ def _convertGens(genlist, vfile):
elif tree.kind == _kind.ALWAYS_DECO:
Visitor = _ConvertAlwaysDecoVisitor
elif tree.kind == _kind.ALWAYS_SEQ:
Visitor = _ConvertAlwaysSeqVisitor
Visitor = _ConvertAlwaysSeqVisitor
else: # ALWAYS_COMB
Visitor = _ConvertAlwaysCombVisitor
v = Visitor(tree, blockBuf, funcBuf)
@ -417,7 +417,7 @@ opmap = {
class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
def __init__(self, tree, buf):
self.tree = tree
self.buf = buf
@ -440,13 +440,13 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
def writeline(self, nr=1):
for i in range(nr):
self.buf.write("\n%s" % self.ind)
def writeDoc(self, node):
assert hasattr(node, 'doc')
doc = _makeDoc(node.doc, self.ind)
self.write(doc)
self.writeline()
def indent(self):
self.ind += ' ' * 4
@ -502,7 +502,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(" = %s;" % inival)
else:
self.write(";")
def writeDeclarations(self):
for name, obj in self.tree.vardict.items():
self.writeline()
@ -566,7 +566,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write(" %s " % opmap[type(node.op)])
self.visit(n)
self.write(")")
def visit_UnaryOp(self, node):
self.write("(%s" % opmap[type(node.op)])
self.visit(node.operand)
@ -793,7 +793,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
# ugly hack to detect an orphan "task" call
if isinstance(expr, ast.Call) and hasattr(expr, 'tree'):
self.write(';')
def visit_IfExp(self, node):
self.visit(node.test)
self.write(' ? ')
@ -912,7 +912,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.dedent()
self.writeline()
self.write("endcase")
def mapToIf(self, node, *args):
first = True
for test, suite in node.tests:
@ -945,7 +945,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
def visit_Module(self, node, *args):
for stmt in node.body:
self.visit(stmt)
def visit_ListComp(self, node):
pass # do nothing
@ -1000,7 +1000,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.write("$signed({1'b0, ")
self.write(s)
if addSignBit:
self.write("})")
self.write("})")
def visit_Pass(self, node):
self.write("// pass")
@ -1054,7 +1054,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
def visit_Raise(self, node):
self.write("$finish;")
def visit_Return(self, node):
self.write("disable %s;" % self.returnLabel)
@ -1163,9 +1163,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.writeSensitivityList(senslist)
self.write(";")
class _ConvertAlwaysVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf):
_ConvertVisitor.__init__(self, tree, blockBuf)
self.funcBuf = funcBuf
@ -1190,14 +1190,14 @@ class _ConvertAlwaysVisitor(_ConvertVisitor):
class _ConvertInitialVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf):
_ConvertVisitor.__init__(self, tree, blockBuf)
self.funcBuf = funcBuf
def visit_FunctionDef(self, node):
self.writeDoc(node)
self.write("initial begin: %s" % self.tree.name)
self.write("initial begin: %s" % self.tree.name)
self.indent()
self.writeDeclarations()
self.visit_stmt(node.body)
@ -1209,7 +1209,7 @@ class _ConvertInitialVisitor(_ConvertVisitor):
class _ConvertAlwaysCombVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf):
_ConvertVisitor.__init__(self, tree, blockBuf)
if toVerilog.prefer_blocking_assignments:
@ -1227,9 +1227,9 @@ class _ConvertAlwaysCombVisitor(_ConvertVisitor):
self.writeline(2)
class _ConvertSimpleAlwaysCombVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf):
_ConvertVisitor.__init__(self, tree, blockBuf)
self.funcBuf = funcBuf
@ -1245,9 +1245,9 @@ class _ConvertSimpleAlwaysCombVisitor(_ConvertVisitor):
self.visit_stmt(node.body)
self.writeline(2)
class _ConvertAlwaysDecoVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf):
_ConvertVisitor.__init__(self, tree, blockBuf)
self.funcBuf = funcBuf
@ -1277,10 +1277,10 @@ def _convertInitVal(reg, init):
assert isinstance(init, EnumItemType)
v = init._toVerilog()
return v
class _ConvertAlwaysSeqVisitor(_ConvertVisitor):
def __init__(self, tree, blockBuf, funcBuf):
_ConvertVisitor.__init__(self, tree, blockBuf)
self.funcBuf = funcBuf
@ -1319,9 +1319,9 @@ class _ConvertAlwaysSeqVisitor(_ConvertVisitor):
self.write("end")
self.writeline(2)
class _ConvertFunctionVisitor(_ConvertVisitor):
def __init__(self, tree, funcBuf):
_ConvertVisitor.__init__(self, tree, funcBuf)
self.returnObj = tree.returnObj
@ -1336,7 +1336,7 @@ class _ConvertFunctionVisitor(_ConvertVisitor):
obj = self.tree.symdict[name]
self.writeline()
self.writeDeclaration(obj, name, "input")
def visit_FunctionDef(self, node):
self.write("function ")
self.writeOutputDeclaration()
@ -1364,9 +1364,9 @@ class _ConvertFunctionVisitor(_ConvertVisitor):
class _ConvertTaskVisitor(_ConvertVisitor):
def __init__(self, tree, funcBuf):
_ConvertVisitor.__init__(self, tree, funcBuf)
self.returnLabel = _Label("RETURN")
@ -1380,7 +1380,7 @@ class _ConvertTaskVisitor(_ConvertVisitor):
dir = (inout and "inout") or (output and "output") or "input"
self.writeline()
self.writeDeclaration(obj, name, dir)
def visit_FunctionDef(self, node):
self.write("task %s;" % self.tree.name)
self.indent()
@ -1410,17 +1410,17 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
def __init__(self, tree):
self.tree = tree
def visit_FunctionDef(self, node):
# don't visit arguments and decorators
for stmt in node.body:
self.visit(stmt)
self.visit(stmt)
def visit_BinOp(self, node):
self.visit(node.left)
self.visit(node.right)
node.signed = node.left.signed or node.right.signed
def visit_BoolOp(self, node):
for n in node.values:
self.visit(n)
@ -1433,20 +1433,20 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
node.obj = int(-1)
if isinstance(node.operand, ast.Num):
node.signed = True
def visit_Attribute(self, node):
if isinstance(node.ctx, ast.Store):
self.setAttr(node)
else:
self.getAttr(node)
def setAttr(self, node):
self.visit(node.value)
def getAttr(self, node):
node.signed = False
self.visit(node.value)
def visit_Call(self, node):
self.generic_visit(node)
f = self.getObj(node.func)
@ -1457,7 +1457,7 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
elif hasattr(node, 'tree'):
v = _AnnotateTypesVisitor(node.tree)
v.visit(node.tree)
node.signed = _maybeNegative(node.tree.returnObj)
node.signed = _maybeNegative(node.tree.returnObj)
def visit_Compare(self, node):
node.signed = False
@ -1466,7 +1466,7 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
self.visit(n)
if n.signed:
node.signed = True
def visit_If(self, node):
if node.ignore:
return
@ -1509,13 +1509,13 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
node.signed = False
self.generic_visit(node)
def _annotateTypes(genlist):
for tree in genlist:
if isinstance(tree, _UserVerilogCode):
continue
v = _AnnotateTypesVisitor(tree)
v.visit(tree)

View File

@ -49,8 +49,8 @@ registerSimulator(
name="GHDL",
hdl="VHDL",
analyze="ghdl -a --workdir=work pck_myhdl_%(version)s.vhd %(topname)s.vhd",
elaborate="ghdl -e --workdir=work -o %(unitname)s_ghdl %(topname)s",
simulate="ghdl -r %(unitname)s_ghdl"
elaborate="ghdl -e --workdir=work -o %(unitname)s %(topname)s",
simulate="ghdl -r --workdir=work %(unitname)s"
)
@ -140,6 +140,7 @@ class _VerificationClass(object):
except:
pass
#print(analyze)
ret = subprocess.call(analyze, shell=True)
if ret != 0:
print >> sys.stderr, "Analysis failed"
@ -165,12 +166,14 @@ class _VerificationClass(object):
if elaborate is not None:
#print(elaborate)
ret = subprocess.call(elaborate, shell=True)
if ret != 0:
print >> sys.stderr, "Elaboration failed"
return ret
g = tempfile.TemporaryFile()
#print(simulate)
ret = subprocess.call(simulate, stdout=g, shell=True)
# if ret != 0:
# print "Simulation run failed"

View File

@ -0,0 +1,123 @@
import sys
from myhdl import *
from myhdl import ConversionError
from myhdl.conversion._misc import _error
from myhdl.conversion import analyze, verify
class MyIntf(object):
def __init__(self):
self.x = Signal(intbv(2,min=0,max=16))
self.y = Signal(intbv(3,min=0,max=18))
def m_one_level(clock,reset,ia,ib):
@always_seq(clock.posedge,reset=reset)
def rtl():
ia.x.next = ib.x + 1
ia.y.next = ib.y + 1
return rtl
def m_two_level(clock,reset,ia,ib):
ic,ie = (MyIntf(),MyIntf(),)
g_one = m_one_level(clock,reset,ic,ie)
@always_seq(clock.posedge,reset=reset)
def rtl():
ia.x.next = ib.x + ic.x
ia.y.next = ib.y + ic.y
return g_one, rtl
def c_testbench_one():
clock = Signal(bool(0))
reset = ResetSignal(0,active=0,async=True)
ia = MyIntf()
ib = MyIntf()
tb_dut = m_one_level(clock,reset,ia,ib)
@instance
def tb_clk():
clock.next = False
yield delay(10)
while True:
clock.next = not clock
yield delay(10)
@instance
def tb_stim():
reset.next = False
yield delay(17)
reset.next = True
yield delay(17)
for ii in range(7):
yield clock.posedge
assert ia.x == 3
assert ia.y == 4
print("%d %d %d %d"%(ia.x,ia.y,ib.x,ib.y))
raise StopSimulation
return tb_dut, tb_clk, tb_stim
def c_testbench_two():
clock = Signal(bool(0))
reset = ResetSignal(0,active=0,async=True)
ia = MyIntf()
ib = MyIntf()
tb_dut = m_two_level(clock,reset,ia,ib)
@instance
def tb_clk():
clock.next = False
yield delay(10)
while True:
clock.next = not clock
yield delay(10)
@instance
def tb_stim():
reset.next = False
yield delay(17)
reset.next = True
yield delay(17)
for ii in range(7):
yield clock.posedge
assert ia.x == 5
assert ia.y == 7
print("%d %d %d %d"%(ia.x,ia.y,ib.x,ib.y))
raise StopSimulation
return tb_dut, tb_clk, tb_stim
def test_one_level_analyze():
clock = Signal(bool(0))
reset = ResetSignal(0,active=0,async=True)
ia = MyIntf()
ib = MyIntf()
analyze(m_one_level,clock,reset,ia,ib)
def test_one_level_verify():
assert verify(c_testbench_one) == 0
def test_two_level_analyze():
clock = Signal(bool(0))
reset = ResetSignal(0,active=0,async=True)
ia = MyIntf()
ib = MyIntf()
analyze(m_two_level,clock,reset,ia,ib)
def test_two_level_verify():
assert verify(c_testbench_two) == 0
if __name__ == '__main__':
print(sys.argv[1])
verify.simulator = analyze.simulator = sys.argv[1]
Simulation(c_testbench_one()).run()
Simulation(c_testbench_two()).run()
print(verify(c_testbench_one))
print(verify(c_testbench_two))

View File

@ -0,0 +1,105 @@
import sys
from myhdl import *
from myhdl.conversion import analyze,verify
class Intf(object):
def __init__(self):
self.x = Signal(intbv(1,min=-1111,max=1111))
self.y = Signal(intbv(2,min=-2211,max=2211))
self.z = Signal(intbv(3,min=-3311,max=3311))
def m_modify(clock,reset,a):
intfa = Intf()
@always_seq(clock.posedge,reset=reset)
def rtl_inc():
intfa.x.next = intfa.x + 1
intfa.y.next = intfa.y + 2
intfa.z.next = intfa.z + 3
@always_comb
def rtl_add():
a.x.next = intfa.x + 1
a.y.next = intfa.y + 2
a.z.next = intfa.z + 3
return rtl_inc,rtl_add
def m_test_intf(clock,reset,a,b,c):
intfa = Intf()
intfaa = Intf()
gen_mod = m_modify(clock,reset,intfaa)
@always_seq(clock.posedge,reset=reset)
def rtl_inc():
intfa.x.next = intfa.x - 1
intfa.y.next = intfa.y - 2
intfa.z.next = intfa.z - 3
b.x.next = b.x + 1
b.y.next = b.y + 2
b.z.next = b.z + 3
c.x.next = c.x + 1
c.y.next = c.y + 2
c.z.next = c.z + 3
@always_comb
def rtl_combine():
a.x.next = intfaa.x + 1
a.y.next = intfaa.y + 2
a.z.next = intfaa.z + 3
return gen_mod,rtl_inc,rtl_combine
def c_testbench():
clock = Signal(bool(0))
reset = ResetSignal(0, active=0, async=False)
a,b,c = (Intf(),Intf(),Intf(),)
tb_dut = m_test_intf(clock,reset,a,b,c)
@instance
def tb_clk():
clock.next = False
yield delay(10)
while True:
clock.next = not clock
yield delay(10)
@instance
def tb_stim():
reset.next = False
yield delay(23)
reset.next = True
yield delay(33)
for ii in range(17):
print("a: x=%d y=%d z=%d"%(a.x,a.y,a.z))
print("b: x=%d y=%d z=%d"%(b.x,b.y,b.z))
print("c: x=%d y=%d z=%d"%(c.x,c.y,c.z))
yield clock.posedge
raise StopSimulation
return tb_dut,tb_clk,tb_stim
def test_name_conflicts_analyze():
clock = Signal(bool(0))
reset = ResetSignal(0, active=0, async=False)
a,b,c = (Intf(),Intf(),Intf(),)
analyze(m_test_intf,clock,reset,a,b,c)
def test_name_conflicts_verify():
assert verify(c_testbench) == 0
if __name__ == '__main__':
verify.simulator = analyze.simulator = sys.argv[1]
Simulation(c_testbench()).run()
print(verify(c_testbench))