Source code for hwtLib.abstract.template_configured

from copy import copy
from typing import Optional, List, Callable, Generator, Tuple, Union

from hwt.hdl.frameTmpl import FrameTmpl
from hwt.hdl.frameTmplUtils import ChoicesOfFrameParts
from hwt.hdl.transPart import TransPart
from hwt.hdl.transTmpl import TransTmpl
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.pyUtils.arrayQuery import iter_with_last


[docs]class TemplateConfigured(): """ Class with functions for extracting metadata from frame template/HdlType. Used for resolving of data mapping between abstract type and physical interface. """
[docs] def __init__(self, structT: HdlType, tmpl: Optional[TransTmpl]=None, frames: Optional[List[FrameTmpl]]=None): """ :param structT: instance of HStruct used as template for this frame If name is None no input port is generated and space is filled with invalid values, little-endian encoding, supported types of interfaces are: Handshaked, Signal can be also instance of FrameTmpl :param tmpl: instance of TransTmpl for this structT :param frames: list of FrameTmpl instances for this tmpl :note: if tmpl and frames are None they are resolved from structT parseTemplate """ if tmpl is not None: assert frames is not None, \ "tmpl and frames can be used only together" else: assert frames is None, "tmpl and frames can be used only together" self._structT = structT self._tmpl = tmpl self._frames = frames
[docs] def parseTemplate(self): if self._tmpl is None: self._tmpl = TransTmpl(self._structT) if self._frames is None: frames = FrameTmpl.framesFromTransTmpl( self._tmpl, self.DATA_WIDTH) self._frames = list(frames)
[docs] def chainFrameWords(self) -> Generator[Tuple[int, List[Union[TransPart, ChoicesOfFrameParts]], bool], None, None]: offset = 0 for f in self._frames: wi = 0 for last, (wi, w) in iter_with_last(f.walkWords(showPadding=True)): yield (offset + wi, w, last) offset += wi + 1
[docs]def HdlType_separate(t: HdlType, do_separate_query: Callable[[HdlType], bool])\ ->Generator[Tuple[bool, HdlType], None, None]: """ Split HStruct type hierachy on the specified fields to multiple type definitions. """ sep = do_separate_query(t) if sep: yield (True, t) elif isinstance(t, HStruct): # fields which were generated by field spliting and are not yet in output HStruct leftovers = [] any_split = False for f in t.fields: for separate_field, _t in HdlType_separate(f.dtype, do_separate_query): if t is f.dtype: leftovers.append(f) else: # the type was spltited somewhere _f = copy(f) _f.dtype = _t if separate_field: if leftovers: new_t = HStruct(*leftovers, name=t.name) yield (False, new_t) leftovers.clear() # create a new HStruct from previous fields new_t = HStruct(_f, name=t.name) leftovers.clear() yield (True, new_t) any_split = True else: leftovers.append(_f) if any_split: if leftovers: new_t = HStruct(*leftovers, name=t.name) yield (False, new_t) else: yield (False, t) else: yield (False, t)
[docs]def separate_streams(t: HdlType): """ Split HStruct type hierarchy on the fields of HStream type. :note: e.g. in HStruct( (HStream(Bits(8)), "data"), (Bits(32), "fcs"), ) is split to HStruct((HStream(Bits(8)), "data"),) and HStruct((Bits(32), "fcs"),) """ yield from HdlType_separate(t, lambda x: isinstance(x, HStream))
[docs]def to_primitive_stream_t(t: HdlType): """ Convert type to a HStream of Bits With proper frame len, offset etc. """ if isinstance(t, HStruct) and len(t.fields) == 1: return to_primitive_stream_t(t.fields[0].dtype) frame_len = (1, 1) start_offsets = [0, ] if isinstance(t, HStream): e_t = t.element_t if isinstance(e_t, Bits): return t else: frame_len = t.frame_len start_offsets = t.start_offsets t = e_t try: bit_len = t.bit_length() except TypeError: bit_len = None if bit_len is not None: return HStream(Bits(bit_len), frame_len=frame_len, start_offsets=start_offsets) else: raise NotImplementedError(t)