Source code for hwt.synthesizer.unit

from copy import copy
from typing import Optional, List, Dict, Tuple, Set, Union

from hdlConvertorAst.hdlAst._structural import HdlCompInst
from hwt.doc_markers import internal
from hwt.hdl.portItem import HdlPortItem
from hwt.synthesizer.dummyPlatform import DummyPlatform
from hwt.synthesizer.exceptions import IntfLvlConfErr
from hwt.synthesizer.interfaceLevel.mainBases import InterfaceBase
from hwt.synthesizer.interfaceLevel.propDeclrCollector import PropDeclrCollector
from hwt.synthesizer.interfaceLevel.unitImplHelpers import UnitImplHelpers, \
    _default_param_updater
from hwt.synthesizer.rtlLevel.netlist import RtlNetlist
from ipCorePackager.constants import DIRECTION


[docs]class HdlConstraintList(list): """ Containers of hw design constraints """ pass
[docs]class Unit(PropDeclrCollector, UnitImplHelpers): """ Container of the netlist with interfaces and internal hierarchical structure :cvar ~._serializeDecision: function to decide if HDL object derived from this unit should be serialized or not, if None all is always serialized :cvar ~._PROTECTED_NAMES: set of names which can not be overridden :ivar ~._interfaces: all public interfaces :type ~._interfaces: List[Interface] :ivar ~._private_interfaces: all internal interfaces which are not accessible from outside of unit :type _private_interfaces: List[Interface] :ivar ~._units: all units defined on this object :type ~._units: List[Unit] :ivar ~._params: all params defined on this object :type ~._params: List[Param] :ivar ~._constraints: additional HW specifications :ivar ~._parent: parent object :type ~._parent: Optional[Unit] :ivar ~._lazy_loaded: container of RTL object which were lazy loaded in implementation phase (this object has to be returned from :func:`~._to_rtl` of parent before it it's own objects) :ivar ~._shared_component_with: Optional tuple of the other :class:`hwt.synthesizer.unit.Unit` instance which produces an exactly same component in HDL and interface signal map current to shared and shared to current :type ~._shared_component_with: Optional[Tuple[Unit, Dict[Interface, Interface], Dict[Interface, Interface]]] :attention: if :func:`~._shared_component_with` is not None the body of this instance is not generated at all and the component from :func:`~._shared_component_with` is used instead :ivar ~._target_platform: meta-informations about target platform :ivar ~._name: a name of this component :ivar ~._hdl_module_name: a name of HDL module for this component (vhdl entity name, Verilog module name) """ _serializeDecision = None # properties which are used internally by this library _PROTECTED_NAMES = set([ "_PROTECTED_NAMES", "_name", "_hdl_module_name", "_interfaces", "_private_interfaces", "_units", "_params", "_parent", "_constraints", "_lazy_loaded", "_ctx", "_shared_component_with", "_target_platform", "_store_manager", ])
[docs] def __init__(self, hdl_name_override:Optional[str]=None): self._parent: Optional[Unit] = None self._name: Optional[str] = None self._shared_component_with = None self._hdl_module_name: Optional[str] = None assert hdl_name_override is None or isinstance(hdl_name_override, str), hdl_name_override self._hdl_name_override = hdl_name_override self._lazy_loaded: List[Union[Unit, InterfaceBase]] = [] self._ctx = RtlNetlist(self) self._constraints = HdlConstraintList() self._loadConfig()
[docs] @internal def _loadInterface(self, i, isExtern): i._loadDeclarations() i._setAsExtern(isExtern)
[docs] @internal def _loadDeclarations(self): """ Load all declarations from _decl() method, recursively for all interfaces/units. """ if not hasattr(self, "_interfaces"): self._interfaces = [] if not hasattr(self, "_private_interfaces"): self._private_interfaces = [] if not hasattr(self, "_units"): self._units = [] self._setAttrListener = self._declrCollector self._declr() self._setAttrListener = None for i in self._interfaces: self._loadInterface(i, True) # if I am a unit load subunits for u in self._units: u._loadDeclarations()
[docs] @internal def _registerIntfInImpl(self, iName, intf): """ Register interface in implementation phase """ self._registerInterface(iName, intf, isPrivate=True) self._loadInterface(intf, False) intf._signalsForInterface( self._ctx, None, self._store_manager.name_scope)
[docs] def _getDefaultName(self) -> str: return self.__class__.__name__
[docs] def _get_hdl_doc(self) -> Optional[str]: if self.__doc__ is not Unit.__doc__: return self.__doc__
[docs] @internal def _to_rtl(self, target_platform: DummyPlatform, store_manager: "StoreManager", add_param_asserts=True): """ synthesize all subunits, make connections between them, build verilog like module/vhdl like entity and architecture for this unit """ if self._hdl_module_name is None: if self._hdl_name_override: self._hdl_module_name = self._hdl_name_override else: self._hdl_module_name = self._getDefaultName() if self._name is None: self._name = self._getDefaultName() self._target_platform = target_platform self._store_manager = store_manager do_serialize_this, replacement = store_manager.filter.do_serialize( self) if replacement is not None: assert not do_serialize_this assert len(self._interfaces) == len(replacement._interfaces), \ "No lazy loaded interfaces declared in _impl()" copy_HdlModuleDec(replacement, self) yield False, self self._cleanAsSubunit() self._units = None self._private_interfaces = None intf_map_repl_to_self = shared_comp_build_interface_map( replacement, self) intf_map_self_to_repl = { v: k for k, v in intf_map_repl_to_self.items()} self._shared_component_with = replacement, \ intf_map_self_to_repl, intf_map_repl_to_self return for proc in target_platform.beforeToRtl: proc(self) mdec = self._ctx.create_HdlModuleDec( self._hdl_module_name, store_manager, self._params) mdec.origin = self mdec.doc = self._get_hdl_doc() # prepare signals for interfaces for i in self._interfaces: if i._isExtern: ei = self._ctx.interfaces else: ei = None # we are reversing direction because we are looking # at the interface from inside of component i._signalsForInterface( self._ctx, ei, store_manager.name_scope, reverse_dir=True) store_manager.hierarchy_pop(mdec) if do_serialize_this: # prepare subunits for u in self._units: yield from u._to_rtl(target_platform, store_manager) # now every sub unit has a HdlModuleDec prepared for u in self._units: subUnitName = u._name u._signalsForSubUnitEntity(self._ctx, "sig_" + subUnitName) for proc in target_platform.beforeToRtlImpl: proc(self) try: store_manager.hierarchy_push(mdec) if do_serialize_this: self._loadImpl() yield from self._lazy_loaded if not self._ctx.interfaces: raise IntfLvlConfErr( "Can not find any external interface for unit %s" "- unit without interfaces are not synthetisable" % self._name) for proc in target_platform.afterToRtlImpl: proc(self) mdec.params.sort(key=lambda x: x.name) mdec.ports.sort(key=lambda x: x.name) if do_serialize_this: # synthesize signal level context mdef = self._ctx.create_HdlModuleDef( target_platform, store_manager) mdef.origin = self for intf in self._interfaces: if intf._isExtern: # reverse because other components # looks at this interface from the outside intf._reverseDirection() if do_serialize_this: if add_param_asserts and self._params: mdef.objs.extend(store_manager.as_hdl_ast._as_hdl_HdlModuleDef_param_asserts(mdec)) store_manager.write(mdef) yield True, self # after synthesis clean up interface so this :class:`hwt.synthesizer.unit.Unit` object can be # used elsewhere self._cleanAsSubunit() if do_serialize_this: self._checkCompInstances() for proc in target_platform.afterToRtl: proc(self) finally: store_manager.hierarchy_pop(mdec)
[docs] def _updateParamsFrom(self, otherObj: PropDeclrCollector, updater=_default_param_updater, exclude: Optional[Tuple[Set[str], Set[str]]]=None, prefix=""): """ :note: doc in :func:`hwt.synthesizer.interfaceLevel.propDeclCollector._updateParamsFrom` """ return PropDeclrCollector._updateParamsFrom(self, otherObj, updater, exclude, prefix)
[docs] @internal def _checkCompInstances(self): cInstances = [o for o in self._ctx.arch.objs if isinstance(o, HdlCompInst)] cInst_cnt = len(cInstances) unit_cnt = len(self._units) if cInst_cnt != unit_cnt: # resolve the error message inRtl = set(x.name for x in cInstances) inIntf = set(x._name for x in self._units) cls_name = self.__class__.__name__ if cInst_cnt > unit_cnt: diff = inRtl - inIntf raise IntfLvlConfErr( f"{cls_name:s}, {self._name:s}: unit(s) were found in HDL but were" f" not registered {diff}") else: assert cInst_cnt < unit_cnt diff = inIntf - inRtl raise IntfLvlConfErr( f"{cls_name:s}, {self._name:s}: _to_rtl: unit(s) are missing in produced HDL {diff}")
[docs]def copy_HdlModuleDec_interface(orig_i: InterfaceBase, new_i: InterfaceBase, ports: List[HdlPortItem], new_u: Unit): new_i._direction = orig_i._direction if orig_i._hdl_port is not None: s = orig_i._sigInside assert s is not None, ( "the component which shares a body with this component" " is actually some parent of this component") pi = copy(orig_i._hdl_port) pi.unit = new_u ports.append(pi) d = pi.direction if d == DIRECTION.OUT: pi.dst = None elif d == DIRECTION.IN: pi.src = None else: raise NotImplementedError(d) new_i._hdl_port = pi new_i._sigInside = s else: for i in orig_i._interfaces: n_i = getattr(new_i, i._name) copy_HdlModuleDec_interface(i, n_i, ports, new_u)
[docs]def copy_HdlModuleDec(orig_u: Unit, new_u: Unit): assert not new_u._ctx.statements assert not new_u._ctx.interfaces assert not new_u._ctx.signals assert new_u._ctx.ent is None new_u._hdl_module_name = orig_u._hdl_module_name e = new_u._ctx.ent = copy(orig_u._ctx.ent) params = [] param_by_name = {p._name: p for p in new_u._params} for p in e.params: new_p_def = copy(p) old_p = new_p_def.origin = param_by_name[p.origin._name] old_p.hdl_name = p.origin.hdl_name new_p_def.value = old_p.get_hdl_value() params.append(new_p_def) e.params = params e.ports = [] for oi, ni in zip(orig_u._interfaces, new_u._interfaces): if oi._isExtern: copy_HdlModuleDec_interface(oi, ni, e.ports, new_u) # params should be already sorted # e.params.sort(key=lambda x: x.name) e.ports.sort(key=lambda x: x.name)
[docs]def _shared_comp_build_interface_map_list(replacement: List[InterfaceBase], substituted: List[InterfaceBase], res: Dict[InterfaceBase, InterfaceBase]): assert len(replacement) == len(substituted) for r, s in zip(replacement, substituted): assert r._name == s._name, (r._name, s._name) res[r] = s if r._interfaces: _shared_comp_build_interface_map_list( r._interfaces, s._interfaces, res)
[docs]def shared_comp_build_interface_map(replacement_u: Unit, substituted_u: Unit): """ Build a dictionary which maps interface of replacement_u to interface of substituted_u """ res = {} _shared_comp_build_interface_map_list( replacement_u._interfaces, substituted_u._interfaces, res) return res