Source code for hwt.interfaces.intf_map

from typing import Union, Tuple, Optional, List

from hwt.doc_markers import internal
from hwt.hdl.types.bits import Bits
from hwt.hdl.types.hdlType import HdlType
from hwt.hdl.types.struct import HStruct, HStructFieldMeta, HStructField
from hwt.interfaces.std import BramPort_withoutClk, RegCntrl, VldSynced, Signal
from hwt.interfaces.structIntf import StructIntf
from hwt.interfaces.unionIntf import UnionSink, UnionSource
from hwt.synthesizer.hObjList import HObjList
from hwt.synthesizer.interface import Interface
from hwt.synthesizer.interfaceLevel.mainBases import InterfaceBase
from hwt.synthesizer.interfaceLevel.unitImplHelpers import getSignalName
from hwt.synthesizer.rtlLevel.mainBases import RtlSignalBase
from hwt.synthesizer.typePath import TypePath


[docs]class IntfMap(list): """ Container of interface map. The interface map object describes the data type using existing interface instances. Items can be Interface/RtlSignal or (type/interface/None/IntfMap, name). None is used for padding. """ pass
[docs]@internal def _HTypeFromIntfMap(intf: Union[RtlSignalBase, VldSynced, RegCntrl, BramPort_withoutClk, StructIntf, UnionSink, UnionSource]): name = getSignalName(intf) if isinstance(intf, (RtlSignalBase, Signal)): dtype = intf._dtype elif isinstance(intf, VldSynced): dtype = intf.data._dtype elif isinstance(intf, RegCntrl): dtype = intf.din._dtype elif isinstance(intf, BramPort_withoutClk): dtype = Bits(int(intf.DATA_WIDTH))[2 ** int(intf.ADDR_WIDTH)] else: dtype, name = intf assert isinstance(dtype, HdlType) assert isinstance(name, str) return (dtype, name)
[docs]@internal def HTypeFromIntfMapItem( interfaceMapItem: Union[Tuple[HdlType, Optional[str]], Tuple[Union[Interface, RtlSignalBase], str], Tuple[List[Union[Interface, RtlSignalBase]], str], Union[Interface, RtlSignalBase]]): isTerminal = False if isinstance(interfaceMapItem, (InterfaceBase, RtlSignalBase)): dtype, nameOrPrefix = _HTypeFromIntfMap(interfaceMapItem) isTerminal = True else: typeOrListOfInterfaces, nameOrPrefix = interfaceMapItem if isinstance(typeOrListOfInterfaces, list) and \ not isinstance(typeOrListOfInterfaces, IntfMap): # list of HType instances for array parts = [] arrayItem_t = None for item in typeOrListOfInterfaces: if isinstance(item, IntfMap): t = HTypeFromIntfMap(item) else: t = HTypeFromIntfMapItem(item).dtype if arrayItem_t is None: arrayItem_t = t else: assert arrayItem_t == t, ( "all items in array has to have same type", arrayItem_t, t) parts.append(t) dtype = arrayItem_t[len(parts)] elif isinstance(typeOrListOfInterfaces, HdlType): dtype = typeOrListOfInterfaces isTerminal = True elif isinstance(typeOrListOfInterfaces, (InterfaceBase, RtlSignalBase)): # renamed interface, ignore original name dtype = _HTypeFromIntfMap(typeOrListOfInterfaces)[0] isTerminal = True elif isinstance(typeOrListOfInterfaces, IntfMap): dtype = HTypeFromIntfMap(typeOrListOfInterfaces) else: # tuple (tuple of interfaces, prefix) assert isinstance(typeOrListOfInterfaces, tuple), typeOrListOfInterfaces dtype = HTypeFromIntfMap(typeOrListOfInterfaces) assert isinstance(nameOrPrefix, str) or nameOrPrefix is None, nameOrPrefix assert isinstance(dtype, HdlType) f = HStructField(dtype, nameOrPrefix) if not isTerminal: f.meta = HStructFieldMeta(split=True) return f
[docs]def HTypeFromIntfMap(interfaceMap: IntfMap) -> HStruct: """ Generate flattened register map for HStruct :param interfaceMap: sequence of a tuple (HdlType, name) (will create HStructField) or a tuple (HdlType, None) (will create HStructField as padding) or a tuple (list of Interface instances, name) (will create HStructField of HStruct type) or an Interface instance (will create a HStructField for an interface, with a name of interface) :param DATA_WIDTH: width of word :param terminalNodes: None or set whre are placed StructField instances which are derived directly from interface :return: generator of tuple (type, name, BusFieldInfo) """ structFields = [] for m in interfaceMap: f = HTypeFromIntfMapItem(m) structFields.append(f) return HStruct(*structFields)
[docs]def isPaddingInIntfMap(item): if isinstance(item, HdlType): return True else: try: if isinstance(item, tuple): _item, name = item if name is None: return True except ValueError: pass return False
[docs]def _walkStructIntfAndIntfMap_unpack(structIntf: Union[HObjList, StructIntf, UnionSink, UnionSource], intfMap): """ Try to unpack intfMap and apply the selection on structIntf :return: Optional tuple Interface, intfMap """ # items are Interface/RtlSignal or (type/interface/None or list of items, name) if isPaddingInIntfMap(intfMap): return elif isinstance(intfMap, tuple): item, name = intfMap else: item = intfMap assert isinstance(item, (InterfaceBase, RtlSignalBase)), item name = getSignalName(item) if isinstance(item, HdlType): # this part of structIntf was generated from type descriptin # and we are re searching only for those parts which were generated # from Interface/RtlSignal return return getattr(structIntf, name), item
[docs]def walkStructIntfAndIntfMap(structIntf: Union[HObjList, StructIntf, UnionSink, UnionSource], intfMap): """ Walk StructInterface and interface map and yield tuples (Interface in StructInterface, interface in intfMap) which are on same place :param structIntf: an interface to walk :param intfMap: interface map :note: typical usecase is when there is StructIntf generated from description in intfMap and then you need to connect interface from intfMap to structIntf and there you can use this function to iterate over interfaces which belongs together """ if isinstance(intfMap, (InterfaceBase, RtlSignalBase)): yield structIntf, intfMap return elif isinstance(intfMap, tuple): item = _walkStructIntfAndIntfMap_unpack(structIntf, intfMap) if item is None: # is padding or there is no interface specified for it in intfMap return else: structIntf, item = item yield from walkStructIntfAndIntfMap(structIntf, item) elif isinstance(structIntf, list): structIntf assert len(structIntf) == len(intfMap) for sItem, item in zip(structIntf, intfMap): yield from walkStructIntfAndIntfMap(sItem, item) else: assert isinstance(intfMap, IntfMap), intfMap for item in intfMap: _item = _walkStructIntfAndIntfMap_unpack(structIntf, item) if _item is not None: sItem, _item = _item yield from walkStructIntfAndIntfMap(sItem, _item)
[docs]def IntfMapItem_find_by_name(intf_map_item, name): if isinstance(intf_map_item, HStructField): intf_map_item = intf_map_item.dtype if isinstance(intf_map_item, IntfMap): for x in intf_map_item: if isinstance(x, InterfaceBase): if x._name == name: return x elif isinstance(x, RtlSignalBase): if x.name == name: return x else: v, n = x if n == name: return v raise KeyError(name) elif isinstance(intf_map_item, HStruct): for f in intf_map_item.fields: if f.name == name: return f raise KeyError(name) else: raise NotImplementedError(intf_map_item)
[docs]def IntfMap_get_by_field_path(root: IntfMap, field_path: TypePath): actual = root # find in interfaceMap, skip first because it is the type itself for rec in field_path: #if isinstance(rec, (InterfaceBase, RtlSignalBase)): # shouldEnter, shouldUse = False, True # return shouldEnter, shouldUse if isinstance(rec, int): actual = actual[rec] elif isinstance(rec, str): actual = IntfMapItem_find_by_name(actual, rec) else: raise NotImplementedError(rec) return actual