Source code for hwt.hdl.types.utils
from typing import Union, List
from hwt.hdl.types.array import HArray
from hwt.hdl.types.bits import Bits
from hwt.hdl.types.hdlType import HdlType
from hwt.hdl.types.stream import HStream
from hwt.hdl.types.struct import HStruct
from hwt.hdl.types.typeCast import toHVal
from hwt.hdl.types.union import HUnion
from hwt.hdl.value import HValue
from hwt.synthesizer.rtlLevel.mainBases import RtlSignalBase
[docs]def walkFlattenFields(sigOrVal: Union[RtlSignalBase, HValue], skipPadding=True):
"""
Walk all simple values in HStruct or HArray
"""
t = sigOrVal._dtype
if isinstance(t, Bits):
yield sigOrVal
elif isinstance(t, HUnion):
yield from walkFlattenFields(sigOrVal._val, skipPadding=skipPadding)
elif isinstance(t, HStruct):
for f in t.fields:
isPadding = f.name is None
if not isPadding or not skipPadding:
if isPadding:
v = f.dtype.from_py(None)
else:
v = getattr(sigOrVal, f.name)
yield from walkFlattenFields(v)
elif isinstance(t, HArray):
for item in sigOrVal:
yield from walkFlattenFields(item)
elif isinstance(t, HStream):
assert isinstance(sigOrVal, HValue), sigOrVal
for v in sigOrVal:
yield from walkFlattenFields(v)
else:
raise NotImplementedError(t)
[docs]def HValue_from_words(t: HdlType,
data: List[Union[HValue, RtlSignalBase, int]],
getDataFn=None, dataWidth=None) -> HValue:
"""
Parse raw Bits array to a value of specified HdlType
"""
if getDataFn is None:
assert dataWidth is not None
def _getDataFn(x):
return toHVal(x)._auto_cast(Bits(dataWidth))
getDataFn = _getDataFn
val = t.from_py(None)
fData = iter(data)
# actual is storage variable for items from frameData
actualOffset = 0
actual = None
for v in walkFlattenFields(val, skipPadding=False):
# walk flatten fields and take values from fData and parse them to
# field
required = v._dtype.bit_length()
if actual is None:
actualOffset = 0
try:
actual = getDataFn(next(fData))
except StopIteration:
raise ValueError("Insufficcient amount of data to build value for specified type", t, v, required)
if dataWidth is None:
dataWidth = actual._dtype.bit_length()
actuallyHave = dataWidth
else:
actuallyHave = actual._dtype.bit_length() - actualOffset
while actuallyHave < required:
# collect data for this field
try:
d = getDataFn(next(fData))
except StopIteration:
raise ValueError("Insufficcient amount of data to build value for specified type", t, v, required, actuallyHave)
actual = d._concat(actual)
actuallyHave += dataWidth
if actuallyHave >= required:
# parse value of actual to field
# skip padding
_v = actual[(required + actualOffset):actualOffset]
_v = _v._auto_cast(v._dtype)
v.val = _v.val
v.vld_mask = _v.vld_mask
# update slice out what was taken
actuallyHave -= required
actualOffset += required
if actuallyHave == 0:
actual = None
if actual is not None:
assert actual._dtype.bit_length(
) - actualOffset < dataWidth, (
"It should be just a padding at the end of frame, but there is some additional data"
)
return val
[docs]def is_only_padding(t: HdlType) -> bool:
if isinstance(t, HStruct):
for f in t.fields:
if f.name is not None and not is_only_padding(f.dtype):
return False
return True
elif isinstance(t, (HArray, HStream)):
return is_only_padding(t.element_t)
return False