Source code for sky130.pcells.contact

from math import floor

import gdsfactory as gf
from gdsfactory.typings import Float2, LayerSpec

from sky130.layers import LAYER


[docs] @gf.cell def contact_array( width: float = 0.29, height: float = 0.29, contact_layer: LayerSpec = (66, 44), contact_size: Float2 = (0.17, 0.17), contact_spacing: Float2 = (0.17, 0.17), enclosure: Float2 = (0.06, 0.06), ) -> gf.Component: """Return a centered array of contacts/vias within the area of width x height. Uses floor rounding to match Magic's contact placement behavior. Args: width: width of the enclosing area. height: height of the enclosing area. contact_layer: layer for the contact rectangles. contact_size: (x, y) size of each contact. contact_spacing: (x, y) spacing between contacts. enclosure: (x, y) minimum enclosure of contacts within the area. .. plot:: :include-source: import sky130 c = sky130.pcells.contact_array() c.plot() """ c = gf.Component() sx, sy = contact_size spx, spy = contact_spacing ex, ey = enclosure avail_w = width - 2 * ex avail_h = height - 2 * ey # Epsilon tolerance to avoid floating-point rounding artifacts. _EPS = 1e-6 # Return empty component if area is too small for even one contact if avail_w < sx - _EPS or avail_h < sy - _EPS: return c # Floor rounding matches Magic's contact placement behavior. # Add epsilon before floor to compensate for floating-point drift # (e.g. 0.34/0.34 yielding 0.9999… instead of 1.0). nc = 1 + floor((avail_w - sx) / (sx + spx) + _EPS) nr = 1 + floor((avail_h - sy) / (sy + spy) + _EPS) nc = max(nc, 1) nr = max(nr, 1) pitch_x = sx + spx pitch_y = sy + spy # Total footprint of the contact array array_w = nc * sx + (nc - 1) * spx array_h = nr * sy + (nr - 1) * spy # Center the array within the available area ox = (width - array_w) / 2 oy = (height - array_h) / 2 rect = gf.components.rectangle(size=(sx, sy), layer=contact_layer) ref = c.add_ref(rect, columns=nc, rows=nr, column_pitch=pitch_x, row_pitch=pitch_y) ref.move((ox, oy)) return c
[docs] def licon_array(width: float = 0.29, height: float = 0.29) -> gf.Component: """Convenience wrapper for licon contact arrays (LiCon, layer 66/44). Uses size=0.17, spacing=0.17, enclosure=0.06 on all sides. Args: width: width of the enclosing area. height: height of the enclosing area. """ return contact_array( width=width, height=height, contact_layer=LAYER.licon1drawing, contact_size=(0.17, 0.17), contact_spacing=(0.17, 0.17), enclosure=(0.06, 0.06), )
[docs] def mcon_array(width: float = 0.29, height: float = 0.29) -> gf.Component: """Convenience wrapper for mcon contact arrays (Metal contact, layer 67/44). Uses size=0.17, spacing=0.19, enclosure=(0.03, 0.06). Args: width: width of the enclosing area. height: height of the enclosing area. """ return contact_array( width=width, height=height, contact_layer=LAYER.mcondrawing, contact_size=(0.17, 0.17), contact_spacing=(0.19, 0.19), enclosure=(0.03, 0.06), )
if __name__ == "__main__": c = contact_array() c.show()