Source code for hwt.hdl.types.bits

from typing import Union, Literal, Optional, Self

from hwt.constants import NOT_SPECIFIED
from hwt.doc_markers import internal
from hwt.hdl.types.hdlType import HdlType
from hwt.pyUtils.typingFuture import override
from hwt.serializer.generic.indent import getIndent
from pyMathBitPrecise.bits3t import Bits3t

BITS_DEFAUTL_SIGNED = None
BITS_DEFAUTL_FORCEVECTOR = False
BITS_DEFAUTL_NEGATED = False
BITS_DEFAUTL_IS_BIGENDIAN = False
BITS_DEFAUTL_BYTE_WIDTH = 8


[docs] class HBits(HdlType, Bits3t): """ Elemental HDL type representing bits (vector or single bit) :see: :class:`pyMathBitPrecise.bits3t.Bits3t` :ivar negated: if true the value is in negated form The result of the _isOn() operator is negation of this value, "~" operator returns value of same type, and or xor operands ignores this flag, others do not support it. This utitilty is there to allow users to write code agnostic to signal negation. For example for reset and reset_n_isOn() check can be used to resolve if reset is activated. :ivar is_bigendian: if True the value is threated as big endian (byte 0 the most significant) this does not affect the direction of bit range (to/downto) :ivar ~.strict_width: if True width can not be auto_casted (in operators/assignment/...) :ivar ~.strict_sign: same thing as strict_width just for signed/unsigned casting rules ============= * strict_width/strict_sign True has the higher priority when resolving operator result type * if False width/sign is allowed to change to dst type value. * strict_width=False: * assignment: auto extended/trimmed * multi operand operator: pick the widest type * strict_sign=False * assignment: auto cast * multi operand operator: signed if any operand signed * cast of negated flag does nothing (if ) | BIT BIT_N =======| ========= ========= BIT | nop nop BIT_N | nop nop * auto_cast - casts flags * explicit_cast - resize/change sign * reinterpret_cast - raw bits as something else """
[docs] def __init__(self, bit_length: Union[int, "AnyHBitsValue"], signed:Literal[None, True, False]=BITS_DEFAUTL_SIGNED, force_vector:bool=BITS_DEFAUTL_FORCEVECTOR, negated:bool=BITS_DEFAUTL_NEGATED, is_bigendian:bool=BITS_DEFAUTL_IS_BIGENDIAN, byte_width: int=8, name:Optional[str]=None, const:bool=False, strict_sign:bool=True, strict_width:bool=True): self.byte_width = byte_width assert not is_bigendian or bit_length % byte_width == 0, ("bigendian requires bit_length to multiple of byte_width", bit_length) self.negated = negated self.is_bigendian = is_bigendian self.strict_sign = strict_sign self.strict_width = strict_width HdlType.__init__(self, const=const) bit_length = int(bit_length) assert bit_length > 0, bit_length Bits3t.__init__(self, bit_length, signed, name=name, force_vector=force_vector or bit_length == 1 and signed is not None )
[docs] def _createMutated(self, bit_length: Union[int, "AnyHBitsValue"]=NOT_SPECIFIED, signed:Literal[None, True, False]=NOT_SPECIFIED, force_vector:bool=NOT_SPECIFIED, negated:bool=NOT_SPECIFIED, is_bigendian=NOT_SPECIFIED, byte_width=NOT_SPECIFIED, name:Optional[str]=NOT_SPECIFIED, const:bool=NOT_SPECIFIED, strict_sign:bool=NOT_SPECIFIED, strict_width:bool=NOT_SPECIFIED ) -> Self: if bit_length is NOT_SPECIFIED: bit_length = self.bit_length() else: if force_vector is NOT_SPECIFIED and self.force_vector and bit_length > 1 and self.bit_length() == 1: force_vector = False if signed is NOT_SPECIFIED: signed = self.signed if force_vector is NOT_SPECIFIED: force_vector = self.force_vector if negated is NOT_SPECIFIED: negated = self.negated if is_bigendian is NOT_SPECIFIED: is_bigendian = self.is_bigendian if byte_width is NOT_SPECIFIED: byte_width = self.byte_width if name is NOT_SPECIFIED: name = None if const is NOT_SPECIFIED: const = self.const if strict_sign is NOT_SPECIFIED: strict_sign = self.strict_sign if strict_width is NOT_SPECIFIED: strict_width = self.strict_width return self.__class__( bit_length, signed=signed, force_vector=force_vector, negated=negated, is_bigendian=is_bigendian, byte_width=byte_width, name=name, const=const, strict_sign=strict_sign, strict_width=strict_width )
[docs] def differs_only_in_strictness_flags(self, other: Self) -> bool: return Bits3t.__eq__(self, other) and \ isinstance(other, self.__class__) and \ self.const == other.const and \ self.negated == other.negated and \ self.is_bigendian == other.is_bigendian and \ self.byte_width == other.byte_width
[docs] @internal def domain_size(self): """ :return: how many values can have specified type """ return int(2 ** self.bit_length())
[docs] @internal @classmethod def get_auto_cast_HConst_fn(cls): from hwt.hdl.types.bitsCast import HBits_auto_cast__HConst return HBits_auto_cast__HConst
[docs] @internal @override @classmethod def get_explicit_cast_HConst_fn(cls): from hwt.hdl.types.bitsCast import HBits_explicit_cast__HConst return HBits_explicit_cast__HConst
[docs] @internal @override @classmethod def get_reinterpret_cast_HConst_fn(cls): from hwt.hdl.types.bitsCast import HBits_reinterpret_cast__HConst return HBits_reinterpret_cast__HConst
[docs] @internal @classmethod def get_auto_cast_RtlSignal_fn(cls): from hwt.hdl.types.bitsCast import HBits_auto_cast__RtlSignal return HBits_auto_cast__RtlSignal
[docs] @internal @classmethod def get_explicit_cast_RtlSignal_fn(cls): from hwt.hdl.types.bitsCast import HBits_explicit_cast__RtlSignal return HBits_explicit_cast__RtlSignal
[docs] @internal @override @classmethod def get_reinterpret_cast_RtlSignal_fn(cls): from hwt.hdl.types.bitsCast import HBits_reinterpret_cast__RtlSignal return HBits_reinterpret_cast__RtlSignal
[docs] @internal @override @classmethod def getConstCls(cls): try: return cls._constCls except AttributeError: from hwt.hdl.types.bitsConst import HBitsConst cls._constCls = HBitsConst return cls._constCls
[docs] @internal @override @classmethod def getRtlSignalCls(cls): try: return cls._rtlSignalCls except AttributeError: from hwt.hdl.types.bitsRtlSignal import HBitsRtlSignal cls._rtlSignalCls = HBitsRtlSignal return cls._rtlSignalCls
[docs] def getAllOnesValue(self): return self.from_py(self._all_mask)
def __hash__(self): return hash((Bits3t.__hash__(self), self.const, self.negated, self.is_bigendian, self.byte_width, self.strict_sign, self.strict_width,)) def __eq__(self, other): return Bits3t.__eq__(self, other) and \ isinstance(other, self.__class__) and \ self.const == other.const and \ self.negated == other.negated and \ self.is_bigendian == other.is_bigendian and \ self.byte_width == other.byte_width and \ self.strict_sign == other.strict_sign and \ self.strict_width == other.strict_width def __repr__(self, indent=0, withAddr=None, expandStructs=False, minify=False) -> str: """ :param indent: number of indentation :param withAddr: if is not None is used as a additional information about on which address this type is stored (used only by HStruct) :param expandStructs: expand HStructTypes (used by HStruct and HArray) """ constr = [] if self.name is not None: constr.append(f'"{self.name:s}"') c = self.bit_length() if c == 1: constr.append("1bit") if self.force_vector: constr.append("force_vector") else: constr.append(f"{c:d}bits") if self.negated: constr.append("n") if self.is_bigendian: constr.append("BE") if self.byte_width != BITS_DEFAUTL_BYTE_WIDTH: constr.append(f"byte_width={self.byte_width:d}") if self.const: constr.append("const") if self.signed: constr.append("signed") elif self.signed is False: constr.append("unsigned") if not self.strict_sign: constr.append("strict_sign=False") if not self.strict_width: constr.append("strict_width=False") return f"{getIndent(indent)}<{self.__class__.__name__}, {', '.join(constr)}>"