mirror of
https://github.com/myhdl/myhdl.git
synced 2025-01-24 21:52:56 +08:00
Initial module decorator support
This commit is contained in:
parent
755d2b8c13
commit
becb7a4cff
@ -32,12 +32,11 @@ from myhdl import Cosimulation, StopSimulation, _SuspendSimulation
|
||||
from myhdl import _simulator, SimulationError
|
||||
from myhdl._simulator import _signals, _siglist, _futureEvents
|
||||
from myhdl._Waiter import _Waiter, _inferWaiter, _SignalWaiter,_SignalTupleWaiter
|
||||
from myhdl._util import _flatten, _printExcInfo
|
||||
from myhdl._util import _printExcInfo
|
||||
from myhdl._instance import _Instantiator
|
||||
from myhdl._module import _ModuleInstance
|
||||
from myhdl._ShadowSignal import _ShadowSignal
|
||||
|
||||
|
||||
|
||||
schedule = _futureEvents.append
|
||||
|
||||
class _error:
|
||||
@ -46,6 +45,21 @@ _error.ArgType = "Inappriopriate argument type"
|
||||
_error.MultipleCosim = "Only a single cosimulator argument allowed"
|
||||
_error.DuplicatedArg = "Duplicated argument"
|
||||
|
||||
# flatten Module objects out
|
||||
def _flatten(*args):
|
||||
arglist = []
|
||||
for arg in args:
|
||||
if isinstance(arg, _ModuleInstance):
|
||||
arg = arg.subs
|
||||
if isinstance(arg, (list, tuple, set)):
|
||||
for item in arg:
|
||||
arglist.extend(_flatten(item))
|
||||
else:
|
||||
arglist.append(arg)
|
||||
return arglist
|
||||
|
||||
|
||||
|
||||
class Simulation(object):
|
||||
|
||||
""" Simulation class.
|
||||
@ -231,4 +245,3 @@ def _makeWaiters(arglist):
|
||||
if hasattr(sig, '_waiter'):
|
||||
waiters.append(sig._waiter)
|
||||
return waiters, cosim
|
||||
|
||||
|
@ -82,6 +82,8 @@ class AlwaysCombError(Error):
|
||||
pass
|
||||
class InstanceError(Error):
|
||||
pass
|
||||
class ModuleError(Error):
|
||||
pass
|
||||
class CosimulationError(Error):
|
||||
pass
|
||||
class ExtractHierarchyError(Error):
|
||||
@ -130,6 +132,7 @@ from ._always_comb import always_comb
|
||||
from ._always_seq import always_seq, ResetSignal
|
||||
from ._always import always
|
||||
from ._instance import instance
|
||||
from ._module import module
|
||||
from ._enum import enum, EnumType, EnumItemType
|
||||
from ._traceSignals import traceSignals
|
||||
|
||||
@ -159,6 +162,7 @@ __all__ = ["bin",
|
||||
"Simulation",
|
||||
"instances",
|
||||
"instance",
|
||||
"module",
|
||||
"always_comb",
|
||||
"always_seq",
|
||||
"ResetSignal",
|
||||
|
@ -29,7 +29,7 @@ from myhdl._delay import delay
|
||||
from myhdl._Signal import _Signal, _WaiterList, posedge, negedge
|
||||
from myhdl._Waiter import _Waiter, _SignalWaiter, _SignalTupleWaiter, \
|
||||
_DelayWaiter, _EdgeWaiter, _EdgeTupleWaiter
|
||||
from myhdl._instance import _Instantiator
|
||||
from myhdl._instance import _Instantiator, _getCallInfo
|
||||
|
||||
class _error:
|
||||
pass
|
||||
@ -40,6 +40,7 @@ _error.DecNrOfArgs = "decorator should have arguments"
|
||||
|
||||
|
||||
def always(*args):
|
||||
modname, modctxt = _getCallInfo()
|
||||
for arg in args:
|
||||
if isinstance(arg, _Signal):
|
||||
arg._read = True
|
||||
@ -56,16 +57,16 @@ def always(*args):
|
||||
raise AlwaysError(_error.ArgType)
|
||||
if func.__code__.co_argcount > 0:
|
||||
raise AlwaysError(_error.NrOfArgs)
|
||||
return _Always(func, args)
|
||||
return _Always(func, args, modname=modname, modctxt=modctxt)
|
||||
return _always_decorator
|
||||
|
||||
|
||||
class _Always(_Instantiator):
|
||||
|
||||
def __init__(self, func, senslist):
|
||||
def __init__(self, func, senslist, modname, modctxt):
|
||||
self.func = func
|
||||
self.senslist = tuple(senslist)
|
||||
super(_Always, self).__init__(self.genfunc)
|
||||
super(_Always, self).__init__(self.genfunc, modname=modname, modctxt=modctxt)
|
||||
|
||||
@property
|
||||
def funcobj(self):
|
||||
|
@ -30,7 +30,7 @@ from myhdl import AlwaysCombError
|
||||
from myhdl._Signal import _Signal, _isListOfSigs
|
||||
from myhdl._util import _isGenFunc, _dedent
|
||||
from myhdl._Waiter import _Waiter, _SignalWaiter, _SignalTupleWaiter
|
||||
from myhdl._instance import _Instantiator
|
||||
from myhdl._instance import _getCallInfo
|
||||
from myhdl._always import _Always
|
||||
|
||||
class _error:
|
||||
@ -43,51 +43,22 @@ _error.EmbeddedFunction = "embedded functions in always_comb function argument n
|
||||
_error.EmptySensitivityList= "sensitivity list is empty"
|
||||
|
||||
def always_comb(func):
|
||||
modname, modctxt = _getCallInfo()
|
||||
if not isinstance( func, FunctionType):
|
||||
raise AlwaysCombError(_error.ArgType)
|
||||
if _isGenFunc(func):
|
||||
raise AlwaysCombError(_error.ArgType)
|
||||
if func.__code__.co_argcount > 0:
|
||||
raise AlwaysCombError(_error.NrOfArgs)
|
||||
c = _AlwaysComb(func)
|
||||
c = _AlwaysComb(func, modname=modname, modctxt=modctxt)
|
||||
return c
|
||||
|
||||
|
||||
# class _AlwaysComb(_Instantiator):
|
||||
class _AlwaysComb(_Always):
|
||||
|
||||
# def __init__(self, func, symdict):
|
||||
# self.func = func
|
||||
# self.symdict = symdict
|
||||
# s = inspect.getsource(func)
|
||||
# # remove decorators
|
||||
# s = re.sub(r"@.*", "", s)
|
||||
# s = s.lstrip()
|
||||
# tree = compiler.parse(s)
|
||||
# v = _SigNameVisitor(symdict)
|
||||
# compiler.walk(tree, v)
|
||||
# self.inputs = v.inputs
|
||||
# self.outputs = v.outputs
|
||||
# senslist = []
|
||||
# for n in self.inputs:
|
||||
# s = self.symdict[n]
|
||||
# if isinstance(s, Signal):
|
||||
# senslist.append(s)
|
||||
# else: # list of sigs
|
||||
# senslist.extend(s)
|
||||
# self.senslist = tuple(senslist)
|
||||
# self.gen = self.genfunc()
|
||||
# if len(self.senslist) == 0:
|
||||
# raise AlwaysCombError(_error.EmptySensitivityList)
|
||||
# if len(self.senslist) == 1:
|
||||
# W = _SignalWaiter
|
||||
# else:
|
||||
# W = _SignalTupleWaiter
|
||||
# self.waiter = W(self.gen)
|
||||
|
||||
def __init__(self, func):
|
||||
def __init__(self, func, modname, modctxt):
|
||||
senslist = []
|
||||
super(_AlwaysComb, self).__init__(func, senslist)
|
||||
super(_AlwaysComb, self).__init__(func, senslist, modname=modname, modctxt=modctxt)
|
||||
|
||||
inouts = self.inouts | self.inputs.intersection(self.outputs)
|
||||
if inouts:
|
||||
|
@ -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._always import _Always
|
||||
from myhdl._instance import _getCallInfo
|
||||
|
||||
# evacuate this later
|
||||
AlwaysSeqError = AlwaysError
|
||||
@ -59,6 +60,7 @@ class ResetSignal(_Signal):
|
||||
|
||||
|
||||
def always_seq(edge, reset):
|
||||
modname, modctxt = _getCallInfo()
|
||||
if not isinstance(edge, _WaiterList):
|
||||
raise AlwaysSeqError(_error.EdgeType)
|
||||
edge.sig._read = True
|
||||
@ -76,13 +78,13 @@ def always_seq(edge, reset):
|
||||
raise AlwaysSeqError(_error.ArgType)
|
||||
if func.__code__.co_argcount > 0:
|
||||
raise AlwaysSeqError(_error.NrOfArgs)
|
||||
return _AlwaysSeq(func, edge, reset)
|
||||
return _AlwaysSeq(func, edge, reset, modname=modname, modctxt=modctxt)
|
||||
return _always_seq_decorator
|
||||
|
||||
|
||||
class _AlwaysSeq(_Always):
|
||||
|
||||
def __init__(self, func, edge, reset):
|
||||
def __init__(self, func, edge, reset, modname, modctxt):
|
||||
senslist = [edge]
|
||||
self.reset = reset
|
||||
if reset is not None:
|
||||
@ -97,7 +99,7 @@ class _AlwaysSeq(_Always):
|
||||
else:
|
||||
self.genfunc = self.genfunc_no_reset
|
||||
|
||||
super(_AlwaysSeq, self).__init__(func, senslist)
|
||||
super(_AlwaysSeq, self).__init__(func, senslist, modname=modname, modctxt=modctxt)
|
||||
|
||||
if self.inouts:
|
||||
raise AlwaysSeqError(_error.SigAugAssign, v.inouts)
|
||||
|
63
myhdl/_getHierarchy.py
Normal file
63
myhdl/_getHierarchy.py
Normal file
@ -0,0 +1,63 @@
|
||||
# This file is part of the myhdl library, a Python package for using
|
||||
# Python as a Hardware Description Language.
|
||||
#
|
||||
# Copyright (C) 2003-2016 Jan Decaluwe
|
||||
#
|
||||
# The myhdl library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public License as
|
||||
# published by the Free Software Foundation; either version 2.1 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
""" myhdl _getHierarchy module.
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from myhdl._extractHierarchy import _Instance
|
||||
from myhdl._instance import _Instantiator
|
||||
from myhdl._module import _ModuleInstance
|
||||
|
||||
class _Hierarchy(object):
|
||||
def __init__(self, name, modinst):
|
||||
self.top = modinst
|
||||
self.hierarchy = hierarchy = []
|
||||
self.absnames = absnames = {}
|
||||
_getHierarchyHelper(1, modinst, hierarchy)
|
||||
# compatibility with _extractHierarchy
|
||||
# walk the hierarchy to define relative and absolute names
|
||||
names = {}
|
||||
top_inst = hierarchy[0]
|
||||
obj, subs = top_inst.obj, top_inst.subs
|
||||
names[id(obj)] = name
|
||||
absnames[id(obj)] = name
|
||||
for inst in hierarchy:
|
||||
obj, subs = inst.obj, inst.subs
|
||||
inst.name = names[id(obj)]
|
||||
tn = absnames[id(obj)]
|
||||
for sn, so in subs:
|
||||
names[id(so)] = sn
|
||||
absnames[id(so)] = "%s_%s" % (tn, sn)
|
||||
# print (names)
|
||||
# print(absnames)
|
||||
|
||||
def _getHierarchy(name, modinst):
|
||||
h = _Hierarchy(name, modinst)
|
||||
return h
|
||||
|
||||
def _getHierarchyHelper(level, modinst, hierarchy):
|
||||
subs = [(s.name, s) for s in modinst.subs]
|
||||
inst = _Instance(level, modinst, subs, modinst.sigdict, modinst.memdict)
|
||||
hierarchy.append(inst)
|
||||
for inst in modinst.subs:
|
||||
if isinstance(inst, _ModuleInstance):
|
||||
_getHierarchyHelper(level+1, inst, hierarchy)
|
@ -21,6 +21,7 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
|
||||
import inspect
|
||||
from types import FunctionType
|
||||
|
||||
from myhdl import InstanceError
|
||||
@ -34,19 +35,42 @@ class _error:
|
||||
_error.NrOfArgs = "decorated generator function should not have arguments"
|
||||
_error.ArgType = "decorated object should be a generator function"
|
||||
|
||||
def _getCallInfo():
|
||||
"""Get info of the callers of e.g. an instantiator decorator.
|
||||
|
||||
For hierarchy extraction, instantator decorators should only be used
|
||||
within a module context. This function is hack to get info to check
|
||||
that. It uses theframe stack:
|
||||
0: this function
|
||||
1: the instantiator decorator
|
||||
2: the module function that defines instances
|
||||
3: the caller of the module function, e.g. the ModuleInstance class.
|
||||
"""
|
||||
from myhdl import _module
|
||||
modname = inspect.stack()[2][3]
|
||||
modctxt = False
|
||||
f_locals = inspect.stack()[3][0].f_locals
|
||||
if 'self' in f_locals:
|
||||
print f_locals['self'].__class__
|
||||
modctxt = isinstance(f_locals['self'], _module._ModuleInstance)
|
||||
return modname, modctxt
|
||||
|
||||
|
||||
def instance(genfunc):
|
||||
modname, modctxt = _getCallInfo()
|
||||
if not isinstance(genfunc, FunctionType):
|
||||
raise InstanceError(_error.ArgType)
|
||||
if not _isGenFunc(genfunc):
|
||||
raise InstanceError(_error.ArgType)
|
||||
if genfunc.__code__.co_argcount > 0:
|
||||
raise InstanceError(_error.NrOfArgs)
|
||||
return _Instantiator(genfunc)
|
||||
return _Instantiator(genfunc, modname=modname, modctxt=modctxt)
|
||||
|
||||
class _Instantiator(object):
|
||||
|
||||
def __init__(self, genfunc):
|
||||
def __init__(self, genfunc, modname, modctxt):
|
||||
self.modname = modname
|
||||
self.modctxt = modctxt
|
||||
self.genfunc = genfunc
|
||||
self.gen = genfunc()
|
||||
# infer symdict
|
||||
@ -73,6 +97,12 @@ class _Instantiator(object):
|
||||
self.outputs = v.outputs
|
||||
self.inouts = v.inouts
|
||||
self.embedded_func = v.embedded_func
|
||||
self.sigdict = v.sigdict
|
||||
self.losdict = v.losdict
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.funcobj.__name__
|
||||
|
||||
@property
|
||||
def funcobj(self):
|
||||
|
95
myhdl/_module.py
Normal file
95
myhdl/_module.py
Normal file
@ -0,0 +1,95 @@
|
||||
# This file is part of the myhdl library, a Python package for using
|
||||
# Python as a Hardware Description Language.
|
||||
#
|
||||
# Copyright (C) 2003-2016 Jan Decaluwe
|
||||
#
|
||||
# The myhdl library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public License as
|
||||
# published by the Free Software Foundation; either version 2.1 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
""" Module with the @module decorator function. """
|
||||
from __future__ import absolute_import
|
||||
|
||||
import functools
|
||||
import inspect
|
||||
|
||||
from myhdl import ModuleError
|
||||
from myhdl._instance import _Instantiator
|
||||
from myhdl._util import _flatten
|
||||
from myhdl._extractHierarchy import _MemInfo, _makeMemInfo
|
||||
|
||||
|
||||
class _error:
|
||||
pass
|
||||
_error.ArgType = "A module should return module or instantiator objects"
|
||||
_error.InstanceError = "%s: submodule %s should be encapsulated in a module decorator"
|
||||
|
||||
def module(modfunc):
|
||||
return _Module(modfunc)
|
||||
|
||||
class _Module(object):
|
||||
|
||||
def __init__(self, modfunc):
|
||||
self.modfunc = modfunc
|
||||
self.__name__ = self.name = modfunc.__name__
|
||||
self.count = 0
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
modinst = _ModuleInstance(self, *args, **kwargs)
|
||||
self.count += 1
|
||||
return modinst
|
||||
|
||||
class _ModuleInstance(object):
|
||||
|
||||
def __init__(self, mod, *args, **kwargs):
|
||||
self.mod = mod
|
||||
self.sigdict = {}
|
||||
self.memdict = {}
|
||||
# flatten, but keep ModuleInstance objects
|
||||
self.subs = _flatten(mod.modfunc(*args, **kwargs))
|
||||
self.verifyMod()
|
||||
self.updateMod()
|
||||
self.inferInterface(*args, **kwargs)
|
||||
self.name = self.__name__ = mod.__name__ + '_' + str(mod.count)
|
||||
|
||||
def verifyMod(self):
|
||||
for inst in self.subs:
|
||||
# print (inst.name, type(inst))
|
||||
if not isinstance(inst, (_ModuleInstance, _Instantiator)):
|
||||
raise ModuleError(_error.ArgType)
|
||||
if isinstance(inst, _Instantiator):
|
||||
if not inst.modctxt:
|
||||
raise ModuleError(_error.InstanceError % (self.mod.name, inst.modname))
|
||||
|
||||
def updateMod(self):
|
||||
losdict = {}
|
||||
for inst in self.subs:
|
||||
if isinstance(inst, _Instantiator):
|
||||
self.sigdict.update(inst.sigdict)
|
||||
losdict.update(inst.losdict)
|
||||
else:
|
||||
# reset instantiation counter
|
||||
self.mod.count = 0
|
||||
# compatibility patches from _extractHierarchy
|
||||
for s in self.sigdict.values():
|
||||
s._markUsed()
|
||||
for n, l in losdict.items():
|
||||
m = _makeMemInfo(l)
|
||||
self.memdict[n] = m
|
||||
m._used = True
|
||||
|
||||
def inferInterface(self, *args, **kwargs):
|
||||
from myhdl.conversion._analyze import _analyzeTopFunc
|
||||
intf = _analyzeTopFunc(self.mod.modfunc, *args, **kwargs)
|
||||
self.argnames = intf.argnames
|
||||
self.argdict = intf.argdict
|
@ -25,6 +25,8 @@ now -- function that returns the current simulation time
|
||||
"""
|
||||
|
||||
|
||||
|
||||
|
||||
_signals = []
|
||||
_siglist = []
|
||||
_futureEvents = []
|
||||
|
@ -13,6 +13,8 @@ class _SigNameVisitor(ast.NodeVisitor):
|
||||
self.inouts = set()
|
||||
self.embedded_func = None
|
||||
self.context = 'input'
|
||||
self.sigdict = {}
|
||||
self.losdict = {}
|
||||
|
||||
def visit_Module(self, node):
|
||||
for n in node.body:
|
||||
@ -34,20 +36,24 @@ class _SigNameVisitor(ast.NodeVisitor):
|
||||
self.generic_visit(node)
|
||||
|
||||
def visit_Name(self, node):
|
||||
id = node.id
|
||||
if id not in self.symdict:
|
||||
n = node.id
|
||||
if n not in self.symdict:
|
||||
return
|
||||
s = self.symdict[id]
|
||||
s = self.symdict[n]
|
||||
if isinstance(s, (_Signal, intbv)) or _isListOfSigs(s):
|
||||
if self.context == 'input':
|
||||
self.inputs.add(id)
|
||||
self.inputs.add(n)
|
||||
elif self.context == 'output':
|
||||
self.outputs.add(id)
|
||||
self.outputs.add(n)
|
||||
elif self.context == 'inout':
|
||||
self.inouts.add(id)
|
||||
self.inouts.add(n)
|
||||
else:
|
||||
print(self.context)
|
||||
raise AssertionError("bug in _SigNameVisitor")
|
||||
if isinstance(s, _Signal):
|
||||
self.sigdict[n] = s
|
||||
elif _isListOfSigs(s):
|
||||
self.losdict[n] = s
|
||||
|
||||
def visit_Assign(self, node):
|
||||
self.context = 'output'
|
||||
|
@ -55,6 +55,8 @@ from myhdl._util import _flatten
|
||||
from myhdl._compat import integer_types, class_types, StringIO
|
||||
from myhdl._ShadowSignal import _TristateSignal, _TristateDriver
|
||||
|
||||
from myhdl._module import _ModuleInstance
|
||||
from myhdl._getHierarchy import _getHierarchy
|
||||
|
||||
_version = myhdl.__version__.replace('.','')
|
||||
_shortversion = _version.replace('dev','')
|
||||
@ -70,6 +72,8 @@ def _checkArgs(arglist):
|
||||
def _flatten(*args):
|
||||
arglist = []
|
||||
for arg in args:
|
||||
if isinstance(arg, _ModuleInstance):
|
||||
arg = arg.subs
|
||||
if id(arg) in _userCodeMap['vhdl']:
|
||||
arglist.append(_userCodeMap['vhdl'][id(arg)])
|
||||
elif isinstance(arg, (list, tuple, set)):
|
||||
@ -125,18 +129,28 @@ class _ToVHDLConvertor(object):
|
||||
from myhdl import _traceSignals
|
||||
if _traceSignals._tracing:
|
||||
raise ToVHDLError("Cannot use toVHDL while tracing signals")
|
||||
if not callable(func):
|
||||
raise ToVHDLError(_error.FirstArgType, "got %s" % type(func))
|
||||
if not isinstance(func, _ModuleInstance):
|
||||
if not callable(func):
|
||||
raise ToVHDLError(_error.FirstArgType, "got %s" % type(func))
|
||||
|
||||
_converting = 1
|
||||
if self.name is None:
|
||||
name = func.__name__
|
||||
if isinstance(func, _ModuleInstance):
|
||||
name = func.mod.__name__
|
||||
else:
|
||||
name = str(self.name)
|
||||
try:
|
||||
h = _HierExtr(name, func, *args, **kwargs)
|
||||
finally:
|
||||
_converting = 0
|
||||
|
||||
if isinstance(func, _ModuleInstance):
|
||||
try:
|
||||
h = _getHierarchy(name, func)
|
||||
finally:
|
||||
_converting = 0
|
||||
else:
|
||||
try:
|
||||
h = _HierExtr(name, func, *args, **kwargs)
|
||||
finally:
|
||||
_converting = 0
|
||||
|
||||
if self.directory is None:
|
||||
directory = ''
|
||||
@ -170,7 +184,10 @@ class _ToVHDLConvertor(object):
|
||||
_annotateTypes(genlist)
|
||||
|
||||
### infer interface
|
||||
intf = _analyzeTopFunc(func, *args, **kwargs)
|
||||
if isinstance(func, _ModuleInstance):
|
||||
intf = func # already inferred
|
||||
else:
|
||||
intf = _analyzeTopFunc(func, *args, **kwargs)
|
||||
intf.name = name
|
||||
# sanity checks on interface
|
||||
for portname in intf.argnames:
|
||||
|
@ -52,6 +52,9 @@ from myhdl.conversion._analyze import (_analyzeSigs, _analyzeGens, _analyzeTopFu
|
||||
from myhdl._Signal import _Signal
|
||||
from myhdl._ShadowSignal import _TristateSignal, _TristateDriver
|
||||
|
||||
from myhdl._module import _ModuleInstance
|
||||
from myhdl._getHierarchy import _getHierarchy
|
||||
|
||||
_converting = 0
|
||||
_profileFunc = None
|
||||
|
||||
@ -63,6 +66,8 @@ def _checkArgs(arglist):
|
||||
def _flatten(*args):
|
||||
arglist = []
|
||||
for arg in args:
|
||||
if isinstance(arg, _ModuleInstance):
|
||||
arg = arg.subs
|
||||
if id(arg) in _userCodeMap['verilog']:
|
||||
arglist.append(_userCodeMap['verilog'][id(arg)])
|
||||
elif isinstance(arg, (list, tuple, set)):
|
||||
@ -120,18 +125,28 @@ class _ToVerilogConvertor(object):
|
||||
from myhdl import _traceSignals
|
||||
if _traceSignals._tracing:
|
||||
raise ToVerilogError("Cannot use toVerilog while tracing signals")
|
||||
if not callable(func):
|
||||
raise ToVerilogError(_error.FirstArgType, "got %s" % type(func))
|
||||
if not isinstance(func, _ModuleInstance):
|
||||
if not callable(func):
|
||||
raise ToVerilogError(_error.FirstArgType, "got %s" % type(func))
|
||||
|
||||
_converting = 1
|
||||
if self.name is None:
|
||||
name = func.__name__
|
||||
if isinstance(func, _ModuleInstance):
|
||||
name = func.mod.__name__
|
||||
else:
|
||||
name = str(self.name)
|
||||
try:
|
||||
h = _HierExtr(name, func, *args, **kwargs)
|
||||
finally:
|
||||
_converting = 0
|
||||
|
||||
if isinstance(func, _ModuleInstance):
|
||||
try:
|
||||
h = _getHierarchy(name, func)
|
||||
finally:
|
||||
_converting = 0
|
||||
else:
|
||||
try:
|
||||
h = _HierExtr(name, func, *args, **kwargs)
|
||||
finally:
|
||||
_converting = 0
|
||||
|
||||
if self.directory is None:
|
||||
directory = ''
|
||||
@ -152,8 +167,13 @@ class _ToVerilogConvertor(object):
|
||||
siglist, memlist = _analyzeSigs(h.hierarchy)
|
||||
_annotateTypes(genlist)
|
||||
|
||||
intf = _analyzeTopFunc(func, *args, **kwargs)
|
||||
### infer interface
|
||||
if isinstance(func, _ModuleInstance):
|
||||
intf = func # already inferred
|
||||
else:
|
||||
intf = _analyzeTopFunc(func, *args, **kwargs)
|
||||
intf.name = name
|
||||
|
||||
doc = _makeDoc(inspect.getdoc(func))
|
||||
|
||||
self._convert_filter(h, intf, siglist, memlist, genlist)
|
||||
|
@ -12,6 +12,7 @@ import myhdl
|
||||
from myhdl._Simulation import Simulation
|
||||
from myhdl.conversion._toVHDL import toVHDL
|
||||
from myhdl.conversion._toVerilog import toVerilog
|
||||
from myhdl._module import _ModuleInstance
|
||||
|
||||
_version = myhdl.__version__.replace('.','')
|
||||
# strip 'dev' for version
|
||||
@ -112,6 +113,8 @@ class _VerificationClass(object):
|
||||
name = toVerilog.name
|
||||
elif hdl == 'VHDL' and toVHDL.name is not None:
|
||||
name = toVHDL.name
|
||||
elif isinstance(func, _ModuleInstance):
|
||||
name = func.mod.__name__
|
||||
else:
|
||||
name = func.__name__
|
||||
|
||||
@ -129,10 +132,16 @@ class _VerificationClass(object):
|
||||
skipchars = hdlsim.skipchars
|
||||
ignore = hdlsim.ignore
|
||||
|
||||
if hdl == "VHDL":
|
||||
inst = toVHDL(func, *args, **kwargs)
|
||||
if isinstance(func, _ModuleInstance):
|
||||
if hdl == "VHDL":
|
||||
inst = toVHDL(func)
|
||||
else:
|
||||
inst = toVerilog(func)
|
||||
else:
|
||||
inst = toVerilog(func, *args, **kwargs)
|
||||
if hdl == "VHDL":
|
||||
inst = toVHDL(func, *args, **kwargs)
|
||||
else:
|
||||
inst = toVerilog(func, *args, **kwargs)
|
||||
|
||||
if hdl == "VHDL":
|
||||
if not os.path.exists("work"):
|
||||
|
@ -5,6 +5,7 @@ path = os.path
|
||||
from myhdl import *
|
||||
from myhdl.conversion import verify
|
||||
|
||||
@module
|
||||
def bin2gray2(B, G, width):
|
||||
""" Gray encoder.
|
||||
|
||||
@ -22,6 +23,7 @@ def bin2gray2(B, G, width):
|
||||
G.next[i] = Bext[i+1] ^ Bext[i]
|
||||
return logic
|
||||
|
||||
@module
|
||||
def bin2gray(B, G, width):
|
||||
|
||||
""" Gray encoder.
|
||||
@ -42,7 +44,7 @@ def bin2gray(B, G, width):
|
||||
return logic
|
||||
|
||||
|
||||
|
||||
@module
|
||||
def bin2grayBench(width, bin2gray):
|
||||
|
||||
B = Signal(intbv(0)[width:])
|
||||
@ -67,8 +69,7 @@ def bin2grayBench(width, bin2gray):
|
||||
|
||||
|
||||
def test1():
|
||||
assert verify(bin2grayBench, width=8, bin2gray=bin2gray) == 0
|
||||
assert verify(bin2grayBench(width=8, bin2gray=bin2gray)) == 0
|
||||
|
||||
def test2():
|
||||
assert verify(bin2grayBench, width=8, bin2gray=bin2gray2) == 0
|
||||
|
||||
assert verify(bin2grayBench(width=8, bin2gray=bin2gray2)) == 0
|
||||
|
@ -12,6 +12,7 @@ t_State_b = enum('SEARCH', 'CONFIRM', 'SYNC')
|
||||
t_State_oh = enum('SEARCH', 'CONFIRM', 'SYNC', encoding="one_hot")
|
||||
t_State_oc = enum('SEARCH', 'CONFIRM', 'SYNC', encoding="one_cold")
|
||||
|
||||
@module
|
||||
def FramerCtrl(SOF, state, syncFlag, clk, reset_n, t_State):
|
||||
|
||||
""" Framing control FSM.
|
||||
@ -55,8 +56,7 @@ def FramerCtrl(SOF, state, syncFlag, clk, reset_n, t_State):
|
||||
|
||||
return FSM
|
||||
|
||||
|
||||
|
||||
@module
|
||||
def FSMBench(FramerCtrl, t_State):
|
||||
|
||||
SOF = Signal(bool(0))
|
||||
@ -110,5 +110,5 @@ def FSMBench(FramerCtrl, t_State):
|
||||
|
||||
|
||||
def test():
|
||||
assert verify(FSMBench, FramerCtrl, t_State_b) == 0
|
||||
assert verify(FSMBench(FramerCtrl, t_State_b)) == 0
|
||||
|
||||
|
@ -12,6 +12,7 @@ from myhdl.conversion import verify
|
||||
|
||||
ACTIVE_LOW, INACTIVE_HIGH = bool(0), bool(1)
|
||||
|
||||
@module
|
||||
def incRef(count, enable, clock, reset, n):
|
||||
""" Incrementer with enable.
|
||||
|
||||
@ -32,6 +33,7 @@ def incRef(count, enable, clock, reset, n):
|
||||
count.next = (count + 1) % n
|
||||
return logic
|
||||
|
||||
@module
|
||||
def inc(count, enable, clock, reset, n):
|
||||
|
||||
""" Incrementer with enable.
|
||||
@ -54,6 +56,7 @@ def inc(count, enable, clock, reset, n):
|
||||
|
||||
return incProcess
|
||||
|
||||
@module
|
||||
def inc2(count, enable, clock, reset, n):
|
||||
|
||||
@always(clock.posedge, reset.negedge)
|
||||
@ -69,6 +72,7 @@ def inc2(count, enable, clock, reset, n):
|
||||
return incProcess
|
||||
|
||||
|
||||
@module
|
||||
def incFunc(count, enable, clock, reset, n):
|
||||
def incFuncFunc(cnt, enable):
|
||||
count_next = intbv(0, min=0, max=n)
|
||||
@ -87,6 +91,7 @@ def incFunc(count, enable, clock, reset, n):
|
||||
return incFuncGen
|
||||
|
||||
|
||||
@module
|
||||
def incTask(count, enable, clock, reset, n):
|
||||
|
||||
def incTaskFunc(cnt, enable, reset, n):
|
||||
@ -109,6 +114,7 @@ def incTask(count, enable, clock, reset, n):
|
||||
return incTaskGen
|
||||
|
||||
|
||||
@module
|
||||
def incTaskFreeVar(count, enable, clock, reset, n):
|
||||
|
||||
def incTaskFunc():
|
||||
@ -126,6 +132,7 @@ def incTaskFreeVar(count, enable, clock, reset, n):
|
||||
return incTaskGen
|
||||
|
||||
|
||||
@module
|
||||
def IncBench(inc):
|
||||
|
||||
NR_CYCLES = 201
|
||||
@ -163,18 +170,18 @@ def IncBench(inc):
|
||||
|
||||
|
||||
def test_incReg():
|
||||
assert verify(IncBench, incRef) == 0
|
||||
assert verify(IncBench(incRef)) == 0
|
||||
|
||||
def test_inc():
|
||||
assert verify(IncBench, inc) == 0
|
||||
assert verify(IncBench(inc)) == 0
|
||||
|
||||
def test_inc2():
|
||||
assert verify(IncBench, inc2) == 0
|
||||
assert verify(IncBench(inc2)) == 0
|
||||
|
||||
def testIncTask():
|
||||
assert verify(IncBench, incTask) == 0
|
||||
assert verify(IncBench(incTask)) == 0
|
||||
|
||||
def testIncFunc():
|
||||
assert verify(IncBench, incFunc) == 0
|
||||
assert verify(IncBench(incFunc)) == 0
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user