Source code for gf180mcu.cells.via_generator

from math import ceil, floor
from typing import Any

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

from gf180mcu.layers import layer


[docs] @gf.cell def via_generator( x_range: Float2 = (0, 1), y_range: Float2 = (0, 1), via_size: Float2 = (0.17, 0.17), via_layer: LayerSpec = (66, 44), via_enclosure: Float2 = (0.06, 0.06), via_spacing: Float2 = (0.17, 0.17), ) -> gf.Component: """Return only vias withen the range xrange and yrange while enclosing by via_enclosure and set number of rows and number of columns according to ranges and via size and spacing. Args: x_range: dx range. y_range: dy range. via_size: via size. via_layer: via layer. via_enclosure: via enclosure. via_spacing: via spacing. """ c = gf.Component() width = x_range[1] - x_range[0] length = y_range[1] - y_range[0] nr = floor(length / (via_size[1] + via_spacing[1])) if (length - nr * via_size[1] - (nr - 1) * via_spacing[1]) / 2 < via_enclosure[1]: nr -= 1 nr = max(nr, 1) nc = ceil(width / (via_size[0] + via_spacing[0])) if ( round(width - nc * via_size[0] - (nc - 1) * via_spacing[0], 2) ) / 2 < via_enclosure[0]: nc -= 1 nc = max(nc, 1) via_sp = (via_size[0] + via_spacing[0], via_size[1] + via_spacing[1]) rect_via = gf.components.rectangle(size=via_size, layer=via_layer) via_arr = c.add_ref( rect_via, rows=nr, columns=nc, column_pitch=via_sp[0], row_pitch=via_sp[1] ) via_arr.dmove((x_range[0], y_range[0])) via_arr.dmovex((width - nc * via_size[0] - (nc - 1) * via_spacing[0]) / 2) via_arr.dmovey((length - nr * via_size[1] - (nr - 1) * via_spacing[1]) / 2) # Add ports for top and bottom connections center_x = (x_range[0] + x_range[1]) / 2 (y_range[0] + y_range[1]) / 2 c.add_port( name="e1", center=(center_x, y_range[0]), width=width, orientation=270, layer=via_layer, port_type="electrical", ) c.add_port( name="e2", center=(center_x, y_range[1]), width=width, orientation=90, layer=via_layer, port_type="electrical", ) return c
[docs] @gf.cell def via_stack( x_range: Float2 = (0, 1), y_range: Float2 = (0, 1), metal_level: int = 1, con_size: Size = (0.22, 0.22), con_enc: float = 0.07, m_enc: float = 0.06, con_spacing: Spacing = (0.28, 0.28), via_size: Size = (0.22, 0.22), via_spacing: Spacing = (0.28, 0.28), via_enc: Float2 = (0.06, 0.06), base_layer: LayerSpec = layer["metal1"], **kwargs: Any, ) -> gf.Component: """Returns a via stack withen the range xrange and yrange and expecting the base_layer to be drawen. Args: x_range: dx range. y_range: dy range. metal_level: metal level. con_size: contact size. con_enc: contact enclosure. m_enc: metal enclosure. con_spacing: contact spacing. via_size: via size. via_spacing: via spacing. via_enc: via enclosure. return via stack till the metal level indicated where : metal_level 1 : till m1 metal_level 2 : till m2 metal_level 3 : till m3 metal_level 4 : till m4 metal_level 5 : till m5 withen the range xrange and yrange and expecting the base_layer to be drawen """ c = gf.Component() if metal_level >= 1: con_gen = via_generator( x_range=x_range, y_range=y_range, via_size=con_size, via_enclosure=(con_enc, con_enc), via_layer=layer["contact"], via_spacing=con_spacing, ) con = c.add_ref(con_gen) m1_x = con.dxsize + 2 * m_enc m1_y = con.dysize + 2 * m_enc m1 = c.add_ref(gf.components.rectangle(size=(m1_x, m1_y), layer=base_layer)) m1.dxmin = con.dxmin - m_enc m1.dymin = con.dymin - m_enc if metal_level >= 2: via1_gen = via_generator( x_range=(m1.dxmin, m1.dxmax), y_range=(m1.dymin, m1.dymax), via_size=via_size, via_enclosure=via_enc, via_layer=layer["via1"], via_spacing=via_spacing, ) via1 = c.add_ref(via1_gen) if (via1.dxmax - via1.dxmin + 2 * m_enc[0]) < ( via_size[0] + 2 * via_enc[0] ) and metal_level >= 3: m2_x = via_size[0] + 2 * via_enc[0] else: m2_x = via1.dxmax - via1.dxmin + 2 * m_enc[0] if (via1.dymax - via1.dymin + 2 * m_enc[1]) < ( via_size[1] + 2 * via_enc[1] ) and metal_level >= 3: m2_y = via_size[1] + 2 * via_enc[1] else: m2_y = via1.dymax - via1.dymin + 2 * m_enc[1] m2_mx = (m2_x - (via1.dxmax - via1.dxmin)) / 2 m2_my = (m2_y - (via1.dymax - via1.dymin)) / 2 m2 = c.add_ref( gf.components.rectangle(size=(m2_x, m2_y), layer=layer["metal2"]) ) m2.dmove((via1.dxmin - m2_mx, via1.dymin - m2_my)) # Add ports for the via stack if metal_level >= 1: # Port at bottom layer c.add_port( name="e1", center=((x_range[0] + x_range[1]) / 2, (y_range[0] + y_range[1]) / 2), width=m1_x, orientation=0, layer=base_layer, port_type="electrical", ) # Port at top metal layer if metal_level == 1: top_layer = base_layer top_width = m1_x elif metal_level >= 2: top_layer = layer["metal2"] top_width = m2_x c.add_port( name="e2", center=((x_range[0] + x_range[1]) / 2, (y_range[0] + y_range[1]) / 2), width=top_width, orientation=0, layer=top_layer, port_type="electrical", ) return c
if __name__ == "__main__": c = via_stack() c.show() # c = vias_gen_draw(start_layer="li",end_layer="poly") # c.show()