Source code for gdsfactory.components.greek_cross

"""Greek cross test structure."""

from itertools import product

import numpy as np

import gdsfactory as gf
from gdsfactory.components.cross import cross
from gdsfactory.components.pad import pad
from gdsfactory.components.rectangle import rectangle
from gdsfactory.components.via_stack import via_stack, via_stack_m1_m3, via_stack_npp_m1
from gdsfactory.cross_section import metal1
from gdsfactory.typings import ComponentSpec, CrossSectionSpec, Floats, LayerSpecs


[docs] @gf.cell def greek_cross( length: float = 30, layers: LayerSpecs = ( "WG", "N", ), widths: Floats = (2.0, 3.0), offsets: Floats | None = None, via_stack: ComponentSpec = via_stack_npp_m1, ) -> gf.Component: """Simple greek cross with via stacks at the endpoints. Process control monitor for dopant sheet resistivity and linewidth variation. Args: length: length of cross arms. layers: list of layers. widths: list of widths (same order as layers). offsets: how much to extend each layer beyond the cross length negative shorter, positive longer. via_stack: via component to attach to the cross. .. code:: via_stack <-------> _________ length ________ | |<-------------------->| 2x | | | ↓ |<-->| | |======== width =======| |_______|<--> | ↑ |<-->|________ offset offset References: - Walton, Anthony J.. “MICROELECTRONIC TEST STRUCTURES.” (1999). - W. Versnel, Analysis of the Greek cross, a Van der Pauw structure with finite contacts, Solid-State Electronics, Volume 22, Issue 11, 1979, Pages 911-914, ISSN 0038-1101, https://doi.org/10.1016/0038-1101(79)90061-3. - S. Enderling et al., "Sheet resistance measurement of non-standard cleanroom materials using suspended Greek cross test structures," IEEE Transactions on Semiconductor Manufacturing, vol. 19, no. 1, pp. 2-9, Feb. 2006, doi: 10.1109/TSM.2005.863248. - https://download.tek.com/document/S530_VanDerPauwSheetRstnce.pdf """ c = gf.Component() if len(layers) != len(widths): raise ValueError("len(layers) must equal len(widths).") offsets = offsets or (0.0,) * len(layers) # Layout cross for layer, width, offset in zip(layers, widths, offsets): cross_ref = c << gf.get_component( cross, length=length + 2 * offset, width=width, layer=layer, port_type="electrical", ) cross_offset = offset port_at_length = [ port.move_polar_copy(d=cross_offset, angle=180 + port.orientation) for port in cross_ref.get_ports_list() ] # Add via for port in port_at_length: via_stack_ref = c << gf.get_component(via_stack) via_stack_ref.connect("e1", port, allow_layer_mismatch=True) c.add_port(name=port.name, port=via_stack_ref.ports["e3"]) c.auto_rename_ports() return c
[docs] @gf.cell def greek_cross_with_pads( pad: ComponentSpec = pad, pad_spacing: float = 150.0, greek_cross_component: ComponentSpec = greek_cross, pad_via: ComponentSpec = via_stack_m1_m3, xs_metal: CrossSectionSpec = metal1, ) -> gf.Component: """Greek cross under 4 DC pads, ready to test. Arguments: pad: component to use for probe pads pad_spacing: spacing between pads greek_cross_component: component to use for greek cross pad_via: via to add to the pad xs_metal: cross-section for cross via to pad via wiring """ c = gf.Component() # Cross cross_ref = c << gf.get_component(greek_cross_component) cross_ref.x = ( 2 * pad_spacing - (pad_spacing - gf.get_component(pad).info["size"][0]) / 2 ) cross_pad_via_port_pairs = { 0: ("e1", "e2"), 1: ("e4", "e2"), 2: ("e2", "e4"), 3: ("e3", "e4"), } # Vias to pads for index in range(4): pad_ref = c << gf.get_component(pad) pad_ref.x = index * pad_spacing + pad_ref.xsize / 2 via_ref = c << gf.get_component(pad_via) if index < 2: via_ref.connect("e2", destination=pad_ref.ports["e4"]) else: via_ref.connect("e4", destination=pad_ref.ports["e2"]) route = gf.routing.get_route( cross_ref[cross_pad_via_port_pairs[index][0]], via_ref[cross_pad_via_port_pairs[index][1]], cross_section=xs_metal, bend=gf.c.wire_corner, start_straight_length=5, end_straight_length=5, ) c.add(route.references) return c
[docs] @gf.cell def greek_cross_offset_pads( cross_struct_length: float = 30.0, cross_struct_width: float = 1.0, cross_struct_layers: LayerSpecs = ("WG",), cross_implant_length: float = 30.0, cross_implant_width: float = 2.0, cross_implant_layers: LayerSpecs = ("N",), contact_layers: LayerSpecs = ("WG", "NPP"), contact_offset: float = 10, contact_buffer: float = 10, pad_width: float = 50, ) -> gf.Component: """Greek cross, with silicon islands on each side of the cross to place larger contacting regions. Args: cross_struct_length: length of structural part of cross e.g. silicon core. cross_struct_width: width of structural part of cross e.g. silicon core. cross_struct_layers: layers to be considered "structural". cross_implant_length: length of implantation part of cross. cross_implant_width: width of implantation part of cross. cross_implant_layers: layers to be considered "implants". contact_layers: layers to include under and around the pad. contact_offset: fudge factor to move pad relative to cross. contact_buffer: amount of dopants around pad in contact. pad_width: pad size. .. code:: pad_width <-------> _________ cross_implant_length, cross_struct_length | |<-------> 4x | | ↓ | |======== cross_implant_width, cross_struct_width |_______| ↑ <--------------> contact_offset (fudge) References: - Walton, Anthony J.. “MICROELECTRONIC TEST STRUCTURES.” (1999). - W. Versnel, Analysis of the Greek cross, a Van der Pauw structure with finite contacts, Solid-State Electronics, Volume 22, Issue 11, 1979, Pages 911-914, ISSN 0038-1101, https://doi.org/10.1016/0038-1101(79)90061-3. - S. Enderling et al., "Sheet resistance measurement of non-standard cleanroom materials using suspended Greek cross test structures," IEEE Transactions on Semiconductor Manufacturing, vol. 19, no. 1, pp. 2-9, Feb. 2006, doi: 10.1109/TSM.2005.863248. """ c = gf.Component() # Layout cross for layer in cross_struct_layers: c << gf.get_component( cross, length=2 * cross_struct_length + cross_struct_width, width=cross_struct_width, layer=layer, ) for layer in cross_implant_layers: c << gf.get_component( cross, length=2 * cross_implant_length + cross_implant_width, width=cross_implant_width, layer=layer, ) pad_offset = pad_width / 2 + cross_implant_length / 2 # contact vias and pads for sgnx, sgny in product([1, -1], [1, -1]): pad_rotation = np.arctan2(sgny, sgnx) * 180 / np.pi - 45 c2 = gf.Component(f"contact_{sgnx}_{sgny}") c2 << gf.get_component(via_stack, size=(pad_width, pad_width)) c2 << gf.get_component(pad, size=(pad_width, pad_width)) for layer in contact_layers: w = gf.get_component( rectangle, size=( pad_width + contact_buffer, pad_width + cross_implant_length / 2 + contact_buffer, ), layer=layer, ) ref = c2 << w ref.move( np.array( [ -1 * pad_offset + cross_implant_length / 2 - contact_buffer / 2, -1 * pad_offset - contact_offset / 2, ] ) ) contact = c << c2 contact.rotate(pad_rotation) contact.move(np.array([sgnx * pad_offset, sgny * pad_offset])) return c.flatten()
if __name__ == "__main__": # c = greek_cross_offset_pads() c = greek_cross_with_pads() c.show(show_ports=True)