Source code for sky130.pcells.p_p_poly

from math import ceil

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


[docs] @gf.cell def p_p_poly( p_poly_width: float = 0.35, p_poly_length: float = 0.5, poly_res_layer: LayerSpec = (66, 13), poly_layer: LayerSpec = (66, 20), psdm_layer: LayerSpec = (94, 20), sdm_enclosure: Float2 = (0.125, 0.125), contact_size: Float2 = (0.17, 0.17), contact_spacing: Float2 = (0.17, 0.17), licon_slots_size: Float2 = (0.19, 2), licon_slots_spacing: Float2 = (0.51, 0.51), contact_layer: LayerSpec = (66, 44), contact_enclosure: Float2 = (0.06, 0.06), li_layer: LayerSpec = (67, 20), li_enclosure: float = 0.08, mcon_layer: LayerSpec = (67, 44), mcon_enclosure: Float2 = (0.09, 0.09), m1_layer: LayerSpec = (68, 20), rpm_layer: LayerSpec = (86, 20), rpm_min_width: float = 1.27, rpm_enclosure: Float2 = (0.2, 0.2), npc_layer: LayerSpec = (95, 20), npc_enclosure: Float2 = (0.095, 0.095), ) -> gf.Component: """Return p+ poly resistor with sheet resistance of 300 ohms/square. Args: p_poly_width: in um. p_poly_length: in um. poly_res_layer: layer of the p+ poly resistor. poly_layer: layer of the polysilicon. psdm_layer: layer of the p+ implants. sdm_enclosure: enclosure of the p+ implants. contact_size: size of the contact. contact_spacing: spacing between the contacts. licon_slots_size: size of the licon slots. licon_slots_spacing: spacing between the licon slots. contact_layer: layer of the contacts. contact_enclosure: enclosure of the contacts. li_layer: layer of the local interconnects. li_enclosure: enclosure of the local interconnects. mcon_layer: layer of the mcon. mcon_enclosure: enclosure of the mcon. m1_layer: layer of the m1. rpm_layer: layer of the poly resistor implant. rpm_min_width: minimum width of the poly resistor implant. rpm_enclosure: enclosure of the poly resistor implant. npc_layer: layer of the nitride poly cut. npc_enclosure: enclosure of the nitride poly cut. .. plot:: :include-source: import sky130 c = sky130.pcells.p_p_poly(p_poly_width= 5.73, p_poly_length=2) c.plot() """ c = gf.Component() # generate poly res R1 rect_r = gf.components.rectangle( size=(p_poly_width, p_poly_length), layer=poly_res_layer ) c.add_ref(rect_r) # generate polysilicon R0 p_length = licon_slots_size[1] + 2 * contact_enclosure[1] rect_p = gf.components.rectangle( size=(p_poly_width, p_poly_length + 2 * p_length), layer=poly_layer ) R_0 = c.add_ref(rect_p) R_0.dmovey(-p_length) # generate contacts (licon ) rect_lc = gf.components.rectangle(size=licon_slots_size, layer=contact_layer) # nr = ceil((p_length / (licon_slots_size[1]+licon_slots_spacing[1]))) # if (p_length- nr*licon_slots_size[1] - (nr-1)*licon_slots_spacing[1])/2 < contact_enclosure[1] : # nr-=1 nc = ceil(p_poly_width / (licon_slots_size[0] + licon_slots_spacing[0])) if ( p_poly_width - nc * licon_slots_size[0] - (nc - 1) * licon_slots_spacing[0] ) / 2 < contact_enclosure[0]: nc -= 1 lic_sp = ( licon_slots_size[0] + licon_slots_spacing[0], licon_slots_size[1] + licon_slots_spacing[1], ) for i in range(2): cont_arr = c.add_ref(rect_lc, rows=1, columns=nc, spacing=lic_sp) cont_arr.dmovex( ( p_poly_width - nc * licon_slots_size[0] - (nc - 1) * licon_slots_spacing[0] ) / 2 ) cont_arr.dmovey( i * (p_poly_length + (p_length - licon_slots_size[1]) / 2) - (1 - i) * (licon_slots_size[1] + (p_length - licon_slots_size[1]) / 2) ) # generate li (local interconnects) and m1 rect_layer = [m1_layer, li_layer] for i in range(2): rect_li_m1 = gf.components.rectangle( size=( p_poly_width + 2 * (1 - i) * (mcon_enclosure[0] - li_enclosure), licon_slots_size[1] + 2 * i * li_enclosure + 2 * (1 - i) * mcon_enclosure[1], ), layer=rect_layer[i], ) li_m1 = c.add_ref( rect_li_m1, rows=2, columns=1, spacing=( 0, p_poly_length + 2 * contact_enclosure[1] + licon_slots_size[1] - (1 - i) * (mcon_enclosure[1] - li_enclosure), ), ) li_m1.dmovey( -licon_slots_size[1] - contact_enclosure[1] - i * li_enclosure - (1 - i) * mcon_enclosure[1] ) li_m1.dmovex((1 - i) * (-mcon_enclosure[0] + li_enclosure)) # generate mcon rect_mc = gf.components.rectangle(size=contact_size, layer=mcon_layer) nr_m = ceil( (rect_li_m1.dymax - rect_li_m1.dymin) / (contact_size[1] + contact_spacing[1]) ) if ( rect_li_m1.dymax - rect_li_m1.dymin - nr_m * contact_size[1] - (nr_m - 1) * contact_spacing[1] ) / 2 < contact_enclosure[1]: nr_m -= 1 nc_m = ceil( (rect_li_m1.dxmax - rect_li_m1.dxmin) / (contact_size[0] + contact_spacing[0]) ) if ( rect_li_m1.dxmax - rect_li_m1.dxmin - nc_m * contact_size[0] - (nc_m - 1) * contact_spacing[0] ) < contact_enclosure[0]: nc_m -= 1 con_sp = ( contact_size[0] + contact_spacing[0], contact_size[1] + contact_spacing[1], ) for i in range(2): mcon_arr = c.add_ref(rect_mc, rows=nr_m, columns=nc_m, spacing=con_sp) # mcon_arr.dmovex((p_poly_width - nc*licon_slots_size[0] - (nc-1)*licon_slots_spacing[0] - 2*li_enclosure )/2) mcon_arr.dmovey( (1 - i) * (-licon_slots_size[1] - contact_enclosure[1] - li_enclosure) + i * (p_poly_length) ) mcon_arr.dmovex( ( rect_li_m1.dxmax - rect_li_m1.dxmin - nc_m * contact_size[0] - (nc_m - 1) * contact_spacing[0] ) / 2 ) mcon_arr.dmovey( ( rect_li_m1.dymax - rect_li_m1.dymin - nr_m * contact_size[1] - (nr_m - 1) * contact_spacing[1] ) / 2 ) # generate npc (nitride poly cut) rect_npc = gf.components.rectangle( size=( p_poly_width + 2 * npc_enclosure[0], p_poly_length + 2 * p_length + 2 * npc_enclosure[1], ), layer=npc_layer, ) npc = c.add_ref(rect_npc) npc.connect( "e1", R_0.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True ) npc.dmovex(p_poly_width + npc_enclosure[0]) # generate rpm (poly resistor implant) if p_poly_width <= rpm_min_width: rpm_width = rpm_min_width + 2 * rpm_enclosure[0] else: rpm_width = p_poly_width + 2 * rpm_enclosure[0] rpm_length = p_poly_length + 2 * p_length + 2 * rpm_enclosure[1] rect_rpm = gf.components.rectangle(size=(rpm_width, rpm_length), layer=rpm_layer) rpm = c.add_ref(rect_rpm) rpm.connect( "e1", R_0.ports["e1"], allow_layer_mismatch=True, allow_width_mismatch=True ) rpm.dmovex(p_poly_width + ((rpm_width - p_poly_width) / 2)) # generate p+ implants rect_psdm = gf.components.rectangle( size=(rpm_width + 2 * sdm_enclosure[0], rpm_length + 2 * sdm_enclosure[1]), layer=psdm_layer, ) psdm = c.add_ref(rect_psdm) psdm.connect( "e1", rpm.ports["e3"], allow_layer_mismatch=True, allow_width_mismatch=True ) psdm.dmovex(rpm_width + sdm_enclosure[0]) return c
if __name__ == "__main__": # c = p_p_poly(p_poly_width= 5.73, p_poly_length=2) c = p_p_poly() c.show()