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:
commit
409c07ee87
54
doc/source/whatsnew/0.9.rst
Normal file
54
doc/source/whatsnew/0.9.rst
Normal 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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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
21
myhdl/_convutils.py
Normal 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
|
@ -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
74
myhdl/_resolverefs.py
Normal 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
|
@ -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]
|
||||
|
@ -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):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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"
|
||||
|
123
myhdl/test/conversion/general/test_interfaces1.py
Normal file
123
myhdl/test/conversion/general/test_interfaces1.py
Normal 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))
|
105
myhdl/test/conversion/general/test_interfaces2.py
Normal file
105
myhdl/test/conversion/general/test_interfaces2.py
Normal 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))
|
||||
|
Loading…
x
Reference in New Issue
Block a user