from typing import Union
from hwt.doc_markers import internal
from hwt.hdl.operator import Operator
from hwt.hdl.operatorDefs import AllOps
from hwt.hdl.types.array import HArray
from hwt.hdl.types.bits import Bits
from hwt.hdl.types.defs import INT, BOOL
from hwt.hdl.types.hdlType import default_auto_cast_fn, HdlType
from hwt.hdl.types.struct import HStruct
from hwt.hdl.types.union import HUnion
from hwt.hdl.value import HValue
from hwt.interfaces.structIntf import HdlType_to_Interface
from hwt.synthesizer.exceptions import TypeConversionErr
from hwt.synthesizer.hObjList import HObjList
from hwt.synthesizer.interfaceLevel.mainBases import InterfaceBase
from hwt.synthesizer.rtlLevel.rtlSignal import RtlSignal
from hwt.synthesizer.rtlLevel.signalUtils.exceptions import SignalDriverErr
from hwt.synthesizer.vectorUtils import iterBits, fitTo_t
from pyMathBitPrecise.bit_utils import set_bit_range, mask
[docs]@internal
def convertBits__val(self: Bits, val: "BitVal", toType: HdlType):
if toType == BOOL:
return val != self.getValueCls().from_py(self, 0)
elif isinstance(toType, Bits):
if self.signed != toType.signed:
if self.strict_sign and bool(self.signed) != bool(toType.signed):
raise TypeConversionErr(self, toType)
val = val._convSign__val(toType.signed)
w_from, w_to = self.bit_length(), toType.bit_length()
if w_from != w_to:
if self.strict_width:
raise TypeConversionErr(self, toType)
if w_from > w_to:
# cut off some bits from value
new_m = val.vld_mask & toType.all_mask()
else:
# w_from < w_to, extend the value to some bit length
extra_mask_bits = mask(w_to - w_from)
new_m = set_bit_range(val.vld_mask, w_from, w_to - w_from, extra_mask_bits)
val = toType.from_py(val.val, new_m)
if val._dtype != toType:
# sign and width checked, only name, strict_* flags can be different
val = toType.from_py(val.val, val.vld_mask)
return val
elif toType == INT:
return INT.getValueCls()(INT, val.val,
int(val._is_full_valid()))
return default_auto_cast_fn(self, val, toType)
[docs]@internal
def convertBits(self: Bits, sigOrVal, toType: HdlType):
"""
Cast Bit subtypes, (integers, bool, ...)
"""
if isinstance(sigOrVal, HValue):
return convertBits__val(self, sigOrVal, toType)
elif toType == BOOL:
if self.bit_length() == 1:
v = 0 if sigOrVal._dtype.negated else 1
if isinstance(sigOrVal, RtlSignal):
sigOrVal: RtlSignal
try:
d = sigOrVal.singleDriver()
except SignalDriverErr:
d = None
if d is not None and isinstance(d, Operator) and d.operator == AllOps.NOT:
# signal itself is negated, ~a = 1 to a = 0
v = int(not bool(v))
sigOrVal = d.operands[0]
return sigOrVal._eq(self.getValueCls().from_py(self, v))
elif isinstance(toType, Bits):
if self.bit_length() == toType.bit_length():
#if self.force_vector != toType.force_vector:
# raise NotImplementedError(self, toType)
if self.const == toType.const:
return sigOrVal._convSign(toType.signed)
return default_auto_cast_fn(self, sigOrVal, toType)
[docs]@internal
def reinterpret_bits_to_hstruct__val(val: HValue, hStructT: HStruct):
"""
Reinterpret signal of type Bits to signal of type HStruct
"""
container = hStructT.from_py(None)
hStructT.vld_mask = int(val._is_full_valid())
offset = 0
for f in hStructT.fields:
t = f.dtype
width = t.bit_length()
if f.name is not None:
v = val[(width + offset):offset]
v = v._reinterpret_cast(t)
setattr(container, f.name, v)
offset += width
return container
[docs]@internal
def transfer_signals(src: InterfaceBase, dst: InterfaceBase):
if src._interfaces:
assert len(src._interfaces) == len(dst._interfaces), (src, dst)
for si, di in zip(src._interfaces, dst._interfaces):
transfer_signals(si, di)
else:
dst._sig = src._sig
dst._sigInside = src._sigInside
[docs]@internal
def reinterpret_bits_to_hstruct(val: Union[RtlSignal, HValue], hStructT: HStruct):
"""
Reinterpret signal of type Bits to signal of type HStruct
"""
container = HdlType_to_Interface().apply(hStructT)
container._loadDeclarations()
offset = 0
for f in hStructT.fields:
t = f.dtype
width = t.bit_length()
if f.name is not None:
v = val[(width + offset):offset]
v = v._reinterpret_cast(t)
current = getattr(container, f.name)
if isinstance(v, InterfaceBase):
transfer_signals(v, current)
elif isinstance(v, HObjList):
raise NotImplementedError()
elif isinstance(v, (RtlSignal, HValue)):
current._sig = v
else:
raise NotImplementedError()
offset += width
return container
[docs]@internal
def reinterpret_bits_to_harray(sigOrVal: Union[RtlSignal, HValue], hArrayT: HArray):
elmT = hArrayT.element_t
elmWidth = elmT.bit_length()
if isinstance(sigOrVal, HValue):
a = hArrayT.from_py(None)
a.vld_mask = int(sigOrVal._is_full_valid())
else:
a = HObjList([None for _ in range(hArrayT.size)])
for i, item in enumerate(iterBits(sigOrVal,
bitsInOne=elmWidth,
skipPadding=False)):
item = item._reinterpret_cast(elmT)
a[i] = item
return a
[docs]@internal
def reinterpretBits__val(self: Bits, val: HValue, toType: HdlType):
if isinstance(toType, Bits):
if self.signed != toType.signed:
val = val._convSign__val(toType.signed)
return fitTo_t(val, toType)
elif isinstance(toType, HStruct):
return reinterpret_bits_to_hstruct__val(val, toType)
elif isinstance(toType, HUnion):
raise NotImplementedError()
elif isinstance(toType, HArray):
return reinterpret_bits_to_harray(val, toType)
return default_auto_cast_fn(self, val, toType)
[docs]@internal
def reinterpretBits(self: Bits, sigOrVal: Union[RtlSignal, HValue], toType: HdlType):
"""
Cast object of same bit size between to other type
(f.e. bits to struct, union or array)
"""
if isinstance(sigOrVal, HValue):
return reinterpretBits__val(self, sigOrVal, toType)
elif isinstance(toType, Bits):
if self.signed != toType.signed:
sigOrVal = sigOrVal._convSign(toType.signed)
return fitTo_t(sigOrVal, toType)
elif sigOrVal._dtype.bit_length() == toType.bit_length():
if isinstance(toType, HStruct):
return reinterpret_bits_to_hstruct(sigOrVal, toType)
elif isinstance(toType, HUnion):
raise NotImplementedError()
elif isinstance(toType, HArray):
return reinterpret_bits_to_harray(sigOrVal, toType)
return default_auto_cast_fn(self, sigOrVal, toType)