def _get_ref_map( self, prefix: edgir.LocalPath) -> IdentityDict[Refable, edgir.LocalPath]: return super()._get_ref_map(prefix) + IdentityDict( [(self.name(), edgir.localpath_concat(prefix, edgir.NAME))], *[ param._get_ref_map(edgir.localpath_concat(prefix, name)) for (name, param) in self._parameters.items() ], *[ port._get_ref_map(edgir.localpath_concat(prefix, name)) for (name, port) in self._ports.items() ])
def _get_ref_map( self, prefix: edgir.LocalPath) -> IdentityDict[Refable, edgir.LocalPath]: if self.__class__ == PortAdapter: # TODO: hack to allow this to elaborate as abstract class while being invalid return IdentityDict() # return super().get_ref_map(prefix) + # TODO: dedup w/ BaseBlock, and does this break anything? return IdentityDict( *[ param._get_ref_map(edgir.localpath_concat(prefix, name)) for (name, param) in self._parameters.items() ], self.src._get_ref_map(edgir.localpath_concat(prefix, 'src')), self.dst._get_ref_map(edgir.localpath_concat(prefix, 'dst')))
def _def_to_proto(self) -> edgir.Link: for cls in self._get_bases_of( BaseBlock ): # type: ignore # TODO avoid 'only concrete class' error assert issubclass(cls, Link) pb = self._populate_def_proto_block_base(edgir.Link()) pb = self._populate_def_proto_block_contents(pb) pb = self._populate_def_proto_param_init(pb) # specifically ignore the port initializers # actually generate the links and connects ref_map = self._get_ref_map(edgir.LocalPath()) self._connects.finalize() self._links_order: Dict[str, str] = self.Metadata({}) for name, connect in self._connects.items_ordered(): self._links_order[str(len(self._links_order))] = f"{name}" connect_elts = connect.generate_connections() assert connect_elts is not None and connect_elts.link_type is not None, "bad connect definition in link" link_path = edgir.localpath_concat(edgir.LocalPath(), name) pb.links[ name].lib_elem.target.name = connect_elts.link_type._static_def_name( ) for idx, (self_port, link_port_path) in enumerate( connect_elts.bridged_connects): # TODO handle Vector types if isinstance( self_port, DerivedVector ): # TODO unify once we get rid of ref_map, especially to be more robust pb.constraints[ f"(export){name}_{idx}"].exported.exterior_port.map_extract.container.ref.CopyFrom( ref_map[self_port.base]) pb.constraints[ f"(export){name}_{idx}"].exported.exterior_port.map_extract.path.steps.add( ).name = self_port.base._get_elt_sample()._name_of( self_port.target) else: pb.constraints[ f"(export){name}_{idx}"].exported.exterior_port.ref.CopyFrom( ref_map[self_port]) pb.constraints[ f"(export){name}_{idx}"].exported.internal_block_port.ref.CopyFrom( edgir.localpath_concat(link_path, link_port_path)) self._namespace_order.append(f"(export){name}_{idx}") return pb
def _get_ref_map( self, prefix: edgir.LocalPath) -> IdentityDict[Refable, edgir.LocalPath]: return super()._get_ref_map(prefix) + IdentityDict(*[ block._get_ref_map(edgir.localpath_concat(prefix, name)) for (name, block) in self._blocks.items() ])
def _get_ref_map( self, prefix: edgir.LocalPath) -> IdentityDict[Refable, edgir.LocalPath]: if self._link_instance is not None: link_refs = self._link_instance._get_ref_map( edgir.localpath_concat(prefix, edgir.CONNECTED_LINK)) else: link_refs = IdentityDict([]) return super()._get_ref_map(prefix) + IdentityDict[ Refable, edgir.LocalPath]( [(self.is_connected(), edgir.localpath_concat(prefix, edgir.IS_CONNECTED)), (self.name(), edgir.localpath_concat(prefix, edgir.NAME))], *[ param._get_ref_map(edgir.localpath_concat(prefix, name)) for name, param in self._parameters.items() ]) + link_refs
def _populate_def_proto_hierarchy( self, pb: edgir.HierarchyBlock) -> edgir.HierarchyBlock: self._blocks.finalize() self._connects.finalize() self._chains.finalize() ref_map = self._get_ref_map(edgir.LocalPath()) # opportunistic check in the frontend that all internal ports marked connected are connected all_connected_ports = IdentitySet[BasePort]() for name, connect in self._connects.items(): if len(connect.ports) > 1: all_connected_ports.update(connect.ports) for name, block in self._blocks.items(): pb.blocks[name].lib_elem.target.name = block._get_def_name() # actually generate the links and connects link_chain_names = IdentityDict[ ConnectedPorts, List[str]]() # prefer chain name where applicable # TODO generate into primary data structures for name, chain in self._chains.items_ordered(): for i, connect in enumerate(chain.links): link_chain_names.setdefault(connect, []).append(f"{name}_{i}") for name, connect in self._connects.items_ordered(): if connect in link_chain_names: if not name.startswith('anon_'): pass # prefer a named link above all else else: name = link_chain_names[connect][ 0] # arbitrarily pick the first one for now, TODO disambiguate? connect_elts = connect.generate_connections() if connect_elts is None: # single port net - effectively discard pass elif connect_elts.link_type is None: # generate direct export pb.constraints[ f"(conn){name}"].exported.exterior_port.ref.CopyFrom( ref_map[connect_elts.bridged_connects[0][0]]) pb.constraints[ f"(conn){name}"].exported.internal_block_port.ref.CopyFrom( ref_map[connect_elts.direct_connects[0][0]]) self._namespace_order.append(f"(conn){name}") else: # generate link link_path = edgir.localpath_concat(edgir.LocalPath(), name) self._namespace_order.append(f"{name}") pb.links[ name].lib_elem.target.name = connect_elts.link_type._static_def_name( ) for idx, (self_port, link_port_path) in enumerate( connect_elts.bridged_connects): assert isinstance(self_port, Port) assert self_port.bridge_type is not None port_name = self._name_of(self_port) pb.blocks[ f"(bridge){port_name}"].lib_elem.target.name = self_port.bridge_type._static_def_name( ) self._namespace_order.append(f"(bridge){port_name}") bridge_path = edgir.localpath_concat( edgir.LocalPath(), f"(bridge){port_name}") pb.constraints[ f"(bridge){name}_b{idx}"].exported.exterior_port.ref.CopyFrom( ref_map[self_port]) pb.constraints[ f"(bridge){name}_b{idx}"].exported.internal_block_port.ref.CopyFrom( edgir.localpath_concat(bridge_path, 'outer_port')) self._namespace_order.append(f"(bridge){name}_b{idx}") pb.constraints[ f"(conn){name}_b{idx}"].connected.block_port.ref.CopyFrom( edgir.localpath_concat(bridge_path, 'inner_link')) pb.constraints[ f"(conn){name}_b{idx}"].connected.link_port.ref.CopyFrom( edgir.localpath_concat(link_path, link_port_path)) self._namespace_order.append(f"(conn){name}_b{idx}") for idx, (subelt_port, link_port_path) in enumerate( connect_elts.direct_connects): pb.constraints[ f"(conn){name}_d{idx}"].connected.block_port.ref.CopyFrom( ref_map[subelt_port]) pb.constraints[ f"(conn){name}_d{idx}"].connected.link_port.ref.CopyFrom( edgir.localpath_concat(link_path, link_port_path)) self._namespace_order.append(f"(conn){name}_d{idx}") # generate block initializers for (block_name, block) in self._blocks.items(): for (block_param_name, block_param) in block._init_params.items(): if block_param.initializer is not None: pb.constraints[ f'(init){block_name}.{block_param_name}'].CopyFrom( # TODO better name AssignBinding.make_assign( block_param, block_param._to_expr_type( block_param.initializer), ref_map)) self._namespace_order.append( f'(init){block_name}.{block_param_name}') # generate H-block-specific order for name in self._blocks.keys_ordered(): self._namespace_order.append(name) return pb