+import builtins
from collections import OrderedDict
from collections.abc import Iterable, MutableMapping, MutableSet
If ``True``, do not generate reset logic for this ``Signal`` in synchronous statements.
The ``reset`` value is only used as a combinatorial default or as the initial value.
Defaults to ``False``.
+ min : int or None
+ max : int or None
+ If `bits_sign` is `None`, the signal bit width and signedness are
+ determined by the integer range given by `min` (inclusive,
+ defaults to 0) and `max` (exclusive, defaults to 2).
Attributes
----------
reset : int
"""
- def __init__(self, bits_sign=1, name=None, reset=0, reset_less=False):
+ def __init__(self, bits_sign=None, name=None, reset=0, reset_less=False, min=None, max=None):
super().__init__()
if name is None:
name = "$signal"
self.name = name
- if isinstance(bits_sign, int):
- bits_sign = bits_sign, False
- self.nbits, self.signed = bits_sign
+ if bits_sign is None:
+ if min is None:
+ min = 0
+ if max is None:
+ max = 2
+ max -= 1 # make both bounds inclusive
+ if not min < max:
+ raise ValueError("Lower bound {!r} should be less than higher bound {!r}"
+ .format(min, max))
+ self.signed = min < 0 or max < 0
+ self.nbits = builtins.max(bits_for(min, self.signed), bits_for(max, self.signed))
+
+ elif isinstance(bits_sign, int):
+ if not (min is None or max is None):
+ raise ValueError("Only one of bits/signedness or bounds may be specified")
+ self.nbits, self.signed = 1, False
+
+ else:
+ self.nbits, self.signed = bits_sign
+
if not isinstance(self.nbits, int) or self.nbits < 0:
- raise TypeError("Width must be a positive integer")
+ raise TypeError("Width must be a positive integer, not {!r}".format(self.nbits))
self.reset = reset
self.reset_less = reset_less
from collections import Iterable
-__all__ = ["flatten", "union"]
+__all__ = ["flatten", "union", "log2_int", "bits_for"]
def flatten(i):
else:
r |= e
return r
+
+
+def log2_int(n, need_pow2=True):
+ if n == 0:
+ return 0
+ r = (n - 1).bit_length()
+ if need_pow2 and (1 << r) != n:
+ raise ValueError("{} is not a power of 2".format(n))
+ return r
+
+
+def bits_for(n, require_sign_bit=False):
+ if n > 0:
+ r = log2_int(n + 1, False)
+ else:
+ require_sign_bit = True
+ r = log2_int(-n, False)
+ if require_sign_bit:
+ r += 1
+ return r