def add_electrical_pads_top(component: Component, **kwargs) -> Component: """connects component electrical ports with pad array at the top Args: component: pad: pad element spacing: pad array (x, y) spacing width: pad width height: pad height layer: pad layer """ c = Component(f"{component.name}_e") ports = component.get_ports_list(port_type="dc") c << component pads = c << pad_array(n=len(ports), port_list=["S"], **kwargs) pads.x = component.x pads.y = component.ymax + 100 ports_pads = list(pads.ports.values()) for p1, p2 in zip(ports_pads, ports): c.add(connect_electrical_shortest_path(p1, p2)) c.ports = component.ports for port in ports: c.ports.pop(port.name) return c
def pad( width: int = 100, height: int = 100, layer: Tuple[int, int] = LAYER.M3 ) -> Component: """rectangular pad with 4 ports (N, S, E, W) Args: width: pad width height: pad height layer: pad layer .. plot:: :include-source: import pp c = pp.c.pad(width=100, height=100, layer=pp.LAYER.M3) pp.plotgds(c) """ c = Component() _c = compass(size=(width, height), layer=layer).ref() c.add(_c) c.absorb(_c) c.ports = _c.ports return c
def rotate(component: Component, angle: int = 90) -> Component: """ returns rotated component """ c = Component(f"{component.name}_r") cr = c.add_ref(component) cr.rotate(angle) c.ports = cr.ports return c
def rotate(component, angle=90): """ returns rotated component """ c = Component( settings=component.get_settings(), test_protocol=component.test_protocol, data_analysis_protocol=component.data_analysis_protocol, ) cr = c.add_ref(component) cr.rotate(angle) c.ports = cr.ports c.name = component.name + "_r" return c
def add_electrical_pads_shortest(component, pad=pad, pad_port_spacing=50, **kwargs): """add a pad to each closest electrical port Args: component: pad: pad element or function pad_port_spacing: between pad and port width: pad width height: pad height layer: pad layer """ c = Component(f"{component.name}_e") ports = component.get_ports_list(port_type="dc") c << component pad = pad(**kwargs) if callable(pad) else pad pad_port_spacing += pad.settings["width"] / 2 for port in ports: p = c << pad if port.orientation == 0: p.x = port.x + pad_port_spacing p.y = port.y c.add(connect_electrical_shortest_path(port, p.ports["W"])) elif port.orientation == 180: p.x = port.x - pad_port_spacing p.y = port.y c.add(connect_electrical_shortest_path(port, p.ports["E"])) elif port.orientation == 90: p.y = port.y + pad_port_spacing p.x = port.x c.add(connect_electrical_shortest_path(port, p.ports["S"])) elif port.orientation == 270: p.y = port.y - pad_port_spacing p.x = port.x c.add(connect_electrical_shortest_path(port, p.ports["N"])) c.ports = component.ports for port in ports: c.ports.pop(port.name) return c
def add_electrical_pads_top( component: Component, component_top_to_pad_bottom_distance: float = 100.0, route_filter=connect_elec_waypoints, **kwargs, ) -> Component: """connects component electrical ports with pad array at the top Args: component: pad: pad element spacing: pad array (x, y) spacing width: pad width height: pad height layer: pad layer """ c = Component(f"{component.name}_e") ports = component.get_ports_list(port_type="dc") # for port in ports: # print(port.name) # print(len(ports)) c << component pads = c << pad_array(n=len(ports), port_list=["S"], **kwargs) pads.x = component.x pads.ymin = component.ymax + component_top_to_pad_bottom_distance ports_pads = list(pads.ports.values()) ports_pads.sort(key=lambda p: p.x) ports.sort(key=lambda p: p.x) for p1, p2 in zip(ports_pads, ports): c.add(connect_electrical_shortest_path(p1, p2)) c.ports = component.ports.copy() for port in ports: c.ports.pop(port.name) return c
def route_fiber_single( component: Component, optical_io_spacing: int = 50, grating_coupler: Component = grating_coupler_te, min_input2output_spacing: int = 230, optical_routing_type: int = 1, optical_port_labels: Optional[List[str]] = None, excluded_ports: Optional[List[str]] = None, **kwargs ) -> Tuple[List[Union[ComponentReference, Label]], List[ComponentReference]]: """Returns routes with grating couplers for single fiber input/output. Args: component: to add grating couplers optical_io_spacing: between grating couplers grating_coupler: min_input2output_spacing: so opposite fibers do not touch optical_routing_type: 0, 1, 2 optical_port_labels: port labels that need connection excluded_ports: ports excluded from routing Returns: elements: list of routes ComponentReference grating_couplers: list of grating_couplers ComponentReferences """ component = component.copy() component_copy = component.copy() if optical_port_labels is None: optical_ports = component.get_ports_list(port_type="optical") else: optical_ports = [component.ports[lbl] for lbl in optical_port_labels] excluded_ports = excluded_ports or [] optical_ports = [p for p in optical_ports if p.name not in excluded_ports] N = len(optical_ports) if isinstance(grating_coupler, list): grating_couplers = [pp.call_if_func(g) for g in grating_coupler] grating_coupler = grating_couplers[0] else: grating_coupler = pp.call_if_func(grating_coupler) grating_couplers = [grating_coupler] * N gc_port2center = getattr(grating_coupler, "port2center", grating_coupler.xsize / 2) if component.xsize + 2 * gc_port2center < min_input2output_spacing: fanout_length = (pp.drc.snap_to_grid( min_input2output_spacing - component.xsize - 2 * gc_port2center, 10) / 2) else: fanout_length = None """ _________ | |_E1 W0_| | | |_E0 |_________| rotate +90 deg and route West ports to South E1 E0 _|___|_ | | | | | | | | | | | | |_______| | W0 """ # route west ports to south component = component.rotate(90) west_ports = component.get_ports_dict(prefix="W") north_ports = { p.name: p for p in component.ports.values() if not p.name.startswith("W") } component.ports = west_ports elements_south, gratings_south, _ = route_fiber_array( component=component, with_align_ports=False, optical_io_spacing=optical_io_spacing, fanout_length=fanout_length, grating_coupler=grating_couplers[0], optical_routing_type=optical_routing_type, **kwargs) # route north ports component = component_copy.rotate(-90) north_ports = { p.name: p for p in component.ports.values() if not p.name.startswith("W") } component.ports = north_ports elements_north, gratings_north, _ = route_fiber_array( component=component, with_align_ports=False, optical_io_spacing=optical_io_spacing, fanout_length=fanout_length, grating_coupler=grating_couplers[1:], **kwargs) for e in elements_north: elements_south.append(e.rotate(180)) if len(gratings_north) > 0: for io in gratings_north[0]: gratings_south.append(io.rotate(180)) return elements_south, gratings_south