"""Via cutback."""
from __future__ import annotations
import warnings
import gdsfactory as gf
from gdsfactory.add_pins import LayerSpec
from gdsfactory.component import Component
from gdsfactory.components.compass import compass
from gdsfactory.components.via_stack import via_stack_heater_m3
from gdsfactory.typings import ComponentSpec, Float2
@gf.cell
def _via_iterable(
via_spacing: float,
wire_width: float,
layer1: LayerSpec,
layer2: LayerSpec,
via_layer: LayerSpec,
via_width: float,
) -> Component:
"""Via chain.
Args:
via_spacing: via_spacing (um).
wire_width: width of wire.
layer1: top wiring.
layer2: bottom wiring.
via_layer: via.
via_width: width of via.
"""
c = gf.Component()
wire1 = c.add_ref(compass(size=(via_spacing, wire_width), layer=layer1))
wire2 = c.add_ref(compass(size=(via_spacing, wire_width), layer=layer2))
viac = c.add_ref(compass(size=(via_width, via_width), layer=via_layer))
via1 = c.add_ref(compass(size=(via_width, via_width), layer=via_layer))
wire1.connect(
port="e3",
destination=wire2.ports["e1"],
overlap=wire_width,
allow_layer_mismatch=True,
)
viac.connect(
port="e1",
destination=wire1.ports["e3"],
overlap=(wire_width + via_width) / 2,
allow_layer_mismatch=True,
)
via1.connect(
port="e1",
destination=wire2.ports["e3"],
overlap=(wire_width + via_width) / 2,
allow_layer_mismatch=True,
)
c.add_port(name="e1", port=wire1.ports["e1"], port_type="electrical", layer=layer1)
c.add_port(name="e3", port=wire2.ports["e3"], port_type="electrical", layer=layer2)
c.add_port(
name="e4",
center=((1 * wire_width) + wire_width / 2, -wire_width / 2),
width=wire_width,
orientation=-90,
port_type="electrical",
layer=layer2,
)
c.add_port(
name="e2",
center=((1 * wire_width) + wire_width / 2, wire_width / 2),
width=wire_width,
orientation=90,
port_type="electrical",
layer=layer2,
)
return c
[docs]
@gf.cell
def via_cutback(
num_vias: float = 200.0,
wire_width: float = 10.0,
via_width: float = 5.0,
via_spacing: float = 30.0,
min_pad_spacing: float = 10.0,
pad: ComponentSpec = via_stack_heater_m3,
pad_size: Float2 = (100, 100),
layer1: LayerSpec = "HEATER",
layer2: LayerSpec = "M1",
via_layer: LayerSpec = "VIAC",
wire_pad_inclusion: float = 2.0,
) -> Component:
"""Via cutback to extract via resistance.
based on phidl.geometry
Args:
num_vias: total requested vias needs to be even.
wire_width: width of wire.
via_width: width of via.
via_spacing: via_spacing.
pad_size: (width, height).
min_pad_spacing.
pad_layer.
layer1: top wiring.
layer2: bottom wiring.
via_layer: via.
wire_pad_inclusion: in um.
"""
warnings.warn("via_cutback is deprecated. Use via_chain instead")
c = gf.Component()
pad_component = pad(size=pad_size)
pad1 = c.add_ref(pad_component)
pad2 = c.add_ref(pad_component)
nub = c.add_ref(pad(size=(3 * wire_width, wire_width)))
head = c.add_ref(pad(size=(wire_width, wire_width)))
nub.ymax = pad1.ymax - 5
nub.xmin = pad1.xmax - wire_pad_inclusion
head.connect(port="e1", destination=nub.ports["e3"])
old_port = head.ports["e4"]
count = 0
width_via_iter = 2 * via_spacing - 2 * wire_width
pad2.xmin = pad1.xmax + min_pad_spacing
up = False
down = True
edge = True
current_width = 3 * wire_width + wire_width # width of nub and 1 overlap
obj_old = head
obj = head
via_iterable = _via_iterable(
via_spacing=via_spacing,
wire_width=wire_width,
layer1=layer1,
layer2=layer2,
via_layer=via_layer,
via_width=via_width,
)
overlap = wire_width
while (count + 2) <= num_vias:
obj = c.add_ref(via_iterable)
obj.connect(
port="e1", destination=old_port, overlap=overlap, allow_layer_mismatch=True
)
old_port = obj.ports["e3"]
edge = False
if obj.ymax > pad1.ymax:
obj.connect(
port="e1",
destination=obj_old.ports["e4"],
overlap=overlap,
allow_layer_mismatch=True,
)
old_port = obj.ports["e4"]
current_width += width_via_iter
down = True
up = False
edge = True
elif obj.ymin < pad1.ymin:
obj.connect(
port="e1",
destination=obj_old.ports["e2"],
overlap=overlap,
allow_layer_mismatch=True,
)
old_port = obj.ports["e2"]
current_width += width_via_iter
up = True
down = False
edge = True
count += 2
obj_old = obj
if (
current_width < min_pad_spacing
and (min_pad_spacing - current_width) > 3 * wire_width
):
tail = c.add_ref(
pad(
size=(min_pad_spacing - current_width + wire_width, wire_width),
)
)
else:
tail = c.add_ref(pad(size=(3 * wire_width, wire_width)))
if up and not edge:
tail.connect(
port="e1",
destination=obj.ports["e4"],
overlap=wire_width,
allow_layer_mismatch=True,
)
elif down and not edge:
tail.connect(
port="e1",
destination=obj.ports["e2"],
overlap=wire_width,
allow_layer_mismatch=True,
)
else:
tail.connect(
port="e1",
destination=obj.ports["e3"],
overlap=wire_width,
allow_layer_mismatch=True,
)
pad2.xmin = tail.xmax - wire_pad_inclusion
c.add_ports(pad1.ports, prefix="p1_")
c.add_ports(pad2.ports, prefix="p2_")
return c
if __name__ == "__main__":
c = via_cutback()
c.show(show_ports=True)