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. .. 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.movey(-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_array(rect_lc, rows=1, columns=nc, spacing=lic_sp) cont_arr.movex( ( p_poly_width - nc * licon_slots_size[0] - (nc - 1) * licon_slots_spacing[0] ) / 2 ) cont_arr.movey( 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_array( 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.movey( -licon_slots_size[1] - contact_enclosure[1] - i * li_enclosure - (1 - i) * mcon_enclosure[1] ) li_m1.movex((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.ymax - rect_li_m1.ymin) / (contact_size[1] + contact_spacing[1]) ) if ( rect_li_m1.ymax - rect_li_m1.ymin - nr_m * contact_size[1] - (nr_m - 1) * contact_spacing[1] ) / 2 < contact_enclosure[1]: nr_m -= 1 nc_m = ceil( (rect_li_m1.xmax - rect_li_m1.xmin) / (contact_size[0] + contact_spacing[0]) ) if ( rect_li_m1.xmax - rect_li_m1.xmin - 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_array(rect_mc, rows=nr_m, columns=nc_m, spacing=con_sp) # mcon_arr.movex((p_poly_width - nc*licon_slots_size[0] - (nc-1)*licon_slots_spacing[0] - 2*li_enclosure )/2) mcon_arr.movey( (1 - i) * (-licon_slots_size[1] - contact_enclosure[1] - li_enclosure) + i * (p_poly_length) ) mcon_arr.movex( ( rect_li_m1.xmax - rect_li_m1.xmin - nc_m * contact_size[0] - (nc_m - 1) * contact_spacing[0] ) / 2 ) mcon_arr.movey( ( rect_li_m1.ymax - rect_li_m1.ymin - 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", destination=R_0.ports["e1"], allow_layer_mismatch=True) npc.movex(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", destination=R_0.ports["e1"], allow_layer_mismatch=True) rpm.movex(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", destination=rpm.ports["e3"], allow_layer_mismatch=True) psdm.movex(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(show_ports=True)