mirror of
https://github.com/myhdl/myhdl.git
synced 2025-01-24 21:52:56 +08:00
**Constant** signals (#423)
* Added `Constant` signal object * Corrected *_shortversion* ToDo: replace by single global variable in myhdl/myhdl/__init__.py * one more *_shortversion* ...
This commit is contained in:
parent
4081474f75
commit
15104a0f8c
@ -180,8 +180,8 @@ class _Signal(object):
|
||||
self._val = deepcopy(self._init)
|
||||
self._next = deepcopy(self._init)
|
||||
self._name = self._driven = None
|
||||
self._read = False # dont clear self._used
|
||||
self._inList = False
|
||||
self._read = False # dont clear self._used
|
||||
self._inList = False
|
||||
self._numeric = True
|
||||
for s in self._slicesigs:
|
||||
s._clear()
|
||||
@ -268,7 +268,7 @@ class _Signal(object):
|
||||
|
||||
@read.setter
|
||||
def read(self, val):
|
||||
if not val in (True, ):
|
||||
if not val in (True,):
|
||||
raise ValueError('Expected value True, got "%s"' % val)
|
||||
self._markRead()
|
||||
|
||||
@ -552,7 +552,7 @@ class _Signal(object):
|
||||
def __setitem__(self, key, val):
|
||||
raise TypeError("Signal object doesn't support item/slice assignment")
|
||||
|
||||
# continues assignment support
|
||||
# continuous assignment support
|
||||
def assign(self, sig):
|
||||
|
||||
self.driven = "wire"
|
||||
@ -637,6 +637,38 @@ class _SignalWrap(object):
|
||||
def apply(self):
|
||||
return self.sig._apply(self.next, self.timeStamp)
|
||||
|
||||
|
||||
class Constant(_Signal):
|
||||
''' effective constants '''
|
||||
|
||||
def __init__(self, val=None):
|
||||
super(Constant, self).__init__(val)
|
||||
|
||||
# override some essentials
|
||||
def __repr__(self):
|
||||
return "Constant(" + repr(self._val) + ")"
|
||||
|
||||
# there is support for the 'next' attribute
|
||||
@property
|
||||
def next(self):
|
||||
return None
|
||||
|
||||
@next.setter
|
||||
def next(self, val):
|
||||
raise PermissionError("A 'Constant' can not be changed!")
|
||||
|
||||
# neither can it be driven
|
||||
# support for the 'driven' attribute
|
||||
@property
|
||||
def driven(self):
|
||||
return None
|
||||
|
||||
@driven.setter
|
||||
def driven(self, val):
|
||||
# quietly ignore?
|
||||
pass
|
||||
|
||||
|
||||
# for export
|
||||
SignalType = _Signal
|
||||
|
||||
|
@ -49,7 +49,7 @@ traceSignals -- function that enables signal tracing in a VCD file
|
||||
toVerilog -- function that converts a design to Verilog
|
||||
|
||||
"""
|
||||
__version__ = "0.11.42"
|
||||
__version__ = "0.11.43"
|
||||
|
||||
|
||||
class StopSimulation(Exception):
|
||||
@ -139,7 +139,7 @@ class ToVHDLWarning(ConversionWarning):
|
||||
# def showwarning(message, category, filename, lineno, *args):
|
||||
# print("** %s: %s" % (category.__name__, message), file=sys.stderr)
|
||||
|
||||
#warnings.showwarning = showwarning
|
||||
# warnings.showwarning = showwarning
|
||||
|
||||
|
||||
from ._bin import bin
|
||||
@ -147,7 +147,7 @@ from ._concat import concat
|
||||
from ._intbv import intbv
|
||||
from ._modbv import modbv
|
||||
from ._join import join
|
||||
from ._Signal import posedge, negedge, Signal, SignalType
|
||||
from ._Signal import posedge, negedge, Signal, SignalType, Constant
|
||||
from ._ShadowSignal import ConcatSignal
|
||||
from ._ShadowSignal import TristateSignal
|
||||
from ._simulator import now
|
||||
@ -169,7 +169,6 @@ from .conversion import toVHDL
|
||||
|
||||
from ._tristate import Tristate
|
||||
|
||||
|
||||
__all__ = ["bin",
|
||||
"concat",
|
||||
"intbv",
|
||||
@ -179,6 +178,7 @@ __all__ = ["bin",
|
||||
"negedge",
|
||||
"Signal",
|
||||
"SignalType",
|
||||
"Constant",
|
||||
"ConcatSignal",
|
||||
"TristateSignal",
|
||||
"now",
|
||||
|
@ -21,7 +21,7 @@
|
||||
from types import FunctionType
|
||||
|
||||
from myhdl import AlwaysCombError
|
||||
from myhdl._Signal import _Signal, _isListOfSigs
|
||||
from myhdl._Signal import _Signal, _isListOfSigs, Constant
|
||||
from myhdl._util import _isGenFunc
|
||||
from myhdl._instance import _getCallInfo
|
||||
from myhdl._always import _Always
|
||||
@ -62,9 +62,9 @@ class _AlwaysComb(_Always):
|
||||
|
||||
for n in self.inputs:
|
||||
s = self.symdict[n]
|
||||
if isinstance(s, _Signal):
|
||||
if isinstance(s, _Signal) and not isinstance(s, Constant):
|
||||
senslist.append(s)
|
||||
elif _isListOfSigs(s):
|
||||
elif _isListOfSigs(s) and not isinstance(s[0], Constant):
|
||||
senslist.extend(s)
|
||||
self.senslist = tuple(senslist)
|
||||
if len(self.senslist) == 0:
|
||||
@ -79,4 +79,3 @@ class _AlwaysComb(_Always):
|
||||
func()
|
||||
yield senslist
|
||||
|
||||
|
||||
|
@ -43,7 +43,7 @@ from myhdl._extractHierarchy import (_HierExtr, _isMem, _getMemInfo,
|
||||
_UserVhdlCode, _userCodeMap)
|
||||
|
||||
from myhdl._instance import _Instantiator
|
||||
from myhdl._Signal import _Signal, _WaiterList, posedge, negedge
|
||||
from myhdl._Signal import _Signal, _WaiterList, posedge, negedge, Constant
|
||||
from myhdl._enum import EnumType, EnumItemType
|
||||
from myhdl._intbv import intbv
|
||||
from myhdl._modbv import modbv
|
||||
@ -65,7 +65,7 @@ from myhdl.conversion._VHDLNameValidation import _nameValid, _usedNames
|
||||
from myhdl import bin as tobin
|
||||
|
||||
_version = myhdl.__version__.replace('.', '')
|
||||
_shortversion = _version.replace('dev', '')
|
||||
_shortversion = _version.replace('dev', '')[:-2] # loose the subminor version number
|
||||
_converting = 0
|
||||
_profileFunc = None
|
||||
_enumPortTypeSet = set()
|
||||
@ -498,11 +498,21 @@ def _writeSigDecls(f, intf, siglist, memlist):
|
||||
# the original exception
|
||||
# raise ToVHDLError(_error.UndrivenSignal, s._name)
|
||||
# changed to a warning and a continuous assignment to a wire
|
||||
warnings.warn("%s: %s" % (_error.UndrivenSignal, s._name),
|
||||
category=ToVHDLWarning
|
||||
)
|
||||
constwires.append(s)
|
||||
print("signal %s: %s%s;" % (s._name, p, r), file=f)
|
||||
if isinstance(s, Constant):
|
||||
if isinstance(s._val, intbv):
|
||||
if s._init:
|
||||
print('constant %s: %s%s := %dX"%s" /* %s */;' % (s._name, p, r, s._nrbits, str(s._init), int(s._init)), file=f)
|
||||
else:
|
||||
print('constant %s: %s%s := %dX"0";' % (s._name, p, r, s._nrbits), file=f)
|
||||
else:
|
||||
print("constant %s: %s%s := %s;" % (s._name, p, r, "'1'" if s._init else "'0'"), file=f)
|
||||
else:
|
||||
warnings.warn("%s: %s" % (_error.UndrivenSignal, s._name),
|
||||
category=ToVHDLWarning
|
||||
)
|
||||
constwires.append(s)
|
||||
print("signal %s: %s%s;" % (s._name, p, r), file=f)
|
||||
|
||||
for m in memlist:
|
||||
if not m._used:
|
||||
continue
|
||||
@ -520,7 +530,7 @@ def _writeSigDecls(f, intf, siglist, memlist):
|
||||
p = _getTypeString(m.elObj)
|
||||
t = "t_array_%s" % m.name
|
||||
|
||||
if not toVHDL.initial_values:
|
||||
if not toVHDL.initial_values and not isinstance(m.mem[0], Constant):
|
||||
val_str = ""
|
||||
else:
|
||||
sig_vhdl_objs = [inferVhdlObj(each) for each in m.mem]
|
||||
@ -542,7 +552,10 @@ def _writeSigDecls(f, intf, siglist, memlist):
|
||||
val_str = ' := (\n ' + _val_str + ')'
|
||||
|
||||
print("type %s is array(0 to %s-1) of %s%s;" % (t, m.depth, p, r), file=f)
|
||||
print("signal %s: %s%s;" % (m.name, t, val_str), file=f)
|
||||
if isinstance(m.mem[0], Constant):
|
||||
print("constant %s: %s%s;" % (m.name, t, val_str), file=f)
|
||||
else:
|
||||
print("signal %s: %s%s;" % (m.name, t, val_str), file=f)
|
||||
print(file=f)
|
||||
|
||||
|
||||
@ -890,7 +903,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
|
||||
lpre, lsuf = self.inferCast(node.dest.vhd, node.left.vhd)
|
||||
if isinstance(node.right, ast.Name):
|
||||
rpre, rsuf = self.inferCast(node.dest.vhd, node.right.vhd)
|
||||
|
||||
|
||||
self.write("(")
|
||||
self.write(lpre)
|
||||
self.visit(node.left)
|
||||
@ -921,13 +934,13 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
|
||||
node.operand.vhd = node.vhd
|
||||
self.visit(node.operand)
|
||||
return
|
||||
|
||||
|
||||
pre, suf = self.inferCast(node.vhd, node.vhdOri)
|
||||
if isinstance(node.op, ast.UAdd):
|
||||
op = ""
|
||||
else:
|
||||
op = opmap[type(node.op)]
|
||||
|
||||
|
||||
if isinstance(node.operand, ast.Constant):
|
||||
self.write("(")
|
||||
self.write(op)
|
||||
@ -950,13 +963,13 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
|
||||
node.operand.vhd = node.vhd
|
||||
self.visit(node.operand)
|
||||
return
|
||||
|
||||
|
||||
pre, suf = self.inferCast(node.vhd, node.vhdOri)
|
||||
if isinstance(node.op, ast.UAdd):
|
||||
op = ""
|
||||
else:
|
||||
op = opmap[type(node.op)]
|
||||
|
||||
|
||||
if isinstance(node.operand, ast.Num):
|
||||
self.write("(")
|
||||
self.write(op)
|
||||
@ -1441,7 +1454,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
|
||||
self.mapToCase(node)
|
||||
else:
|
||||
self.mapToIf(node)
|
||||
|
||||
|
||||
def visit_Match(self, node):
|
||||
self.write("case ")
|
||||
self.visit(node.subject)
|
||||
@ -1454,7 +1467,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
|
||||
self.dedent()
|
||||
self.writeline()
|
||||
self.write("end case;")
|
||||
|
||||
|
||||
def visit_match_case(self, node):
|
||||
self.writeline()
|
||||
self.write("when ")
|
||||
@ -1472,10 +1485,10 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
|
||||
self.dedent()
|
||||
|
||||
def visit_MatchValue(self, node):
|
||||
baseobj = self.getObj(node.subject)
|
||||
baseobj = self.getObj(node.subject)
|
||||
item = node.value
|
||||
obj = self.getObj(item)
|
||||
|
||||
|
||||
if isinstance(obj, EnumItemType):
|
||||
itemRepr = obj._toVHDL()
|
||||
elif hasattr(baseobj, '_nrbits'):
|
||||
@ -1506,12 +1519,12 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
|
||||
self.write("others")
|
||||
else:
|
||||
raise AssertionError("Unknown name %s or pattern %s" % (node.name, node.pattern))
|
||||
|
||||
|
||||
def visit_MatchOr(self, node):
|
||||
for i, pattern in enumerate(node.patterns):
|
||||
pattern.subject = node.subject
|
||||
self.visit(pattern)
|
||||
if not i == len(node.patterns)-1:
|
||||
if not i == len(node.patterns) - 1:
|
||||
self.write(" | ")
|
||||
|
||||
def mapToCase(self, node):
|
||||
|
@ -20,7 +20,7 @@
|
||||
import myhdl
|
||||
|
||||
_version = myhdl.__version__.replace('.', '')
|
||||
_shortversion = _version.replace('dev', '')
|
||||
_shortversion = _version.replace('dev', '')[:-2]
|
||||
|
||||
_package = """\
|
||||
library ieee;
|
||||
@ -191,4 +191,4 @@ package body pck_myhdl_%(version)s is
|
||||
|
||||
end pck_myhdl_%(version)s;
|
||||
|
||||
""" % {'version' : _shortversion}
|
||||
""" % {'version': _shortversion}
|
||||
|
@ -45,7 +45,7 @@ from myhdl.conversion._misc import (_error, _kind, _context,
|
||||
_ConversionMixin, _Label, _genUniqueSuffix, _isConstant)
|
||||
from myhdl.conversion._analyze import (_analyzeSigs, _analyzeGens, _analyzeTopFunc,
|
||||
_Ram, _Rom)
|
||||
from myhdl._Signal import _Signal
|
||||
from myhdl._Signal import _Signal, Constant
|
||||
from myhdl._ShadowSignal import _TristateSignal, _TristateDriver
|
||||
|
||||
from myhdl._block import _Block
|
||||
@ -340,14 +340,20 @@ def _writeSigDecls(f, intf, siglist, memlist):
|
||||
print("%s %s%s%s = %s;" %
|
||||
(k, p, r, s._name, _intRepr(s._init)), file=f)
|
||||
elif s._read:
|
||||
# the original exception
|
||||
# raise ToVerilogError(_error.UndrivenSignal, s._name)
|
||||
# changed to a warning and a continuous assignment to a wire
|
||||
warnings.warn("%s: %s" % (_error.UndrivenSignal, s._name),
|
||||
category=ToVerilogWarning
|
||||
)
|
||||
constwires.append(s)
|
||||
print("wire %s%s;" % (r, s._name), file=f)
|
||||
if isinstance(s, Constant):
|
||||
c = int(s.val)
|
||||
c_len = s._nrbits
|
||||
c_str = "%s" % c
|
||||
print("localparam %s%s = %s'd%s;" % (r, s._name, c_len, c_str), file=f)
|
||||
else:
|
||||
# the original exception
|
||||
# raise ToVerilogError(_error.UndrivenSignal, s._name)
|
||||
# changed to a warning and a continuous assignment to a wire
|
||||
warnings.warn("%s: %s" % (_error.UndrivenSignal, s._name),
|
||||
category=ToVerilogWarning
|
||||
)
|
||||
constwires.append(s)
|
||||
print("wire %s%s;" % (r, s._name), file=f)
|
||||
# print(file=f)
|
||||
for m in memlist:
|
||||
if not m._used:
|
||||
@ -392,9 +398,16 @@ def _writeSigDecls(f, intf, siglist, memlist):
|
||||
for n, each in enumerate(m.mem)])
|
||||
initial_assignments = (
|
||||
'initial begin\n' + val_assignments + '\nend')
|
||||
print("%s %s%s%s [0:%s-1];" % (k, p, r, m.name, m.depth), file=f)
|
||||
else:
|
||||
# can assume it is a localparam array
|
||||
# build the initial values list
|
||||
vals = []
|
||||
w = m.mem[0]._nrbits
|
||||
for s in m.mem:
|
||||
vals.append('{}\'d{}'.format(w, _intRepr(s._init)))
|
||||
|
||||
print("%s %s%s%s [0:%s-1];" % (k, p, r, m.name, m.depth),
|
||||
file=f)
|
||||
print('localparam {} {} {} [0:{}-1] = {{{}}};'.format(p, r, m.name, m.depth, ', '.join(vals)), file=f)
|
||||
|
||||
if initial_assignments is not None:
|
||||
print(initial_assignments, file=f)
|
||||
@ -1100,11 +1113,11 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
|
||||
self.write("default")
|
||||
else:
|
||||
raise AssertionError("Unknown name %s or pattern %s" % (node.name, node.pattern))
|
||||
|
||||
|
||||
def visit_MatchOr(self, node):
|
||||
for i, pattern in enumerate(node.patterns):
|
||||
self.visit(pattern)
|
||||
if not i == len(node.patterns)-1:
|
||||
if not i == len(node.patterns) - 1:
|
||||
self.write(" | ")
|
||||
|
||||
def mapToCase(self, node, *args):
|
||||
|
@ -15,7 +15,7 @@ from myhdl._block import _Block
|
||||
|
||||
_version = myhdl.__version__.replace('.', '')
|
||||
# strip 'dev' for version
|
||||
_version = _version.replace('dev', '')
|
||||
_version = _version.replace('dev', '')[:-2]
|
||||
|
||||
_simulators = {}
|
||||
|
||||
|
@ -7,7 +7,7 @@ from myhdl import (block, Signal, intbv, always, toVHDL, toVerilog)
|
||||
|
||||
from myhdl import __version__
|
||||
_version = __version__.replace('.', '')
|
||||
_shortversion = _version.replace('dev', '')
|
||||
_shortversion = _version.replace('dev', '')[:-2]
|
||||
|
||||
|
||||
@block
|
||||
|
Loading…
x
Reference in New Issue
Block a user