Source code for gdsfactory.components.via_corner
from __future__ import annotations
from numpy import floor
import gdsfactory as gf
from gdsfactory.components.compass import compass
from gdsfactory.components.via import via1
from gdsfactory.cross_section import metal2, metal3
from gdsfactory.port import select_ports
from gdsfactory.typings import ComponentSpec, MultiCrossSectionAngleSpec
[docs]
@gf.cell
def via_corner(
cross_section: MultiCrossSectionAngleSpec = (
(metal2, (0, 180)),
(metal3, (90, 270)),
),
vias: tuple[ComponentSpec] = (via1,),
layers_labels: tuple[str, ...] = ("m2", "m3"),
**kwargs,
) -> gf.Component:
"""Returns Corner via.
Use in place of wire_corner to route between two layers.
Args:
cross_section: list of cross_section, orientation pairs.
vias: vias to use to fill the rectangles.
layers_labels: Labels to use for each layer.
kwargs: cross_section settings.
"""
cross_sections = [gf.get_cross_section(x[0], **kwargs) for x in cross_section]
port_orientations = [x[1] for x in cross_section]
widths = heights = [x.width for x in cross_sections]
layers = [x.layer for x in cross_sections]
layers_ports = layers
max_width = max(widths)
max_height = max(heights)
min_height = min(heights)
min_width = min(widths)
a = min_width / 2
b = min_height / 2
c = gf.Component()
c.height = max_height
c.info["size"] = (float(max_width), float(max_height))
c.info["length"] = max(max_width, max_height)
for i, layer in enumerate(layers):
ref = c << compass(size=(widths[i], heights[i]), layer=layer)
if layer in layers_ports:
orientations = port_orientations[i]
if (90 in orientations) or (270 in orientations):
orientation = 90
elif (0 in orientations) or (180 in orientations):
orientation = 180
else:
raise ValueError(f"Port orientation {orientations} not valid.")
ports = ref.ports
ports = select_ports(ports, orientation=orientation)
c.add_ports(ports, prefix=f"{layers_labels[i]}_")
for via in vias:
via = gf.get_component(via)
w, h = via.info["size"]
g = via.info["enclosure"]
pitch_x, pitch_y = via.info["spacing"]
nb_vias_x = (min_width - w - 2 * g) / pitch_x + 1
nb_vias_y = (min_height - h - 2 * g) / pitch_y + 1
nb_vias_x = int(floor(nb_vias_x)) or 1
nb_vias_y = int(floor(nb_vias_y)) or 1
ref = c.add_array(
via, columns=nb_vias_x, rows=nb_vias_y, spacing=(pitch_x, pitch_y)
)
cw = (min_width - (nb_vias_x - 1) * pitch_x - w) / 2
ch = (min_height - (nb_vias_y - 1) * pitch_y - h) / 2
x0 = -a + cw + w / 2
y0 = -b + ch + h / 2
ref.move((x0, y0))
return c
if __name__ == "__main__":
# c = via_corner(cross_section=[(metal2, (0, 180)), (metal3, (90, 270))])
c = via_corner()
c.pprint_ports()
# c.plot()
c.show()