From 5805c8fac0ba09a17b850288198bb228243f2ee2 Mon Sep 17 00:00:00 2001 From: RehabSayed-G Date: Wed, 25 Jan 2023 17:16:03 +0200 Subject: [PATCH] start rewriting gf180 mosfet pcell --- cells/klayout/pymacros/cells/__init__.py | 148 +- .../__pycache__/layers_def.cpython-310.pyc | Bin 0 -> 458 bytes cells/klayout/pymacros/cells/draw_fet.py | 6434 ++--------------- cells/klayout/pymacros/cells/draw_fet_old.py | 5977 +++++++++++++++ cells/klayout/pymacros/cells/fet.py | 678 +- cells/klayout/pymacros/cells/layers_def.py | 31 + 6 files changed, 6922 insertions(+), 6346 deletions(-) create mode 100644 cells/klayout/pymacros/cells/__pycache__/layers_def.cpython-310.pyc create mode 100644 cells/klayout/pymacros/cells/draw_fet_old.py create mode 100644 cells/klayout/pymacros/cells/layers_def.py diff --git a/cells/klayout/pymacros/cells/__init__.py b/cells/klayout/pymacros/cells/__init__.py index 43a98bd2..5bc1cc5c 100644 --- a/cells/klayout/pymacros/cells/__init__.py +++ b/cells/klayout/pymacros/cells/__init__.py @@ -42,85 +42,85 @@ def __init__(self): self.layout().register_pcell( "nfet", nfet() ) # nfet_03v3 , nfet_05v0 , nfet_06v0 - self.layout().register_pcell( - "pfet", pfet() - ) # pfet_03v3 , pfet_05v0 , pfet_06v0 - self.layout().register_pcell("nfet_06v0_nvt", nfet_06v0_nvt()) - self.layout().register_pcell("nfet_10v0_asym", nfet_10v0_asym()) - self.layout().register_pcell("pfet_10v0_asym", pfet_10v0_asym()) + # self.layout().register_pcell( + # "pfet", pfet() + # ) # pfet_03v3 , pfet_05v0 , pfet_06v0 + # self.layout().register_pcell("nfet_06v0_nvt", nfet_06v0_nvt()) + # self.layout().register_pcell("nfet_10v0_asym", nfet_10v0_asym()) + # self.layout().register_pcell("pfet_10v0_asym", pfet_10v0_asym()) - # BJT - self.layout().register_pcell( - "npn_bjt", npn_bjt() - ) # npn_10p00x10p00 , npn_05p00x05p00 , npn_00p54x16p00 , - # npn_00p54x08p00 , npn_00p54x04p00 , npn_00p54x02p00 - self.layout().register_pcell( - "pnp_bjt", pnp_bjt() - ) # pnp_10p00x10p00 , pnp_05p00x05p00 , pnp_10p00x00p42 , pnp_05p00x00p42 + # # BJT + # self.layout().register_pcell( + # "npn_bjt", npn_bjt() + # ) # npn_10p00x10p00 , npn_05p00x05p00 , npn_00p54x16p00 , + # # npn_00p54x08p00 , npn_00p54x04p00 , npn_00p54x02p00 + # self.layout().register_pcell( + # "pnp_bjt", pnp_bjt() + # ) # pnp_10p00x10p00 , pnp_05p00x05p00 , pnp_10p00x00p42 , pnp_05p00x00p42 - # DIODE DEVICES - self.layout().register_pcell( - "diode_nd2ps", diode_nd2ps() - ) # diode_nd2ps_03v3 , diode_nd2ps_06v0 - self.layout().register_pcell( - "diode_pd2nw", diode_pd2nw() - ) # diode_pd2nw_03v3 , diode_pd2nw_06v0 - self.layout().register_pcell( - "diode_nw2ps", diode_nw2ps() - ) # diode_nw2ps_03v3 , diode_nw2ps_06v0 - self.layout().register_pcell( - "diode_pw2dw", diode_pw2dw() - ) # diode_pw2dw_03v3 , diode_pw2dw_06v0 - self.layout().register_pcell( - "diode_dw2ps", diode_dw2ps() - ) # diode_dw2ps_03v3 , diode_dw2ps_06v0 - self.layout().register_pcell("sc_diode", sc_diode()) + # # DIODE DEVICES + # self.layout().register_pcell( + # "diode_nd2ps", diode_nd2ps() + # ) # diode_nd2ps_03v3 , diode_nd2ps_06v0 + # self.layout().register_pcell( + # "diode_pd2nw", diode_pd2nw() + # ) # diode_pd2nw_03v3 , diode_pd2nw_06v0 + # self.layout().register_pcell( + # "diode_nw2ps", diode_nw2ps() + # ) # diode_nw2ps_03v3 , diode_nw2ps_06v0 + # self.layout().register_pcell( + # "diode_pw2dw", diode_pw2dw() + # ) # diode_pw2dw_03v3 , diode_pw2dw_06v0 + # self.layout().register_pcell( + # "diode_dw2ps", diode_dw2ps() + # ) # diode_dw2ps_03v3 , diode_dw2ps_06v0 + # self.layout().register_pcell("sc_diode", sc_diode()) - # cap_mos - self.layout().register_pcell( - "cap_nmos", cap_nmos() - ) # cap_nmos_03v3 , cap_nmos_06v0 - self.layout().register_pcell( - "cap_pmos", cap_pmos() - ) # cap_pmos_03v3 , cap_pmos_06v0 - self.layout().register_pcell( - "cap_nmos_b", cap_nmos_b() - ) # cap_nmos_03v3_b , cap_nmos_06v0_b - self.layout().register_pcell( - "cap_pmos_b", cap_pmos_b() - ) # cap_pmos_03v3_b , cap_pmos_06v0_b + # # cap_mos + # self.layout().register_pcell( + # "cap_nmos", cap_nmos() + # ) # cap_nmos_03v3 , cap_nmos_06v0 + # self.layout().register_pcell( + # "cap_pmos", cap_pmos() + # ) # cap_pmos_03v3 , cap_pmos_06v0 + # self.layout().register_pcell( + # "cap_nmos_b", cap_nmos_b() + # ) # cap_nmos_03v3_b , cap_nmos_06v0_b + # self.layout().register_pcell( + # "cap_pmos_b", cap_pmos_b() + # ) # cap_pmos_03v3_b , cap_pmos_06v0_b - # cap_mim - self.layout().register_pcell( - "cap_mim", cap_mim() - ) # cap_mim (Option-A) , cap_mim_tm (Option-B) + # # cap_mim + # self.layout().register_pcell( + # "cap_mim", cap_mim() + # ) # cap_mim (Option-A) , cap_mim_tm (Option-B) - # RES - self.layout().register_pcell( - "metal_resistor", metal_resistor()) - self.layout().register_pcell( - "nplus_s_resistor", nplus_s_resistor()) - self.layout().register_pcell( - "pplus_s_resistor", pplus_s_resistor()) - self.layout().register_pcell( - "nplus_u_resistor", nplus_u_resistor()) - self.layout().register_pcell( - "pplus_u_resistor", pplus_u_resistor()) - self.layout().register_pcell( - "nwell_resistor", nwell_resistor()) - self.layout().register_pcell( - "pwell_resistor", pwell_resistor()) - self.layout().register_pcell( - "npolyf_s_resistor", npolyf_s_resistor()) - self.layout().register_pcell( - "ppolyf_s_resistor", ppolyf_s_resistor()) - self.layout().register_pcell( - "npolyf_u_resistor", npolyf_u_resistor()) - self.layout().register_pcell( - "ppolyf_u_resistor", ppolyf_u_resistor()) - self.layout().register_pcell( - "ppolyf_u_high_Rs_resistor", ppolyf_u_high_Rs_resistor() - ) + # # RES + # self.layout().register_pcell( + # "metal_resistor", metal_resistor()) + # self.layout().register_pcell( + # "nplus_s_resistor", nplus_s_resistor()) + # self.layout().register_pcell( + # "pplus_s_resistor", pplus_s_resistor()) + # self.layout().register_pcell( + # "nplus_u_resistor", nplus_u_resistor()) + # self.layout().register_pcell( + # "pplus_u_resistor", pplus_u_resistor()) + # self.layout().register_pcell( + # "nwell_resistor", nwell_resistor()) + # self.layout().register_pcell( + # "pwell_resistor", pwell_resistor()) + # self.layout().register_pcell( + # "npolyf_s_resistor", npolyf_s_resistor()) + # self.layout().register_pcell( + # "ppolyf_s_resistor", ppolyf_s_resistor()) + # self.layout().register_pcell( + # "npolyf_u_resistor", npolyf_u_resistor()) + # self.layout().register_pcell( + # "ppolyf_u_resistor", ppolyf_u_resistor()) + # self.layout().register_pcell( + # "ppolyf_u_high_Rs_resistor", ppolyf_u_high_Rs_resistor() + # ) # eFuse # self.layout().register_pcell( diff --git a/cells/klayout/pymacros/cells/__pycache__/layers_def.cpython-310.pyc b/cells/klayout/pymacros/cells/__pycache__/layers_def.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8e6f8c4b3f08b4b0e48b743409f43fc4f9143386 GIT binary patch literal 458 zcmYk2y-ve06ou{dFa3jxff109kTSFZCWZUrWoqN73%lGQ>c!1!1U4F2uHbS4F_iv$)e z-kKxc&f1OdfbV9V#`nO-S-0_h@Ph?PhC6r%CAjWCQ!nho2$n>y(4x>KEjPMw zgxGFCageZ{cVx%G2l@8tS}T!Sv8K!PNwZ3cqIBshzqz|6^34&$gp?3Sy`(bNRl)5> zxT)dWsoX5xwCPl=A~`3 gf.Component: + + ''' + Retern nfet + + Args: + layout : layout object + l : Float of gate length + w : Float of gate width + sd_l : Float of source and drain diffusion length + inter_sd_l : Float of source and drain diffusion length between fingers + nf : integer of number of fingers + M : integer of number of multipliers + grw : gaurd ring width when enabled + type : string of the device type + bulk : String of bulk connection type (None, Bulk Tie, Guard Ring) + con_bet_fin : boolean of having contacts for diffusion between fingers + gate_con_pos : string of choosing the gate contact position (bottom, top, alternating ) + + ''' + # used layers and dimensions + + end_cap: float = 0.22 + if volt == "3.3V" : + comp_spacing : float = 0.28 + poly2_comp_spacing : float = 0.1 + else : + comp_spacing : float = 0.36 + poly2_comp_spacing : float = 0.3 + + + + gate_np_enc : float = 0.23 + comp_np_enc : float = 0.16 + comp_pp_enc : float = 0.16 + + +# gate_npc_ext = 0.11 +# npc_spacing = 0.27 + + +# gate_lvt_enc : float = 0.18 + + +# hv_enclosing : float = 0.185 + + +# areaid_lvn_enc : float = 0.1 + + + + con_size = 0.22 + con_sp = 0.28 + con_comp_enc = 0.07 + con_pl_enc = 0.07 + + + sd_l_con = ((sd_con_col)*con_size) + ((sd_con_col-1)*con_sp) + 2*con_comp_enc + sd_l = sd_l_con + + # gds components to store a single instance and the generated device + c = gf.Component("sky_nfet_dev") + + c_inst = gf.Component("dev_temp") + + # generating sd diffusion + + +# if interdig == 1 and nf >1 and nf != len(patt) and patt !="": +# nf = len(patt) + + l_d = nf*l + (nf-1)*inter_sd_l + 2*(con_comp_enc) # diffution total length + rect_d_intr = gf.components.rectangle(size = (l_d,w), layer= comp_layer) + sd_diff_intr = c_inst.add_ref(rect_d_intr) + +# # generatin sd contacts + + if (w <= con_size+ 2*con_comp_enc) : + cmpc_y = con_comp_enc + con_size + con_comp_enc + + else : + cmpc_y = w + + cmpc_size = (sd_l_con, cmpc_y) + + sd_diff = c_inst.add_array( + component= gf.components.rectangle(size=cmpc_size,layer=comp_layer), + rows=1, + columns=2, + spacing=(cmpc_size[0]+sd_diff_intr.size[0],0), + ) + + sd_diff.xmin = sd_diff_intr.xmin - cmpc_size[0] + sd_diff.ymin = sd_diff_intr.ymin - (sd_diff.size[1]-sd_diff_intr.size[1])/2 + +# sd_con = via_stack(x_range = (0,sd_l),y_range=(0,w),base_layer=diff_layer,metal_level=1) +# c_inst.add_array(component=sd_con,columns=2,rows=1,spacing=(sd_l+ nf*l + (nf-1)*inter_sd_l,0)) + + + +# if con_bet_fin == 1 and nf>1: +# inter_sd_con = via_stack(x_range = (sd_l + l,sd_l + l+ inter_sd_l),y_range=(0,w),base_layer=diff_layer,metal_level=1) +# c_inst.add_array(component=inter_sd_con,columns=nf-1,rows=1,spacing=(l+inter_sd_l,0)) + + + +# # generating poly + +# if (l <= licon_size[0]+ 2*licon_p_enc[0]) : +# pc_x = licon_p_enc[0] +licon_size[0] + licon_p_enc[0] + +# else : +# pc_x = l + +# pc_size = (pc_x, licon_p_enc[1] +licon_size[1] + licon_p_enc[1]) + +# c_pc = gf.Component("poly con") + +# rect_pc = c_pc.add_ref(gf.components.rectangle(size=pc_size,layer=poly_layer)) + + +# poly_con = via_stack(x_range=(rect_pc.xmin, rect_pc.xmax),y_range=(rect_pc.ymin, rect_pc.ymax),base_layer=poly_layer,metal_level=1,li_enc_dir="H") +# c_pc.add_ref(poly_con) + + if nf == 1 : + poly = c_inst.add_ref(gf.components.rectangle(size=(l,w+2*end_cap),layer=poly2_layer)) + poly.xmin = sd_diff_intr.xmin + con_comp_enc + poly.ymin = sd_diff_intr.ymin - end_cap + + # if gate_con_pos == "bottom": + # mv = 0 + # nr = 1 + # elif gate_con_pos == "top" : + # mv = pc_size[1]+ w + 2*end_cap + # nr = 1 + # else : + # mv = 0 + # nr = 2 + + # pc = c_inst.add_array(component=c_pc,rows=nr,columns=1, spacing=(0,pc_size[1]+w+2*end_cap)) + # pc.move((sd_l- ((pc_x - l)/2), -pc_size[1] - end_cap + mv)) + + + + + else : + + w_p1 = end_cap + w + end_cap # poly total width + + # if inter_sd_l < (npc_spacing + 2*gate_npc_ext) : + + # if gate_con_pos == "alternating": + # w_p1 += 0.2 + # w_p2 = w_p1 + # e_c = 0.2 + # else : + # w_p2 = w_p1 + licon_p_enc[1] +licon_size[1] + licon_p_enc[1] + npc_spacing + 0.1 + # e_c = 0 + + # if gate_con_pos == "bottom" : + # p_mv = -end_cap - (w_p2-w_p1) + # else : + # p_mv = -end_cap + + # else : + + w_p2 = w_p1 + p_mv = -end_cap + e_c = 0 + + rect_p1 = gf.components.rectangle(size = (l,w_p1), layer= poly2_layer) + rect_p2 = gf.components.rectangle(size = (l,w_p2), layer= poly2_layer) + poly1 = c_inst.add_array(rect_p1, rows= 1 , columns= ceil(nf/2) , spacing= [2*(inter_sd_l+l), 0 ]) + poly1.move((sd_l,-end_cap - e_c)) + + + poly2 = c_inst.add_array(rect_p2, rows= 1 , columns= floor(nf/2) , spacing= [2*(inter_sd_l+l), 0 ]) + poly2.move((sd_l+l+inter_sd_l,p_mv)) + + +# #generating poly contacts setups + +# if gate_con_pos == "bottom": +# mv_1 = 0 +# mv_2 = - (w_p2-w_p1) +# elif gate_con_pos == "top" : +# mv_1 = pc_size[1]+ w_p1 +# mv_2 = pc_size[1]+ w_p2 +# else : +# mv_1 = -e_c +# mv_2 = pc_size[1]+ w_p2 + + +# nc1 = ceil(nf/2) +# nc2 = floor(nf/2) + +# pc_spacing = 2*(inter_sd_l + l) + +# # generating poly contacts + +# pc1 = c_inst.add_array(component=c_pc,rows=1,columns=nc1,spacing=(pc_spacing,0)) +# pc1.move((sd_l- ((pc_x - l)/2), -pc_size[1] - end_cap + mv_1)) + +# pc2 = c_inst.add_array(component=c_pc,rows=1,columns=nc2,spacing=(pc_spacing,0)) +# pc2.move((sd_l- ((pc_x - l)/2) + (inter_sd_l + l), -pc_size[1] - end_cap + mv_2)) + + + +# if interdig == 1 : +# if nf == len(patt): +# pat = list(patt) +# nt = [] # list to store the symbols of transistors and thier number nt(number of transistors) +# [nt.append(x) for x in pat if x not in nt] +# nl = int(len(nt)) + +# m2_spacing = 0.14 +# via1_size = (0.15,0.15) +# via1_enc = (0.085,0.055) +# via1_spacing = (0.17,0.17) +# via2_size = (0.2,0.2) +# via2_enc = (0.085,0.065) +# via2_spacing = (0.2,0.2) + +# m2_y = via1_size[1]+2*via1_enc[1] +# m2 = gf.components.rectangle(size=(sd_diff.xmax - sd_diff.xmin, m2_y),layer=m2_layer) + +# if gate_con_pos == "alternating": +# pat_o = [] +# pat_e = [] + +# for i in range(int(nf)): +# if i%2 == 0 : +# pat_e.append(pat[i]) +# else : +# pat_o.append(pat[i]) + +# nt_o = [] +# [nt_o.append(x) for x in pat_o if x not in nt_o] + +# nt_e = [] +# [nt_e.append(x) for x in pat_e if x not in nt_e] + +# nl_b = len(nt_e) +# nl_u = len(nt_o) + +# m2_y = via2_size[1]+2*via2_enc[1] +# m2 = gf.components.rectangle(size=(sd_diff.xmax - sd_diff.xmin, m2_y),layer=m2_layer) + +# m2_arrb = c_inst.add_array(component=m2, columns=1, rows=nl_b,spacing= (0, -m2_y - m2_spacing)) +# m2_arrb.movey(pc1.ymin - m2_spacing - m2_y) + +# m2_arru = c_inst.add_array(component=m2, columns=1, rows=nl_u,spacing= (0, m2_y + m2_spacing)) +# m2_arru.movey(pc2.ymax + m2_spacing) + + +# for i in range(nl_u): +# for j in range(floor(nf/2)): +# if pat_o[j] == nt_o[i]: +# m1 = c_inst.add_ref(gf.components.rectangle( +# size=(poly_con.xmax - poly_con.xmin , ((pc2.ymax + (i+1)*(m2_spacing+ m2_y)) - pc2.ymin )),layer=m1_layer)) +# m1.move(((sd_l- ((poly_con.xmax - poly_con.xmin - l)/2) + (2*j +1)*(l+inter_sd_l)) +# , (pc2.ymin+0.06))) +# via1_dr = via_generator(x_range=(m1.xmin,m1.xmax),y_range=(m2_arru.ymin + i*(m2_y+m2_spacing),m2_arru.ymin + i*(m2_y+m2_spacing)+m2_y) +# , via_enclosure=via1_enc,via_layer=via1_layer,via_size=via1_size,via_spacing=via1_spacing) +# via1 = c_inst.add_ref(via1_dr) +# c_inst.add_label(f"{pat_o[j]}",position=((via1.xmax+via1.xmin)/2, (via1.ymax+via1.ymin)/2),layer=m1_lbl) + + + +# for i in range(nl_b): +# for j in range(ceil(nf/2)): +# if pat_e[j] == nt_e[i]: + +# m1 = c_inst.add_ref(gf.components.rectangle( +# size=(poly_con.xmax - poly_con.xmin , ((pc1.ymax + (i+1)*(m2_spacing+ m2_y)) -pc1.ymin )),layer=m1_layer)) +# m1.move(((sd_l- ((poly_con.xmax - poly_con.xmin - l)/2) + (2*j)*(l+inter_sd_l)), -(m1.ymax - m1.ymin) + (pc1.ymax-0.06))) +# via1_dr = via_generator(x_range=(m1.xmin,m1.xmax),y_range=(m2_arrb.ymax - i*(m2_spacing+m2_y) - m2_y,m2_arrb.ymax - i*(m2_spacing+m2_y)) +# , via_enclosure=via1_enc,via_layer=via1_layer,via_size=via1_size,via_spacing=via1_spacing) +# via1 = c_inst.add_ref(via1_dr) +# c_inst.add_label(f"{pat_e[j]}",position=((via1.xmax+via1.xmin)/2, (via1.ymax+via1.ymin)/2),layer=m1_lbl) + + + +# m3_x = via2_size[0] + 2*via2_enc[0] +# m3_spacing = 0.3 + +# for i in range(nl_b): +# for j in range(nl_u): +# if nt_e[i] == nt_o[j]: + +# m2_join_b = c_inst.add_ref(gf.components.rectangle(size=(m2_y+ (i+1)*(m3_spacing+m3_x),m2_y),layer=m2_layer) +# .move((m2_arrb.xmin -(m2_y + (i+1)*(m3_spacing+m3_x)),m2_arrb.ymax - i*(m2_spacing+m2_y) - m2_y))) +# m2_join_u = c_inst.add_ref(gf.components.rectangle(size=(m2_y+ (i+1)*(m3_spacing+m3_x),m2_y),layer=m2_layer) +# .move((m2_arru.xmin -( m2_y + (i+1)*(m3_spacing+m3_x) ),m2_arru.ymin + j*(m2_spacing+m2_y)))) +# m3 = c_inst.add_ref(gf.components.rectangle(size=(m3_x, m2_join_u.ymax - m2_join_b.ymin),layer=m1_layer)) +# m3.move((m2_join_b.xmin,m2_join_b.ymin)) +# via2_dr = via_generator(x_range=(m3.xmin,m3.xmax),y_range=(m2_join_b.ymin,m2_join_b.ymax),via_enclosure=via1_enc,via_size=via1_size +# ,via_layer=via1_layer,via_spacing=via1_spacing) +# via2 = c_inst.add_array(component=via2_dr,columns=1,rows=2,spacing=(0,m2_join_u.ymin-m2_join_b.ymin)) + + + +# elif gate_con_pos == "top" : + +# m2_arr = c_inst.add_array(component=m2, columns=1, rows=nl , spacing=(0,m2.ymax-m2.ymin + m2_spacing)) +# m2_arr.movey(pc2.ymax + m2_spacing) + +# for i in range(nl): +# for j in range(int(nf)): +# if pat[j] == nt[i]: +# m1 = c_inst.add_ref(gf.components.rectangle( +# size=(poly_con.xmax - poly_con.xmin , ((pc2.ymax + (i+1)*(m2_spacing+ m2_y)) - ((1-j%2)*pc1.ymin) - (j%2)*pc2.ymin )),layer=m1_layer)) +# m1.move(((sd_l- ((poly_con.xmax - poly_con.xmin - l)/2) + j*(l+inter_sd_l)) +# , (1-j%2)*(pc1.ymin+0.06) + (j%2)*(pc2.ymin+0.06))) +# via1_dr = via_generator(x_range=(m1.xmin,m1.xmax),y_range=(m2_arr.ymin + i*(m2_spacing+m2_y),m2_arr.ymin + i*(m2_spacing+m2_y)+m2_y) +# , via_enclosure=via1_enc,via_layer=via1_layer,via_size=via1_size,via_spacing=via1_spacing) +# via1 = c_inst.add_ref(via1_dr) +# c_inst.add_label(f"{pat[j]}",position=((via1.xmax+via1.xmin)/2, (via1.ymax+via1.ymin)/2),layer=m1_lbl) + + + +# elif gate_con_pos == "bottom" : + +# m2_arr = c_inst.add_array(component=m2, columns=1, rows=nl , spacing=(0,-m2_y - m2_spacing)) +# m2_arr.movey(pc2.ymin - m2_spacing - m2_y) + +# for i in range(nl): +# for j in range(int(nf)): +# if pat[j] == nt[i]: + +# m1 = c_inst.add_ref(gf.components.rectangle( +# size=(poly_con.xmax - poly_con.xmin , ((pc1.ymax + (i+1)*(m2_spacing+ m2_y)) - (j%2)*pc1.ymin - (1-j%2)*pc2.ymin)),layer=m1_layer)) +# m1.move(((sd_l- ((poly_con.xmax - poly_con.xmin - l)/2) + j*(l+inter_sd_l)), -(m1.ymax - m1.ymin) + (1-j%2)*(pc1.ymax-0.06)+ (j%2)*(pc2.ymax-0.06))) +# via1_dr = via_generator(x_range=(m1.xmin,m1.xmax),y_range=(m2_arr.ymax - i*(m2_spacing+m2_y) -m2_y,m2_arr.ymax - i*(m2_spacing+m2_y) ) +# , via_enclosure=via1_enc,via_layer=via1_layer,via_size=via1_size,via_spacing=via1_spacing) +# via1 = c_inst.add_ref(via1_dr) +# c_inst.add_label(f"{pat[j]}",position=((via1.xmax+via1.xmin)/2, (via1.ymax+via1.ymin)/2),layer=m1_lbl) + + + + + + + # generating bulk + if bulk == "None": + nplus = c_inst.add_ref(gf.components.rectangle(size=(sd_diff.size[0]+ 2*comp_np_enc, w+ 2*gate_np_enc),layer= nplus_layer)) + nplus.xmin = sd_diff.xmin - comp_np_enc + nplus.ymin = sd_diff_intr.ymin - gate_np_enc + + # if type=="sky130_fd_pr__nfet_g5v0d10v5" or type== "sky130_fd_pr__nfet_05v0_nvt" or type == "sky130_fd_pr__nfet_03v3_nvt": + # hvntm = c_inst.add_ref(gf.components.rectangle(size=(l_d+2*hv_enclosing,w+2*hv_enclosing),layer=hvntm_layer)) + # hvntm.move((sd_diff.xmin - hv_enclosing, sd_diff.ymin- hv_enclosing)) + + +# elif bulk == "bulk tie": +# rect_bulk = c_inst.add_ref(gf.components.rectangle(size=(sd_l*1.5,w),layer=tap_layer)) +# rect_bulk.connect("e1",destination=sd_diff.ports["e3"]) +# nsdm = c_inst.add_ref(gf.components.rectangle(size=(sd_diff.xmax - sd_diff.xmin +diff_nsdm_enc,w + 2*diff_nsdm_enc),layer=nsdm_layer)) +# nsdm.move((-diff_nsdm_enc,-diff_nsdm_enc)) +# psdm = c_inst.add_ref(gf.components.rectangle(size=(rect_bulk.xmax - rect_bulk.xmin +tap_psdm_enc, w+ 2*tap_psdm_enc), layer= psdm_layer)) +# psdm.connect("e1",destination = nsdm.ports["e3"]) + +# bulk_con = via_stack(x_range= (rect_bulk.xmin+0.1,rect_bulk.xmax-0.1),y_range=(rect_bulk.ymin,rect_bulk.ymax),base_layer=tap_layer,metal_level=0) +# c_inst.add_ref(bulk_con) + + +# if type=="sky130_fd_pr__nfet_g5v0d10v5" or type== "sky130_fd_pr__nfet_05v0_nvt" or type == "sky130_fd_pr__nfet_03v3_nvt": +# hvntm = c_inst.add_ref(gf.components.rectangle(size=(l_d+hv_enclosing,w+2*hv_enclosing),layer=hvntm_layer)) +# hvntm.move((sd_diff.xmin - hv_enclosing, sd_diff.ymin- hv_enclosing)) + + + + + +# elif bulk == "Gaurd Ring": + +# nsdm = c_inst.add_ref(gf.components.rectangle(size=(l_d+ 2*diff_nsdm_enc, w+ 2*diff_nsdm_enc),layer= nsdm_layer)) +# nsdm.move((-diff_nsdm_enc,-diff_nsdm_enc)) +# c.add_ref(c_inst) + +# c_temp = gf.Component("temp_store") +# rect_bulk_in = c_temp.add_ref(gf.components.rectangle(size=((c_inst.xmax - c_inst.xmin) + 2*diff_tap_spacing, +# (c_inst.ymax - c_inst.ymin) + 2*poly_tap_spacing ) +# , layer= tap_layer)) +# rect_bulk_in.move((c_inst.xmin -diff_tap_spacing,c_inst.ymin - poly_tap_spacing)) +# rect_bulk_out = c_temp.add_ref(gf.components.rectangle(size=((rect_bulk_in.xmax - rect_bulk_in.xmin) + 2*grw,(rect_bulk_in.ymax - rect_bulk_in.ymin) + 2*grw ) +# , layer= tap_layer)) +# rect_bulk_out.move((rect_bulk_in.xmin - grw , rect_bulk_in.ymin -grw )) +# B = c.add_ref(gf.geometry.boolean(A= rect_bulk_out , B = rect_bulk_in , operation= "A-B", layer= tap_layer) ) + +# psdm_in = c_temp.add_ref(gf.components.rectangle(size=((rect_bulk_in.xmax - rect_bulk_in.xmin) - 2*tap_psdm_enc, (rect_bulk_in.ymax - rect_bulk_in.ymin) - 2*tap_psdm_enc ) +# , layer= psdm_layer)) +# psdm_in.move((rect_bulk_in.xmin + tap_psdm_enc, rect_bulk_in.ymin + tap_psdm_enc)) +# psdm_out = c_temp.add_ref(gf.components.rectangle(size=((rect_bulk_out.xmax - rect_bulk_out.xmin) + 2*tap_psdm_enc, (rect_bulk_out.ymax - rect_bulk_out.ymin) + 2*tap_psdm_enc ) +# , layer= nsdm_layer)) +# psdm_out.move((rect_bulk_out.xmin - tap_psdm_enc, rect_bulk_out.ymin - tap_psdm_enc)) +# psdm = c.add_ref(gf.geometry.boolean(A= psdm_out , B = psdm_in , operation= "A-B", layer= psdm_layer) ) + + + +# # generating contacts + + +# ring_con_bot = c.add_ref(via_generator(x_range=(rect_bulk_in.xmin + 0.17,rect_bulk_in.xmax-0.17),y_range=(rect_bulk_out.ymin,rect_bulk_in.ymin) +# , via_enclosure=licon_dt_enc, via_layer=licon_layer,via_size=licon_size,via_spacing=licon_spacing)) + +# ring_con_up = c.add_ref(via_generator(x_range=(rect_bulk_in.xmin+0.17,rect_bulk_in.xmax-0.17),y_range=(rect_bulk_in.ymax,rect_bulk_out.ymax) +# , via_enclosure=licon_dt_enc, via_layer=licon_layer,via_size=licon_size,via_spacing=licon_spacing)) + +# ring_con_r = c.add_ref(via_generator(x_range=(rect_bulk_out.xmin,rect_bulk_in.xmin),y_range=(rect_bulk_in.ymin+0.17,rect_bulk_in.ymax-0.17) +# , via_enclosure=licon_dt_enc, via_layer=licon_layer,via_size=licon_size,via_spacing=licon_spacing)) + +# ring_con_l = c.add_ref(via_generator(x_range=(rect_bulk_in.xmax,rect_bulk_out.xmax),y_range=(rect_bulk_in.ymin+0.17,rect_bulk_in.ymax-0.17) +# , via_enclosure=licon_dt_enc, via_layer=licon_layer,via_size=licon_size,via_spacing=licon_spacing)) + +# tap_li_in = c_temp.add_ref(gf.components.rectangle(size=((l_d ) + 2*diff_tap_spacing, +# (c_inst.ymax - c_inst.ymin) + 2*poly_tap_spacing ) +# , layer= li_layer)) +# tap_li_in.move((-diff_tap_spacing,c_inst.ymin - poly_tap_spacing)) +# tap_li_out = c_temp.add_ref(gf.components.rectangle(size=((rect_bulk_in.xmax - rect_bulk_in.xmin) + 2*grw,(rect_bulk_in.ymax - rect_bulk_in.ymin) + 2*grw ) +# , layer= li_layer)) +# tap_li_out.move((rect_bulk_in.xmin - grw , rect_bulk_in.ymin -grw )) +# li = c.add_ref(gf.geometry.boolean(A= rect_bulk_out , B = rect_bulk_in , operation= "A-B", layer= li_layer) ) + + + +# # generating hvi for high voltage +# if type=="sky130_fd_pr__nfet_g5v0d10v5" or type== "sky130_fd_pr__nfet_05v0_nvt" or type == "sky130_fd_pr__nfet_03v3_nvt": +# hvi = c.add_ref(gf.components.rectangle(size=(rect_bulk_out.xmax-rect_bulk_out.xmin + 2*hv_enclosing +# , rect_bulk_out.ymax - rect_bulk_out.ymin + 2*hv_enclosing),layer=hvi_layer)) +# hvi.move((rect_bulk_out.xmin-hv_enclosing, rect_bulk_out.ymin-hv_enclosing)) -tol = 1.05 - - -def draw_nfet(layout, l, w, ld, nf, grw, bulk, volt, deepnwell, pcmpgr): - """ - Usage:- - used to draw NFET transistor by specifying parameters - Arguments:- - layout : Object of layout - l : Float of gate length - w : Float of gate width - ld : Float of diffusion length - nf : Integer of number of fingers - grw : Float of guard ring width [If enabled] - bulk : String of bulk connection type [None, Bulk Tie, Guard Ring] - volt : String of operating voltage of the FET [3.3V, 5V, 6V] - deepnwell : Boolean of using Deep NWELL device - pcmpgr : Boolean of using P+ Guard Ring for Deep NWELL devices only - """ - - # Define layers - dnwell = layout.layer(12, 0) - lvpwell = layout.layer(204, 0) - dualgate = layout.layer(55, 0) - v5_xtor = layout.layer(112, 1) - comp = layout.layer(22, 0) - poly2 = layout.layer(30, 0) - nplus = layout.layer(32, 0) - pplus = layout.layer(31, 0) - contact = layout.layer(33, 0) - metal1 = layout.layer(34, 0) - - # Define variables - dbu_PERCISION = 1 / layout.dbu - nf = int(nf) - grw = grw * dbu_PERCISION - ld = ld * dbu_PERCISION - l = l * dbu_PERCISION - w = w * dbu_PERCISION - cmp2cont = 0.07 * dbu_PERCISION - cont_size = 0.22 * dbu_PERCISION - np_enc_cmp = 0.16 * dbu_PERCISION - pp_enc_cmp = 0.16 * dbu_PERCISION - cont2ply = 0.15 * dbu_PERCISION - ply_ext_cmp = 0.22 * dbu_PERCISION - np_enc_gate = 0.23 * dbu_PERCISION - cont2cont = 0.28 * dbu_PERCISION - dg_enc_ply = 0.4 * dbu_PERCISION - dg_enc_cmp = 0.24 * dbu_PERCISION - cmp2cmp = 0.32 * dbu_PERCISION - ply2gr = 0.26 * dbu_PERCISION - ld_violat = 0 * dbu_PERCISION - tie_violat = 0 * dbu_PERCISION - metal_violat = 0.01 * dbu_PERCISION - min_cmp_area = 0.2025 * dbu_PERCISION * dbu_PERCISION - dg_enc_dnwell = 0.5 * dbu_PERCISION - lvpwell_enc_ncmp = 0.43 * dbu_PERCISION - lvpwell_enc_pcmp = 0.12 * dbu_PERCISION - dnwell_enc_lvpwell = 2.5 * dbu_PERCISION - pcmp_gr2dnw = 2.5 * dbu_PERCISION - gr_w = 0.36 * dbu_PERCISION - - if deepnwell == True: - cmp2cmp = 0.36 * dbu_PERCISION - ply2gr = 0.3 * dbu_PERCISION - - if volt == "5V" or volt == "6V": - lvpwell_enc_ncmp = 0.6 * dbu_PERCISION - lvpwell_enc_pcmp = 0.16 * dbu_PERCISION - cmp2cmp = 0.36 * dbu_PERCISION - ply2gr = 0.3 * dbu_PERCISION - cmp2cmp = 0.36 * dbu_PERCISION - - if w < cont_size + 2 * cmp2cont: - if nf == 1: - if volt == "5V" or volt == "6V": - ld_violat = 0.22 * dbu_PERCISION - else: - ld_violat = 0.02 * dbu_PERCISION - - # Inserting NFET cell - cell_index = layout.add_cell("nfet") - cell = layout.cell(cell_index) - - w_changed = False - - # Inserting diffusion - if w < cont_size + 2 * cmp2cont: - cell.shapes(comp).insert( - pya.Box( - 0, - (cont_size + 2 * cmp2cont - w) / 2, - ( - 2 * (ld + ld_violat) - + l - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + (cont_size + 2 * cmp2cont - w) / 2, - ) - ) - w = cont_size + 2 * cmp2cont - w_changed = True - else: - cell.shapes(comp).insert( - pya.Box(0, 0, (2 * ld + l + (nf - 1) * (ld + l + cont2ply - cmp2cont)), w) - ) - - cell.shapes(nplus).insert( - pya.Box( - -np_enc_cmp, - -np_enc_gate, - ( - 2 * (ld + ld_violat) - + l - + np_enc_cmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + np_enc_gate, - ) - ) - - # Inserting gate/s - # Inserting a gate cell - gate_cell_index = layout.add_cell("gate") - gate_cell = layout.cell(gate_cell_index) - gate_cell.shapes(poly2).insert( - pya.Box(ld + ld_violat, -ply_ext_cmp, (ld + ld_violat + l), (w + ply_ext_cmp)) - ) - - # adding gate array - cell.insert( - pya.CellInstArray.new( - gate_cell_index, - pya.Trans.new(pya.Point.new(0, 0)), - pya.Point.new(ld + ld_violat + l + cont2ply - cmp2cont, 0), - pya.Point.new(0, 0), - int(nf), - 1, - ) - ) - - # Inserting a contact cell - cont_cell_index = layout.add_cell("contact") - cont_cell = layout.cell(cont_cell_index) - - # Inserting shapes now into the *contact* cell - cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) - - # Contact array count and postions - nx = int((ld - (cont_size + cmp2cont + cont2ply)) / (cont2cont + cont_size)) + 1 - ny = int((w - (cont_size + 2 * cmp2cont)) / (cont2cont + cont_size)) + 1 - dx = (ld - nx * cont_size - (nx - 1) * cont2cont) * cmp2cont / cont_size - dy = (w - ny * cont_size - (ny - 1) * cont2cont) / 2 - - # adding contact array and metals - # Left contacts - if not (w_changed == True and nf > 1) and (ld >= 440): - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new(pya.Point.new(dx, dy)), - pya.Point.new((cont2cont + cont_size), 0), - pya.Point.new(0, (cont2cont + cont_size)), - nx, - ny, - ) - ) - # Left metal - cell.shapes(metal1).insert( - pya.Box( - -metal_violat, - -metal_violat, - ld + metal_violat - (cont_size - 2 * cmp2cont), - w + metal_violat, - ) - ) - - # Adding diffusion to avoid contact violation - if nf == 1 and w_changed == True: - cell.shapes(comp).insert(pya.Box(0, 0, ld - (cont_size - 2 * cmp2cont), w)) - - # Right contacts and metals for each finger - for i in range(nf): - # Contacts - if not (w_changed == True and nf > 1) and (ld >= 440): - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - ( - (l + ld + ld_violat + cont2ply - cmp2cont) * i - + 2 * (ld + ld_violat) - + l - - cont_size - - dx - ), - dy, - ) - ), - pya.Point.new(-(cont2cont + cont_size), 0), - pya.Point.new(0, (cont2cont + cont_size)), - nx, - ny, - ) - ) - # Metals - cell.shapes(metal1).insert( - pya.Box( - (ld + 2 * ld_violat + l + cont2ply - cmp2cont) * (i + 1) - - metal_violat, - -metal_violat, - ld - + metal_violat - + ld_violat - + (ld + ld_violat + l + cont2ply - cmp2cont) * (i + 1) - - (cont_size - 2 * cmp2cont), - w + metal_violat, - ) - ) - - # Adding diffusion to avoid contact violation - if nf == 1 and w_changed == True: - cell.shapes(comp).insert( - pya.Box( - (ld + 2 * ld_violat + l + cont2ply - cmp2cont) * (i + 1), - 0, - ld - + ld_violat - + (ld + ld_violat + l + cont2ply - cmp2cont) * (i + 1) - - (cont_size - 2 * cmp2cont), - w, - ) - ) - region = pya.Region.new(cell.begin_shapes_rec(comp)) - region.merge() - cell.clear(comp) - cell.shapes(comp).insert(region) - - if bulk == "Bulk Tie": - if deepnwell == True: - if volt == "5V": - # Inserting 5V layers - cell.shapes(v5_xtor).insert( - pya.Box( - -dg_enc_dnwell - - dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - cmp2cmp - - ld, - -dg_enc_dnwell - dnwell_enc_lvpwell - lvpwell_enc_ncmp, - ( - 2 * (ld + ld_violat) - + l - + dg_enc_dnwell - + dnwell_enc_lvpwell - + lvpwell_enc_ncmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + dg_enc_dnwell, - ) - ) - - cell.shapes(dualgate).insert( - pya.Box( - -dg_enc_dnwell - - dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - cmp2cmp - - ld, - -dg_enc_dnwell - dnwell_enc_lvpwell - lvpwell_enc_ncmp, - ( - 2 * (ld + ld_violat) - + l - + dg_enc_dnwell - + dnwell_enc_lvpwell - + lvpwell_enc_ncmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + dg_enc_dnwell, - ) - ) - - elif volt == "6V": - # Inserting 6V layers - cell.shapes(dualgate).insert( - pya.Box( - -dg_enc_dnwell - - dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - cmp2cmp - - ld, - -dg_enc_dnwell - dnwell_enc_lvpwell - lvpwell_enc_ncmp, - ( - 2 * (ld + ld_violat) - + l - + dg_enc_dnwell - + dnwell_enc_lvpwell - + lvpwell_enc_ncmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + dg_enc_dnwell, - ) - ) - - # Inserting LVPWELL - cell.shapes(lvpwell).insert( - pya.Box( - -lvpwell_enc_pcmp - cmp2cmp - ld, - -lvpwell_enc_ncmp, - ( - 2 * (ld + ld_violat) - + l - + lvpwell_enc_ncmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + lvpwell_enc_ncmp, - ) - ) - - # Inserting DNWELL - cell.shapes(dnwell).insert( - pya.Box( - -dnwell_enc_lvpwell - lvpwell_enc_pcmp - cmp2cmp - ld, - -dnwell_enc_lvpwell - lvpwell_enc_ncmp, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_lvpwell - + lvpwell_enc_ncmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + lvpwell_enc_ncmp + dnwell_enc_lvpwell, - ) - ) - - # Inserting Double Guard Ring - if pcmpgr == True: - cmp_inner = pya.Box( - -dnwell_enc_lvpwell - lvpwell_enc_pcmp - cmp2cmp - ld - pcmp_gr2dnw, - -dnwell_enc_lvpwell - lvpwell_enc_ncmp - pcmp_gr2dnw, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_lvpwell - + lvpwell_enc_ncmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ) - + pcmp_gr2dnw, - w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + pcmp_gr2dnw, - ) - cmp_outer = pya.Box( - -dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - cmp2cmp - - ld - - pcmp_gr2dnw - - gr_w, - -dnwell_enc_lvpwell - lvpwell_enc_ncmp - pcmp_gr2dnw - gr_w, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_lvpwell - + lvpwell_enc_ncmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ) - + pcmp_gr2dnw - + gr_w, - w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + pcmp_gr2dnw + gr_w, - ) - cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) - cell.shapes(comp).insert(cmp_gr) - - pp_inner = pya.Box( - -dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - cmp2cmp - - ld - - pcmp_gr2dnw - + pp_enc_cmp, - -dnwell_enc_lvpwell - lvpwell_enc_ncmp - pcmp_gr2dnw + pp_enc_cmp, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_lvpwell - + lvpwell_enc_ncmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ) - + pcmp_gr2dnw - - pp_enc_cmp, - w - + lvpwell_enc_ncmp - + dnwell_enc_lvpwell - + pcmp_gr2dnw - - pp_enc_cmp, - ) - pp_outer = pya.Box( - -dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - cmp2cmp - - ld - - pcmp_gr2dnw - - gr_w - - pp_enc_cmp, - -dnwell_enc_lvpwell - - lvpwell_enc_ncmp - - pcmp_gr2dnw - - gr_w - - pp_enc_cmp, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_lvpwell - + lvpwell_enc_ncmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ) - + pcmp_gr2dnw - + gr_w - + pp_enc_cmp, - w - + lvpwell_enc_ncmp - + dnwell_enc_lvpwell - + pcmp_gr2dnw - + gr_w - + pp_enc_cmp, - ) - pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) - cell.shapes(pplus).insert(pp_gr) - - else: - if volt == "5V": - # Inserting 5V layers - cell.shapes(v5_xtor).insert( - pya.Box( - -(cmp2cmp + dg_enc_cmp) - ld, - -(dg_enc_ply + ply_ext_cmp), - ( - 2 * (ld + ld_violat) - + l - + dg_enc_cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - w + (dg_enc_ply + ply_ext_cmp), - ) - ) - cell.shapes(dualgate).insert( - pya.Box( - -(cmp2cmp + dg_enc_cmp) - ld, - -(dg_enc_ply + ply_ext_cmp), - ( - 2 * (ld + ld_violat) - + l - + dg_enc_cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - w + (dg_enc_ply + ply_ext_cmp), - ) - ) - elif volt == "6V": - # Inserting 6V layers - cell.shapes(dualgate).insert( - pya.Box( - -(cmp2cmp + dg_enc_cmp) - ld, - -(dg_enc_ply + ply_ext_cmp), - ( - 2 * (ld + ld_violat) - + l - + dg_enc_cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - w + (dg_enc_ply + ply_ext_cmp), - ) - ) - - # Inserting Tie - if (w * ld) < min_cmp_area: - tie_violat = (min_cmp_area * tol / ld - w) / 2 - cell.shapes(comp).insert( - pya.Box(-cmp2cmp - ld, -tie_violat, -cmp2cmp, w + tie_violat) - ) - cell.shapes(pplus).insert( - pya.Box( - -cmp2cmp - pp_enc_cmp - ld, - -pp_enc_cmp - tie_violat, - -cmp2cmp + pp_enc_cmp, - w + tie_violat + pp_enc_cmp, - ) - ) - - # Tie contacts - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - (-(cmp2cmp + cont_size) - dx * cont_size / (2 * cmp2cont)), dy - ) - ), - pya.Point.new(-(cont2cont + cont_size), 0), - pya.Point.new(0, (cont2cont + cont_size)), - nx, - ny, - ) - ) - - # Tie metal - cell.shapes(metal1).insert( - pya.Box(-cmp2cmp - ld, -tie_violat, -cmp2cmp, w + tie_violat) - ) - - elif bulk == "Guard Ring": - if deepnwell == True: - if volt == "5V": - # Inserting 5V layers - cell.shapes(v5_xtor).insert( - pya.Box( - -dg_enc_dnwell - - dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - cmp2cmp - - grw, - -dg_enc_dnwell - - dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - (ply_ext_cmp + ply2gr) - - grw, - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + lvpwell_enc_pcmp - + dnwell_enc_lvpwell - + dg_enc_dnwell - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - ( - w - + (ply_ext_cmp + ply2gr) - + grw - + lvpwell_enc_pcmp - + dnwell_enc_lvpwell - + dg_enc_dnwell - ), - ) - ) - - cell.shapes(dualgate).insert( - pya.Box( - -dg_enc_dnwell - - dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - cmp2cmp - - grw, - -dg_enc_dnwell - - dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - (ply_ext_cmp + ply2gr) - - grw, - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + lvpwell_enc_pcmp - + dnwell_enc_lvpwell - + dg_enc_dnwell - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - ( - w - + (ply_ext_cmp + ply2gr) - + grw - + lvpwell_enc_pcmp - + dnwell_enc_lvpwell - + dg_enc_dnwell - ), - ) - ) - - elif volt == "6V": - # Inserting 6V layers - cell.shapes(dualgate).insert( - pya.Box( - -dg_enc_dnwell - - dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - cmp2cmp - - grw, - -dg_enc_dnwell - - dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - (ply_ext_cmp + ply2gr) - - grw, - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + lvpwell_enc_pcmp - + dnwell_enc_lvpwell - + dg_enc_dnwell - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - ( - w - + (ply_ext_cmp + ply2gr) - + grw - + lvpwell_enc_pcmp - + dnwell_enc_lvpwell - + dg_enc_dnwell - ), - ) - ) - - # Inserting LVPWELL - cell.shapes(lvpwell).insert( - pya.Box( - -lvpwell_enc_pcmp - cmp2cmp - grw, - -lvpwell_enc_pcmp - (ply_ext_cmp + ply2gr) - grw, - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + lvpwell_enc_pcmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + (ply_ext_cmp + ply2gr) + grw + lvpwell_enc_pcmp), - ) - ) - - # Inserting DNWELL - cell.shapes(dnwell).insert( - pya.Box( - -dnwell_enc_lvpwell - lvpwell_enc_pcmp - cmp2cmp - grw, - -dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - (ply_ext_cmp + ply2gr) - - grw, - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + lvpwell_enc_pcmp - + dnwell_enc_lvpwell - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - ( - w - + (ply_ext_cmp + ply2gr) - + grw - + lvpwell_enc_pcmp - + dnwell_enc_lvpwell - ), - ) - ) - - # Inserting Double Guard Ring - if pcmpgr == True: - cmp_inner = pya.Box( - -dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - cmp2cmp - - grw - - pcmp_gr2dnw, - -dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - (ply_ext_cmp + ply2gr) - - grw - - pcmp_gr2dnw, - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + lvpwell_enc_pcmp - + dnwell_enc_lvpwell - + pcmp_gr2dnw - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - ( - w - + (ply_ext_cmp + ply2gr) - + grw - + pcmp_gr2dnw - + lvpwell_enc_pcmp - + dnwell_enc_lvpwell - ), - ) - cmp_outer = pya.Box( - -dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - cmp2cmp - - grw - - pcmp_gr2dnw - - gr_w, - -dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - (ply_ext_cmp + ply2gr) - - grw - - pcmp_gr2dnw - - gr_w, - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + lvpwell_enc_pcmp - + dnwell_enc_lvpwell - + pcmp_gr2dnw - + gr_w - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - ( - w - + (ply_ext_cmp + ply2gr) - + grw - + pcmp_gr2dnw - + gr_w - + lvpwell_enc_pcmp - + dnwell_enc_lvpwell - ), - ) - cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) - cell.shapes(comp).insert(cmp_gr) - - pp_inner = pya.Box( - -dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - cmp2cmp - - grw - - pcmp_gr2dnw - + pp_enc_cmp, - -dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - (ply_ext_cmp + ply2gr) - - grw - - pcmp_gr2dnw - + pp_enc_cmp, - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + lvpwell_enc_pcmp - + dnwell_enc_lvpwell - + pcmp_gr2dnw - - pp_enc_cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - ( - w - + (ply_ext_cmp + ply2gr) - + grw - + pcmp_gr2dnw - + lvpwell_enc_pcmp - + dnwell_enc_lvpwell - - pp_enc_cmp - ), - ) - pp_outer = pya.Box( - -dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - cmp2cmp - - grw - - pcmp_gr2dnw - - gr_w - - pp_enc_cmp, - -dnwell_enc_lvpwell - - lvpwell_enc_pcmp - - (ply_ext_cmp + ply2gr) - - grw - - pcmp_gr2dnw - - gr_w - - pp_enc_cmp, - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + lvpwell_enc_pcmp - + dnwell_enc_lvpwell - + pcmp_gr2dnw - + gr_w - + pp_enc_cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - ( - w - + (ply_ext_cmp + ply2gr) - + grw - + pcmp_gr2dnw - + gr_w - + pp_enc_cmp - + lvpwell_enc_pcmp - + dnwell_enc_lvpwell - ), - ) - pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) - cell.shapes(pplus).insert(pp_gr) - - else: - if volt == "5V": - # Inserting 5V layers - cell.shapes(v5_xtor).insert( - pya.Box( - -(cmp2cmp + dg_enc_cmp) - grw, - -(ply_ext_cmp + ply2gr + dg_enc_cmp) - grw, - ( - 2 * (ld + ld_violat) - + l - + grw - + (cmp2cmp + dg_enc_cmp) - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + ply_ext_cmp + ply2gr + dg_enc_cmp + grw), - ) - ) - cell.shapes(dualgate).insert( - pya.Box( - -(cmp2cmp + dg_enc_cmp) - grw, - -(ply_ext_cmp + ply2gr + dg_enc_cmp) - grw, - ( - 2 * (ld + ld_violat) - + l - + grw - + (cmp2cmp + dg_enc_cmp) - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + ply_ext_cmp + ply2gr + dg_enc_cmp + grw), - ) - ) - elif volt == "6V": - # Inserting 6V layers - cell.shapes(dualgate).insert( - pya.Box( - -(cmp2cmp + dg_enc_cmp) - grw, - -(ply_ext_cmp + ply2gr + dg_enc_cmp) - grw, - ( - 2 * (ld + ld_violat) - + l - + grw - + (cmp2cmp + dg_enc_cmp) - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + ply_ext_cmp + ply2gr + dg_enc_cmp + grw), - ) - ) - - # Inserting guard ring diffusion - cell.shapes(comp).insert( - pya.Polygon( - [ - pya.Point(-cmp2cmp - grw, -(ply_ext_cmp + ply2gr) - grw), - pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), - pya.Point(-cmp2cmp, (w + (ply_ext_cmp + ply2gr))), - pya.Point(-cmp2cmp, -(ply_ext_cmp + ply2gr)), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + cmp2cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - -(ply_ext_cmp + ply2gr), - ), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + cmp2cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + (ply_ext_cmp + ply2gr)), - ), - pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), - pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr) + grw)), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + (ply_ext_cmp + ply2gr) + grw), - ), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - -(ply_ext_cmp + ply2gr) - grw, - ), - ], - True, - ) - ) - cell.shapes(pplus).insert( - pya.Polygon( - [ - pya.Point( - -(cmp2cmp + pp_enc_cmp) - grw, - -(ply_ext_cmp + ply2gr + pp_enc_cmp) - grw, - ), - pya.Point( - -(cmp2cmp + pp_enc_cmp) - grw, - (w + (ply_ext_cmp + ply2gr - pp_enc_cmp)), - ), - pya.Point( - -(cmp2cmp - pp_enc_cmp), - (w + (ply_ext_cmp + ply2gr - pp_enc_cmp)), - ), - pya.Point( - -(cmp2cmp - pp_enc_cmp), -(ply_ext_cmp + ply2gr - pp_enc_cmp) - ), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + (cmp2cmp - pp_enc_cmp) - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - -(ply_ext_cmp + ply2gr - pp_enc_cmp), - ), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + (cmp2cmp - pp_enc_cmp) - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + (ply_ext_cmp + ply2gr - pp_enc_cmp)), - ), - pya.Point( - -(cmp2cmp + pp_enc_cmp) - grw, - (w + (ply_ext_cmp + ply2gr - pp_enc_cmp)), - ), - pya.Point( - -(cmp2cmp + pp_enc_cmp) - grw, - (w + (ply_ext_cmp + ply2gr + pp_enc_cmp) + grw), - ), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + grw - + (cmp2cmp + pp_enc_cmp) - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + (ply_ext_cmp + ply2gr + pp_enc_cmp) + grw), - ), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + grw - + (cmp2cmp + pp_enc_cmp) - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - -(ply_ext_cmp + ply2gr + pp_enc_cmp) - grw, - ), - ], - True, - ) - ) - - # Inserting Guard Ring metal - cell.shapes(metal1).insert( - pya.Polygon( - [ - pya.Point(-cmp2cmp - grw, -(ply_ext_cmp + ply2gr) - grw), - pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), - pya.Point(-cmp2cmp, (w + (ply_ext_cmp + ply2gr))), - pya.Point(-cmp2cmp, -(ply_ext_cmp + ply2gr)), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + cmp2cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - -(ply_ext_cmp + ply2gr), - ), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + cmp2cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + (ply_ext_cmp + ply2gr)), - ), - pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), - pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr) + grw)), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + (ply_ext_cmp + ply2gr) + grw), - ), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - -(ply_ext_cmp + ply2gr) - grw, - ), - ], - True, - ) - ) - - nxgr = int((grw - (cont_size + 2 * cmp2cont)) / (cont2cont + cont_size)) + 1 - nygr = ( - int( - ( - (2 * grw + w + 2 * (ply_ext_cmp + ply2gr)) - - (cont_size + 2 * cmp2cont) - ) - / (cont2cont + cont_size) - ) - + 1 - ) - dxgr = (grw - nxgr * cont_size - (nxgr - 1) * cont2cont) / 2 - dygr = ( - (2 * grw + w + 2 * (ply_ext_cmp + ply2gr)) - - nygr * cont_size - - (nygr - 1) * cont2cont - ) / 2 - nxgr_h = ( - int( - ( - ( - 2 * (ld + ld_violat) - + l - + 2 * cmp2cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ) - - 3 * cont2cont - ) - / (cont2cont + cont_size) - ) - + 1 - ) - dxgr_h = ( - ( - 2 * (ld + ld_violat) - + l - + cont2cont - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ) - - nxgr_h * cont_size - - (nxgr_h - 1) * cont2cont - ) / 2 - - # Inserting Guard Ring contacts - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - (-cmp2cmp - grw + dxgr), (-(ply_ext_cmp + ply2gr) - grw + dygr) - ) - ), - pya.Point.new((cont2cont + cont_size), 0), - pya.Point.new(0, (cont2cont + cont_size)), - nxgr, - nygr, - ) - ) - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - -(2 * cmp2cont) + dxgr_h, -(2 * cont_size) - ply2gr - dxgr - ) - ), - pya.Point.new((cont2cont + cont_size), 0), - pya.Point.new(0, -(cont2cont + cont_size)), - nxgr_h, - nxgr, - ) - ) - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - 2 * (ld + ld_violat) - + l - + grw - - dxgr - + (cmp2cmp - cont_size) - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont), - (-(ply_ext_cmp + ply2gr) - grw + dygr), - ) - ), - pya.Point.new(-(cont2cont + cont_size), 0), - pya.Point.new(0, (cont2cont + cont_size)), - nxgr, - nygr, - ) - ) - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - (-(2 * cmp2cont) + dxgr_h), (w + (ply_ext_cmp + ply2gr) + dxgr) - ) - ), - pya.Point.new((cont2cont + cont_size), 0), - pya.Point.new(0, (cont2cont + cont_size)), - nxgr_h, - nxgr, - ) - ) - - else: - if deepnwell == True: - if volt == "5V": - # Inserting 5V layers - cell.shapes(v5_xtor).insert( - pya.Box( - -dg_enc_dnwell - dnwell_enc_lvpwell - lvpwell_enc_ncmp, - -dg_enc_dnwell - dnwell_enc_lvpwell - lvpwell_enc_ncmp, - ( - 2 * (ld + ld_violat) - + l - + dg_enc_dnwell - + dnwell_enc_lvpwell - + lvpwell_enc_ncmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + dg_enc_dnwell, - ) - ) - - cell.shapes(dualgate).insert( - pya.Box( - -dg_enc_dnwell - dnwell_enc_lvpwell - lvpwell_enc_ncmp, - -dg_enc_dnwell - dnwell_enc_lvpwell - lvpwell_enc_ncmp, - ( - 2 * (ld + ld_violat) - + l - + dg_enc_dnwell - + dnwell_enc_lvpwell - + lvpwell_enc_ncmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + dg_enc_dnwell, - ) - ) - - elif volt == "6V": - # Inserting 6V layers - cell.shapes(dualgate).insert( - pya.Box( - -dg_enc_dnwell - dnwell_enc_lvpwell - lvpwell_enc_ncmp, - -dg_enc_dnwell - dnwell_enc_lvpwell - lvpwell_enc_ncmp, - ( - 2 * (ld + ld_violat) - + l - + dg_enc_dnwell - + dnwell_enc_lvpwell - + lvpwell_enc_ncmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + dg_enc_dnwell, - ) - ) - - # Inserting LVPWELL - cell.shapes(lvpwell).insert( - pya.Box( - -lvpwell_enc_ncmp, - -lvpwell_enc_ncmp, - ( - 2 * (ld + ld_violat) - + l - + lvpwell_enc_ncmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + lvpwell_enc_ncmp, - ) - ) - - # Inserting DNWELL - cell.shapes(dnwell).insert( - pya.Box( - -dnwell_enc_lvpwell - lvpwell_enc_ncmp, - -dnwell_enc_lvpwell - lvpwell_enc_ncmp, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_lvpwell - + lvpwell_enc_ncmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + lvpwell_enc_ncmp + dnwell_enc_lvpwell, - ) - ) - - # Inserting Double Guard Ring - if pcmpgr == True: - cmp_inner = pya.Box( - -dnwell_enc_lvpwell - lvpwell_enc_ncmp - pcmp_gr2dnw, - -dnwell_enc_lvpwell - lvpwell_enc_ncmp - pcmp_gr2dnw, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_lvpwell - + lvpwell_enc_ncmp - + pcmp_gr2dnw - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + pcmp_gr2dnw, - ) - cmp_outer = pya.Box( - -dnwell_enc_lvpwell - lvpwell_enc_ncmp - pcmp_gr2dnw - gr_w, - -dnwell_enc_lvpwell - lvpwell_enc_ncmp - pcmp_gr2dnw - gr_w, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_lvpwell - + lvpwell_enc_ncmp - + pcmp_gr2dnw - + gr_w - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + pcmp_gr2dnw + gr_w, - ) - cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) - cell.shapes(comp).insert(cmp_gr) - - pp_inner = pya.Box( - -dnwell_enc_lvpwell - lvpwell_enc_ncmp - pcmp_gr2dnw + pp_enc_cmp, - -dnwell_enc_lvpwell - lvpwell_enc_ncmp - pcmp_gr2dnw + pp_enc_cmp, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_lvpwell - + lvpwell_enc_ncmp - + pcmp_gr2dnw - - pp_enc_cmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w - + lvpwell_enc_ncmp - + dnwell_enc_lvpwell - + pcmp_gr2dnw - - pp_enc_cmp, - ) - pp_outer = pya.Box( - -dnwell_enc_lvpwell - - lvpwell_enc_ncmp - - pcmp_gr2dnw - - gr_w - - pp_enc_cmp, - -dnwell_enc_lvpwell - - lvpwell_enc_ncmp - - pcmp_gr2dnw - - gr_w - - pp_enc_cmp, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_lvpwell - + lvpwell_enc_ncmp - + pcmp_gr2dnw - + gr_w - + pp_enc_cmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w - + lvpwell_enc_ncmp - + dnwell_enc_lvpwell - + pcmp_gr2dnw - + gr_w - + pp_enc_cmp, - ) - pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) - cell.shapes(pplus).insert(pp_gr) - - else: - if volt == "5V": - # Inserting 5V layers - cell.shapes(v5_xtor).insert( - pya.Box( - -dg_enc_cmp, - -(dg_enc_ply + ply_ext_cmp), - ( - 2 * (ld + ld_violat) - + l - + dg_enc_cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - w + (dg_enc_ply + ply_ext_cmp), - ) - ) - cell.shapes(dualgate).insert( - pya.Box( - -dg_enc_cmp, - -(dg_enc_ply + ply_ext_cmp), - ( - 2 * (ld + ld_violat) - + l - + dg_enc_cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - w + (dg_enc_ply + ply_ext_cmp), - ) - ) - elif volt == "6V": - # Inserting 6V layers - cell.shapes(dualgate).insert( - pya.Box( - -dg_enc_cmp, - -(dg_enc_ply + ply_ext_cmp), - ( - 2 * (ld + ld_violat) - + l - + dg_enc_cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - w + (dg_enc_ply + ply_ext_cmp), - ) - ) - - cell.flatten(True) - return cell - - -def draw_pfet(layout, l, w, ld, nf, grw, bulk, volt, deepnwell, pcmpgr): - """ - Usage:- - used to draw PFET transistor by specifying parameters - Arguments:- - layout : Object of layout - l : Float of gate length - w : Float of gate width - ld : Float of diffusion length - nf : Integer of number of fingers - grw : Float of guard ring width [If enabled] - bulk : String of bulk connection type [None, Bulk Tie, Guard Ring] - volt : String of operating voltage of the FET [3.3V, 5V, 6V] - deepnwell : Boolean of using Deep NWELL device - pcmpgr : Boolean of using P+ Guard Ring for Deep NWELL devices only - """ - - # Define layers - dnwell = layout.layer(12, 0) - dualgate = layout.layer(55, 0) - v5_xtor = layout.layer(112, 1) - nwell = layout.layer(21, 0) - comp = layout.layer(22, 0) - poly2 = layout.layer(30, 0) - nplus = layout.layer(32, 0) - pplus = layout.layer(31, 0) - contact = layout.layer(33, 0) - metal1 = layout.layer(34, 0) - - # Define variables - dbu_PERCISION = 1 / layout.dbu - nf = int(nf) - grw = grw * dbu_PERCISION - ld = ld * dbu_PERCISION - l = l * dbu_PERCISION - w = w * dbu_PERCISION - cmp2cont = 0.07 * dbu_PERCISION - cont_size = 0.22 * dbu_PERCISION - np_enc_cmp = 0.16 * dbu_PERCISION - pp_enc_cmp = 0.16 * dbu_PERCISION - cont2ply = 0.15 * dbu_PERCISION - ply_ext_cmp = 0.22 * dbu_PERCISION - np_enc_gate = 0.23 * dbu_PERCISION - cont2cont = 0.28 * dbu_PERCISION - dg_enc_ply = 0.4 * dbu_PERCISION - dg_enc_cmp = 0.24 * dbu_PERCISION - cmp2cmp = 0.32 * dbu_PERCISION - ply2gr = 0.26 * dbu_PERCISION - nwell_enc_pcomp = 0.43 * dbu_PERCISION - nwell_enc_ncomp = 0.12 * dbu_PERCISION - ld_violat = 0 * dbu_PERCISION - tie_violat = 0 * dbu_PERCISION - metal_violat = 0.01 * dbu_PERCISION - min_cmp_area = 0.2025 * dbu_PERCISION * dbu_PERCISION - dg_enc_dnwell = 0.5 * dbu_PERCISION - dnwell_enc_ncmp = 0.62 * dbu_PERCISION - dnwell_enc_pcmp = 0.93 * dbu_PERCISION - pcmp_gr2dnw = 2.5 * dbu_PERCISION - gr_w = 0.36 * dbu_PERCISION - - if deepnwell == True: - cmp2cmp = 0.36 * dbu_PERCISION - ply2gr = 0.3 * dbu_PERCISION - - if volt == "5V" or volt == "6V": - cmp2cmp = 0.36 * dbu_PERCISION - ply2gr = 0.3 * dbu_PERCISION - cmp2cmp = 0.36 * dbu_PERCISION - dnwell_enc_ncmp = 0.66 * dbu_PERCISION - dnwell_enc_pcmp = 1.1 * dbu_PERCISION - nwell_enc_pcomp = 0.6 * dbu_PERCISION - nwell_enc_ncomp = 0.16 * dbu_PERCISION - - if w < cont_size + 2 * cmp2cont: - if nf == 1: - if volt == "5V" or volt == "6V": - ld_violat = 0.22 * dbu_PERCISION - else: - ld_violat = 0.02 * dbu_PERCISION - - # Inserting PFET cell - cell_index = layout.add_cell("pfet") - cell = layout.cell(cell_index) - - w_changed = False - - # Inserting diffusion - if w < cont_size + 2 * cmp2cont: - cell.shapes(comp).insert( - pya.Box( - 0, - (cont_size + 2 * cmp2cont - w) / 2, - ( - 2 * (ld + ld_violat) - + l - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + (cont_size + 2 * cmp2cont - w) / 2, - ) - ) - w = cont_size + 2 * cmp2cont - w_changed = True - else: - cell.shapes(comp).insert( - pya.Box(0, 0, (2 * ld + l + (nf - 1) * (ld + l + cont2ply - cmp2cont)), w) - ) - - cell.shapes(pplus).insert( - pya.Box( - -np_enc_cmp, - -np_enc_gate, - ( - 2 * (ld + ld_violat) - + l - + np_enc_cmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + np_enc_gate, - ) - ) - - # Inserting gate/s - # Inserting a gate cell - gate_cell_index = layout.add_cell("gate") - gate_cell = layout.cell(gate_cell_index) - gate_cell.shapes(poly2).insert( - pya.Box(ld + ld_violat, -ply_ext_cmp, (ld + ld_violat + l), (w + ply_ext_cmp)) - ) - - # adding gate array - cell.insert( - pya.CellInstArray.new( - gate_cell_index, - pya.Trans.new(pya.Point.new(0, 0)), - pya.Point.new(ld + ld_violat + l + cont2ply - cmp2cont, 0), - pya.Point.new(0, 0), - int(nf), - 1, - ) - ) - - # Inserting a contact cell - cont_cell_index = layout.add_cell("contact") - cont_cell = layout.cell(cont_cell_index) - - # Inserting shapes now into the *contact* cell - cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) - - # Contact array count and postions - nx = int((ld - (cont_size + cmp2cont + cont2ply)) / (cont2cont + cont_size)) + 1 - ny = int((w - (cont_size + 2 * cmp2cont)) / (cont2cont + cont_size)) + 1 - dx = (ld - nx * cont_size - (nx - 1) * cont2cont) * cmp2cont / cont_size - dy = (w - ny * cont_size - (ny - 1) * cont2cont) / 2 - - # adding contact array and metals - # Left contacts - if not (w_changed == True and nf > 1) and (ld >= 440): - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new(pya.Point.new(dx, dy)), - pya.Point.new((cont2cont + cont_size), 0), - pya.Point.new(0, (cont2cont + cont_size)), - nx, - ny, - ) - ) - # Left metal - cell.shapes(metal1).insert( - pya.Box( - -metal_violat, - -metal_violat, - ld + metal_violat - (cont_size - 2 * cmp2cont), - w + metal_violat, - ) - ) - - # Adding diffusion to avoid contact violation - if nf == 1 and w_changed == True: - cell.shapes(comp).insert(pya.Box(0, 0, ld - (cont_size - 2 * cmp2cont), w)) - - # Right contacts and metals for each finger - for i in range(nf): - # Contacts - if not (w_changed == True and nf > 1) and (ld >= 440): - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - ( - (l + ld + ld_violat + cont2ply - cmp2cont) * i - + 2 * (ld + ld_violat) - + l - - cont_size - - dx - ), - dy, - ) - ), - pya.Point.new(-(cont2cont + cont_size), 0), - pya.Point.new(0, (cont2cont + cont_size)), - nx, - ny, - ) - ) - # Metals - - cell.shapes(metal1).insert( - pya.Box( - (ld + 2 * ld_violat + l + cont2ply - cmp2cont) * (i + 1) - - metal_violat, - -metal_violat, - ld - + metal_violat - + ld_violat - + (ld + ld_violat + l + cont2ply - cmp2cont) * (i + 1) - - (cont_size - 2 * cmp2cont), - w + metal_violat, - ) - ) - - # Adding diffusion to avoid contact violation - if nf == 1 and w_changed == True: - cell.shapes(comp).insert( - pya.Box( - (ld + 2 * ld_violat + l + cont2ply - cmp2cont) * (i + 1), - 0, - ld - + ld_violat - + (ld + ld_violat + l + cont2ply - cmp2cont) * (i + 1) - - (cont_size - 2 * cmp2cont), - w, - ) - ) - region = pya.Region.new(cell.begin_shapes_rec(comp)) - region.merge() - cell.clear(comp) - cell.shapes(comp).insert(region) - - if bulk == "Bulk Tie": - if deepnwell == True: - if volt == "5V": - # Inserting 5V layers - cell.shapes(v5_xtor).insert( - pya.Box( - -dg_enc_dnwell - dnwell_enc_ncmp - cmp2cmp - ld, - -dg_enc_dnwell - dnwell_enc_pcmp, - ( - 2 * (ld + ld_violat) - + l - + dg_enc_dnwell - + dnwell_enc_pcmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + dnwell_enc_pcmp + dg_enc_dnwell, - ) - ) - - cell.shapes(dualgate).insert( - pya.Box( - -dg_enc_dnwell - dnwell_enc_ncmp - cmp2cmp - ld, - -dg_enc_dnwell - dnwell_enc_pcmp, - ( - 2 * (ld + ld_violat) - + l - + dg_enc_dnwell - + dnwell_enc_pcmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + dnwell_enc_pcmp + dg_enc_dnwell, - ) - ) - - elif volt == "6V": - # Inserting 6V layers - cell.shapes(dualgate).insert( - pya.Box( - -dg_enc_dnwell - dnwell_enc_ncmp - cmp2cmp - ld, - -dg_enc_dnwell - dnwell_enc_pcmp, - ( - 2 * (ld + ld_violat) - + l - + dg_enc_dnwell - + dnwell_enc_pcmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + dnwell_enc_pcmp + dg_enc_dnwell, - ) - ) - - # Inserting DNWELL - cell.shapes(dnwell).insert( - pya.Box( - -dnwell_enc_ncmp - cmp2cmp - ld, - -dnwell_enc_pcmp, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_pcmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + dnwell_enc_pcmp, - ) - ) - - # Inserting Double Guard Ring - if pcmpgr == True: - cmp_inner = pya.Box( - -dnwell_enc_ncmp - cmp2cmp - ld - pcmp_gr2dnw, - -dnwell_enc_pcmp - pcmp_gr2dnw, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_pcmp - + pcmp_gr2dnw - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + dnwell_enc_pcmp + pcmp_gr2dnw, - ) - cmp_outer = pya.Box( - -dnwell_enc_ncmp - cmp2cmp - ld - pcmp_gr2dnw - gr_w, - -dnwell_enc_pcmp - pcmp_gr2dnw - gr_w, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_pcmp - + pcmp_gr2dnw - + gr_w - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + dnwell_enc_pcmp + pcmp_gr2dnw + gr_w, - ) - cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) - cell.shapes(comp).insert(cmp_gr) - - pp_inner = pya.Box( - -dnwell_enc_ncmp - cmp2cmp - ld - pcmp_gr2dnw + pp_enc_cmp, - -dnwell_enc_pcmp - pcmp_gr2dnw + pp_enc_cmp, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_pcmp - + pcmp_gr2dnw - - pp_enc_cmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + dnwell_enc_pcmp + pcmp_gr2dnw - pp_enc_cmp, - ) - pp_outer = pya.Box( - -dnwell_enc_ncmp - cmp2cmp - ld - pcmp_gr2dnw - gr_w - pp_enc_cmp, - -dnwell_enc_pcmp - pcmp_gr2dnw - gr_w - pp_enc_cmp, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_pcmp - + pcmp_gr2dnw - + gr_w - + pp_enc_cmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + dnwell_enc_pcmp + pcmp_gr2dnw + gr_w + pp_enc_cmp, - ) - pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) - cell.shapes(pplus).insert(pp_gr) - - else: - if volt == "5V": - # Inserting 5V layers - cell.shapes(v5_xtor).insert( - pya.Box( - -(cmp2cmp + dg_enc_cmp) - ld, - -(dg_enc_ply + ply_ext_cmp), - ( - 2 * (ld + ld_violat) - + l - + dg_enc_cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - w + (dg_enc_ply + ply_ext_cmp), - ) - ) - cell.shapes(dualgate).insert( - pya.Box( - -(cmp2cmp + dg_enc_cmp) - ld, - -(dg_enc_ply + ply_ext_cmp), - ( - 2 * (ld + ld_violat) - + l - + dg_enc_cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - w + (dg_enc_ply + ply_ext_cmp), - ) - ) - elif volt == "6V": - # Inserting 6V layers - cell.shapes(dualgate).insert( - pya.Box( - -(cmp2cmp + dg_enc_cmp) - ld, - -(dg_enc_ply + ply_ext_cmp), - ( - 2 * (ld + ld_violat) - + l - + dg_enc_cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - w + (dg_enc_ply + ply_ext_cmp), - ) - ) - - # Inserting nwell - cell.shapes(nwell).insert( - pya.Box( - -nwell_enc_ncomp - cmp2cmp - ld, - -nwell_enc_pcomp, - ( - 2 * (ld + ld_violat) - + l - + nwell_enc_pcomp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - w + nwell_enc_pcomp, - ) - ) - - # Inserting Tie - if (w * ld) < min_cmp_area: - tie_violat = (min_cmp_area * tol / ld - w) / 2 - cell.shapes(comp).insert( - pya.Box(-cmp2cmp - ld, -tie_violat, -cmp2cmp, w + tie_violat) - ) - cell.shapes(nplus).insert( - pya.Box( - -cmp2cmp - np_enc_cmp - ld, - -np_enc_cmp - tie_violat, - -cmp2cmp + np_enc_cmp, - w + tie_violat + np_enc_cmp, - ) - ) - - # Tie contacts - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - (-(cmp2cmp + cont_size) - dx * cont_size / (2 * cmp2cont)), dy - ) - ), - pya.Point.new(-(cont2cont + cont_size), 0), - pya.Point.new(0, (cont2cont + cont_size)), - nx, - ny, - ) - ) - - # Tie metal - cell.shapes(metal1).insert( - pya.Box(-cmp2cmp - ld, -tie_violat, -cmp2cmp, w + tie_violat) - ) - - elif bulk == "Guard Ring": - if deepnwell == True: - if volt == "5V": - # Inserting 5V layers - cell.shapes(v5_xtor).insert( - pya.Box( - -dg_enc_dnwell - dnwell_enc_ncmp - cmp2cmp - grw, - -dg_enc_dnwell - dnwell_enc_ncmp - (ply_ext_cmp + ply2gr) - grw, - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + dnwell_enc_ncmp - + dg_enc_dnwell - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - ( - w - + (ply_ext_cmp + ply2gr) - + grw - + dnwell_enc_ncmp - + dg_enc_dnwell - ), - ) - ) - - cell.shapes(dualgate).insert( - pya.Box( - -dg_enc_dnwell - dnwell_enc_ncmp - cmp2cmp - grw, - -dg_enc_dnwell - dnwell_enc_ncmp - (ply_ext_cmp + ply2gr) - grw, - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + dnwell_enc_ncmp - + dg_enc_dnwell - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - ( - w - + (ply_ext_cmp + ply2gr) - + grw - + dnwell_enc_ncmp - + dg_enc_dnwell - ), - ) - ) - - elif volt == "6V": - # Inserting 6V layers - cell.shapes(dualgate).insert( - pya.Box( - -dg_enc_dnwell - dnwell_enc_ncmp - cmp2cmp - grw, - -dg_enc_dnwell - dnwell_enc_ncmp - (ply_ext_cmp + ply2gr) - grw, - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + dnwell_enc_ncmp - + dg_enc_dnwell - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - ( - w - + (ply_ext_cmp + ply2gr) - + grw - + dnwell_enc_ncmp - + dg_enc_dnwell - ), - ) - ) - - # Inserting DNWELL - cell.shapes(dnwell).insert( - pya.Box( - -dnwell_enc_ncmp - cmp2cmp - grw, - -dnwell_enc_ncmp - (ply_ext_cmp + ply2gr) - grw, - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + dnwell_enc_ncmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + (ply_ext_cmp + ply2gr) + grw + dnwell_enc_ncmp), - ) - ) - - # Inserting Double Guard Ring - if pcmpgr == True: - cmp_inner = pya.Box( - -dnwell_enc_ncmp - cmp2cmp - grw - pcmp_gr2dnw, - -dnwell_enc_ncmp - (ply_ext_cmp + ply2gr) - grw - pcmp_gr2dnw, - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + dnwell_enc_ncmp - + pcmp_gr2dnw - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + (ply_ext_cmp + ply2gr) + grw + dnwell_enc_ncmp + pcmp_gr2dnw), - ) - cmp_outer = pya.Box( - -dnwell_enc_ncmp - cmp2cmp - grw - pcmp_gr2dnw - gr_w, - -dnwell_enc_ncmp - - (ply_ext_cmp + ply2gr) - - grw - - pcmp_gr2dnw - - gr_w, - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + dnwell_enc_ncmp - + pcmp_gr2dnw - + gr_w - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - ( - w - + (ply_ext_cmp + ply2gr) - + grw - + dnwell_enc_ncmp - + pcmp_gr2dnw - + gr_w - ), - ) - cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) - cell.shapes(comp).insert(cmp_gr) - - pp_inner = pya.Box( - -dnwell_enc_ncmp - cmp2cmp - grw - pcmp_gr2dnw + pp_enc_cmp, - -dnwell_enc_ncmp - - (ply_ext_cmp + ply2gr) - - grw - - pcmp_gr2dnw - + pp_enc_cmp, - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + dnwell_enc_ncmp - + pcmp_gr2dnw - - pp_enc_cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - ( - w - + (ply_ext_cmp + ply2gr) - + grw - + dnwell_enc_ncmp - + pcmp_gr2dnw - - pp_enc_cmp - ), - ) - pp_outer = pya.Box( - -dnwell_enc_ncmp - cmp2cmp - grw - pcmp_gr2dnw - gr_w - pp_enc_cmp, - -dnwell_enc_ncmp - - (ply_ext_cmp + ply2gr) - - grw - - pcmp_gr2dnw - - gr_w - - pp_enc_cmp, - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + dnwell_enc_ncmp - + pcmp_gr2dnw - + gr_w - + pp_enc_cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - ( - w - + (ply_ext_cmp + ply2gr) - + grw - + dnwell_enc_ncmp - + pcmp_gr2dnw - + gr_w - + pp_enc_cmp - ), - ) - pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) - cell.shapes(pplus).insert(pp_gr) - - else: - if volt == "5V": - # Inserting 5V layers - cell.shapes(v5_xtor).insert( - pya.Box( - -(cmp2cmp + dg_enc_cmp) - grw, - -(ply_ext_cmp + ply2gr + dg_enc_cmp) - grw, - ( - 2 * (ld + ld_violat) - + l - + grw - + (cmp2cmp + dg_enc_cmp) - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + ply_ext_cmp + ply2gr + dg_enc_cmp + grw), - ) - ) - cell.shapes(dualgate).insert( - pya.Box( - -(cmp2cmp + dg_enc_cmp) - grw, - -(ply_ext_cmp + ply2gr + dg_enc_cmp) - grw, - ( - 2 * (ld + ld_violat) - + l - + grw - + (cmp2cmp + dg_enc_cmp) - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + ply_ext_cmp + ply2gr + dg_enc_cmp + grw), - ) - ) - elif volt == "6V": - # Inserting 6V layers - cell.shapes(dualgate).insert( - pya.Box( - -(cmp2cmp + dg_enc_cmp) - grw, - -(ply_ext_cmp + ply2gr + dg_enc_cmp) - grw, - ( - 2 * (ld + ld_violat) - + l - + grw - + (cmp2cmp + dg_enc_cmp) - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + ply_ext_cmp + ply2gr + dg_enc_cmp + grw), - ) - ) - - # Inserting nwell - cell.shapes(nwell).insert( - pya.Box( - -nwell_enc_ncomp - cmp2cmp - grw, - -ply_ext_cmp - ply2gr - nwell_enc_ncomp - grw, - ( - 2 * (ld + ld_violat) - + l - + grw - + nwell_enc_ncomp - + cmp2cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + ply_ext_cmp + ply2gr + nwell_enc_ncomp + grw), - ) - ) - - # Inserting Guard Ring diffusion - cell.shapes(comp).insert( - pya.Polygon( - [ - pya.Point(-cmp2cmp - grw, -(ply_ext_cmp + ply2gr) - grw), - pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), - pya.Point(-cmp2cmp, (w + (ply_ext_cmp + ply2gr))), - pya.Point(-cmp2cmp, -(ply_ext_cmp + ply2gr)), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + cmp2cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - -(ply_ext_cmp + ply2gr), - ), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + cmp2cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + (ply_ext_cmp + ply2gr)), - ), - pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), - pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr) + grw)), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + (ply_ext_cmp + ply2gr) + grw), - ), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - -(ply_ext_cmp + ply2gr) - grw, - ), - ], - True, - ) - ) - cell.shapes(nplus).insert( - pya.Polygon( - [ - pya.Point( - -(cmp2cmp + pp_enc_cmp) - grw, - -(ply_ext_cmp + ply2gr + pp_enc_cmp) - grw, - ), - pya.Point( - -(cmp2cmp + pp_enc_cmp) - grw, - (w + (ply_ext_cmp + ply2gr - pp_enc_cmp)), - ), - pya.Point( - -(cmp2cmp - pp_enc_cmp), - (w + (ply_ext_cmp + ply2gr - pp_enc_cmp)), - ), - pya.Point( - -(cmp2cmp - pp_enc_cmp), -(ply_ext_cmp + ply2gr - pp_enc_cmp) - ), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + (cmp2cmp - pp_enc_cmp) - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - -(ply_ext_cmp + ply2gr - pp_enc_cmp), - ), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + (cmp2cmp - pp_enc_cmp) - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + (ply_ext_cmp + ply2gr - pp_enc_cmp)), - ), - pya.Point( - -(cmp2cmp + pp_enc_cmp) - grw, - (w + (ply_ext_cmp + ply2gr - pp_enc_cmp)), - ), - pya.Point( - -(cmp2cmp + pp_enc_cmp) - grw, - (w + (ply_ext_cmp + ply2gr + pp_enc_cmp) + grw), - ), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + grw - + (cmp2cmp + pp_enc_cmp) - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + (ply_ext_cmp + ply2gr + pp_enc_cmp) + grw), - ), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + grw - + (cmp2cmp + pp_enc_cmp) - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - -(ply_ext_cmp + ply2gr + pp_enc_cmp) - grw, - ), - ], - True, - ) - ) - - # Inserting Guard Ring metal - cell.shapes(metal1).insert( - pya.Polygon( - [ - pya.Point(-cmp2cmp - grw, -(ply_ext_cmp + ply2gr) - grw), - pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), - pya.Point(-cmp2cmp, (w + (ply_ext_cmp + ply2gr))), - pya.Point(-cmp2cmp, -(ply_ext_cmp + ply2gr)), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + cmp2cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - -(ply_ext_cmp + ply2gr), - ), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + cmp2cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + (ply_ext_cmp + ply2gr)), - ), - pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), - pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr) + grw)), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - (w + (ply_ext_cmp + ply2gr) + grw), - ), - pya.Point( - ( - 2 * (ld + ld_violat) - + l - + grw - + cmp2cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - -(ply_ext_cmp + ply2gr) - grw, - ), - ], - True, - ) - ) - - nxgr = int((grw - (cont_size + 2 * cmp2cont)) / (cont2cont + cont_size)) + 1 - nygr = ( - int( - ( - (2 * grw + w + 2 * (ply_ext_cmp + ply2gr)) - - (cont_size + 2 * cmp2cont) - ) - / (cont2cont + cont_size) - ) - + 1 - ) - dxgr = (grw - nxgr * cont_size - (nxgr - 1) * cont2cont) / 2 - dygr = ( - (2 * grw + w + 2 * (ply_ext_cmp + ply2gr)) - - nygr * cont_size - - (nygr - 1) * cont2cont - ) / 2 - nxgr_h = ( - int( - ( - ( - 2 * (ld + ld_violat) - + l - + 2 * cmp2cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ) - - 3 * cont2cont - ) - / (cont2cont + cont_size) - ) - + 1 - ) - dxgr_h = ( - ( - 2 * (ld + ld_violat) - + l - + cont2cont - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ) - - nxgr_h * cont_size - - (nxgr_h - 1) * cont2cont - ) / 2 - - # Inserting Guard Ring contacts - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - (-cmp2cmp - grw + dxgr), (-(ply_ext_cmp + ply2gr) - grw + dygr) - ) - ), - pya.Point.new((cont2cont + cont_size), 0), - pya.Point.new(0, (cont2cont + cont_size)), - nxgr, - nygr, - ) - ) - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - -(2 * cmp2cont) + dxgr_h, -(2 * cont_size) - ply2gr - dxgr - ) - ), - pya.Point.new((cont2cont + cont_size), 0), - pya.Point.new(0, -(cont2cont + cont_size)), - nxgr_h, - nxgr, - ) - ) - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - 2 * (ld + ld_violat) - + l - + grw - - dxgr - + (cmp2cmp - cont_size) - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont), - (-(ply_ext_cmp + ply2gr) - grw + dygr), - ) - ), - pya.Point.new(-(cont2cont + cont_size), 0), - pya.Point.new(0, (cont2cont + cont_size)), - nxgr, - nygr, - ) - ) - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - (-(2 * cmp2cont) + dxgr_h), (w + (ply_ext_cmp + ply2gr) + dxgr) - ) - ), - pya.Point.new((cont2cont + cont_size), 0), - pya.Point.new(0, (cont2cont + cont_size)), - nxgr_h, - nxgr, - ) - ) - - else: - if deepnwell == True: - if volt == "5V": - # Inserting 5V layers - cell.shapes(v5_xtor).insert( - pya.Box( - -dg_enc_dnwell - dnwell_enc_pcmp, - -dg_enc_dnwell - dnwell_enc_pcmp, - ( - 2 * (ld + ld_violat) - + l - + dg_enc_dnwell - + dnwell_enc_pcmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + dnwell_enc_pcmp + dg_enc_dnwell, - ) - ) - - cell.shapes(dualgate).insert( - pya.Box( - -dg_enc_dnwell - dnwell_enc_pcmp, - -dg_enc_dnwell - dnwell_enc_pcmp, - ( - 2 * (ld + ld_violat) - + l - + dg_enc_dnwell - + dnwell_enc_pcmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + dnwell_enc_pcmp + dg_enc_dnwell, - ) - ) - - elif volt == "6V": - # Inserting 6V layers - cell.shapes(dualgate).insert( - pya.Box( - -dg_enc_dnwell - dnwell_enc_pcmp, - -dg_enc_dnwell - dnwell_enc_pcmp, - ( - 2 * (ld + ld_violat) - + l - + dg_enc_dnwell - + dnwell_enc_pcmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + dnwell_enc_pcmp + dg_enc_dnwell, - ) - ) - - # Inserting DNWELL - cell.shapes(dnwell).insert( - pya.Box( - -dnwell_enc_pcmp, - -dnwell_enc_pcmp, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_pcmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + dnwell_enc_pcmp, - ) - ) - - # Inserting Double Guard Ring - if pcmpgr == True: - cmp_inner = pya.Box( - -dnwell_enc_pcmp - pcmp_gr2dnw, - -dnwell_enc_pcmp - pcmp_gr2dnw, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_pcmp - + pcmp_gr2dnw - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + dnwell_enc_pcmp + pcmp_gr2dnw, - ) - cmp_outer = pya.Box( - -dnwell_enc_pcmp - pcmp_gr2dnw - gr_w, - -dnwell_enc_pcmp - pcmp_gr2dnw - gr_w, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_pcmp - + pcmp_gr2dnw - + gr_w - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + dnwell_enc_pcmp + pcmp_gr2dnw + gr_w, - ) - cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) - cell.shapes(comp).insert(cmp_gr) - - pp_inner = pya.Box( - -dnwell_enc_pcmp - pcmp_gr2dnw + pp_enc_cmp, - -dnwell_enc_pcmp - pcmp_gr2dnw + pp_enc_cmp, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_pcmp - + pcmp_gr2dnw - - pp_enc_cmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + dnwell_enc_pcmp + pcmp_gr2dnw - pp_enc_cmp, - ) - pp_outer = pya.Box( - -dnwell_enc_pcmp - pcmp_gr2dnw - gr_w - pp_enc_cmp, - -dnwell_enc_pcmp - pcmp_gr2dnw - gr_w - pp_enc_cmp, - ( - 2 * (ld + ld_violat) - + l - + dnwell_enc_pcmp - + pcmp_gr2dnw - + gr_w - + pp_enc_cmp - + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) - ), - w + dnwell_enc_pcmp + pcmp_gr2dnw + gr_w + pp_enc_cmp, - ) - pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) - cell.shapes(pplus).insert(pp_gr) - - else: - if volt == "5V": - # Inserting 5V layers - cell.shapes(v5_xtor).insert( - pya.Box( - -dg_enc_cmp, - -(dg_enc_ply + ply_ext_cmp), - ( - 2 * (ld + ld_violat) - + l - + dg_enc_cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - w + (dg_enc_ply + ply_ext_cmp), - ) - ) - cell.shapes(dualgate).insert( - pya.Box( - -dg_enc_cmp, - -(dg_enc_ply + ply_ext_cmp), - ( - 2 * (ld + ld_violat) - + l - + dg_enc_cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - w + (dg_enc_ply + ply_ext_cmp), - ) - ) - elif volt == "6V": - # Inserting 6V layers - cell.shapes(dualgate).insert( - pya.Box( - -dg_enc_cmp, - -(dg_enc_ply + ply_ext_cmp), - ( - 2 * (ld + ld_violat) - + l - + dg_enc_cmp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - w + (dg_enc_ply + ply_ext_cmp), - ) - ) - - # Inserting NWELL - cell.shapes(nwell).insert( - pya.Box( - -nwell_enc_pcomp, - -nwell_enc_pcomp, - ( - 2 * (ld + ld_violat) - + l - + nwell_enc_pcomp - + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) - ), - w + nwell_enc_pcomp, - ) - ) - - cell.flatten(True) - return cell - - -def draw_nfet_06v0_nvt(layout, l, w, ld, nf, grw, bulk): - """ - Usage:- - used to draw Native NFET 6V transistor by specifying parameters - Arguments:- - layout : Object of layout - l : Float of gate length - w : Float of gate width - ld : Float of diffusion length - nf : Integer of number of fingers - grw : Float of guard ring width [If enabled] - bulk : String of bulk connection type [None, Bulk Tie, Guard Ring] - """ +# hvntm = c_inst.add_ref(gf.components.rectangle(size=(l_d+2*hv_enclosing,w+2*hv_enclosing),layer=hvntm_layer)) +# hvntm.move((sd_diff.xmin - hv_enclosing, sd_diff.ymin- hv_enclosing)) - # Define layers - dualgate = layout.layer(55, 0) - nat = layout.layer(5, 0) - comp = layout.layer(22, 0) - poly2 = layout.layer(30, 0) - nplus = layout.layer(32, 0) - pplus = layout.layer(31, 0) - contact = layout.layer(33, 0) - metal1 = layout.layer(34, 0) - # Define variables - dbu_PERCISION = 1 / layout.dbu - nf = int(nf) - grw = grw * dbu_PERCISION - ld = ld * dbu_PERCISION - l = l * dbu_PERCISION - w = w * dbu_PERCISION - cmp2cont = 0.07 * dbu_PERCISION - cont_size = 0.22 * dbu_PERCISION - np_enc_cmp = 0.16 * dbu_PERCISION - pp_enc_cmp = 0.16 * dbu_PERCISION - cont2ply = 0.15 * dbu_PERCISION - ply_ext_cmp = 0.22 * dbu_PERCISION - np_enc_gate = 0.23 * dbu_PERCISION - cont2cont = 0.28 * dbu_PERCISION - cmp2cmp = 0.36 * dbu_PERCISION - nat_enc_cmp = 2 * dbu_PERCISION - # Inserting NFET cell - cell_index = layout.add_cell("nfet_06v0_nvt") - cell = layout.cell(cell_index) +# if bulk != "Gaurd Ring": +# c.add_ref(c_inst) - # Inserting diffusion - cell.shapes(comp).insert( - pya.Box(0, 0, (2 * ld + l + (nf - 1) * (ld + l + cont2ply - cmp2cont)), w) - ) - cell.shapes(nplus).insert( - pya.Box( - -np_enc_cmp, - -np_enc_gate, - (2 * ld + l + np_enc_cmp + (nf - 1) * (ld + l + cont2ply - cmp2cont)), - w + np_enc_gate, - ) - ) - cell.shapes(nat).insert( - pya.Box( - -nat_enc_cmp, - -nat_enc_cmp, - (2 * ld + l + nat_enc_cmp + (nf - 1) * (ld + l + cont2ply - cmp2cont)), - w + nat_enc_cmp, - ) - ) - cell.shapes(dualgate).insert( - pya.Box( - -nat_enc_cmp, - -nat_enc_cmp, - (2 * ld + l + nat_enc_cmp + (nf - 1) * (ld + l + cont2ply - cmp2cont)), - w + nat_enc_cmp, - ) - ) - - # Inserting gate/s - # Inserting a gate cell - gate_cell_index = layout.add_cell("gate") - gate_cell = layout.cell(gate_cell_index) - gate_cell.shapes(poly2).insert( - pya.Box(ld, -ply_ext_cmp, (ld + l), (w + ply_ext_cmp)) - ) - - # adding gate array - cell.insert( - pya.CellInstArray.new( - gate_cell_index, - pya.Trans.new(pya.Point.new(0, 0)), - pya.Point.new(ld + l + cont2ply - cmp2cont, 0), - pya.Point.new(0, 0), - int(nf), - 1, - ) - ) - - # Inserting a contact cell - cont_cell_index = layout.add_cell("contact") - cont_cell = layout.cell(cont_cell_index) - - # Inserting shapes now into the *contact* cell - cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) - - # Contact array count and postions - nx = int((ld - (cont_size + cmp2cont + cont2ply)) / (cont2cont + cont_size)) + 1 - ny = int((w - (cont_size + 2 * cmp2cont)) / (cont2cont + cont_size)) + 1 - dx = (ld - nx * cont_size - (nx - 1) * cont2cont) * cmp2cont / cont_size - dy = (w - ny * cont_size - (ny - 1) * cont2cont) / 2 - - # adding contact array and metals - # Left contacts - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new(pya.Point.new(dx, dy)), - pya.Point.new((cont2cont + cont_size), 0), - pya.Point.new(0, (cont2cont + cont_size)), - nx, - ny, - ) - ) - # Left metal - cell.shapes(metal1).insert(pya.Box(0, 0, ld - (cont_size - 2 * cmp2cont), w)) - - # Right contacts and metals for each finger - for i in range(nf): - # Contacts - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - ( - (l + ld + cont2ply - cmp2cont) * i - + 2 * ld - + l - - cont_size - - dx - ), - dy, - ) - ), - pya.Point.new(-(cont2cont + cont_size), 0), - pya.Point.new(0, (cont2cont + cont_size)), - nx, - ny, - ) - ) - # Metals - cell.shapes(metal1).insert( - pya.Box( - (ld + l + cont2ply - cmp2cont) * (i + 1), - 0, - ld - + (ld + l + cont2ply - cmp2cont) * (i + 1) - - (cont_size - 2 * cmp2cont), - w, - ) - ) - - if bulk == "Bulk Tie": - # Inserting tie - cell.shapes(comp).insert( - pya.Box(-(nat_enc_cmp + cmp2cmp) - ld, 0, -(nat_enc_cmp + cmp2cmp), w) - ) - cell.shapes(pplus).insert( - pya.Box( - -(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - ld, - -pp_enc_cmp, - -(nat_enc_cmp + cmp2cmp - pp_enc_cmp), - w + pp_enc_cmp, - ) - ) - - # Tie contacts - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - ( - -(nat_enc_cmp + cmp2cmp + cont_size) - - dx * cont_size / (2 * cmp2cont) - ), - dy, - ) - ), - pya.Point.new(-(cont2cont + cont_size), 0), - pya.Point.new(0, (cont2cont + cont_size)), - nx, - ny, - ) - ) - - # Tie metal - cell.shapes(metal1).insert( - pya.Box(-(nat_enc_cmp + cmp2cmp) - ld, 0, -(nat_enc_cmp + cmp2cmp), w) - ) - - elif bulk == "Guard Ring": - # Inserting Guard Ring diffusion - cell.shapes(comp).insert( - pya.Polygon( - [ - pya.Point( - -(nat_enc_cmp + cmp2cmp) - grw, -(nat_enc_cmp + cmp2cmp) - grw - ), - pya.Point( - -(nat_enc_cmp + cmp2cmp) - grw, (w + (nat_enc_cmp + cmp2cmp)) - ), - pya.Point(-(nat_enc_cmp + cmp2cmp), (w + (nat_enc_cmp + cmp2cmp))), - pya.Point(-(nat_enc_cmp + cmp2cmp), -(nat_enc_cmp + cmp2cmp)), - pya.Point( - ( - 2 * ld - + l - + (nat_enc_cmp + cmp2cmp) - + (nf - 1) * (ld + l + cont2ply - cmp2cont) - ), - -(nat_enc_cmp + cmp2cmp), - ), - pya.Point( - ( - 2 * ld - + l - + (nat_enc_cmp + cmp2cmp) - + (nf - 1) * (ld + l + cont2ply - cmp2cont) - ), - (w + (nat_enc_cmp + cmp2cmp)), - ), - pya.Point( - -(nat_enc_cmp + cmp2cmp) - grw, (w + (nat_enc_cmp + cmp2cmp)) - ), - pya.Point( - -(nat_enc_cmp + cmp2cmp) - grw, - (w + (nat_enc_cmp + cmp2cmp) + grw), - ), - pya.Point( - ( - 2 * ld - + l - + grw - + (nat_enc_cmp + cmp2cmp) - + (nf - 1) * (ld + l + cont2ply - cmp2cont) - ), - (w + (nat_enc_cmp + cmp2cmp) + grw), - ), - pya.Point( - ( - 2 * ld - + l - + grw - + (nat_enc_cmp + cmp2cmp) - + (nf - 1) * (ld + l + cont2ply - cmp2cont) - ), - -(nat_enc_cmp + cmp2cmp) - grw, - ), - ], - True, - ) - ) - cell.shapes(pplus).insert( - pya.Polygon( - [ - pya.Point( - -(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - grw, - -(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - grw, - ), - pya.Point( - -(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - grw, - (w + (nat_enc_cmp + cmp2cmp - pp_enc_cmp)), - ), - pya.Point( - -(nat_enc_cmp + cmp2cmp - pp_enc_cmp), - (w + (nat_enc_cmp + cmp2cmp - pp_enc_cmp)), - ), - pya.Point( - -(nat_enc_cmp + cmp2cmp - pp_enc_cmp), - -(nat_enc_cmp + cmp2cmp - pp_enc_cmp), - ), - pya.Point( - ( - 2 * ld - + l - + (nat_enc_cmp + cmp2cmp - pp_enc_cmp) - + (nf - 1) * (ld + l + cont2ply - cmp2cont) - ), - -(nat_enc_cmp + cmp2cmp - pp_enc_cmp), - ), - pya.Point( - ( - 2 * ld - + l - + (nat_enc_cmp + cmp2cmp - pp_enc_cmp) - + (nf - 1) * (ld + l + cont2ply - cmp2cont) - ), - (w + (nat_enc_cmp + cmp2cmp - pp_enc_cmp)), - ), - pya.Point( - -(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - grw, - (w + (nat_enc_cmp + cmp2cmp - pp_enc_cmp)), - ), - pya.Point( - -(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - grw, - (w + (nat_enc_cmp + cmp2cmp + pp_enc_cmp) + grw), - ), - pya.Point( - ( - 2 * ld - + l - + grw - + (nat_enc_cmp + cmp2cmp + pp_enc_cmp) - + (nf - 1) * (ld + l + cont2ply - cmp2cont) - ), - (w + (nat_enc_cmp + cmp2cmp + pp_enc_cmp) + grw), - ), - pya.Point( - ( - 2 * ld - + l - + grw - + (nat_enc_cmp + cmp2cmp + pp_enc_cmp) - + (nf - 1) * (ld + l + cont2ply - cmp2cont) - ), - -(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - grw, - ), - ], - True, - ) - ) - - # Inserting Guard Ring metal - cell.shapes(metal1).insert( - pya.Polygon( - [ - pya.Point( - -(nat_enc_cmp + cmp2cmp) - grw, -(nat_enc_cmp + cmp2cmp) - grw - ), - pya.Point( - -(nat_enc_cmp + cmp2cmp) - grw, (w + (nat_enc_cmp + cmp2cmp)) - ), - pya.Point(-(nat_enc_cmp + cmp2cmp), (w + (nat_enc_cmp + cmp2cmp))), - pya.Point(-(nat_enc_cmp + cmp2cmp), -(nat_enc_cmp + cmp2cmp)), - pya.Point( - ( - 2 * ld - + l - + (nat_enc_cmp + cmp2cmp) - + (nf - 1) * (ld + l + cont2ply - cmp2cont) - ), - -(nat_enc_cmp + cmp2cmp), - ), - pya.Point( - ( - 2 * ld - + l - + (nat_enc_cmp + cmp2cmp) - + (nf - 1) * (ld + l + cont2ply - cmp2cont) - ), - (w + (nat_enc_cmp + cmp2cmp)), - ), - pya.Point( - -(nat_enc_cmp + cmp2cmp) - grw, (w + (nat_enc_cmp + cmp2cmp)) - ), - pya.Point( - -(nat_enc_cmp + cmp2cmp) - grw, - (w + (nat_enc_cmp + cmp2cmp) + grw), - ), - pya.Point( - ( - 2 * ld - + l - + grw - + (nat_enc_cmp + cmp2cmp) - + (nf - 1) * (ld + l + cont2ply - cmp2cont) - ), - (w + (nat_enc_cmp + cmp2cmp) + grw), - ), - pya.Point( - ( - 2 * ld - + l - + grw - + (nat_enc_cmp + cmp2cmp) - + (nf - 1) * (ld + l + cont2ply - cmp2cont) - ), - -(nat_enc_cmp + cmp2cmp) - grw, - ), - ], - True, - ) - ) - - nxgr = int((grw - (cont_size + 2 * cmp2cont)) / (cont2cont + cont_size)) + 1 - nygr = ( - int( - ( - (2 * grw + w + 2 * (nat_enc_cmp + cmp2cmp)) - - (cont_size + 2 * cmp2cont) - ) - / (cont2cont + cont_size) - ) - + 1 - ) - dxgr = (grw - nxgr * cont_size - (nxgr - 1) * cont2cont) / 2 - dygr = ( - (2 * grw + w + 2 * (nat_enc_cmp + cmp2cmp)) - - nygr * cont_size - - (nygr - 1) * cont2cont - ) / 2 - nxgr_h = ( - int( - ( - ( - 2 * ld - + l - + 2 * (nat_enc_cmp + cmp2cmp) - + (nf - 1) * (ld + l + cont2ply - cmp2cont) - ) - - 3 * cont2cont - ) - / (cont2cont + cont_size) - ) - + 1 - ) - dxgr_h = ( - ( - 2 * ld - + l - + (nat_enc_cmp + cmp2cmp) - + (nf - 1) * (ld + l + cont2ply - cmp2cont) - ) - - nxgr_h * cont_size - - (nxgr_h - 1) * cont2cont - ) / 2 - - # Inserting Guard Ring contacts - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - (-(nat_enc_cmp + cmp2cmp) - grw + dxgr), - (-(nat_enc_cmp + cmp2cmp) - grw + dygr), - ) - ), - pya.Point.new((cont2cont + cont_size), 0), - pya.Point.new(0, (cont2cont + cont_size)), - nxgr, - nygr, - ) - ) - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - -(nat_enc_cmp + cmp2cmp) / 2 + dxgr_h, - -(nat_enc_cmp + cmp2cmp + cont_size) - dxgr, - ) - ), - pya.Point.new((cont2cont + cont_size), 0), - pya.Point.new(0, -(cont2cont + cont_size)), - nxgr_h, - nxgr, - ) - ) - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - 2 * ld - + l - + grw - - dxgr - + nat_enc_cmp - + cmp2cmp - - cont_size - + (nf - 1) * (ld + l + cont2ply - cmp2cont), - (-(nat_enc_cmp + cmp2cmp) - grw + dygr), - ) - ), - pya.Point.new(-(cont2cont + cont_size), 0), - pya.Point.new(0, (cont2cont + cont_size)), - nxgr, - nygr, - ) - ) - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - -(nat_enc_cmp + cmp2cmp) / 2 + dxgr_h, - w + (nat_enc_cmp + cmp2cmp) + dxgr, - ) - ), - pya.Point.new((cont2cont + cont_size), 0), - pya.Point.new(0, (cont2cont + cont_size)), - nxgr_h, - nxgr, - ) - ) - - cell.flatten(True) - return cell - - -def draw_nfet_10v0_asym(layout, l, w): - """ - Usage:- - used to draw LDNFET 10V transistor by specifying parameters - Arguments:- - layout : Object of layout - l : Float of gate length - w : Float of gate width - """ - # Define layers - dualgate = layout.layer(55, 0) - ldmos_xtor = layout.layer(226, 0) - mvsd = layout.layer(210, 0) - comp = layout.layer(22, 0) - poly2 = layout.layer(30, 0) - nplus = layout.layer(32, 0) - pplus = layout.layer(31, 0) - contact = layout.layer(33, 0) - metal1 = layout.layer(34, 0) +# # generating hvi and hvntm for high voltage +# if type=="sky130_fd_pr__nfet_g5v0d10v5" or type== "sky130_fd_pr__nfet_05v0_nvt" or type == "sky130_fd_pr__nfet_03v3_nvt" : +# hvi = c.add_ref(gf.components.rectangle(size=(c_inst.xmax-c_inst.xmin + 2*hv_enclosing +# , (c_inst.ymax - c_inst.ymin )+ 2*hv_enclosing),layer=hvi_layer)) +# hvi.move((c_inst.xmin-hv_enclosing, c_inst.ymin-hv_enclosing)) - # Define variables - dbu_PERCISION = 1 / layout.dbu - l = l * dbu_PERCISION - w = w * dbu_PERCISION - cmp2cont = 0.07 * dbu_PERCISION - cont_size = 0.22 * dbu_PERCISION - np_enc_cmp = 0.16 * dbu_PERCISION - pp_enc_cmp = 0.16 * dbu_PERCISION - cont2ply = 0.15 * dbu_PERCISION - metal_w = 0.38 * dbu_PERCISION - ply_ext_cmp = 0.4 * dbu_PERCISION - ply_fld = 0.2 * dbu_PERCISION - np_enc_gate = 0.23 * dbu_PERCISION - cont2cont = 0.25 * dbu_PERCISION - cmp2cmp = 0.36 * dbu_PERCISION - cmp2gr = 0.4 * dbu_PERCISION - mvsd_ext_cmp = 0.5 * dbu_PERCISION - mvsd_ov_cmp = 0.4 * dbu_PERCISION - mvsd2gr = 1 * dbu_PERCISION - ply2gr = 0.4 * dbu_PERCISION - drain2ply = 0.16 * dbu_PERCISION - dg_enc_cmp = 0.5 * dbu_PERCISION - # Inserting NFET cell - cell_index = layout.add_cell("nfet_10v0_asym") - cell = layout.cell(cell_index) - # Inserting layers for LDFET - cell.shapes(dualgate).insert( - pya.Box( - -( - dg_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont2ply - + cont_size - + cmp2cont - + mvsd_ov_cmp - + cmp2cmp - ) - - l, - -(mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size + dg_enc_cmp) - w / 2, - ( - dg_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont2ply - + cont_size - + cmp2cont - + mvsd_ov_cmp - + cmp2cmp - ) - + l, - (mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size + dg_enc_cmp) + w / 2, - ) - ) - cell.shapes(ldmos_xtor).insert( - pya.Box( - -( - dg_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont2ply - + cont_size - + cmp2cont - + mvsd_ov_cmp - + cmp2cmp - ) - - l, - -(mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size + dg_enc_cmp) - w / 2, - ( - dg_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont2ply - + cont_size - + cmp2cont - + mvsd_ov_cmp - + cmp2cmp - ) - + l, - (mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size + dg_enc_cmp) + w / 2, - ) - ) - - # Inserting drain diffusion - cell.shapes(comp).insert(pya.Box(-cont_size / 2, -w / 2, cont_size / 2, w / 2)) - cell.shapes(mvsd).insert( - pya.Box( - -(cont_size / 2 + cmp2cmp + mvsd_ov_cmp), - -w / 2 - mvsd_ext_cmp, - (cont_size / 2 + cmp2cmp + mvsd_ov_cmp), - w / 2 + mvsd_ext_cmp, - ) - ) - - # Inserting source diffusion - cell.shapes(comp).insert( - pya.Box( - (cont_size / 2 + cmp2cmp), - -w / 2, - (cont_size / 2 + cmp2cmp + mvsd_ov_cmp + cont2ply + cont_size + cmp2cont) - + l, - w / 2, - ) - ) - cell.shapes(comp).insert( - pya.Box( - -(cont_size / 2 + cmp2cmp), - -w / 2, - -(cont_size / 2 + cmp2cmp + mvsd_ov_cmp + cont2ply + cont_size + cmp2cont) - - l, - w / 2, - ) - ) + +# if type == "sky130_fd_pr__nfet_01v8_lvt": +# lvt = c_inst.add_ref(gf.components.rectangle(size= (nf*l + (nf-1)*inter_sd_l + 2*gate_lvt_enc, w + 2*gate_lvt_enc) +# , layer= lvtn_layer)) +# lvt.move((sd_l - gate_lvt_enc,-gate_lvt_enc)) + +# if type == "sky130_fd_pr__nfet_03v3_nvt" or type == "sky130_fd_pr__nfet_05v0_nvt": - cell.shapes(nplus).insert( - pya.Box( - -( - cont_size / 2 - + cmp2cmp - + mvsd_ov_cmp - + cont2ply - + cont_size - + cmp2cont - + np_enc_cmp - ) - - l, - -w / 2 - np_enc_gate, - ( - cont_size / 2 - + cmp2cmp - + mvsd_ov_cmp - + cont2ply - + cont_size - + cmp2cont - + np_enc_cmp - ) - + l, - w / 2 + np_enc_gate, - ) - ) +# nvt = c_inst.add_ref(gf.components.rectangle(size= (nf*l + (nf-1)*inter_sd_l + 2*gate_lvt_enc, w + 2*gate_lvt_enc) +# , layer= lvtn_layer)) +# nvt.move((sd_l - gate_lvt_enc,-gate_lvt_enc)) - # Inserting gates - cell.shapes(poly2).insert( - pya.Box( - (cont_size / 2 + drain2ply), - -w / 2 - ply_ext_cmp, - (cont_size / 2 + cmp2cmp + mvsd_ov_cmp) + l, - w / 2 + mvsd_ext_cmp + mvsd2gr - ply2gr, - ) - ) - cell.shapes(poly2).insert( - pya.Box( - -(cont_size / 2 + drain2ply), - -w / 2 - ply_ext_cmp, - -(cont_size / 2 + cmp2cmp + mvsd_ov_cmp) - l, - w / 2 + mvsd_ext_cmp + mvsd2gr - ply2gr, - ) - ) +# if type == "sky130_fd_pr__nfet_03v3_nvt" : +# areaid_lvn = gf.components.rectangle(size=(l+2*areaid_lvn_enc,w+2*areaid_lvn_enc),layer=areaid_lvn_layer) +# areaid_lvn_arr = c_inst.add_array(component=areaid_lvn,columns=nf,rows=1,spacing=[l+inter_sd_l,0]) +# areaid_lvn_arr.move((sd_l-areaid_lvn_enc , sd_diff.ymin - areaid_lvn_enc)) - # Inserting a contact cell - cont_cell_index = layout.add_cell("contact") - cont_cell = layout.cell(cont_cell_index) + c.add_ref(c_inst) + # creating layout and cell in klayout + c.write_gds(f"nfet_temp.gds") + layout.read(f"nfet_temp.gds") + cell_name = "sky_nfet_dev" - # Inserting shapes now into the *contact* cell - cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) - - # Contact array count and postions - ny = int((w - (cont_size + 2 * cmp2cont)) / (cont_size + cont2cont)) + 1 - dy = (w - ny * cont_size - (ny - 1) * cont2cont) / 2 - ng = ( - int( - ((l + mvsd_ov_cmp + ply_fld) - (cont_size + 2 * cmp2cont)) - / (cont_size + cont2cont) - ) - + 1 - ) - dg = (l + mvsd_ov_cmp + ply_fld - ng * cont_size - (ng - 1) * cont2cont) / 2 - - # Inserting contact array and metals - # gate contacts and metal - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - (cont_size / 2 + drain2ply) + dg, - w / 2 + mvsd_ext_cmp + mvsd2gr - ply2gr - (metal_w + cont_size) / 2, - ) - ), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - ng, - 1, - ) - ) - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - -(1.5 * cont_size + drain2ply) - dg, - w / 2 + mvsd_ext_cmp + mvsd2gr - ply2gr - (metal_w + cont_size) / 2, - ) - ), - pya.Point.new(-(cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - ng, - 1, - ) - ) - cell.shapes(metal1).insert( - pya.Box( - (cont_size / 2 + drain2ply), - w / 2 + mvsd_ext_cmp + mvsd2gr - ply2gr - metal_w, - (cont_size / 2 + cmp2cmp + mvsd_ov_cmp) + l, - w / 2 + mvsd_ext_cmp + mvsd2gr - ply2gr, - ) - ) - cell.shapes(metal1).insert( - pya.Box( - -(cont_size / 2 + drain2ply), - w / 2 + mvsd_ext_cmp + mvsd2gr - ply2gr - metal_w, - -(cont_size / 2 + cmp2cmp + mvsd_ov_cmp) - l, - w / 2 + mvsd_ext_cmp + mvsd2gr - ply2gr, - ) - ) - - # Drain contacts and metal - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new(pya.Point.new(-cont_size / 2, -w / 2 + dy)), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - 1, - ny, - ) - ) - cell.shapes(metal1).insert(pya.Box(-metal_w / 2, -w / 2, metal_w / 2, w / 2)) - - # Source contacts and metals - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - (cont_size / 2 + cmp2cmp + mvsd_ov_cmp + cont2ply) + l, -w / 2 + dy - ) - ), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - 1, - ny, - ) - ) - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - -(1.5 * cont_size + cmp2cmp + mvsd_ov_cmp + cont2ply) - l, - -w / 2 + dy, - ) - ), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - 1, - ny, - ) - ) - cell.shapes(metal1).insert( - pya.Box( - (1.5 * cont_size + cmp2cmp + mvsd_ov_cmp + cont2ply + cmp2cont - metal_w) - + l, - -w / 2, - (1.5 * cont_size + cmp2cmp + mvsd_ov_cmp + cont2ply + cmp2cont) + l, - w / 2, - ) - ) - cell.shapes(metal1).insert( - pya.Box( - -(1.5 * cont_size + cmp2cmp + mvsd_ov_cmp + cont2ply + cmp2cont - metal_w) - - l, - -w / 2, - -(1.5 * cont_size + cmp2cmp + mvsd_ov_cmp + cont2ply + cmp2cont) - l, - w / 2, - ) - ) - - # Inserting Guard Ring diffusion - cell.shapes(comp).insert( - pya.Polygon( - [ - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - - l, - -(mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size) - w / 2, - ), - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - - l, - (mvsd_ext_cmp + mvsd2gr) + w / 2, - ), - pya.Point( - -( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - - l, - (mvsd_ext_cmp + mvsd2gr) + w / 2, - ), - pya.Point( - -( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - - l, - -(mvsd_ext_cmp + mvsd2gr) - w / 2, - ), - pya.Point( - ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - + l, - -(mvsd_ext_cmp + mvsd2gr) - w / 2, - ), - pya.Point( - ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - + l, - (mvsd_ext_cmp + mvsd2gr) + w / 2, - ), - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - - l, - (mvsd_ext_cmp + mvsd2gr) + w / 2, - ), - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - - l, - (mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size) + w / 2, - ), - pya.Point( - ( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - + l, - (mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size) + w / 2, - ), - pya.Point( - ( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - + l, - -(mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size) - w / 2, - ), - ], - True, - ) - ) - - cell.shapes(pplus).insert( - pya.Polygon( - [ - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - + pp_enc_cmp - ) - - l, - -(mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size + pp_enc_cmp) - - w / 2, - ), - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - + pp_enc_cmp - ) - - l, - (mvsd_ext_cmp + mvsd2gr - pp_enc_cmp) + w / 2, - ), - pya.Point( - -( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - - pp_enc_cmp - ) - - l, - (mvsd_ext_cmp + mvsd2gr - pp_enc_cmp) + w / 2, - ), - pya.Point( - -( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - - pp_enc_cmp - ) - - l, - -(mvsd_ext_cmp + mvsd2gr - pp_enc_cmp) - w / 2, - ), - pya.Point( - ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - - pp_enc_cmp - ) - + l, - -(mvsd_ext_cmp + mvsd2gr - pp_enc_cmp) - w / 2, - ), - pya.Point( - ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - - pp_enc_cmp - ) - + l, - (mvsd_ext_cmp + mvsd2gr - pp_enc_cmp) + w / 2, - ), - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - + pp_enc_cmp - ) - - l, - (mvsd_ext_cmp + mvsd2gr - pp_enc_cmp) + w / 2, - ), - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - + pp_enc_cmp - ) - - l, - (mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size + pp_enc_cmp) - + w / 2, - ), - pya.Point( - ( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - + pp_enc_cmp - ) - + l, - (mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size + pp_enc_cmp) - + w / 2, - ), - pya.Point( - ( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - + pp_enc_cmp - ) - + l, - -(mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size + pp_enc_cmp) - - w / 2, - ), - ], - True, - ) - ) - - cell.shapes(metal1).insert( - pya.Polygon( - [ - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - - l, - -(mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size) - w / 2, - ), - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - - l, - (mvsd_ext_cmp + mvsd2gr) + w / 2, - ), - pya.Point( - -( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - - l, - (mvsd_ext_cmp + mvsd2gr) + w / 2, - ), - pya.Point( - -( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - - l, - -(mvsd_ext_cmp + mvsd2gr) - w / 2, - ), - pya.Point( - ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - + l, - -(mvsd_ext_cmp + mvsd2gr) - w / 2, - ), - pya.Point( - ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - + l, - (mvsd_ext_cmp + mvsd2gr) + w / 2, - ), - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - - l, - (mvsd_ext_cmp + mvsd2gr) + w / 2, - ), - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - - l, - (mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size) + w / 2, - ), - pya.Point( - ( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - + l, - (mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size) + w / 2, - ), - pya.Point( - ( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - + l, - -(mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size) - w / 2, - ), - ], - True, - ) - ) - - nygr = int( - (w + 2 * (mvsd_ext_cmp + mvsd2gr + cmp2cont + cont_size) + cont2cont) - / (cont_size + cont2cont) - ) - dygr = ( - w - + 2 * (mvsd_ext_cmp + mvsd2gr + cmp2cont + cont_size) - - nygr * (cont_size + cont2cont) - + cont2cont - ) / 2 - nxgr_h = int( - ( - 2 * l - + 2 - * ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - + cmp2cont - ) - - cont2cont - ) - / (cont_size + cont2cont) - ) - dxgr_h = ( - 2 * l - + 2 - * ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - + cmp2cont - ) - - nxgr_h * (cont_size + cont2cont) - + cont2cont - ) / 2 - - # Inserting Guard Ring contacts - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - -( - cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - - l, - dygr - (mvsd_ext_cmp + mvsd2gr + cmp2cont + cont_size) - w / 2, - ) - ), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - 1, - nygr, - ) - ) - - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - dxgr_h - - ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - + cmp2cont - ) - - l, - -(mvsd_ext_cmp + mvsd2gr + cmp2cont + cont_size) - w / 2, - ) - ), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - nxgr_h, - 1, - ) - ) - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - ( - cmp2cont - + 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - ) - + l, - dygr - (mvsd_ext_cmp + mvsd2gr + cmp2cont + cont_size) - w / 2, - ) - ), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - 1, - nygr, - ) - ) - - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - dxgr_h - - ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvsd_ov_cmp - + cmp2cmp - + cmp2cont - ) - - l, - (mvsd_ext_cmp + mvsd2gr + cmp2cont) + w / 2, - ) - ), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - nxgr_h, - 1, - ) - ) - - cell.flatten(True) - return cell - - -def draw_pfet_10v0_asym(layout, l, w, dgr_en): - """ - Usage:- - used to draw LDPFET 10V transistor by specifying parameters - Arguments:- - layout : Object of layout - l : Float of gate length - w : Float of gate width - dgr_en : Boolean to enable double guard ring - """ - - # Define layers - dnwell = layout.layer(12, 0) - dualgate = layout.layer(55, 0) - ldmos_xtor = layout.layer(226, 0) - mvpsd = layout.layer(11, 39) - comp = layout.layer(22, 0) - poly2 = layout.layer(30, 0) - nplus = layout.layer(32, 0) - pplus = layout.layer(31, 0) - contact = layout.layer(33, 0) - metal1 = layout.layer(34, 0) - - # Define variables - dbu_PERCISION = 1 / layout.dbu - l = l * dbu_PERCISION - w = w * dbu_PERCISION - cmp2cont = 0.07 * dbu_PERCISION - cont_size = 0.22 * dbu_PERCISION - np_enc_cmp = 0.16 * dbu_PERCISION - pp_enc_cmp = 0.16 * dbu_PERCISION - cont2ply = 0.15 * dbu_PERCISION - metal_w = 0.38 * dbu_PERCISION - ply_ext_cmp = 0.4 * dbu_PERCISION - ply_fld = 0.2 * dbu_PERCISION - np_enc_gate = 0.23 * dbu_PERCISION - cont2cont = 0.25 * dbu_PERCISION - cmp2cmp = 0.36 * dbu_PERCISION - cmp2gr = 0.4 * dbu_PERCISION - mvpsd_ext_cmp = 0.8 * dbu_PERCISION - mvpsd_ov_cmp = 0.4 * dbu_PERCISION - mvpsd2gr = 1 * dbu_PERCISION - ply2gr = 0.4 * dbu_PERCISION - drain2ply = 0.16 * dbu_PERCISION - dnw_enc_cmp = 0.66 * dbu_PERCISION - dg_enc_pcmp = 0.5 * dbu_PERCISION - pcmp_gr2dnw = 2.5 * dbu_PERCISION - - # Inserting PFET cell - cell_index = layout.add_cell("pfet_10v0_asym") - cell = layout.cell(cell_index) - - # Inserting layers for LDFET - cell.shapes(dnwell).insert( - pya.Box( - -( - dnw_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - -(mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size + dnw_enc_cmp) - - w / 2, - ( - dnw_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - (mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size + dnw_enc_cmp) + w / 2, - ) - ) - cell.shapes(dualgate).insert( - pya.Box( - -( - dg_enc_pcmp - + pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - -( - mvpsd_ext_cmp - + mvpsd2gr - + 4 * cmp2cont - + 2 * cont_size - + dg_enc_pcmp - + pcmp_gr2dnw - + dnw_enc_cmp - ) - - w / 2, - ( - dg_enc_pcmp - + pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 4 * cmp2cont - + 2 * cont_size - + dg_enc_pcmp - + pcmp_gr2dnw - + dnw_enc_cmp - ) - + w / 2, - ) - ) - cell.shapes(ldmos_xtor).insert( - pya.Box( - -( - dg_enc_pcmp - + pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - -( - mvpsd_ext_cmp - + mvpsd2gr - + 4 * cmp2cont - + 2 * cont_size - + dg_enc_pcmp - + pcmp_gr2dnw - + dnw_enc_cmp - ) - - w / 2, - ( - dg_enc_pcmp - + pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 4 * cmp2cont - + 2 * cont_size - + dg_enc_pcmp - + pcmp_gr2dnw - + dnw_enc_cmp - ) - + w / 2, - ) - ) - - # Inserting drain diffusion - cell.shapes(comp).insert(pya.Box(-cont_size / 2, -w / 2, cont_size / 2, w / 2)) - cell.shapes(mvpsd).insert( - pya.Box( - -(cont_size / 2 + cmp2cmp + mvpsd_ov_cmp), - -w / 2 - mvpsd_ext_cmp, - (cont_size / 2 + cmp2cmp + mvpsd_ov_cmp), - w / 2 + mvpsd_ext_cmp, - ) - ) - - # Inserting source diffusion - cell.shapes(comp).insert( - pya.Box( - (cont_size / 2 + cmp2cmp), - -w / 2, - (cont_size / 2 + cmp2cmp + mvpsd_ov_cmp + cont2ply + cont_size + cmp2cont) - + l, - w / 2, - ) - ) - cell.shapes(comp).insert( - pya.Box( - -(cont_size / 2 + cmp2cmp), - -w / 2, - -(cont_size / 2 + cmp2cmp + mvpsd_ov_cmp + cont2ply + cont_size + cmp2cont) - - l, - w / 2, - ) - ) - - cell.shapes(pplus).insert( - pya.Box( - -( - cont_size / 2 - + cmp2cmp - + mvpsd_ov_cmp - + cont2ply - + cont_size - + cmp2cont - + np_enc_cmp - ) - - l, - -w / 2 - np_enc_gate, - ( - cont_size / 2 - + cmp2cmp - + mvpsd_ov_cmp - + cont2ply - + cont_size - + cmp2cont - + np_enc_cmp - ) - + l, - w / 2 + np_enc_gate, - ) - ) - - # Inserting gates - cell.shapes(poly2).insert( - pya.Box( - (cont_size / 2 + drain2ply), - -w / 2 - ply_ext_cmp, - (cont_size / 2 + cmp2cmp + mvpsd_ov_cmp) + l, - w / 2 + mvpsd_ext_cmp + mvpsd2gr - ply2gr, - ) - ) - cell.shapes(poly2).insert( - pya.Box( - -(cont_size / 2 + drain2ply), - -w / 2 - ply_ext_cmp, - -(cont_size / 2 + cmp2cmp + mvpsd_ov_cmp) - l, - w / 2 + mvpsd_ext_cmp + mvpsd2gr - ply2gr, - ) - ) - - # Inserting a contact cell - cont_cell_index = layout.add_cell("contact") - cont_cell = layout.cell(cont_cell_index) - - # Inserting shapes now into the *contact* cell - cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) - - # Contact array count and postions - ny = int((w - (cont_size + 2 * cmp2cont)) / (cont_size + cont2cont)) + 1 - dy = (w - ny * cont_size - (ny - 1) * cont2cont) / 2 - ng = ( - int( - ((l + mvpsd_ov_cmp + ply_fld) - (cont_size + 2 * cmp2cont)) - / (cont_size + cont2cont) - ) - + 1 - ) - dg = (l + mvpsd_ov_cmp + ply_fld - ng * cont_size - (ng - 1) * cont2cont) / 2 - - # Inserting contact array and metals - # Gate contacts and metal - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - (cont_size / 2 + drain2ply) + dg, - w / 2 - + mvpsd_ext_cmp - + mvpsd2gr - - ply2gr - - (metal_w + cont_size) / 2, - ) - ), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - ng, - 1, - ) - ) - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - -(1.5 * cont_size + drain2ply) - dg, - w / 2 - + mvpsd_ext_cmp - + mvpsd2gr - - ply2gr - - (metal_w + cont_size) / 2, - ) - ), - pya.Point.new(-(cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - ng, - 1, - ) - ) - cell.shapes(metal1).insert( - pya.Box( - (cont_size / 2 + drain2ply), - w / 2 + mvpsd_ext_cmp + mvpsd2gr - ply2gr - metal_w, - (cont_size / 2 + cmp2cmp + mvpsd_ov_cmp) + l, - w / 2 + mvpsd_ext_cmp + mvpsd2gr - ply2gr, - ) - ) - cell.shapes(metal1).insert( - pya.Box( - -(cont_size / 2 + drain2ply), - w / 2 + mvpsd_ext_cmp + mvpsd2gr - ply2gr - metal_w, - -(cont_size / 2 + cmp2cmp + mvpsd_ov_cmp) - l, - w / 2 + mvpsd_ext_cmp + mvpsd2gr - ply2gr, - ) - ) - - # Drain contacts and metal - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new(pya.Point.new(-cont_size / 2, -w / 2 + dy)), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - 1, - ny, - ) - ) - cell.shapes(metal1).insert(pya.Box(-metal_w / 2, -w / 2, metal_w / 2, w / 2)) - - # Source contacts and metals - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - (cont_size / 2 + cmp2cmp + mvpsd_ov_cmp + cont2ply) + l, -w / 2 + dy - ) - ), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - 1, - ny, - ) - ) - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - -(1.5 * cont_size + cmp2cmp + mvpsd_ov_cmp + cont2ply) - l, - -w / 2 + dy, - ) - ), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - 1, - ny, - ) - ) - cell.shapes(metal1).insert( - pya.Box( - (1.5 * cont_size + cmp2cmp + mvpsd_ov_cmp + cont2ply + cmp2cont - metal_w) - + l, - -w / 2, - (1.5 * cont_size + cmp2cmp + mvpsd_ov_cmp + cont2ply + cmp2cont) + l, - w / 2, - ) - ) - cell.shapes(metal1).insert( - pya.Box( - -(1.5 * cont_size + cmp2cmp + mvpsd_ov_cmp + cont2ply + cmp2cont - metal_w) - - l, - -w / 2, - -(1.5 * cont_size + cmp2cmp + mvpsd_ov_cmp + cont2ply + cmp2cont) - l, - w / 2, - ) - ) - - # Inserting Guard Ring diffusion - cell.shapes(comp).insert( - pya.Polygon( - [ - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - -(mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size) - w / 2, - ), - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - (mvpsd_ext_cmp + mvpsd2gr) + w / 2, - ), - pya.Point( - -( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - (mvpsd_ext_cmp + mvpsd2gr) + w / 2, - ), - pya.Point( - -( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - -(mvpsd_ext_cmp + mvpsd2gr) - w / 2, - ), - pya.Point( - ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - -(mvpsd_ext_cmp + mvpsd2gr) - w / 2, - ), - pya.Point( - ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - (mvpsd_ext_cmp + mvpsd2gr) + w / 2, - ), - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - (mvpsd_ext_cmp + mvpsd2gr) + w / 2, - ), - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - (mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size) + w / 2, - ), - pya.Point( - ( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - (mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size) + w / 2, - ), - pya.Point( - ( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - -(mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size) - w / 2, - ), - ], - True, - ) - ) - - cell.shapes(nplus).insert( - pya.Polygon( - [ - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - + pp_enc_cmp - ) - - l, - -(mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size + pp_enc_cmp) - - w / 2, - ), - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - + pp_enc_cmp - ) - - l, - (mvpsd_ext_cmp + mvpsd2gr - pp_enc_cmp) + w / 2, - ), - pya.Point( - -( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - - pp_enc_cmp - ) - - l, - (mvpsd_ext_cmp + mvpsd2gr - pp_enc_cmp) + w / 2, - ), - pya.Point( - -( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - - pp_enc_cmp - ) - - l, - -(mvpsd_ext_cmp + mvpsd2gr - pp_enc_cmp) - w / 2, - ), - pya.Point( - ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - - pp_enc_cmp - ) - + l, - -(mvpsd_ext_cmp + mvpsd2gr - pp_enc_cmp) - w / 2, - ), - pya.Point( - ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - - pp_enc_cmp - ) - + l, - (mvpsd_ext_cmp + mvpsd2gr - pp_enc_cmp) + w / 2, - ), - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - + pp_enc_cmp - ) - - l, - (mvpsd_ext_cmp + mvpsd2gr - pp_enc_cmp) + w / 2, - ), - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - + pp_enc_cmp - ) - - l, - (mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size + pp_enc_cmp) - + w / 2, - ), - pya.Point( - ( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - + pp_enc_cmp - ) - + l, - (mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size + pp_enc_cmp) - + w / 2, - ), - pya.Point( - ( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - + pp_enc_cmp - ) - + l, - -(mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size + pp_enc_cmp) - - w / 2, - ), - ], - True, - ) - ) - - cell.shapes(metal1).insert( - pya.Polygon( - [ - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - -(mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size) - w / 2, - ), - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - (mvpsd_ext_cmp + mvpsd2gr) + w / 2, - ), - pya.Point( - -( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - (mvpsd_ext_cmp + mvpsd2gr) + w / 2, - ), - pya.Point( - -( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - -(mvpsd_ext_cmp + mvpsd2gr) - w / 2, - ), - pya.Point( - ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - -(mvpsd_ext_cmp + mvpsd2gr) - w / 2, - ), - pya.Point( - ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - (mvpsd_ext_cmp + mvpsd2gr) + w / 2, - ), - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - (mvpsd_ext_cmp + mvpsd2gr) + w / 2, - ), - pya.Point( - -( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - (mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size) + w / 2, - ), - pya.Point( - ( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - (mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size) + w / 2, - ), - pya.Point( - ( - 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - -(mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size) - w / 2, - ), - ], - True, - ) - ) - - nygr = int( - (w + 2 * (mvpsd_ext_cmp + mvpsd2gr + cmp2cont + cont_size) + cont2cont) - / (cont_size + cont2cont) - ) - dygr = ( - w - + 2 * (mvpsd_ext_cmp + mvpsd2gr + cmp2cont + cont_size) - - nygr * (cont_size + cont2cont) - + cont2cont - ) / 2 - nxgr_h = int( - ( - 2 * l - + 2 - * ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - + cmp2cont - ) - - cont2cont - ) - / (cont_size + cont2cont) - ) - dxgr_h = ( - 2 * l - + 2 - * ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - + cmp2cont - ) - - nxgr_h * (cont_size + cont2cont) - + cont2cont - ) / 2 - - # Inserting Guard Ring contacts - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - -( - cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - dygr - (mvpsd_ext_cmp + mvpsd2gr + cmp2cont + cont_size) - w / 2, - ) - ), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - 1, - nygr, - ) - ) - - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - dxgr_h - - ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - + cmp2cont - ) - - l, - -(mvpsd_ext_cmp + mvpsd2gr + cmp2cont + cont_size) - w / 2, - ) - ), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - nxgr_h, - 1, - ) - ) - - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - ( - cmp2cont - + 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - dygr - (mvpsd_ext_cmp + mvpsd2gr + cmp2cont + cont_size) - w / 2, - ) - ), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - 1, - nygr, - ) - ) - - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - dxgr_h - - ( - 0.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - + cmp2cont - ) - - l, - (mvpsd_ext_cmp + mvpsd2gr + cmp2cont) + w / 2, - ) - ), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - nxgr_h, - 1, - ) - ) - - # Inserting DNWELL Guard Ring - if dgr_en: - # Inserting DNWELL Guard Ring diffusion - cell.shapes(comp).insert( - pya.Polygon( - [ - pya.Point( - -( - pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - -( - mvpsd_ext_cmp - + mvpsd2gr - + 4 * cmp2cont - + 2 * cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - - w / 2, - ), - pya.Point( - -( - pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 2 * cmp2cont - + cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - + w / 2, - ), - pya.Point( - -( - pcmp_gr2dnw - + dnw_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 2 * cmp2cont - + cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - + w / 2, - ), - pya.Point( - -( - pcmp_gr2dnw - + dnw_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - -( - mvpsd_ext_cmp - + mvpsd2gr - + 2 * cmp2cont - + cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - - w / 2, - ), - pya.Point( - ( - pcmp_gr2dnw - + dnw_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - -( - mvpsd_ext_cmp - + mvpsd2gr - + 2 * cmp2cont - + cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - - w / 2, - ), - pya.Point( - ( - pcmp_gr2dnw - + dnw_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 2 * cmp2cont - + cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - + w / 2, - ), - pya.Point( - -( - pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 2 * cmp2cont - + cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - + w / 2, - ), - pya.Point( - -( - pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 4 * cmp2cont - + 2 * cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - + w / 2, - ), - pya.Point( - ( - pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 4 * cmp2cont - + 2 * cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - + w / 2, - ), - pya.Point( - ( - pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - -( - mvpsd_ext_cmp - + mvpsd2gr - + 4 * cmp2cont - + 2 * cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - - w / 2, - ), - ], - True, - ) - ) - - cell.shapes(pplus).insert( - pya.Polygon( - [ - pya.Point( - -( - pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - + np_enc_cmp - ) - - l, - -( - mvpsd_ext_cmp - + mvpsd2gr - + 4 * cmp2cont - + 2 * cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - + np_enc_cmp - ) - - w / 2, - ), - pya.Point( - -( - pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - + np_enc_cmp - ) - - l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 2 * cmp2cont - + cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - - np_enc_cmp - ) - + w / 2, - ), - pya.Point( - -( - pcmp_gr2dnw - + dnw_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - - np_enc_cmp - ) - - l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 2 * cmp2cont - + cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - - np_enc_cmp - ) - + w / 2, - ), - pya.Point( - -( - pcmp_gr2dnw - + dnw_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - - np_enc_cmp - ) - - l, - -( - mvpsd_ext_cmp - + mvpsd2gr - + 2 * cmp2cont - + cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - - np_enc_cmp - ) - - w / 2, - ), - pya.Point( - ( - pcmp_gr2dnw - + dnw_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - - np_enc_cmp - ) - + l, - -( - mvpsd_ext_cmp - + mvpsd2gr - + 2 * cmp2cont - + cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - - np_enc_cmp - ) - - w / 2, - ), - pya.Point( - ( - pcmp_gr2dnw - + dnw_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - - np_enc_cmp - ) - + l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 2 * cmp2cont - + cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - - np_enc_cmp - ) - + w / 2, - ), - pya.Point( - -( - pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - + np_enc_cmp - ) - - l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 2 * cmp2cont - + cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - - np_enc_cmp - ) - + w / 2, - ), - pya.Point( - -( - pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - + np_enc_cmp - ) - - l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 4 * cmp2cont - + 2 * cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - + np_enc_cmp - ) - + w / 2, - ), - pya.Point( - ( - pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - + np_enc_cmp - ) - + l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 4 * cmp2cont - + 2 * cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - + np_enc_cmp - ) - + w / 2, - ), - pya.Point( - ( - pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - + np_enc_cmp - ) - + l, - -( - mvpsd_ext_cmp - + mvpsd2gr - + 4 * cmp2cont - + 2 * cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - + np_enc_cmp - ) - - w / 2, - ), - ], - True, - ) - ) - - # Inserting DNWELL Guard Ring metal - cell.shapes(metal1).insert( - pya.Polygon( - [ - pya.Point( - -( - pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - -( - mvpsd_ext_cmp - + mvpsd2gr - + 4 * cmp2cont - + 2 * cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - - w / 2, - ), - pya.Point( - -( - pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 2 * cmp2cont - + cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - + w / 2, - ), - pya.Point( - -( - pcmp_gr2dnw - + dnw_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 2 * cmp2cont - + cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - + w / 2, - ), - pya.Point( - -( - pcmp_gr2dnw - + dnw_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - -( - mvpsd_ext_cmp - + mvpsd2gr - + 2 * cmp2cont - + cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - - w / 2, - ), - pya.Point( - ( - pcmp_gr2dnw - + dnw_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - -( - mvpsd_ext_cmp - + mvpsd2gr - + 2 * cmp2cont - + cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - - w / 2, - ), - pya.Point( - ( - pcmp_gr2dnw - + dnw_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 2 * cmp2cont - + cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - + w / 2, - ), - pya.Point( - -( - pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 2 * cmp2cont - + cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - + w / 2, - ), - pya.Point( - -( - pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 4 * cmp2cont - + 2 * cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - + w / 2, - ), - pya.Point( - ( - pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - ( - mvpsd_ext_cmp - + mvpsd2gr - + 4 * cmp2cont - + 2 * cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - + w / 2, - ), - pya.Point( - ( - pcmp_gr2dnw - + dnw_enc_cmp - + 4 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - -( - mvpsd_ext_cmp - + mvpsd2gr - + 4 * cmp2cont - + 2 * cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - - w / 2, - ), - ], - True, - ) - ) - - # Inserting DNWELL guard ring contacts - nygr = int( - ( - w - + 2 - * ( - mvpsd_ext_cmp - + mvpsd2gr - + 3 * cmp2cont - + 2 * cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - + cont2cont - ) - / (cont_size + cont2cont) - ) - dygr = ( - w - + 2 - * ( - mvpsd_ext_cmp - + mvpsd2gr - + 3 * cmp2cont - + 2 * cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - - nygr * (cont_size + cont2cont) - + cont2cont - ) / 2 - nxgr_h = int( - ( - 2 * l - + 2 - * ( - pcmp_gr2dnw - + dnw_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + 2 * cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - cont2cont - ) - / (cont_size + cont2cont) - ) - dxgr_h = ( - 2 * l - + 2 - * ( - pcmp_gr2dnw - + dnw_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + 2 * cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - nxgr_h * (cont_size + cont2cont) - + cont2cont - ) / 2 - - # Inserting DNWELL Guard Ring contacts - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - -( - pcmp_gr2dnw - + dnw_enc_cmp - + 3 * cmp2cont - + 2.5 * cont_size - + cmp2gr - + cont_size - + cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - dygr - - ( - mvpsd_ext_cmp - + mvpsd2gr - + 3 * cmp2cont - + 2 * cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - - w / 2, - ) - ), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - 1, - nygr, - ) - ) - - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - dxgr_h - - ( - pcmp_gr2dnw - + dnw_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + 2 * cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - -( - mvpsd_ext_cmp - + mvpsd2gr - + 3 * cmp2cont - + 2 * cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - - w / 2, - ) - ), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, -(cont_size + cont2cont)), - nxgr_h, - 1, - ) - ) - - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - ( - pcmp_gr2dnw - + dnw_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + 2 * cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - + l, - dygr - - ( - mvpsd_ext_cmp - + mvpsd2gr - + 3 * cmp2cont - + 2 * cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - ) - - w / 2, - ) - ), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - 1, - nygr, - ) - ) - - cell.insert( - pya.CellInstArray.new( - cont_cell_index, - pya.Trans.new( - pya.Point.new( - dxgr_h - - ( - pcmp_gr2dnw - + dnw_enc_cmp - + 2 * cmp2cont - + 1.5 * cont_size - + cmp2gr - + cont_size - + 2 * cmp2cont - + cont2ply - + mvpsd_ov_cmp - + cmp2cmp - ) - - l, - mvpsd_ext_cmp - + mvpsd2gr - + 3 * cmp2cont - + cont_size - + pcmp_gr2dnw - + dnw_enc_cmp - + w / 2, - ) - ), - pya.Point.new((cont_size + cont2cont), 0), - pya.Point.new(0, (cont_size + cont2cont)), - nxgr_h, - 1, - ) - ) + return layout.cell(cell_name) + # return c - cell.flatten(True) - return cell +if __name__ == "__main__": + c = draw_nfet() + c.show() + \ No newline at end of file diff --git a/cells/klayout/pymacros/cells/draw_fet_old.py b/cells/klayout/pymacros/cells/draw_fet_old.py new file mode 100644 index 00000000..76eba4dd --- /dev/null +++ b/cells/klayout/pymacros/cells/draw_fet_old.py @@ -0,0 +1,5977 @@ +# Copyright 2022 GlobalFoundries PDK Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +######################################################################################################################## +## FET Pcells Generators for Klayout of GF180MCU +######################################################################################################################## + +import pya + +tol = 1.05 + + +def draw_nfet(layout, l, w, ld, nf, grw, bulk, volt, deepnwell, pcmpgr): + """ + Usage:- + used to draw NFET transistor by specifying parameters + Arguments:- + layout : Object of layout + l : Float of gate length + w : Float of gate width + ld : Float of diffusion length + nf : Integer of number of fingers + grw : Float of guard ring width [If enabled] + bulk : String of bulk connection type [None, Bulk Tie, Guard Ring] + volt : String of operating voltage of the FET [3.3V, 5V, 6V] + deepnwell : Boolean of using Deep NWELL device + pcmpgr : Boolean of using P+ Guard Ring for Deep NWELL devices only + """ + + # Define layers + dnwell = layout.layer(12, 0) + lvpwell = layout.layer(204, 0) + dualgate = layout.layer(55, 0) + v5_xtor = layout.layer(112, 1) + comp = layout.layer(22, 0) + poly2 = layout.layer(30, 0) + nplus = layout.layer(32, 0) + pplus = layout.layer(31, 0) + contact = layout.layer(33, 0) + metal1 = layout.layer(34, 0) + + # Define variables + dbu_PERCISION = 1 / layout.dbu + nf = int(nf) + grw = grw * dbu_PERCISION + ld = ld * dbu_PERCISION + l = l * dbu_PERCISION + w = w * dbu_PERCISION + cmp2cont = 0.07 * dbu_PERCISION + cont_size = 0.22 * dbu_PERCISION + np_enc_cmp = 0.16 * dbu_PERCISION + pp_enc_cmp = 0.16 * dbu_PERCISION + cont2ply = 0.15 * dbu_PERCISION + ply_ext_cmp = 0.22 * dbu_PERCISION + np_enc_gate = 0.23 * dbu_PERCISION + cont2cont = 0.28 * dbu_PERCISION + dg_enc_ply = 0.4 * dbu_PERCISION + dg_enc_cmp = 0.24 * dbu_PERCISION + cmp2cmp = 0.32 * dbu_PERCISION + ply2gr = 0.26 * dbu_PERCISION + ld_violat = 0 * dbu_PERCISION + tie_violat = 0 * dbu_PERCISION + metal_violat = 0.01 * dbu_PERCISION + min_cmp_area = 0.2025 * dbu_PERCISION * dbu_PERCISION + dg_enc_dnwell = 0.5 * dbu_PERCISION + lvpwell_enc_ncmp = 0.43 * dbu_PERCISION + lvpwell_enc_pcmp = 0.12 * dbu_PERCISION + dnwell_enc_lvpwell = 2.5 * dbu_PERCISION + pcmp_gr2dnw = 2.5 * dbu_PERCISION + gr_w = 0.36 * dbu_PERCISION + + if deepnwell == True: + cmp2cmp = 0.36 * dbu_PERCISION + ply2gr = 0.3 * dbu_PERCISION + + if volt == "5V" or volt == "6V": + lvpwell_enc_ncmp = 0.6 * dbu_PERCISION + lvpwell_enc_pcmp = 0.16 * dbu_PERCISION + cmp2cmp = 0.36 * dbu_PERCISION + ply2gr = 0.3 * dbu_PERCISION + cmp2cmp = 0.36 * dbu_PERCISION + + if w < cont_size + 2 * cmp2cont: + if nf == 1: + if volt == "5V" or volt == "6V": + ld_violat = 0.22 * dbu_PERCISION + else: + ld_violat = 0.02 * dbu_PERCISION + + # Inserting NFET cell + cell_index = layout.add_cell("nfet") + cell = layout.cell(cell_index) + + w_changed = False + + # Inserting diffusion + if w < cont_size + 2 * cmp2cont: + cell.shapes(comp).insert( + pya.Box( + 0, + (cont_size + 2 * cmp2cont - w) / 2, + ( + 2 * (ld + ld_violat) + + l + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + (cont_size + 2 * cmp2cont - w) / 2, + ) + ) + w = cont_size + 2 * cmp2cont + w_changed = True + else: + cell.shapes(comp).insert( + pya.Box(0, 0, (2 * ld + l + (nf - 1) * (ld + l + cont2ply - cmp2cont)), w) + ) + + cell.shapes(nplus).insert( + pya.Box( + -np_enc_cmp, + -np_enc_gate, + ( + 2 * (ld + ld_violat) + + l + + np_enc_cmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + np_enc_gate, + ) + ) + + # Inserting gate/s + # Inserting a gate cell + gate_cell_index = layout.add_cell("gate") + gate_cell = layout.cell(gate_cell_index) + gate_cell.shapes(poly2).insert( + pya.Box(ld + ld_violat, -ply_ext_cmp, (ld + ld_violat + l), (w + ply_ext_cmp)) + ) + + # adding gate array + cell.insert( + pya.CellInstArray.new( + gate_cell_index, + pya.Trans.new(pya.Point.new(0, 0)), + pya.Point.new(ld + ld_violat + l + cont2ply - cmp2cont, 0), + pya.Point.new(0, 0), + int(nf), + 1, + ) + ) + + # Inserting a contact cell + cont_cell_index = layout.add_cell("contact") + cont_cell = layout.cell(cont_cell_index) + + # Inserting shapes now into the *contact* cell + cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) + + # Contact array count and postions + nx = int((ld - (cont_size + cmp2cont + cont2ply)) / (cont2cont + cont_size)) + 1 + ny = int((w - (cont_size + 2 * cmp2cont)) / (cont2cont + cont_size)) + 1 + dx = (ld - nx * cont_size - (nx - 1) * cont2cont) * cmp2cont / cont_size + dy = (w - ny * cont_size - (ny - 1) * cont2cont) / 2 + + # adding contact array and metals + # Left contacts + if not (w_changed == True and nf > 1) and (ld >= 440): + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new(pya.Point.new(dx, dy)), + pya.Point.new((cont2cont + cont_size), 0), + pya.Point.new(0, (cont2cont + cont_size)), + nx, + ny, + ) + ) + # Left metal + cell.shapes(metal1).insert( + pya.Box( + -metal_violat, + -metal_violat, + ld + metal_violat - (cont_size - 2 * cmp2cont), + w + metal_violat, + ) + ) + + # Adding diffusion to avoid contact violation + if nf == 1 and w_changed == True: + cell.shapes(comp).insert(pya.Box(0, 0, ld - (cont_size - 2 * cmp2cont), w)) + + # Right contacts and metals for each finger + for i in range(nf): + # Contacts + if not (w_changed == True and nf > 1) and (ld >= 440): + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + ( + (l + ld + ld_violat + cont2ply - cmp2cont) * i + + 2 * (ld + ld_violat) + + l + - cont_size + - dx + ), + dy, + ) + ), + pya.Point.new(-(cont2cont + cont_size), 0), + pya.Point.new(0, (cont2cont + cont_size)), + nx, + ny, + ) + ) + # Metals + + cell.shapes(metal1).insert( + pya.Box( + (ld + 2 * ld_violat + l + cont2ply - cmp2cont) * (i + 1) + - metal_violat, + -metal_violat, + ld + + metal_violat + + ld_violat + + (ld + ld_violat + l + cont2ply - cmp2cont) * (i + 1) + - (cont_size - 2 * cmp2cont), + w + metal_violat, + ) + ) + + # Adding diffusion to avoid contact violation + if nf == 1 and w_changed == True: + cell.shapes(comp).insert( + pya.Box( + (ld + 2 * ld_violat + l + cont2ply - cmp2cont) * (i + 1), + 0, + ld + + ld_violat + + (ld + ld_violat + l + cont2ply - cmp2cont) * (i + 1) + - (cont_size - 2 * cmp2cont), + w, + ) + ) + region = pya.Region.new(cell.begin_shapes_rec(comp)) + region.merge() + cell.clear(comp) + cell.shapes(comp).insert(region) + + if bulk == "Bulk Tie": + if deepnwell == True: + if volt == "5V": + # Inserting 5V layers + cell.shapes(v5_xtor).insert( + pya.Box( + -dg_enc_dnwell + - dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - cmp2cmp + - ld, + -dg_enc_dnwell - dnwell_enc_lvpwell - lvpwell_enc_ncmp, + ( + 2 * (ld + ld_violat) + + l + + dg_enc_dnwell + + dnwell_enc_lvpwell + + lvpwell_enc_ncmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + dg_enc_dnwell, + ) + ) + + cell.shapes(dualgate).insert( + pya.Box( + -dg_enc_dnwell + - dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - cmp2cmp + - ld, + -dg_enc_dnwell - dnwell_enc_lvpwell - lvpwell_enc_ncmp, + ( + 2 * (ld + ld_violat) + + l + + dg_enc_dnwell + + dnwell_enc_lvpwell + + lvpwell_enc_ncmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + dg_enc_dnwell, + ) + ) + + elif volt == "6V": + # Inserting 6V layers + cell.shapes(dualgate).insert( + pya.Box( + -dg_enc_dnwell + - dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - cmp2cmp + - ld, + -dg_enc_dnwell - dnwell_enc_lvpwell - lvpwell_enc_ncmp, + ( + 2 * (ld + ld_violat) + + l + + dg_enc_dnwell + + dnwell_enc_lvpwell + + lvpwell_enc_ncmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + dg_enc_dnwell, + ) + ) + + # Inserting LVPWELL + cell.shapes(lvpwell).insert( + pya.Box( + -lvpwell_enc_pcmp - cmp2cmp - ld, + -lvpwell_enc_ncmp, + ( + 2 * (ld + ld_violat) + + l + + lvpwell_enc_ncmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + lvpwell_enc_ncmp, + ) + ) + + # Inserting DNWELL + cell.shapes(dnwell).insert( + pya.Box( + -dnwell_enc_lvpwell - lvpwell_enc_pcmp - cmp2cmp - ld, + -dnwell_enc_lvpwell - lvpwell_enc_ncmp, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_lvpwell + + lvpwell_enc_ncmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + lvpwell_enc_ncmp + dnwell_enc_lvpwell, + ) + ) + + # Inserting Double Guard Ring + if pcmpgr == True: + cmp_inner = pya.Box( + -dnwell_enc_lvpwell - lvpwell_enc_pcmp - cmp2cmp - ld - pcmp_gr2dnw, + -dnwell_enc_lvpwell - lvpwell_enc_ncmp - pcmp_gr2dnw, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_lvpwell + + lvpwell_enc_ncmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ) + + pcmp_gr2dnw, + w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + pcmp_gr2dnw, + ) + cmp_outer = pya.Box( + -dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - cmp2cmp + - ld + - pcmp_gr2dnw + - gr_w, + -dnwell_enc_lvpwell - lvpwell_enc_ncmp - pcmp_gr2dnw - gr_w, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_lvpwell + + lvpwell_enc_ncmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ) + + pcmp_gr2dnw + + gr_w, + w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + pcmp_gr2dnw + gr_w, + ) + cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) + cell.shapes(comp).insert(cmp_gr) + + pp_inner = pya.Box( + -dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - cmp2cmp + - ld + - pcmp_gr2dnw + + pp_enc_cmp, + -dnwell_enc_lvpwell - lvpwell_enc_ncmp - pcmp_gr2dnw + pp_enc_cmp, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_lvpwell + + lvpwell_enc_ncmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ) + + pcmp_gr2dnw + - pp_enc_cmp, + w + + lvpwell_enc_ncmp + + dnwell_enc_lvpwell + + pcmp_gr2dnw + - pp_enc_cmp, + ) + pp_outer = pya.Box( + -dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - cmp2cmp + - ld + - pcmp_gr2dnw + - gr_w + - pp_enc_cmp, + -dnwell_enc_lvpwell + - lvpwell_enc_ncmp + - pcmp_gr2dnw + - gr_w + - pp_enc_cmp, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_lvpwell + + lvpwell_enc_ncmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ) + + pcmp_gr2dnw + + gr_w + + pp_enc_cmp, + w + + lvpwell_enc_ncmp + + dnwell_enc_lvpwell + + pcmp_gr2dnw + + gr_w + + pp_enc_cmp, + ) + pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) + cell.shapes(pplus).insert(pp_gr) + + else: + if volt == "5V": + # Inserting 5V layers + cell.shapes(v5_xtor).insert( + pya.Box( + -(cmp2cmp + dg_enc_cmp) - ld, + -(dg_enc_ply + ply_ext_cmp), + ( + 2 * (ld + ld_violat) + + l + + dg_enc_cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + w + (dg_enc_ply + ply_ext_cmp), + ) + ) + cell.shapes(dualgate).insert( + pya.Box( + -(cmp2cmp + dg_enc_cmp) - ld, + -(dg_enc_ply + ply_ext_cmp), + ( + 2 * (ld + ld_violat) + + l + + dg_enc_cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + w + (dg_enc_ply + ply_ext_cmp), + ) + ) + elif volt == "6V": + # Inserting 6V layers + cell.shapes(dualgate).insert( + pya.Box( + -(cmp2cmp + dg_enc_cmp) - ld, + -(dg_enc_ply + ply_ext_cmp), + ( + 2 * (ld + ld_violat) + + l + + dg_enc_cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + w + (dg_enc_ply + ply_ext_cmp), + ) + ) + + # Inserting Tie + if (w * ld) < min_cmp_area: + tie_violat = (min_cmp_area * tol / ld - w) / 2 + cell.shapes(comp).insert( + pya.Box(-cmp2cmp - ld, -tie_violat, -cmp2cmp, w + tie_violat) + ) + cell.shapes(pplus).insert( + pya.Box( + -cmp2cmp - pp_enc_cmp - ld, + -pp_enc_cmp - tie_violat, + -cmp2cmp + pp_enc_cmp, + w + tie_violat + pp_enc_cmp, + ) + ) + + # Tie contacts + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + (-(cmp2cmp + cont_size) - dx * cont_size / (2 * cmp2cont)), dy + ) + ), + pya.Point.new(-(cont2cont + cont_size), 0), + pya.Point.new(0, (cont2cont + cont_size)), + nx, + ny, + ) + ) + + # Tie metal + cell.shapes(metal1).insert( + pya.Box(-cmp2cmp - ld, -tie_violat, -cmp2cmp, w + tie_violat) + ) + + elif bulk == "Guard Ring": + if deepnwell == True: + if volt == "5V": + # Inserting 5V layers + cell.shapes(v5_xtor).insert( + pya.Box( + -dg_enc_dnwell + - dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - cmp2cmp + - grw, + -dg_enc_dnwell + - dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - (ply_ext_cmp + ply2gr) + - grw, + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + lvpwell_enc_pcmp + + dnwell_enc_lvpwell + + dg_enc_dnwell + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + ( + w + + (ply_ext_cmp + ply2gr) + + grw + + lvpwell_enc_pcmp + + dnwell_enc_lvpwell + + dg_enc_dnwell + ), + ) + ) + + cell.shapes(dualgate).insert( + pya.Box( + -dg_enc_dnwell + - dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - cmp2cmp + - grw, + -dg_enc_dnwell + - dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - (ply_ext_cmp + ply2gr) + - grw, + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + lvpwell_enc_pcmp + + dnwell_enc_lvpwell + + dg_enc_dnwell + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + ( + w + + (ply_ext_cmp + ply2gr) + + grw + + lvpwell_enc_pcmp + + dnwell_enc_lvpwell + + dg_enc_dnwell + ), + ) + ) + + elif volt == "6V": + # Inserting 6V layers + cell.shapes(dualgate).insert( + pya.Box( + -dg_enc_dnwell + - dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - cmp2cmp + - grw, + -dg_enc_dnwell + - dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - (ply_ext_cmp + ply2gr) + - grw, + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + lvpwell_enc_pcmp + + dnwell_enc_lvpwell + + dg_enc_dnwell + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + ( + w + + (ply_ext_cmp + ply2gr) + + grw + + lvpwell_enc_pcmp + + dnwell_enc_lvpwell + + dg_enc_dnwell + ), + ) + ) + + # Inserting LVPWELL + cell.shapes(lvpwell).insert( + pya.Box( + -lvpwell_enc_pcmp - cmp2cmp - grw, + -lvpwell_enc_pcmp - (ply_ext_cmp + ply2gr) - grw, + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + lvpwell_enc_pcmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + (ply_ext_cmp + ply2gr) + grw + lvpwell_enc_pcmp), + ) + ) + + # Inserting DNWELL + cell.shapes(dnwell).insert( + pya.Box( + -dnwell_enc_lvpwell - lvpwell_enc_pcmp - cmp2cmp - grw, + -dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - (ply_ext_cmp + ply2gr) + - grw, + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + lvpwell_enc_pcmp + + dnwell_enc_lvpwell + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + ( + w + + (ply_ext_cmp + ply2gr) + + grw + + lvpwell_enc_pcmp + + dnwell_enc_lvpwell + ), + ) + ) + + # Inserting Double Guard Ring + if pcmpgr == True: + cmp_inner = pya.Box( + -dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - cmp2cmp + - grw + - pcmp_gr2dnw, + -dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - (ply_ext_cmp + ply2gr) + - grw + - pcmp_gr2dnw, + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + lvpwell_enc_pcmp + + dnwell_enc_lvpwell + + pcmp_gr2dnw + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + ( + w + + (ply_ext_cmp + ply2gr) + + grw + + pcmp_gr2dnw + + lvpwell_enc_pcmp + + dnwell_enc_lvpwell + ), + ) + cmp_outer = pya.Box( + -dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - cmp2cmp + - grw + - pcmp_gr2dnw + - gr_w, + -dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - (ply_ext_cmp + ply2gr) + - grw + - pcmp_gr2dnw + - gr_w, + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + lvpwell_enc_pcmp + + dnwell_enc_lvpwell + + pcmp_gr2dnw + + gr_w + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + ( + w + + (ply_ext_cmp + ply2gr) + + grw + + pcmp_gr2dnw + + gr_w + + lvpwell_enc_pcmp + + dnwell_enc_lvpwell + ), + ) + cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) + cell.shapes(comp).insert(cmp_gr) + + pp_inner = pya.Box( + -dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - cmp2cmp + - grw + - pcmp_gr2dnw + + pp_enc_cmp, + -dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - (ply_ext_cmp + ply2gr) + - grw + - pcmp_gr2dnw + + pp_enc_cmp, + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + lvpwell_enc_pcmp + + dnwell_enc_lvpwell + + pcmp_gr2dnw + - pp_enc_cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + ( + w + + (ply_ext_cmp + ply2gr) + + grw + + pcmp_gr2dnw + + lvpwell_enc_pcmp + + dnwell_enc_lvpwell + - pp_enc_cmp + ), + ) + pp_outer = pya.Box( + -dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - cmp2cmp + - grw + - pcmp_gr2dnw + - gr_w + - pp_enc_cmp, + -dnwell_enc_lvpwell + - lvpwell_enc_pcmp + - (ply_ext_cmp + ply2gr) + - grw + - pcmp_gr2dnw + - gr_w + - pp_enc_cmp, + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + lvpwell_enc_pcmp + + dnwell_enc_lvpwell + + pcmp_gr2dnw + + gr_w + + pp_enc_cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + ( + w + + (ply_ext_cmp + ply2gr) + + grw + + pcmp_gr2dnw + + gr_w + + pp_enc_cmp + + lvpwell_enc_pcmp + + dnwell_enc_lvpwell + ), + ) + pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) + cell.shapes(pplus).insert(pp_gr) + + else: + if volt == "5V": + # Inserting 5V layers + cell.shapes(v5_xtor).insert( + pya.Box( + -(cmp2cmp + dg_enc_cmp) - grw, + -(ply_ext_cmp + ply2gr + dg_enc_cmp) - grw, + ( + 2 * (ld + ld_violat) + + l + + grw + + (cmp2cmp + dg_enc_cmp) + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + ply_ext_cmp + ply2gr + dg_enc_cmp + grw), + ) + ) + cell.shapes(dualgate).insert( + pya.Box( + -(cmp2cmp + dg_enc_cmp) - grw, + -(ply_ext_cmp + ply2gr + dg_enc_cmp) - grw, + ( + 2 * (ld + ld_violat) + + l + + grw + + (cmp2cmp + dg_enc_cmp) + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + ply_ext_cmp + ply2gr + dg_enc_cmp + grw), + ) + ) + elif volt == "6V": + # Inserting 6V layers + cell.shapes(dualgate).insert( + pya.Box( + -(cmp2cmp + dg_enc_cmp) - grw, + -(ply_ext_cmp + ply2gr + dg_enc_cmp) - grw, + ( + 2 * (ld + ld_violat) + + l + + grw + + (cmp2cmp + dg_enc_cmp) + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + ply_ext_cmp + ply2gr + dg_enc_cmp + grw), + ) + ) + + # Inserting guard ring diffusion + cell.shapes(comp).insert( + pya.Polygon( + [ + pya.Point(-cmp2cmp - grw, -(ply_ext_cmp + ply2gr) - grw), + pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), + pya.Point(-cmp2cmp, (w + (ply_ext_cmp + ply2gr))), + pya.Point(-cmp2cmp, -(ply_ext_cmp + ply2gr)), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + cmp2cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + -(ply_ext_cmp + ply2gr), + ), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + cmp2cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + (ply_ext_cmp + ply2gr)), + ), + pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), + pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr) + grw)), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + (ply_ext_cmp + ply2gr) + grw), + ), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + -(ply_ext_cmp + ply2gr) - grw, + ), + ], + True, + ) + ) + cell.shapes(pplus).insert( + pya.Polygon( + [ + pya.Point( + -(cmp2cmp + pp_enc_cmp) - grw, + -(ply_ext_cmp + ply2gr + pp_enc_cmp) - grw, + ), + pya.Point( + -(cmp2cmp + pp_enc_cmp) - grw, + (w + (ply_ext_cmp + ply2gr - pp_enc_cmp)), + ), + pya.Point( + -(cmp2cmp - pp_enc_cmp), + (w + (ply_ext_cmp + ply2gr - pp_enc_cmp)), + ), + pya.Point( + -(cmp2cmp - pp_enc_cmp), -(ply_ext_cmp + ply2gr - pp_enc_cmp) + ), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + (cmp2cmp - pp_enc_cmp) + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + -(ply_ext_cmp + ply2gr - pp_enc_cmp), + ), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + (cmp2cmp - pp_enc_cmp) + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + (ply_ext_cmp + ply2gr - pp_enc_cmp)), + ), + pya.Point( + -(cmp2cmp + pp_enc_cmp) - grw, + (w + (ply_ext_cmp + ply2gr - pp_enc_cmp)), + ), + pya.Point( + -(cmp2cmp + pp_enc_cmp) - grw, + (w + (ply_ext_cmp + ply2gr + pp_enc_cmp) + grw), + ), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + grw + + (cmp2cmp + pp_enc_cmp) + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + (ply_ext_cmp + ply2gr + pp_enc_cmp) + grw), + ), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + grw + + (cmp2cmp + pp_enc_cmp) + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + -(ply_ext_cmp + ply2gr + pp_enc_cmp) - grw, + ), + ], + True, + ) + ) + + # Inserting Guard Ring metal + cell.shapes(metal1).insert( + pya.Polygon( + [ + pya.Point(-cmp2cmp - grw, -(ply_ext_cmp + ply2gr) - grw), + pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), + pya.Point(-cmp2cmp, (w + (ply_ext_cmp + ply2gr))), + pya.Point(-cmp2cmp, -(ply_ext_cmp + ply2gr)), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + cmp2cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + -(ply_ext_cmp + ply2gr), + ), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + cmp2cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + (ply_ext_cmp + ply2gr)), + ), + pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), + pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr) + grw)), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + (ply_ext_cmp + ply2gr) + grw), + ), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + -(ply_ext_cmp + ply2gr) - grw, + ), + ], + True, + ) + ) + + nxgr = int((grw - (cont_size + 2 * cmp2cont)) / (cont2cont + cont_size)) + 1 + nygr = ( + int( + ( + (2 * grw + w + 2 * (ply_ext_cmp + ply2gr)) + - (cont_size + 2 * cmp2cont) + ) + / (cont2cont + cont_size) + ) + + 1 + ) + dxgr = (grw - nxgr * cont_size - (nxgr - 1) * cont2cont) / 2 + dygr = ( + (2 * grw + w + 2 * (ply_ext_cmp + ply2gr)) + - nygr * cont_size + - (nygr - 1) * cont2cont + ) / 2 + nxgr_h = ( + int( + ( + ( + 2 * (ld + ld_violat) + + l + + 2 * cmp2cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ) + - 3 * cont2cont + ) + / (cont2cont + cont_size) + ) + + 1 + ) + dxgr_h = ( + ( + 2 * (ld + ld_violat) + + l + + cont2cont + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ) + - nxgr_h * cont_size + - (nxgr_h - 1) * cont2cont + ) / 2 + + # Inserting Guard Ring contacts + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + (-cmp2cmp - grw + dxgr), (-(ply_ext_cmp + ply2gr) - grw + dygr) + ) + ), + pya.Point.new((cont2cont + cont_size), 0), + pya.Point.new(0, (cont2cont + cont_size)), + nxgr, + nygr, + ) + ) + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + -(2 * cmp2cont) + dxgr_h, -(2 * cont_size) - ply2gr - dxgr + ) + ), + pya.Point.new((cont2cont + cont_size), 0), + pya.Point.new(0, -(cont2cont + cont_size)), + nxgr_h, + nxgr, + ) + ) + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + 2 * (ld + ld_violat) + + l + + grw + - dxgr + + (cmp2cmp - cont_size) + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont), + (-(ply_ext_cmp + ply2gr) - grw + dygr), + ) + ), + pya.Point.new(-(cont2cont + cont_size), 0), + pya.Point.new(0, (cont2cont + cont_size)), + nxgr, + nygr, + ) + ) + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + (-(2 * cmp2cont) + dxgr_h), (w + (ply_ext_cmp + ply2gr) + dxgr) + ) + ), + pya.Point.new((cont2cont + cont_size), 0), + pya.Point.new(0, (cont2cont + cont_size)), + nxgr_h, + nxgr, + ) + ) + + else: + if deepnwell == True: + if volt == "5V": + # Inserting 5V layers + cell.shapes(v5_xtor).insert( + pya.Box( + -dg_enc_dnwell - dnwell_enc_lvpwell - lvpwell_enc_ncmp, + -dg_enc_dnwell - dnwell_enc_lvpwell - lvpwell_enc_ncmp, + ( + 2 * (ld + ld_violat) + + l + + dg_enc_dnwell + + dnwell_enc_lvpwell + + lvpwell_enc_ncmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + dg_enc_dnwell, + ) + ) + + cell.shapes(dualgate).insert( + pya.Box( + -dg_enc_dnwell - dnwell_enc_lvpwell - lvpwell_enc_ncmp, + -dg_enc_dnwell - dnwell_enc_lvpwell - lvpwell_enc_ncmp, + ( + 2 * (ld + ld_violat) + + l + + dg_enc_dnwell + + dnwell_enc_lvpwell + + lvpwell_enc_ncmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + dg_enc_dnwell, + ) + ) + + elif volt == "6V": + # Inserting 6V layers + cell.shapes(dualgate).insert( + pya.Box( + -dg_enc_dnwell - dnwell_enc_lvpwell - lvpwell_enc_ncmp, + -dg_enc_dnwell - dnwell_enc_lvpwell - lvpwell_enc_ncmp, + ( + 2 * (ld + ld_violat) + + l + + dg_enc_dnwell + + dnwell_enc_lvpwell + + lvpwell_enc_ncmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + dg_enc_dnwell, + ) + ) + + # Inserting LVPWELL + cell.shapes(lvpwell).insert( + pya.Box( + -lvpwell_enc_ncmp, + -lvpwell_enc_ncmp, + ( + 2 * (ld + ld_violat) + + l + + lvpwell_enc_ncmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + lvpwell_enc_ncmp, + ) + ) + + # Inserting DNWELL + cell.shapes(dnwell).insert( + pya.Box( + -dnwell_enc_lvpwell - lvpwell_enc_ncmp, + -dnwell_enc_lvpwell - lvpwell_enc_ncmp, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_lvpwell + + lvpwell_enc_ncmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + lvpwell_enc_ncmp + dnwell_enc_lvpwell, + ) + ) + + # Inserting Double Guard Ring + if pcmpgr == True: + cmp_inner = pya.Box( + -dnwell_enc_lvpwell - lvpwell_enc_ncmp - pcmp_gr2dnw, + -dnwell_enc_lvpwell - lvpwell_enc_ncmp - pcmp_gr2dnw, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_lvpwell + + lvpwell_enc_ncmp + + pcmp_gr2dnw + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + pcmp_gr2dnw, + ) + cmp_outer = pya.Box( + -dnwell_enc_lvpwell - lvpwell_enc_ncmp - pcmp_gr2dnw - gr_w, + -dnwell_enc_lvpwell - lvpwell_enc_ncmp - pcmp_gr2dnw - gr_w, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_lvpwell + + lvpwell_enc_ncmp + + pcmp_gr2dnw + + gr_w + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + pcmp_gr2dnw + gr_w, + ) + cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) + cell.shapes(comp).insert(cmp_gr) + + pp_inner = pya.Box( + -dnwell_enc_lvpwell - lvpwell_enc_ncmp - pcmp_gr2dnw + pp_enc_cmp, + -dnwell_enc_lvpwell - lvpwell_enc_ncmp - pcmp_gr2dnw + pp_enc_cmp, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_lvpwell + + lvpwell_enc_ncmp + + pcmp_gr2dnw + - pp_enc_cmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + + lvpwell_enc_ncmp + + dnwell_enc_lvpwell + + pcmp_gr2dnw + - pp_enc_cmp, + ) + pp_outer = pya.Box( + -dnwell_enc_lvpwell + - lvpwell_enc_ncmp + - pcmp_gr2dnw + - gr_w + - pp_enc_cmp, + -dnwell_enc_lvpwell + - lvpwell_enc_ncmp + - pcmp_gr2dnw + - gr_w + - pp_enc_cmp, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_lvpwell + + lvpwell_enc_ncmp + + pcmp_gr2dnw + + gr_w + + pp_enc_cmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + + lvpwell_enc_ncmp + + dnwell_enc_lvpwell + + pcmp_gr2dnw + + gr_w + + pp_enc_cmp, + ) + pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) + cell.shapes(pplus).insert(pp_gr) + + else: + if volt == "5V": + # Inserting 5V layers + cell.shapes(v5_xtor).insert( + pya.Box( + -dg_enc_cmp, + -(dg_enc_ply + ply_ext_cmp), + ( + 2 * (ld + ld_violat) + + l + + dg_enc_cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + w + (dg_enc_ply + ply_ext_cmp), + ) + ) + cell.shapes(dualgate).insert( + pya.Box( + -dg_enc_cmp, + -(dg_enc_ply + ply_ext_cmp), + ( + 2 * (ld + ld_violat) + + l + + dg_enc_cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + w + (dg_enc_ply + ply_ext_cmp), + ) + ) + elif volt == "6V": + # Inserting 6V layers + cell.shapes(dualgate).insert( + pya.Box( + -dg_enc_cmp, + -(dg_enc_ply + ply_ext_cmp), + ( + 2 * (ld + ld_violat) + + l + + dg_enc_cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + w + (dg_enc_ply + ply_ext_cmp), + ) + ) + + cell.flatten(True) + return cell + + +def draw_pfet(layout, l, w, ld, nf, grw, bulk, volt, deepnwell, pcmpgr): + """ + Usage:- + used to draw PFET transistor by specifying parameters + Arguments:- + layout : Object of layout + l : Float of gate length + w : Float of gate width + ld : Float of diffusion length + nf : Integer of number of fingers + grw : Float of guard ring width [If enabled] + bulk : String of bulk connection type [None, Bulk Tie, Guard Ring] + volt : String of operating voltage of the FET [3.3V, 5V, 6V] + deepnwell : Boolean of using Deep NWELL device + pcmpgr : Boolean of using P+ Guard Ring for Deep NWELL devices only + """ + + # Define layers + dnwell = layout.layer(12, 0) + dualgate = layout.layer(55, 0) + v5_xtor = layout.layer(112, 1) + nwell = layout.layer(21, 0) + comp = layout.layer(22, 0) + poly2 = layout.layer(30, 0) + nplus = layout.layer(32, 0) + pplus = layout.layer(31, 0) + contact = layout.layer(33, 0) + metal1 = layout.layer(34, 0) + + # Define variables + dbu_PERCISION = 1 / layout.dbu + nf = int(nf) + grw = grw * dbu_PERCISION + ld = ld * dbu_PERCISION + l = l * dbu_PERCISION + w = w * dbu_PERCISION + cmp2cont = 0.07 * dbu_PERCISION + cont_size = 0.22 * dbu_PERCISION + np_enc_cmp = 0.16 * dbu_PERCISION + pp_enc_cmp = 0.16 * dbu_PERCISION + cont2ply = 0.15 * dbu_PERCISION + ply_ext_cmp = 0.22 * dbu_PERCISION + np_enc_gate = 0.23 * dbu_PERCISION + cont2cont = 0.28 * dbu_PERCISION + dg_enc_ply = 0.4 * dbu_PERCISION + dg_enc_cmp = 0.24 * dbu_PERCISION + cmp2cmp = 0.32 * dbu_PERCISION + ply2gr = 0.26 * dbu_PERCISION + nwell_enc_pcomp = 0.43 * dbu_PERCISION + nwell_enc_ncomp = 0.12 * dbu_PERCISION + ld_violat = 0 * dbu_PERCISION + tie_violat = 0 * dbu_PERCISION + metal_violat = 0.01 * dbu_PERCISION + min_cmp_area = 0.2025 * dbu_PERCISION * dbu_PERCISION + dg_enc_dnwell = 0.5 * dbu_PERCISION + dnwell_enc_ncmp = 0.62 * dbu_PERCISION + dnwell_enc_pcmp = 0.93 * dbu_PERCISION + pcmp_gr2dnw = 2.5 * dbu_PERCISION + gr_w = 0.36 * dbu_PERCISION + + if deepnwell == True: + cmp2cmp = 0.36 * dbu_PERCISION + ply2gr = 0.3 * dbu_PERCISION + + if volt == "5V" or volt == "6V": + cmp2cmp = 0.36 * dbu_PERCISION + ply2gr = 0.3 * dbu_PERCISION + cmp2cmp = 0.36 * dbu_PERCISION + dnwell_enc_ncmp = 0.66 * dbu_PERCISION + dnwell_enc_pcmp = 1.1 * dbu_PERCISION + nwell_enc_pcomp = 0.6 * dbu_PERCISION + nwell_enc_ncomp = 0.16 * dbu_PERCISION + + if w < cont_size + 2 * cmp2cont: + if nf == 1: + if volt == "5V" or volt == "6V": + ld_violat = 0.22 * dbu_PERCISION + else: + ld_violat = 0.02 * dbu_PERCISION + + # Inserting PFET cell + cell_index = layout.add_cell("pfet") + cell = layout.cell(cell_index) + + w_changed = False + + # Inserting diffusion + if w < cont_size + 2 * cmp2cont: + cell.shapes(comp).insert( + pya.Box( + 0, + (cont_size + 2 * cmp2cont - w) / 2, + ( + 2 * (ld + ld_violat) + + l + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + (cont_size + 2 * cmp2cont - w) / 2, + ) + ) + w = cont_size + 2 * cmp2cont + w_changed = True + else: + cell.shapes(comp).insert( + pya.Box(0, 0, (2 * ld + l + (nf - 1) * (ld + l + cont2ply - cmp2cont)), w) + ) + + cell.shapes(pplus).insert( + pya.Box( + -np_enc_cmp, + -np_enc_gate, + ( + 2 * (ld + ld_violat) + + l + + np_enc_cmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + np_enc_gate, + ) + ) + + # Inserting gate/s + # Inserting a gate cell + gate_cell_index = layout.add_cell("gate") + gate_cell = layout.cell(gate_cell_index) + gate_cell.shapes(poly2).insert( + pya.Box(ld + ld_violat, -ply_ext_cmp, (ld + ld_violat + l), (w + ply_ext_cmp)) + ) + + # adding gate array + cell.insert( + pya.CellInstArray.new( + gate_cell_index, + pya.Trans.new(pya.Point.new(0, 0)), + pya.Point.new(ld + ld_violat + l + cont2ply - cmp2cont, 0), + pya.Point.new(0, 0), + int(nf), + 1, + ) + ) + + # Inserting a contact cell + cont_cell_index = layout.add_cell("contact") + cont_cell = layout.cell(cont_cell_index) + + # Inserting shapes now into the *contact* cell + cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) + + # Contact array count and postions + nx = int((ld - (cont_size + cmp2cont + cont2ply)) / (cont2cont + cont_size)) + 1 + ny = int((w - (cont_size + 2 * cmp2cont)) / (cont2cont + cont_size)) + 1 + dx = (ld - nx * cont_size - (nx - 1) * cont2cont) * cmp2cont / cont_size + dy = (w - ny * cont_size - (ny - 1) * cont2cont) / 2 + + # adding contact array and metals + # Left contacts + if not (w_changed == True and nf > 1) and (ld >= 440): + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new(pya.Point.new(dx, dy)), + pya.Point.new((cont2cont + cont_size), 0), + pya.Point.new(0, (cont2cont + cont_size)), + nx, + ny, + ) + ) + # Left metal + cell.shapes(metal1).insert( + pya.Box( + -metal_violat, + -metal_violat, + ld + metal_violat - (cont_size - 2 * cmp2cont), + w + metal_violat, + ) + ) + + # Adding diffusion to avoid contact violation + if nf == 1 and w_changed == True: + cell.shapes(comp).insert(pya.Box(0, 0, ld - (cont_size - 2 * cmp2cont), w)) + + # Right contacts and metals for each finger + for i in range(nf): + # Contacts + if not (w_changed == True and nf > 1) and (ld >= 440): + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + ( + (l + ld + ld_violat + cont2ply - cmp2cont) * i + + 2 * (ld + ld_violat) + + l + - cont_size + - dx + ), + dy, + ) + ), + pya.Point.new(-(cont2cont + cont_size), 0), + pya.Point.new(0, (cont2cont + cont_size)), + nx, + ny, + ) + ) + # Metals + + cell.shapes(metal1).insert( + pya.Box( + (ld + 2 * ld_violat + l + cont2ply - cmp2cont) * (i + 1) + - metal_violat, + -metal_violat, + ld + + metal_violat + + ld_violat + + (ld + ld_violat + l + cont2ply - cmp2cont) * (i + 1) + - (cont_size - 2 * cmp2cont), + w + metal_violat, + ) + ) + + # Adding diffusion to avoid contact violation + if nf == 1 and w_changed == True: + cell.shapes(comp).insert( + pya.Box( + (ld + 2 * ld_violat + l + cont2ply - cmp2cont) * (i + 1), + 0, + ld + + ld_violat + + (ld + ld_violat + l + cont2ply - cmp2cont) * (i + 1) + - (cont_size - 2 * cmp2cont), + w, + ) + ) + region = pya.Region.new(cell.begin_shapes_rec(comp)) + region.merge() + cell.clear(comp) + cell.shapes(comp).insert(region) + + if bulk == "Bulk Tie": + if deepnwell == True: + if volt == "5V": + # Inserting 5V layers + cell.shapes(v5_xtor).insert( + pya.Box( + -dg_enc_dnwell - dnwell_enc_ncmp - cmp2cmp - ld, + -dg_enc_dnwell - dnwell_enc_pcmp, + ( + 2 * (ld + ld_violat) + + l + + dg_enc_dnwell + + dnwell_enc_pcmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + dnwell_enc_pcmp + dg_enc_dnwell, + ) + ) + + cell.shapes(dualgate).insert( + pya.Box( + -dg_enc_dnwell - dnwell_enc_ncmp - cmp2cmp - ld, + -dg_enc_dnwell - dnwell_enc_pcmp, + ( + 2 * (ld + ld_violat) + + l + + dg_enc_dnwell + + dnwell_enc_pcmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + dnwell_enc_pcmp + dg_enc_dnwell, + ) + ) + + elif volt == "6V": + # Inserting 6V layers + cell.shapes(dualgate).insert( + pya.Box( + -dg_enc_dnwell - dnwell_enc_ncmp - cmp2cmp - ld, + -dg_enc_dnwell - dnwell_enc_pcmp, + ( + 2 * (ld + ld_violat) + + l + + dg_enc_dnwell + + dnwell_enc_pcmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + dnwell_enc_pcmp + dg_enc_dnwell, + ) + ) + + # Inserting DNWELL + cell.shapes(dnwell).insert( + pya.Box( + -dnwell_enc_ncmp - cmp2cmp - ld, + -dnwell_enc_pcmp, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_pcmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + dnwell_enc_pcmp, + ) + ) + + # Inserting Double Guard Ring + if pcmpgr == True: + cmp_inner = pya.Box( + -dnwell_enc_ncmp - cmp2cmp - ld - pcmp_gr2dnw, + -dnwell_enc_pcmp - pcmp_gr2dnw, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_pcmp + + pcmp_gr2dnw + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + dnwell_enc_pcmp + pcmp_gr2dnw, + ) + cmp_outer = pya.Box( + -dnwell_enc_ncmp - cmp2cmp - ld - pcmp_gr2dnw - gr_w, + -dnwell_enc_pcmp - pcmp_gr2dnw - gr_w, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_pcmp + + pcmp_gr2dnw + + gr_w + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + dnwell_enc_pcmp + pcmp_gr2dnw + gr_w, + ) + cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) + cell.shapes(comp).insert(cmp_gr) + + pp_inner = pya.Box( + -dnwell_enc_ncmp - cmp2cmp - ld - pcmp_gr2dnw + pp_enc_cmp, + -dnwell_enc_pcmp - pcmp_gr2dnw + pp_enc_cmp, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_pcmp + + pcmp_gr2dnw + - pp_enc_cmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + dnwell_enc_pcmp + pcmp_gr2dnw - pp_enc_cmp, + ) + pp_outer = pya.Box( + -dnwell_enc_ncmp - cmp2cmp - ld - pcmp_gr2dnw - gr_w - pp_enc_cmp, + -dnwell_enc_pcmp - pcmp_gr2dnw - gr_w - pp_enc_cmp, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_pcmp + + pcmp_gr2dnw + + gr_w + + pp_enc_cmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + dnwell_enc_pcmp + pcmp_gr2dnw + gr_w + pp_enc_cmp, + ) + pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) + cell.shapes(pplus).insert(pp_gr) + + else: + if volt == "5V": + # Inserting 5V layers + cell.shapes(v5_xtor).insert( + pya.Box( + -(cmp2cmp + dg_enc_cmp) - ld, + -(dg_enc_ply + ply_ext_cmp), + ( + 2 * (ld + ld_violat) + + l + + dg_enc_cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + w + (dg_enc_ply + ply_ext_cmp), + ) + ) + cell.shapes(dualgate).insert( + pya.Box( + -(cmp2cmp + dg_enc_cmp) - ld, + -(dg_enc_ply + ply_ext_cmp), + ( + 2 * (ld + ld_violat) + + l + + dg_enc_cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + w + (dg_enc_ply + ply_ext_cmp), + ) + ) + elif volt == "6V": + # Inserting 6V layers + cell.shapes(dualgate).insert( + pya.Box( + -(cmp2cmp + dg_enc_cmp) - ld, + -(dg_enc_ply + ply_ext_cmp), + ( + 2 * (ld + ld_violat) + + l + + dg_enc_cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + w + (dg_enc_ply + ply_ext_cmp), + ) + ) + + # Inserting nwell + cell.shapes(nwell).insert( + pya.Box( + -nwell_enc_ncomp - cmp2cmp - ld, + -nwell_enc_pcomp, + ( + 2 * (ld + ld_violat) + + l + + nwell_enc_pcomp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + w + nwell_enc_pcomp, + ) + ) + + # Inserting Tie + if (w * ld) < min_cmp_area: + tie_violat = (min_cmp_area * tol / ld - w) / 2 + cell.shapes(comp).insert( + pya.Box(-cmp2cmp - ld, -tie_violat, -cmp2cmp, w + tie_violat) + ) + cell.shapes(nplus).insert( + pya.Box( + -cmp2cmp - np_enc_cmp - ld, + -np_enc_cmp - tie_violat, + -cmp2cmp + np_enc_cmp, + w + tie_violat + np_enc_cmp, + ) + ) + + # Tie contacts + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + (-(cmp2cmp + cont_size) - dx * cont_size / (2 * cmp2cont)), dy + ) + ), + pya.Point.new(-(cont2cont + cont_size), 0), + pya.Point.new(0, (cont2cont + cont_size)), + nx, + ny, + ) + ) + + # Tie metal + cell.shapes(metal1).insert( + pya.Box(-cmp2cmp - ld, -tie_violat, -cmp2cmp, w + tie_violat) + ) + + elif bulk == "Guard Ring": + if deepnwell == True: + if volt == "5V": + # Inserting 5V layers + cell.shapes(v5_xtor).insert( + pya.Box( + -dg_enc_dnwell - dnwell_enc_ncmp - cmp2cmp - grw, + -dg_enc_dnwell - dnwell_enc_ncmp - (ply_ext_cmp + ply2gr) - grw, + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + dnwell_enc_ncmp + + dg_enc_dnwell + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + ( + w + + (ply_ext_cmp + ply2gr) + + grw + + dnwell_enc_ncmp + + dg_enc_dnwell + ), + ) + ) + + cell.shapes(dualgate).insert( + pya.Box( + -dg_enc_dnwell - dnwell_enc_ncmp - cmp2cmp - grw, + -dg_enc_dnwell - dnwell_enc_ncmp - (ply_ext_cmp + ply2gr) - grw, + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + dnwell_enc_ncmp + + dg_enc_dnwell + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + ( + w + + (ply_ext_cmp + ply2gr) + + grw + + dnwell_enc_ncmp + + dg_enc_dnwell + ), + ) + ) + + elif volt == "6V": + # Inserting 6V layers + cell.shapes(dualgate).insert( + pya.Box( + -dg_enc_dnwell - dnwell_enc_ncmp - cmp2cmp - grw, + -dg_enc_dnwell - dnwell_enc_ncmp - (ply_ext_cmp + ply2gr) - grw, + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + dnwell_enc_ncmp + + dg_enc_dnwell + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + ( + w + + (ply_ext_cmp + ply2gr) + + grw + + dnwell_enc_ncmp + + dg_enc_dnwell + ), + ) + ) + + # Inserting DNWELL + cell.shapes(dnwell).insert( + pya.Box( + -dnwell_enc_ncmp - cmp2cmp - grw, + -dnwell_enc_ncmp - (ply_ext_cmp + ply2gr) - grw, + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + dnwell_enc_ncmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + (ply_ext_cmp + ply2gr) + grw + dnwell_enc_ncmp), + ) + ) + + # Inserting Double Guard Ring + if pcmpgr == True: + cmp_inner = pya.Box( + -dnwell_enc_ncmp - cmp2cmp - grw - pcmp_gr2dnw, + -dnwell_enc_ncmp - (ply_ext_cmp + ply2gr) - grw - pcmp_gr2dnw, + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + dnwell_enc_ncmp + + pcmp_gr2dnw + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + (ply_ext_cmp + ply2gr) + grw + dnwell_enc_ncmp + pcmp_gr2dnw), + ) + cmp_outer = pya.Box( + -dnwell_enc_ncmp - cmp2cmp - grw - pcmp_gr2dnw - gr_w, + -dnwell_enc_ncmp + - (ply_ext_cmp + ply2gr) + - grw + - pcmp_gr2dnw + - gr_w, + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + dnwell_enc_ncmp + + pcmp_gr2dnw + + gr_w + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + ( + w + + (ply_ext_cmp + ply2gr) + + grw + + dnwell_enc_ncmp + + pcmp_gr2dnw + + gr_w + ), + ) + cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) + cell.shapes(comp).insert(cmp_gr) + + pp_inner = pya.Box( + -dnwell_enc_ncmp - cmp2cmp - grw - pcmp_gr2dnw + pp_enc_cmp, + -dnwell_enc_ncmp + - (ply_ext_cmp + ply2gr) + - grw + - pcmp_gr2dnw + + pp_enc_cmp, + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + dnwell_enc_ncmp + + pcmp_gr2dnw + - pp_enc_cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + ( + w + + (ply_ext_cmp + ply2gr) + + grw + + dnwell_enc_ncmp + + pcmp_gr2dnw + - pp_enc_cmp + ), + ) + pp_outer = pya.Box( + -dnwell_enc_ncmp - cmp2cmp - grw - pcmp_gr2dnw - gr_w - pp_enc_cmp, + -dnwell_enc_ncmp + - (ply_ext_cmp + ply2gr) + - grw + - pcmp_gr2dnw + - gr_w + - pp_enc_cmp, + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + dnwell_enc_ncmp + + pcmp_gr2dnw + + gr_w + + pp_enc_cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + ( + w + + (ply_ext_cmp + ply2gr) + + grw + + dnwell_enc_ncmp + + pcmp_gr2dnw + + gr_w + + pp_enc_cmp + ), + ) + pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) + cell.shapes(pplus).insert(pp_gr) + + else: + if volt == "5V": + # Inserting 5V layers + cell.shapes(v5_xtor).insert( + pya.Box( + -(cmp2cmp + dg_enc_cmp) - grw, + -(ply_ext_cmp + ply2gr + dg_enc_cmp) - grw, + ( + 2 * (ld + ld_violat) + + l + + grw + + (cmp2cmp + dg_enc_cmp) + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + ply_ext_cmp + ply2gr + dg_enc_cmp + grw), + ) + ) + cell.shapes(dualgate).insert( + pya.Box( + -(cmp2cmp + dg_enc_cmp) - grw, + -(ply_ext_cmp + ply2gr + dg_enc_cmp) - grw, + ( + 2 * (ld + ld_violat) + + l + + grw + + (cmp2cmp + dg_enc_cmp) + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + ply_ext_cmp + ply2gr + dg_enc_cmp + grw), + ) + ) + elif volt == "6V": + # Inserting 6V layers + cell.shapes(dualgate).insert( + pya.Box( + -(cmp2cmp + dg_enc_cmp) - grw, + -(ply_ext_cmp + ply2gr + dg_enc_cmp) - grw, + ( + 2 * (ld + ld_violat) + + l + + grw + + (cmp2cmp + dg_enc_cmp) + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + ply_ext_cmp + ply2gr + dg_enc_cmp + grw), + ) + ) + + # Inserting nwell + cell.shapes(nwell).insert( + pya.Box( + -nwell_enc_ncomp - cmp2cmp - grw, + -ply_ext_cmp - ply2gr - nwell_enc_ncomp - grw, + ( + 2 * (ld + ld_violat) + + l + + grw + + nwell_enc_ncomp + + cmp2cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + ply_ext_cmp + ply2gr + nwell_enc_ncomp + grw), + ) + ) + + # Inserting Guard Ring diffusion + cell.shapes(comp).insert( + pya.Polygon( + [ + pya.Point(-cmp2cmp - grw, -(ply_ext_cmp + ply2gr) - grw), + pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), + pya.Point(-cmp2cmp, (w + (ply_ext_cmp + ply2gr))), + pya.Point(-cmp2cmp, -(ply_ext_cmp + ply2gr)), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + cmp2cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + -(ply_ext_cmp + ply2gr), + ), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + cmp2cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + (ply_ext_cmp + ply2gr)), + ), + pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), + pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr) + grw)), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + (ply_ext_cmp + ply2gr) + grw), + ), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + -(ply_ext_cmp + ply2gr) - grw, + ), + ], + True, + ) + ) + cell.shapes(nplus).insert( + pya.Polygon( + [ + pya.Point( + -(cmp2cmp + pp_enc_cmp) - grw, + -(ply_ext_cmp + ply2gr + pp_enc_cmp) - grw, + ), + pya.Point( + -(cmp2cmp + pp_enc_cmp) - grw, + (w + (ply_ext_cmp + ply2gr - pp_enc_cmp)), + ), + pya.Point( + -(cmp2cmp - pp_enc_cmp), + (w + (ply_ext_cmp + ply2gr - pp_enc_cmp)), + ), + pya.Point( + -(cmp2cmp - pp_enc_cmp), -(ply_ext_cmp + ply2gr - pp_enc_cmp) + ), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + (cmp2cmp - pp_enc_cmp) + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + -(ply_ext_cmp + ply2gr - pp_enc_cmp), + ), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + (cmp2cmp - pp_enc_cmp) + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + (ply_ext_cmp + ply2gr - pp_enc_cmp)), + ), + pya.Point( + -(cmp2cmp + pp_enc_cmp) - grw, + (w + (ply_ext_cmp + ply2gr - pp_enc_cmp)), + ), + pya.Point( + -(cmp2cmp + pp_enc_cmp) - grw, + (w + (ply_ext_cmp + ply2gr + pp_enc_cmp) + grw), + ), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + grw + + (cmp2cmp + pp_enc_cmp) + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + (ply_ext_cmp + ply2gr + pp_enc_cmp) + grw), + ), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + grw + + (cmp2cmp + pp_enc_cmp) + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + -(ply_ext_cmp + ply2gr + pp_enc_cmp) - grw, + ), + ], + True, + ) + ) + + # Inserting Guard Ring metal + cell.shapes(metal1).insert( + pya.Polygon( + [ + pya.Point(-cmp2cmp - grw, -(ply_ext_cmp + ply2gr) - grw), + pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), + pya.Point(-cmp2cmp, (w + (ply_ext_cmp + ply2gr))), + pya.Point(-cmp2cmp, -(ply_ext_cmp + ply2gr)), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + cmp2cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + -(ply_ext_cmp + ply2gr), + ), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + cmp2cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + (ply_ext_cmp + ply2gr)), + ), + pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), + pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr) + grw)), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + (w + (ply_ext_cmp + ply2gr) + grw), + ), + pya.Point( + ( + 2 * (ld + ld_violat) + + l + + grw + + cmp2cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + -(ply_ext_cmp + ply2gr) - grw, + ), + ], + True, + ) + ) + + nxgr = int((grw - (cont_size + 2 * cmp2cont)) / (cont2cont + cont_size)) + 1 + nygr = ( + int( + ( + (2 * grw + w + 2 * (ply_ext_cmp + ply2gr)) + - (cont_size + 2 * cmp2cont) + ) + / (cont2cont + cont_size) + ) + + 1 + ) + dxgr = (grw - nxgr * cont_size - (nxgr - 1) * cont2cont) / 2 + dygr = ( + (2 * grw + w + 2 * (ply_ext_cmp + ply2gr)) + - nygr * cont_size + - (nygr - 1) * cont2cont + ) / 2 + nxgr_h = ( + int( + ( + ( + 2 * (ld + ld_violat) + + l + + 2 * cmp2cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ) + - 3 * cont2cont + ) + / (cont2cont + cont_size) + ) + + 1 + ) + dxgr_h = ( + ( + 2 * (ld + ld_violat) + + l + + cont2cont + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ) + - nxgr_h * cont_size + - (nxgr_h - 1) * cont2cont + ) / 2 + + # Inserting Guard Ring contacts + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + (-cmp2cmp - grw + dxgr), (-(ply_ext_cmp + ply2gr) - grw + dygr) + ) + ), + pya.Point.new((cont2cont + cont_size), 0), + pya.Point.new(0, (cont2cont + cont_size)), + nxgr, + nygr, + ) + ) + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + -(2 * cmp2cont) + dxgr_h, -(2 * cont_size) - ply2gr - dxgr + ) + ), + pya.Point.new((cont2cont + cont_size), 0), + pya.Point.new(0, -(cont2cont + cont_size)), + nxgr_h, + nxgr, + ) + ) + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + 2 * (ld + ld_violat) + + l + + grw + - dxgr + + (cmp2cmp - cont_size) + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont), + (-(ply_ext_cmp + ply2gr) - grw + dygr), + ) + ), + pya.Point.new(-(cont2cont + cont_size), 0), + pya.Point.new(0, (cont2cont + cont_size)), + nxgr, + nygr, + ) + ) + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + (-(2 * cmp2cont) + dxgr_h), (w + (ply_ext_cmp + ply2gr) + dxgr) + ) + ), + pya.Point.new((cont2cont + cont_size), 0), + pya.Point.new(0, (cont2cont + cont_size)), + nxgr_h, + nxgr, + ) + ) + + else: + if deepnwell == True: + if volt == "5V": + # Inserting 5V layers + cell.shapes(v5_xtor).insert( + pya.Box( + -dg_enc_dnwell - dnwell_enc_pcmp, + -dg_enc_dnwell - dnwell_enc_pcmp, + ( + 2 * (ld + ld_violat) + + l + + dg_enc_dnwell + + dnwell_enc_pcmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + dnwell_enc_pcmp + dg_enc_dnwell, + ) + ) + + cell.shapes(dualgate).insert( + pya.Box( + -dg_enc_dnwell - dnwell_enc_pcmp, + -dg_enc_dnwell - dnwell_enc_pcmp, + ( + 2 * (ld + ld_violat) + + l + + dg_enc_dnwell + + dnwell_enc_pcmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + dnwell_enc_pcmp + dg_enc_dnwell, + ) + ) + + elif volt == "6V": + # Inserting 6V layers + cell.shapes(dualgate).insert( + pya.Box( + -dg_enc_dnwell - dnwell_enc_pcmp, + -dg_enc_dnwell - dnwell_enc_pcmp, + ( + 2 * (ld + ld_violat) + + l + + dg_enc_dnwell + + dnwell_enc_pcmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + dnwell_enc_pcmp + dg_enc_dnwell, + ) + ) + + # Inserting DNWELL + cell.shapes(dnwell).insert( + pya.Box( + -dnwell_enc_pcmp, + -dnwell_enc_pcmp, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_pcmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + dnwell_enc_pcmp, + ) + ) + + # Inserting Double Guard Ring + if pcmpgr == True: + cmp_inner = pya.Box( + -dnwell_enc_pcmp - pcmp_gr2dnw, + -dnwell_enc_pcmp - pcmp_gr2dnw, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_pcmp + + pcmp_gr2dnw + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + dnwell_enc_pcmp + pcmp_gr2dnw, + ) + cmp_outer = pya.Box( + -dnwell_enc_pcmp - pcmp_gr2dnw - gr_w, + -dnwell_enc_pcmp - pcmp_gr2dnw - gr_w, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_pcmp + + pcmp_gr2dnw + + gr_w + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + dnwell_enc_pcmp + pcmp_gr2dnw + gr_w, + ) + cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) + cell.shapes(comp).insert(cmp_gr) + + pp_inner = pya.Box( + -dnwell_enc_pcmp - pcmp_gr2dnw + pp_enc_cmp, + -dnwell_enc_pcmp - pcmp_gr2dnw + pp_enc_cmp, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_pcmp + + pcmp_gr2dnw + - pp_enc_cmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + dnwell_enc_pcmp + pcmp_gr2dnw - pp_enc_cmp, + ) + pp_outer = pya.Box( + -dnwell_enc_pcmp - pcmp_gr2dnw - gr_w - pp_enc_cmp, + -dnwell_enc_pcmp - pcmp_gr2dnw - gr_w - pp_enc_cmp, + ( + 2 * (ld + ld_violat) + + l + + dnwell_enc_pcmp + + pcmp_gr2dnw + + gr_w + + pp_enc_cmp + + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont) + ), + w + dnwell_enc_pcmp + pcmp_gr2dnw + gr_w + pp_enc_cmp, + ) + pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) + cell.shapes(pplus).insert(pp_gr) + + else: + if volt == "5V": + # Inserting 5V layers + cell.shapes(v5_xtor).insert( + pya.Box( + -dg_enc_cmp, + -(dg_enc_ply + ply_ext_cmp), + ( + 2 * (ld + ld_violat) + + l + + dg_enc_cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + w + (dg_enc_ply + ply_ext_cmp), + ) + ) + cell.shapes(dualgate).insert( + pya.Box( + -dg_enc_cmp, + -(dg_enc_ply + ply_ext_cmp), + ( + 2 * (ld + ld_violat) + + l + + dg_enc_cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + w + (dg_enc_ply + ply_ext_cmp), + ) + ) + elif volt == "6V": + # Inserting 6V layers + cell.shapes(dualgate).insert( + pya.Box( + -dg_enc_cmp, + -(dg_enc_ply + ply_ext_cmp), + ( + 2 * (ld + ld_violat) + + l + + dg_enc_cmp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + w + (dg_enc_ply + ply_ext_cmp), + ) + ) + + # Inserting NWELL + cell.shapes(nwell).insert( + pya.Box( + -nwell_enc_pcomp, + -nwell_enc_pcomp, + ( + 2 * (ld + ld_violat) + + l + + nwell_enc_pcomp + + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont) + ), + w + nwell_enc_pcomp, + ) + ) + + cell.flatten(True) + return cell + + +def draw_nfet_06v0_nvt(layout, l, w, ld, nf, grw, bulk): + """ + Usage:- + used to draw Native NFET 6V transistor by specifying parameters + Arguments:- + layout : Object of layout + l : Float of gate length + w : Float of gate width + ld : Float of diffusion length + nf : Integer of number of fingers + grw : Float of guard ring width [If enabled] + bulk : String of bulk connection type [None, Bulk Tie, Guard Ring] + """ + + # Define layers + dualgate = layout.layer(55, 0) + nat = layout.layer(5, 0) + comp = layout.layer(22, 0) + poly2 = layout.layer(30, 0) + nplus = layout.layer(32, 0) + pplus = layout.layer(31, 0) + contact = layout.layer(33, 0) + metal1 = layout.layer(34, 0) + + # Define variables + dbu_PERCISION = 1 / layout.dbu + nf = int(nf) + grw = grw * dbu_PERCISION + ld = ld * dbu_PERCISION + l = l * dbu_PERCISION + w = w * dbu_PERCISION + cmp2cont = 0.07 * dbu_PERCISION + cont_size = 0.22 * dbu_PERCISION + np_enc_cmp = 0.16 * dbu_PERCISION + pp_enc_cmp = 0.16 * dbu_PERCISION + cont2ply = 0.15 * dbu_PERCISION + ply_ext_cmp = 0.22 * dbu_PERCISION + np_enc_gate = 0.23 * dbu_PERCISION + cont2cont = 0.28 * dbu_PERCISION + cmp2cmp = 0.36 * dbu_PERCISION + nat_enc_cmp = 2 * dbu_PERCISION + + # Inserting NFET cell + cell_index = layout.add_cell("nfet_06v0_nvt") + cell = layout.cell(cell_index) + + # Inserting diffusion + cell.shapes(comp).insert( + pya.Box(0, 0, (2 * ld + l + (nf - 1) * (ld + l + cont2ply - cmp2cont)), w) + ) + cell.shapes(nplus).insert( + pya.Box( + -np_enc_cmp, + -np_enc_gate, + (2 * ld + l + np_enc_cmp + (nf - 1) * (ld + l + cont2ply - cmp2cont)), + w + np_enc_gate, + ) + ) + cell.shapes(nat).insert( + pya.Box( + -nat_enc_cmp, + -nat_enc_cmp, + (2 * ld + l + nat_enc_cmp + (nf - 1) * (ld + l + cont2ply - cmp2cont)), + w + nat_enc_cmp, + ) + ) + cell.shapes(dualgate).insert( + pya.Box( + -nat_enc_cmp, + -nat_enc_cmp, + (2 * ld + l + nat_enc_cmp + (nf - 1) * (ld + l + cont2ply - cmp2cont)), + w + nat_enc_cmp, + ) + ) + + # Inserting gate/s + # Inserting a gate cell + gate_cell_index = layout.add_cell("gate") + gate_cell = layout.cell(gate_cell_index) + gate_cell.shapes(poly2).insert( + pya.Box(ld, -ply_ext_cmp, (ld + l), (w + ply_ext_cmp)) + ) + + # adding gate array + cell.insert( + pya.CellInstArray.new( + gate_cell_index, + pya.Trans.new(pya.Point.new(0, 0)), + pya.Point.new(ld + l + cont2ply - cmp2cont, 0), + pya.Point.new(0, 0), + int(nf), + 1, + ) + ) + + # Inserting a contact cell + cont_cell_index = layout.add_cell("contact") + cont_cell = layout.cell(cont_cell_index) + + # Inserting shapes now into the *contact* cell + cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) + + # Contact array count and postions + nx = int((ld - (cont_size + cmp2cont + cont2ply)) / (cont2cont + cont_size)) + 1 + ny = int((w - (cont_size + 2 * cmp2cont)) / (cont2cont + cont_size)) + 1 + dx = (ld - nx * cont_size - (nx - 1) * cont2cont) * cmp2cont / cont_size + dy = (w - ny * cont_size - (ny - 1) * cont2cont) / 2 + + # adding contact array and metals + # Left contacts + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new(pya.Point.new(dx, dy)), + pya.Point.new((cont2cont + cont_size), 0), + pya.Point.new(0, (cont2cont + cont_size)), + nx, + ny, + ) + ) + # Left metal + cell.shapes(metal1).insert(pya.Box(0, 0, ld - (cont_size - 2 * cmp2cont), w)) + + # Right contacts and metals for each finger + for i in range(nf): + # Contacts + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + ( + (l + ld + cont2ply - cmp2cont) * i + + 2 * ld + + l + - cont_size + - dx + ), + dy, + ) + ), + pya.Point.new(-(cont2cont + cont_size), 0), + pya.Point.new(0, (cont2cont + cont_size)), + nx, + ny, + ) + ) + # Metals + cell.shapes(metal1).insert( + pya.Box( + (ld + l + cont2ply - cmp2cont) * (i + 1), + 0, + ld + + (ld + l + cont2ply - cmp2cont) * (i + 1) + - (cont_size - 2 * cmp2cont), + w, + ) + ) + + if bulk == "Bulk Tie": + # Inserting tie + cell.shapes(comp).insert( + pya.Box(-(nat_enc_cmp + cmp2cmp) - ld, 0, -(nat_enc_cmp + cmp2cmp), w) + ) + cell.shapes(pplus).insert( + pya.Box( + -(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - ld, + -pp_enc_cmp, + -(nat_enc_cmp + cmp2cmp - pp_enc_cmp), + w + pp_enc_cmp, + ) + ) + + # Tie contacts + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + ( + -(nat_enc_cmp + cmp2cmp + cont_size) + - dx * cont_size / (2 * cmp2cont) + ), + dy, + ) + ), + pya.Point.new(-(cont2cont + cont_size), 0), + pya.Point.new(0, (cont2cont + cont_size)), + nx, + ny, + ) + ) + + # Tie metal + cell.shapes(metal1).insert( + pya.Box(-(nat_enc_cmp + cmp2cmp) - ld, 0, -(nat_enc_cmp + cmp2cmp), w) + ) + + elif bulk == "Guard Ring": + # Inserting Guard Ring diffusion + cell.shapes(comp).insert( + pya.Polygon( + [ + pya.Point( + -(nat_enc_cmp + cmp2cmp) - grw, -(nat_enc_cmp + cmp2cmp) - grw + ), + pya.Point( + -(nat_enc_cmp + cmp2cmp) - grw, (w + (nat_enc_cmp + cmp2cmp)) + ), + pya.Point(-(nat_enc_cmp + cmp2cmp), (w + (nat_enc_cmp + cmp2cmp))), + pya.Point(-(nat_enc_cmp + cmp2cmp), -(nat_enc_cmp + cmp2cmp)), + pya.Point( + ( + 2 * ld + + l + + (nat_enc_cmp + cmp2cmp) + + (nf - 1) * (ld + l + cont2ply - cmp2cont) + ), + -(nat_enc_cmp + cmp2cmp), + ), + pya.Point( + ( + 2 * ld + + l + + (nat_enc_cmp + cmp2cmp) + + (nf - 1) * (ld + l + cont2ply - cmp2cont) + ), + (w + (nat_enc_cmp + cmp2cmp)), + ), + pya.Point( + -(nat_enc_cmp + cmp2cmp) - grw, (w + (nat_enc_cmp + cmp2cmp)) + ), + pya.Point( + -(nat_enc_cmp + cmp2cmp) - grw, + (w + (nat_enc_cmp + cmp2cmp) + grw), + ), + pya.Point( + ( + 2 * ld + + l + + grw + + (nat_enc_cmp + cmp2cmp) + + (nf - 1) * (ld + l + cont2ply - cmp2cont) + ), + (w + (nat_enc_cmp + cmp2cmp) + grw), + ), + pya.Point( + ( + 2 * ld + + l + + grw + + (nat_enc_cmp + cmp2cmp) + + (nf - 1) * (ld + l + cont2ply - cmp2cont) + ), + -(nat_enc_cmp + cmp2cmp) - grw, + ), + ], + True, + ) + ) + cell.shapes(pplus).insert( + pya.Polygon( + [ + pya.Point( + -(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - grw, + -(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - grw, + ), + pya.Point( + -(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - grw, + (w + (nat_enc_cmp + cmp2cmp - pp_enc_cmp)), + ), + pya.Point( + -(nat_enc_cmp + cmp2cmp - pp_enc_cmp), + (w + (nat_enc_cmp + cmp2cmp - pp_enc_cmp)), + ), + pya.Point( + -(nat_enc_cmp + cmp2cmp - pp_enc_cmp), + -(nat_enc_cmp + cmp2cmp - pp_enc_cmp), + ), + pya.Point( + ( + 2 * ld + + l + + (nat_enc_cmp + cmp2cmp - pp_enc_cmp) + + (nf - 1) * (ld + l + cont2ply - cmp2cont) + ), + -(nat_enc_cmp + cmp2cmp - pp_enc_cmp), + ), + pya.Point( + ( + 2 * ld + + l + + (nat_enc_cmp + cmp2cmp - pp_enc_cmp) + + (nf - 1) * (ld + l + cont2ply - cmp2cont) + ), + (w + (nat_enc_cmp + cmp2cmp - pp_enc_cmp)), + ), + pya.Point( + -(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - grw, + (w + (nat_enc_cmp + cmp2cmp - pp_enc_cmp)), + ), + pya.Point( + -(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - grw, + (w + (nat_enc_cmp + cmp2cmp + pp_enc_cmp) + grw), + ), + pya.Point( + ( + 2 * ld + + l + + grw + + (nat_enc_cmp + cmp2cmp + pp_enc_cmp) + + (nf - 1) * (ld + l + cont2ply - cmp2cont) + ), + (w + (nat_enc_cmp + cmp2cmp + pp_enc_cmp) + grw), + ), + pya.Point( + ( + 2 * ld + + l + + grw + + (nat_enc_cmp + cmp2cmp + pp_enc_cmp) + + (nf - 1) * (ld + l + cont2ply - cmp2cont) + ), + -(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - grw, + ), + ], + True, + ) + ) + + # Inserting Guard Ring metal + cell.shapes(metal1).insert( + pya.Polygon( + [ + pya.Point( + -(nat_enc_cmp + cmp2cmp) - grw, -(nat_enc_cmp + cmp2cmp) - grw + ), + pya.Point( + -(nat_enc_cmp + cmp2cmp) - grw, (w + (nat_enc_cmp + cmp2cmp)) + ), + pya.Point(-(nat_enc_cmp + cmp2cmp), (w + (nat_enc_cmp + cmp2cmp))), + pya.Point(-(nat_enc_cmp + cmp2cmp), -(nat_enc_cmp + cmp2cmp)), + pya.Point( + ( + 2 * ld + + l + + (nat_enc_cmp + cmp2cmp) + + (nf - 1) * (ld + l + cont2ply - cmp2cont) + ), + -(nat_enc_cmp + cmp2cmp), + ), + pya.Point( + ( + 2 * ld + + l + + (nat_enc_cmp + cmp2cmp) + + (nf - 1) * (ld + l + cont2ply - cmp2cont) + ), + (w + (nat_enc_cmp + cmp2cmp)), + ), + pya.Point( + -(nat_enc_cmp + cmp2cmp) - grw, (w + (nat_enc_cmp + cmp2cmp)) + ), + pya.Point( + -(nat_enc_cmp + cmp2cmp) - grw, + (w + (nat_enc_cmp + cmp2cmp) + grw), + ), + pya.Point( + ( + 2 * ld + + l + + grw + + (nat_enc_cmp + cmp2cmp) + + (nf - 1) * (ld + l + cont2ply - cmp2cont) + ), + (w + (nat_enc_cmp + cmp2cmp) + grw), + ), + pya.Point( + ( + 2 * ld + + l + + grw + + (nat_enc_cmp + cmp2cmp) + + (nf - 1) * (ld + l + cont2ply - cmp2cont) + ), + -(nat_enc_cmp + cmp2cmp) - grw, + ), + ], + True, + ) + ) + + nxgr = int((grw - (cont_size + 2 * cmp2cont)) / (cont2cont + cont_size)) + 1 + nygr = ( + int( + ( + (2 * grw + w + 2 * (nat_enc_cmp + cmp2cmp)) + - (cont_size + 2 * cmp2cont) + ) + / (cont2cont + cont_size) + ) + + 1 + ) + dxgr = (grw - nxgr * cont_size - (nxgr - 1) * cont2cont) / 2 + dygr = ( + (2 * grw + w + 2 * (nat_enc_cmp + cmp2cmp)) + - nygr * cont_size + - (nygr - 1) * cont2cont + ) / 2 + nxgr_h = ( + int( + ( + ( + 2 * ld + + l + + 2 * (nat_enc_cmp + cmp2cmp) + + (nf - 1) * (ld + l + cont2ply - cmp2cont) + ) + - 3 * cont2cont + ) + / (cont2cont + cont_size) + ) + + 1 + ) + dxgr_h = ( + ( + 2 * ld + + l + + (nat_enc_cmp + cmp2cmp) + + (nf - 1) * (ld + l + cont2ply - cmp2cont) + ) + - nxgr_h * cont_size + - (nxgr_h - 1) * cont2cont + ) / 2 + + # Inserting Guard Ring contacts + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + (-(nat_enc_cmp + cmp2cmp) - grw + dxgr), + (-(nat_enc_cmp + cmp2cmp) - grw + dygr), + ) + ), + pya.Point.new((cont2cont + cont_size), 0), + pya.Point.new(0, (cont2cont + cont_size)), + nxgr, + nygr, + ) + ) + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + -(nat_enc_cmp + cmp2cmp) / 2 + dxgr_h, + -(nat_enc_cmp + cmp2cmp + cont_size) - dxgr, + ) + ), + pya.Point.new((cont2cont + cont_size), 0), + pya.Point.new(0, -(cont2cont + cont_size)), + nxgr_h, + nxgr, + ) + ) + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + 2 * ld + + l + + grw + - dxgr + + nat_enc_cmp + + cmp2cmp + - cont_size + + (nf - 1) * (ld + l + cont2ply - cmp2cont), + (-(nat_enc_cmp + cmp2cmp) - grw + dygr), + ) + ), + pya.Point.new(-(cont2cont + cont_size), 0), + pya.Point.new(0, (cont2cont + cont_size)), + nxgr, + nygr, + ) + ) + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + -(nat_enc_cmp + cmp2cmp) / 2 + dxgr_h, + w + (nat_enc_cmp + cmp2cmp) + dxgr, + ) + ), + pya.Point.new((cont2cont + cont_size), 0), + pya.Point.new(0, (cont2cont + cont_size)), + nxgr_h, + nxgr, + ) + ) + + cell.flatten(True) + return cell + + +def draw_nfet_10v0_asym(layout, l, w): + """ + Usage:- + used to draw LDNFET 10V transistor by specifying parameters + Arguments:- + layout : Object of layout + l : Float of gate length + w : Float of gate width + """ + + # Define layers + dualgate = layout.layer(55, 0) + ldmos_xtor = layout.layer(226, 0) + mvsd = layout.layer(210, 0) + comp = layout.layer(22, 0) + poly2 = layout.layer(30, 0) + nplus = layout.layer(32, 0) + pplus = layout.layer(31, 0) + contact = layout.layer(33, 0) + metal1 = layout.layer(34, 0) + + # Define variables + dbu_PERCISION = 1 / layout.dbu + l = l * dbu_PERCISION + w = w * dbu_PERCISION + cmp2cont = 0.07 * dbu_PERCISION + cont_size = 0.22 * dbu_PERCISION + np_enc_cmp = 0.16 * dbu_PERCISION + pp_enc_cmp = 0.16 * dbu_PERCISION + cont2ply = 0.15 * dbu_PERCISION + metal_w = 0.38 * dbu_PERCISION + ply_ext_cmp = 0.4 * dbu_PERCISION + ply_fld = 0.2 * dbu_PERCISION + np_enc_gate = 0.23 * dbu_PERCISION + cont2cont = 0.25 * dbu_PERCISION + cmp2cmp = 0.36 * dbu_PERCISION + cmp2gr = 0.4 * dbu_PERCISION + mvsd_ext_cmp = 0.5 * dbu_PERCISION + mvsd_ov_cmp = 0.4 * dbu_PERCISION + mvsd2gr = 1 * dbu_PERCISION + ply2gr = 0.4 * dbu_PERCISION + drain2ply = 0.16 * dbu_PERCISION + dg_enc_cmp = 0.5 * dbu_PERCISION + + # Inserting NFET cell + cell_index = layout.add_cell("nfet_10v0_asym") + cell = layout.cell(cell_index) + + # Inserting layers for LDFET + cell.shapes(dualgate).insert( + pya.Box( + -( + dg_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont2ply + + cont_size + + cmp2cont + + mvsd_ov_cmp + + cmp2cmp + ) + - l, + -(mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size + dg_enc_cmp) - w / 2, + ( + dg_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont2ply + + cont_size + + cmp2cont + + mvsd_ov_cmp + + cmp2cmp + ) + + l, + (mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size + dg_enc_cmp) + w / 2, + ) + ) + cell.shapes(ldmos_xtor).insert( + pya.Box( + -( + dg_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont2ply + + cont_size + + cmp2cont + + mvsd_ov_cmp + + cmp2cmp + ) + - l, + -(mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size + dg_enc_cmp) - w / 2, + ( + dg_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont2ply + + cont_size + + cmp2cont + + mvsd_ov_cmp + + cmp2cmp + ) + + l, + (mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size + dg_enc_cmp) + w / 2, + ) + ) + + # Inserting drain diffusion + cell.shapes(comp).insert(pya.Box(-cont_size / 2, -w / 2, cont_size / 2, w / 2)) + cell.shapes(mvsd).insert( + pya.Box( + -(cont_size / 2 + cmp2cmp + mvsd_ov_cmp), + -w / 2 - mvsd_ext_cmp, + (cont_size / 2 + cmp2cmp + mvsd_ov_cmp), + w / 2 + mvsd_ext_cmp, + ) + ) + + # Inserting source diffusion + cell.shapes(comp).insert( + pya.Box( + (cont_size / 2 + cmp2cmp), + -w / 2, + (cont_size / 2 + cmp2cmp + mvsd_ov_cmp + cont2ply + cont_size + cmp2cont) + + l, + w / 2, + ) + ) + cell.shapes(comp).insert( + pya.Box( + -(cont_size / 2 + cmp2cmp), + -w / 2, + -(cont_size / 2 + cmp2cmp + mvsd_ov_cmp + cont2ply + cont_size + cmp2cont) + - l, + w / 2, + ) + ) + + cell.shapes(nplus).insert( + pya.Box( + -( + cont_size / 2 + + cmp2cmp + + mvsd_ov_cmp + + cont2ply + + cont_size + + cmp2cont + + np_enc_cmp + ) + - l, + -w / 2 - np_enc_gate, + ( + cont_size / 2 + + cmp2cmp + + mvsd_ov_cmp + + cont2ply + + cont_size + + cmp2cont + + np_enc_cmp + ) + + l, + w / 2 + np_enc_gate, + ) + ) + + # Inserting gates + cell.shapes(poly2).insert( + pya.Box( + (cont_size / 2 + drain2ply), + -w / 2 - ply_ext_cmp, + (cont_size / 2 + cmp2cmp + mvsd_ov_cmp) + l, + w / 2 + mvsd_ext_cmp + mvsd2gr - ply2gr, + ) + ) + cell.shapes(poly2).insert( + pya.Box( + -(cont_size / 2 + drain2ply), + -w / 2 - ply_ext_cmp, + -(cont_size / 2 + cmp2cmp + mvsd_ov_cmp) - l, + w / 2 + mvsd_ext_cmp + mvsd2gr - ply2gr, + ) + ) + + # Inserting a contact cell + cont_cell_index = layout.add_cell("contact") + cont_cell = layout.cell(cont_cell_index) + + # Inserting shapes now into the *contact* cell + cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) + + # Contact array count and postions + ny = int((w - (cont_size + 2 * cmp2cont)) / (cont_size + cont2cont)) + 1 + dy = (w - ny * cont_size - (ny - 1) * cont2cont) / 2 + ng = ( + int( + ((l + mvsd_ov_cmp + ply_fld) - (cont_size + 2 * cmp2cont)) + / (cont_size + cont2cont) + ) + + 1 + ) + dg = (l + mvsd_ov_cmp + ply_fld - ng * cont_size - (ng - 1) * cont2cont) / 2 + + # Inserting contact array and metals + # gate contacts and metal + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + (cont_size / 2 + drain2ply) + dg, + w / 2 + mvsd_ext_cmp + mvsd2gr - ply2gr - (metal_w + cont_size) / 2, + ) + ), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + ng, + 1, + ) + ) + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + -(1.5 * cont_size + drain2ply) - dg, + w / 2 + mvsd_ext_cmp + mvsd2gr - ply2gr - (metal_w + cont_size) / 2, + ) + ), + pya.Point.new(-(cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + ng, + 1, + ) + ) + cell.shapes(metal1).insert( + pya.Box( + (cont_size / 2 + drain2ply), + w / 2 + mvsd_ext_cmp + mvsd2gr - ply2gr - metal_w, + (cont_size / 2 + cmp2cmp + mvsd_ov_cmp) + l, + w / 2 + mvsd_ext_cmp + mvsd2gr - ply2gr, + ) + ) + cell.shapes(metal1).insert( + pya.Box( + -(cont_size / 2 + drain2ply), + w / 2 + mvsd_ext_cmp + mvsd2gr - ply2gr - metal_w, + -(cont_size / 2 + cmp2cmp + mvsd_ov_cmp) - l, + w / 2 + mvsd_ext_cmp + mvsd2gr - ply2gr, + ) + ) + + # Drain contacts and metal + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new(pya.Point.new(-cont_size / 2, -w / 2 + dy)), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + 1, + ny, + ) + ) + cell.shapes(metal1).insert(pya.Box(-metal_w / 2, -w / 2, metal_w / 2, w / 2)) + + # Source contacts and metals + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + (cont_size / 2 + cmp2cmp + mvsd_ov_cmp + cont2ply) + l, -w / 2 + dy + ) + ), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + 1, + ny, + ) + ) + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + -(1.5 * cont_size + cmp2cmp + mvsd_ov_cmp + cont2ply) - l, + -w / 2 + dy, + ) + ), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + 1, + ny, + ) + ) + cell.shapes(metal1).insert( + pya.Box( + (1.5 * cont_size + cmp2cmp + mvsd_ov_cmp + cont2ply + cmp2cont - metal_w) + + l, + -w / 2, + (1.5 * cont_size + cmp2cmp + mvsd_ov_cmp + cont2ply + cmp2cont) + l, + w / 2, + ) + ) + cell.shapes(metal1).insert( + pya.Box( + -(1.5 * cont_size + cmp2cmp + mvsd_ov_cmp + cont2ply + cmp2cont - metal_w) + - l, + -w / 2, + -(1.5 * cont_size + cmp2cmp + mvsd_ov_cmp + cont2ply + cmp2cont) - l, + w / 2, + ) + ) + + # Inserting Guard Ring diffusion + cell.shapes(comp).insert( + pya.Polygon( + [ + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + - l, + -(mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size) - w / 2, + ), + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + - l, + (mvsd_ext_cmp + mvsd2gr) + w / 2, + ), + pya.Point( + -( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + - l, + (mvsd_ext_cmp + mvsd2gr) + w / 2, + ), + pya.Point( + -( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + - l, + -(mvsd_ext_cmp + mvsd2gr) - w / 2, + ), + pya.Point( + ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + + l, + -(mvsd_ext_cmp + mvsd2gr) - w / 2, + ), + pya.Point( + ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + + l, + (mvsd_ext_cmp + mvsd2gr) + w / 2, + ), + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + - l, + (mvsd_ext_cmp + mvsd2gr) + w / 2, + ), + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + - l, + (mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size) + w / 2, + ), + pya.Point( + ( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + + l, + (mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size) + w / 2, + ), + pya.Point( + ( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + + l, + -(mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size) - w / 2, + ), + ], + True, + ) + ) + + cell.shapes(pplus).insert( + pya.Polygon( + [ + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + + pp_enc_cmp + ) + - l, + -(mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size + pp_enc_cmp) + - w / 2, + ), + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + + pp_enc_cmp + ) + - l, + (mvsd_ext_cmp + mvsd2gr - pp_enc_cmp) + w / 2, + ), + pya.Point( + -( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + - pp_enc_cmp + ) + - l, + (mvsd_ext_cmp + mvsd2gr - pp_enc_cmp) + w / 2, + ), + pya.Point( + -( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + - pp_enc_cmp + ) + - l, + -(mvsd_ext_cmp + mvsd2gr - pp_enc_cmp) - w / 2, + ), + pya.Point( + ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + - pp_enc_cmp + ) + + l, + -(mvsd_ext_cmp + mvsd2gr - pp_enc_cmp) - w / 2, + ), + pya.Point( + ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + - pp_enc_cmp + ) + + l, + (mvsd_ext_cmp + mvsd2gr - pp_enc_cmp) + w / 2, + ), + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + + pp_enc_cmp + ) + - l, + (mvsd_ext_cmp + mvsd2gr - pp_enc_cmp) + w / 2, + ), + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + + pp_enc_cmp + ) + - l, + (mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size + pp_enc_cmp) + + w / 2, + ), + pya.Point( + ( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + + pp_enc_cmp + ) + + l, + (mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size + pp_enc_cmp) + + w / 2, + ), + pya.Point( + ( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + + pp_enc_cmp + ) + + l, + -(mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size + pp_enc_cmp) + - w / 2, + ), + ], + True, + ) + ) + + cell.shapes(metal1).insert( + pya.Polygon( + [ + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + - l, + -(mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size) - w / 2, + ), + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + - l, + (mvsd_ext_cmp + mvsd2gr) + w / 2, + ), + pya.Point( + -( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + - l, + (mvsd_ext_cmp + mvsd2gr) + w / 2, + ), + pya.Point( + -( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + - l, + -(mvsd_ext_cmp + mvsd2gr) - w / 2, + ), + pya.Point( + ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + + l, + -(mvsd_ext_cmp + mvsd2gr) - w / 2, + ), + pya.Point( + ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + + l, + (mvsd_ext_cmp + mvsd2gr) + w / 2, + ), + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + - l, + (mvsd_ext_cmp + mvsd2gr) + w / 2, + ), + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + - l, + (mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size) + w / 2, + ), + pya.Point( + ( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + + l, + (mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size) + w / 2, + ), + pya.Point( + ( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + + l, + -(mvsd_ext_cmp + mvsd2gr + 2 * cmp2cont + cont_size) - w / 2, + ), + ], + True, + ) + ) + + nygr = int( + (w + 2 * (mvsd_ext_cmp + mvsd2gr + cmp2cont + cont_size) + cont2cont) + / (cont_size + cont2cont) + ) + dygr = ( + w + + 2 * (mvsd_ext_cmp + mvsd2gr + cmp2cont + cont_size) + - nygr * (cont_size + cont2cont) + + cont2cont + ) / 2 + nxgr_h = int( + ( + 2 * l + + 2 + * ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + + cmp2cont + ) + - cont2cont + ) + / (cont_size + cont2cont) + ) + dxgr_h = ( + 2 * l + + 2 + * ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + + cmp2cont + ) + - nxgr_h * (cont_size + cont2cont) + + cont2cont + ) / 2 + + # Inserting Guard Ring contacts + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + -( + cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + - l, + dygr - (mvsd_ext_cmp + mvsd2gr + cmp2cont + cont_size) - w / 2, + ) + ), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + 1, + nygr, + ) + ) + + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + dxgr_h + - ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + + cmp2cont + ) + - l, + -(mvsd_ext_cmp + mvsd2gr + cmp2cont + cont_size) - w / 2, + ) + ), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + nxgr_h, + 1, + ) + ) + + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + ( + cmp2cont + + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + ) + + l, + dygr - (mvsd_ext_cmp + mvsd2gr + cmp2cont + cont_size) - w / 2, + ) + ), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + 1, + nygr, + ) + ) + + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + dxgr_h + - ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvsd_ov_cmp + + cmp2cmp + + cmp2cont + ) + - l, + (mvsd_ext_cmp + mvsd2gr + cmp2cont) + w / 2, + ) + ), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + nxgr_h, + 1, + ) + ) + + cell.flatten(True) + return cell + + +def draw_pfet_10v0_asym(layout, l, w, dgr_en): + """ + Usage:- + used to draw LDPFET 10V transistor by specifying parameters + Arguments:- + layout : Object of layout + l : Float of gate length + w : Float of gate width + dgr_en : Boolean to enable double guard ring + """ + + # Define layers + dnwell = layout.layer(12, 0) + dualgate = layout.layer(55, 0) + ldmos_xtor = layout.layer(226, 0) + mvpsd = layout.layer(11, 39) + comp = layout.layer(22, 0) + poly2 = layout.layer(30, 0) + nplus = layout.layer(32, 0) + pplus = layout.layer(31, 0) + contact = layout.layer(33, 0) + metal1 = layout.layer(34, 0) + + # Define variables + dbu_PERCISION = 1 / layout.dbu + l = l * dbu_PERCISION + w = w * dbu_PERCISION + cmp2cont = 0.07 * dbu_PERCISION + cont_size = 0.22 * dbu_PERCISION + np_enc_cmp = 0.16 * dbu_PERCISION + pp_enc_cmp = 0.16 * dbu_PERCISION + cont2ply = 0.15 * dbu_PERCISION + metal_w = 0.38 * dbu_PERCISION + ply_ext_cmp = 0.4 * dbu_PERCISION + ply_fld = 0.2 * dbu_PERCISION + np_enc_gate = 0.23 * dbu_PERCISION + cont2cont = 0.25 * dbu_PERCISION + cmp2cmp = 0.36 * dbu_PERCISION + cmp2gr = 0.4 * dbu_PERCISION + mvpsd_ext_cmp = 0.8 * dbu_PERCISION + mvpsd_ov_cmp = 0.4 * dbu_PERCISION + mvpsd2gr = 1 * dbu_PERCISION + ply2gr = 0.4 * dbu_PERCISION + drain2ply = 0.16 * dbu_PERCISION + dnw_enc_cmp = 0.66 * dbu_PERCISION + dg_enc_pcmp = 0.5 * dbu_PERCISION + pcmp_gr2dnw = 2.5 * dbu_PERCISION + + # Inserting PFET cell + cell_index = layout.add_cell("pfet_10v0_asym") + cell = layout.cell(cell_index) + + # Inserting layers for LDFET + cell.shapes(dnwell).insert( + pya.Box( + -( + dnw_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + -(mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size + dnw_enc_cmp) + - w / 2, + ( + dnw_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + (mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size + dnw_enc_cmp) + w / 2, + ) + ) + cell.shapes(dualgate).insert( + pya.Box( + -( + dg_enc_pcmp + + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + -( + mvpsd_ext_cmp + + mvpsd2gr + + 4 * cmp2cont + + 2 * cont_size + + dg_enc_pcmp + + pcmp_gr2dnw + + dnw_enc_cmp + ) + - w / 2, + ( + dg_enc_pcmp + + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 4 * cmp2cont + + 2 * cont_size + + dg_enc_pcmp + + pcmp_gr2dnw + + dnw_enc_cmp + ) + + w / 2, + ) + ) + cell.shapes(ldmos_xtor).insert( + pya.Box( + -( + dg_enc_pcmp + + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + -( + mvpsd_ext_cmp + + mvpsd2gr + + 4 * cmp2cont + + 2 * cont_size + + dg_enc_pcmp + + pcmp_gr2dnw + + dnw_enc_cmp + ) + - w / 2, + ( + dg_enc_pcmp + + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 4 * cmp2cont + + 2 * cont_size + + dg_enc_pcmp + + pcmp_gr2dnw + + dnw_enc_cmp + ) + + w / 2, + ) + ) + + # Inserting drain diffusion + cell.shapes(comp).insert(pya.Box(-cont_size / 2, -w / 2, cont_size / 2, w / 2)) + cell.shapes(mvpsd).insert( + pya.Box( + -(cont_size / 2 + cmp2cmp + mvpsd_ov_cmp), + -w / 2 - mvpsd_ext_cmp, + (cont_size / 2 + cmp2cmp + mvpsd_ov_cmp), + w / 2 + mvpsd_ext_cmp, + ) + ) + + # Inserting source diffusion + cell.shapes(comp).insert( + pya.Box( + (cont_size / 2 + cmp2cmp), + -w / 2, + (cont_size / 2 + cmp2cmp + mvpsd_ov_cmp + cont2ply + cont_size + cmp2cont) + + l, + w / 2, + ) + ) + cell.shapes(comp).insert( + pya.Box( + -(cont_size / 2 + cmp2cmp), + -w / 2, + -(cont_size / 2 + cmp2cmp + mvpsd_ov_cmp + cont2ply + cont_size + cmp2cont) + - l, + w / 2, + ) + ) + + cell.shapes(pplus).insert( + pya.Box( + -( + cont_size / 2 + + cmp2cmp + + mvpsd_ov_cmp + + cont2ply + + cont_size + + cmp2cont + + np_enc_cmp + ) + - l, + -w / 2 - np_enc_gate, + ( + cont_size / 2 + + cmp2cmp + + mvpsd_ov_cmp + + cont2ply + + cont_size + + cmp2cont + + np_enc_cmp + ) + + l, + w / 2 + np_enc_gate, + ) + ) + + # Inserting gates + cell.shapes(poly2).insert( + pya.Box( + (cont_size / 2 + drain2ply), + -w / 2 - ply_ext_cmp, + (cont_size / 2 + cmp2cmp + mvpsd_ov_cmp) + l, + w / 2 + mvpsd_ext_cmp + mvpsd2gr - ply2gr, + ) + ) + cell.shapes(poly2).insert( + pya.Box( + -(cont_size / 2 + drain2ply), + -w / 2 - ply_ext_cmp, + -(cont_size / 2 + cmp2cmp + mvpsd_ov_cmp) - l, + w / 2 + mvpsd_ext_cmp + mvpsd2gr - ply2gr, + ) + ) + + # Inserting a contact cell + cont_cell_index = layout.add_cell("contact") + cont_cell = layout.cell(cont_cell_index) + + # Inserting shapes now into the *contact* cell + cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) + + # Contact array count and postions + ny = int((w - (cont_size + 2 * cmp2cont)) / (cont_size + cont2cont)) + 1 + dy = (w - ny * cont_size - (ny - 1) * cont2cont) / 2 + ng = ( + int( + ((l + mvpsd_ov_cmp + ply_fld) - (cont_size + 2 * cmp2cont)) + / (cont_size + cont2cont) + ) + + 1 + ) + dg = (l + mvpsd_ov_cmp + ply_fld - ng * cont_size - (ng - 1) * cont2cont) / 2 + + # Inserting contact array and metals + # Gate contacts and metal + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + (cont_size / 2 + drain2ply) + dg, + w / 2 + + mvpsd_ext_cmp + + mvpsd2gr + - ply2gr + - (metal_w + cont_size) / 2, + ) + ), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + ng, + 1, + ) + ) + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + -(1.5 * cont_size + drain2ply) - dg, + w / 2 + + mvpsd_ext_cmp + + mvpsd2gr + - ply2gr + - (metal_w + cont_size) / 2, + ) + ), + pya.Point.new(-(cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + ng, + 1, + ) + ) + cell.shapes(metal1).insert( + pya.Box( + (cont_size / 2 + drain2ply), + w / 2 + mvpsd_ext_cmp + mvpsd2gr - ply2gr - metal_w, + (cont_size / 2 + cmp2cmp + mvpsd_ov_cmp) + l, + w / 2 + mvpsd_ext_cmp + mvpsd2gr - ply2gr, + ) + ) + cell.shapes(metal1).insert( + pya.Box( + -(cont_size / 2 + drain2ply), + w / 2 + mvpsd_ext_cmp + mvpsd2gr - ply2gr - metal_w, + -(cont_size / 2 + cmp2cmp + mvpsd_ov_cmp) - l, + w / 2 + mvpsd_ext_cmp + mvpsd2gr - ply2gr, + ) + ) + + # Drain contacts and metal + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new(pya.Point.new(-cont_size / 2, -w / 2 + dy)), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + 1, + ny, + ) + ) + cell.shapes(metal1).insert(pya.Box(-metal_w / 2, -w / 2, metal_w / 2, w / 2)) + + # Source contacts and metals + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + (cont_size / 2 + cmp2cmp + mvpsd_ov_cmp + cont2ply) + l, -w / 2 + dy + ) + ), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + 1, + ny, + ) + ) + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + -(1.5 * cont_size + cmp2cmp + mvpsd_ov_cmp + cont2ply) - l, + -w / 2 + dy, + ) + ), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + 1, + ny, + ) + ) + cell.shapes(metal1).insert( + pya.Box( + (1.5 * cont_size + cmp2cmp + mvpsd_ov_cmp + cont2ply + cmp2cont - metal_w) + + l, + -w / 2, + (1.5 * cont_size + cmp2cmp + mvpsd_ov_cmp + cont2ply + cmp2cont) + l, + w / 2, + ) + ) + cell.shapes(metal1).insert( + pya.Box( + -(1.5 * cont_size + cmp2cmp + mvpsd_ov_cmp + cont2ply + cmp2cont - metal_w) + - l, + -w / 2, + -(1.5 * cont_size + cmp2cmp + mvpsd_ov_cmp + cont2ply + cmp2cont) - l, + w / 2, + ) + ) + + # Inserting Guard Ring diffusion + cell.shapes(comp).insert( + pya.Polygon( + [ + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + -(mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size) - w / 2, + ), + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + (mvpsd_ext_cmp + mvpsd2gr) + w / 2, + ), + pya.Point( + -( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + (mvpsd_ext_cmp + mvpsd2gr) + w / 2, + ), + pya.Point( + -( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + -(mvpsd_ext_cmp + mvpsd2gr) - w / 2, + ), + pya.Point( + ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + -(mvpsd_ext_cmp + mvpsd2gr) - w / 2, + ), + pya.Point( + ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + (mvpsd_ext_cmp + mvpsd2gr) + w / 2, + ), + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + (mvpsd_ext_cmp + mvpsd2gr) + w / 2, + ), + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + (mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size) + w / 2, + ), + pya.Point( + ( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + (mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size) + w / 2, + ), + pya.Point( + ( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + -(mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size) - w / 2, + ), + ], + True, + ) + ) + + cell.shapes(nplus).insert( + pya.Polygon( + [ + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + + pp_enc_cmp + ) + - l, + -(mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size + pp_enc_cmp) + - w / 2, + ), + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + + pp_enc_cmp + ) + - l, + (mvpsd_ext_cmp + mvpsd2gr - pp_enc_cmp) + w / 2, + ), + pya.Point( + -( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + - pp_enc_cmp + ) + - l, + (mvpsd_ext_cmp + mvpsd2gr - pp_enc_cmp) + w / 2, + ), + pya.Point( + -( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + - pp_enc_cmp + ) + - l, + -(mvpsd_ext_cmp + mvpsd2gr - pp_enc_cmp) - w / 2, + ), + pya.Point( + ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + - pp_enc_cmp + ) + + l, + -(mvpsd_ext_cmp + mvpsd2gr - pp_enc_cmp) - w / 2, + ), + pya.Point( + ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + - pp_enc_cmp + ) + + l, + (mvpsd_ext_cmp + mvpsd2gr - pp_enc_cmp) + w / 2, + ), + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + + pp_enc_cmp + ) + - l, + (mvpsd_ext_cmp + mvpsd2gr - pp_enc_cmp) + w / 2, + ), + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + + pp_enc_cmp + ) + - l, + (mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size + pp_enc_cmp) + + w / 2, + ), + pya.Point( + ( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + + pp_enc_cmp + ) + + l, + (mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size + pp_enc_cmp) + + w / 2, + ), + pya.Point( + ( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + + pp_enc_cmp + ) + + l, + -(mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size + pp_enc_cmp) + - w / 2, + ), + ], + True, + ) + ) + + cell.shapes(metal1).insert( + pya.Polygon( + [ + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + -(mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size) - w / 2, + ), + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + (mvpsd_ext_cmp + mvpsd2gr) + w / 2, + ), + pya.Point( + -( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + (mvpsd_ext_cmp + mvpsd2gr) + w / 2, + ), + pya.Point( + -( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + -(mvpsd_ext_cmp + mvpsd2gr) - w / 2, + ), + pya.Point( + ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + -(mvpsd_ext_cmp + mvpsd2gr) - w / 2, + ), + pya.Point( + ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + (mvpsd_ext_cmp + mvpsd2gr) + w / 2, + ), + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + (mvpsd_ext_cmp + mvpsd2gr) + w / 2, + ), + pya.Point( + -( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + (mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size) + w / 2, + ), + pya.Point( + ( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + (mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size) + w / 2, + ), + pya.Point( + ( + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + -(mvpsd_ext_cmp + mvpsd2gr + 2 * cmp2cont + cont_size) - w / 2, + ), + ], + True, + ) + ) + + nygr = int( + (w + 2 * (mvpsd_ext_cmp + mvpsd2gr + cmp2cont + cont_size) + cont2cont) + / (cont_size + cont2cont) + ) + dygr = ( + w + + 2 * (mvpsd_ext_cmp + mvpsd2gr + cmp2cont + cont_size) + - nygr * (cont_size + cont2cont) + + cont2cont + ) / 2 + nxgr_h = int( + ( + 2 * l + + 2 + * ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + + cmp2cont + ) + - cont2cont + ) + / (cont_size + cont2cont) + ) + dxgr_h = ( + 2 * l + + 2 + * ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + + cmp2cont + ) + - nxgr_h * (cont_size + cont2cont) + + cont2cont + ) / 2 + + # Inserting Guard Ring contacts + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + -( + cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + dygr - (mvpsd_ext_cmp + mvpsd2gr + cmp2cont + cont_size) - w / 2, + ) + ), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + 1, + nygr, + ) + ) + + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + dxgr_h + - ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + + cmp2cont + ) + - l, + -(mvpsd_ext_cmp + mvpsd2gr + cmp2cont + cont_size) - w / 2, + ) + ), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + nxgr_h, + 1, + ) + ) + + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + ( + cmp2cont + + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + dygr - (mvpsd_ext_cmp + mvpsd2gr + cmp2cont + cont_size) - w / 2, + ) + ), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + 1, + nygr, + ) + ) + + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + dxgr_h + - ( + 0.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + + cmp2cont + ) + - l, + (mvpsd_ext_cmp + mvpsd2gr + cmp2cont) + w / 2, + ) + ), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + nxgr_h, + 1, + ) + ) + + # Inserting DNWELL Guard Ring + if dgr_en: + # Inserting DNWELL Guard Ring diffusion + cell.shapes(comp).insert( + pya.Polygon( + [ + pya.Point( + -( + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + -( + mvpsd_ext_cmp + + mvpsd2gr + + 4 * cmp2cont + + 2 * cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + - w / 2, + ), + pya.Point( + -( + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 2 * cmp2cont + + cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + + w / 2, + ), + pya.Point( + -( + pcmp_gr2dnw + + dnw_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 2 * cmp2cont + + cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + + w / 2, + ), + pya.Point( + -( + pcmp_gr2dnw + + dnw_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + -( + mvpsd_ext_cmp + + mvpsd2gr + + 2 * cmp2cont + + cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + - w / 2, + ), + pya.Point( + ( + pcmp_gr2dnw + + dnw_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + -( + mvpsd_ext_cmp + + mvpsd2gr + + 2 * cmp2cont + + cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + - w / 2, + ), + pya.Point( + ( + pcmp_gr2dnw + + dnw_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 2 * cmp2cont + + cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + + w / 2, + ), + pya.Point( + -( + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 2 * cmp2cont + + cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + + w / 2, + ), + pya.Point( + -( + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 4 * cmp2cont + + 2 * cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + + w / 2, + ), + pya.Point( + ( + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 4 * cmp2cont + + 2 * cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + + w / 2, + ), + pya.Point( + ( + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + -( + mvpsd_ext_cmp + + mvpsd2gr + + 4 * cmp2cont + + 2 * cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + - w / 2, + ), + ], + True, + ) + ) + + cell.shapes(pplus).insert( + pya.Polygon( + [ + pya.Point( + -( + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + + np_enc_cmp + ) + - l, + -( + mvpsd_ext_cmp + + mvpsd2gr + + 4 * cmp2cont + + 2 * cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + + np_enc_cmp + ) + - w / 2, + ), + pya.Point( + -( + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + + np_enc_cmp + ) + - l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 2 * cmp2cont + + cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + - np_enc_cmp + ) + + w / 2, + ), + pya.Point( + -( + pcmp_gr2dnw + + dnw_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + - np_enc_cmp + ) + - l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 2 * cmp2cont + + cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + - np_enc_cmp + ) + + w / 2, + ), + pya.Point( + -( + pcmp_gr2dnw + + dnw_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + - np_enc_cmp + ) + - l, + -( + mvpsd_ext_cmp + + mvpsd2gr + + 2 * cmp2cont + + cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + - np_enc_cmp + ) + - w / 2, + ), + pya.Point( + ( + pcmp_gr2dnw + + dnw_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + - np_enc_cmp + ) + + l, + -( + mvpsd_ext_cmp + + mvpsd2gr + + 2 * cmp2cont + + cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + - np_enc_cmp + ) + - w / 2, + ), + pya.Point( + ( + pcmp_gr2dnw + + dnw_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + - np_enc_cmp + ) + + l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 2 * cmp2cont + + cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + - np_enc_cmp + ) + + w / 2, + ), + pya.Point( + -( + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + + np_enc_cmp + ) + - l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 2 * cmp2cont + + cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + - np_enc_cmp + ) + + w / 2, + ), + pya.Point( + -( + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + + np_enc_cmp + ) + - l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 4 * cmp2cont + + 2 * cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + + np_enc_cmp + ) + + w / 2, + ), + pya.Point( + ( + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + + np_enc_cmp + ) + + l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 4 * cmp2cont + + 2 * cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + + np_enc_cmp + ) + + w / 2, + ), + pya.Point( + ( + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + + np_enc_cmp + ) + + l, + -( + mvpsd_ext_cmp + + mvpsd2gr + + 4 * cmp2cont + + 2 * cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + + np_enc_cmp + ) + - w / 2, + ), + ], + True, + ) + ) + + # Inserting DNWELL Guard Ring metal + cell.shapes(metal1).insert( + pya.Polygon( + [ + pya.Point( + -( + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + -( + mvpsd_ext_cmp + + mvpsd2gr + + 4 * cmp2cont + + 2 * cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + - w / 2, + ), + pya.Point( + -( + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 2 * cmp2cont + + cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + + w / 2, + ), + pya.Point( + -( + pcmp_gr2dnw + + dnw_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 2 * cmp2cont + + cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + + w / 2, + ), + pya.Point( + -( + pcmp_gr2dnw + + dnw_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + -( + mvpsd_ext_cmp + + mvpsd2gr + + 2 * cmp2cont + + cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + - w / 2, + ), + pya.Point( + ( + pcmp_gr2dnw + + dnw_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + -( + mvpsd_ext_cmp + + mvpsd2gr + + 2 * cmp2cont + + cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + - w / 2, + ), + pya.Point( + ( + pcmp_gr2dnw + + dnw_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 2 * cmp2cont + + cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + + w / 2, + ), + pya.Point( + -( + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 2 * cmp2cont + + cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + + w / 2, + ), + pya.Point( + -( + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 4 * cmp2cont + + 2 * cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + + w / 2, + ), + pya.Point( + ( + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + ( + mvpsd_ext_cmp + + mvpsd2gr + + 4 * cmp2cont + + 2 * cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + + w / 2, + ), + pya.Point( + ( + pcmp_gr2dnw + + dnw_enc_cmp + + 4 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + -( + mvpsd_ext_cmp + + mvpsd2gr + + 4 * cmp2cont + + 2 * cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + - w / 2, + ), + ], + True, + ) + ) + + # Inserting DNWELL guard ring contacts + nygr = int( + ( + w + + 2 + * ( + mvpsd_ext_cmp + + mvpsd2gr + + 3 * cmp2cont + + 2 * cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + + cont2cont + ) + / (cont_size + cont2cont) + ) + dygr = ( + w + + 2 + * ( + mvpsd_ext_cmp + + mvpsd2gr + + 3 * cmp2cont + + 2 * cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + - nygr * (cont_size + cont2cont) + + cont2cont + ) / 2 + nxgr_h = int( + ( + 2 * l + + 2 + * ( + pcmp_gr2dnw + + dnw_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + 2 * cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - cont2cont + ) + / (cont_size + cont2cont) + ) + dxgr_h = ( + 2 * l + + 2 + * ( + pcmp_gr2dnw + + dnw_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + 2 * cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - nxgr_h * (cont_size + cont2cont) + + cont2cont + ) / 2 + + # Inserting DNWELL Guard Ring contacts + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + -( + pcmp_gr2dnw + + dnw_enc_cmp + + 3 * cmp2cont + + 2.5 * cont_size + + cmp2gr + + cont_size + + cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + dygr + - ( + mvpsd_ext_cmp + + mvpsd2gr + + 3 * cmp2cont + + 2 * cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + - w / 2, + ) + ), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + 1, + nygr, + ) + ) + + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + dxgr_h + - ( + pcmp_gr2dnw + + dnw_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + 2 * cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + -( + mvpsd_ext_cmp + + mvpsd2gr + + 3 * cmp2cont + + 2 * cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + - w / 2, + ) + ), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, -(cont_size + cont2cont)), + nxgr_h, + 1, + ) + ) + + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + ( + pcmp_gr2dnw + + dnw_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + 2 * cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + + l, + dygr + - ( + mvpsd_ext_cmp + + mvpsd2gr + + 3 * cmp2cont + + 2 * cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + ) + - w / 2, + ) + ), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + 1, + nygr, + ) + ) + + cell.insert( + pya.CellInstArray.new( + cont_cell_index, + pya.Trans.new( + pya.Point.new( + dxgr_h + - ( + pcmp_gr2dnw + + dnw_enc_cmp + + 2 * cmp2cont + + 1.5 * cont_size + + cmp2gr + + cont_size + + 2 * cmp2cont + + cont2ply + + mvpsd_ov_cmp + + cmp2cmp + ) + - l, + mvpsd_ext_cmp + + mvpsd2gr + + 3 * cmp2cont + + cont_size + + pcmp_gr2dnw + + dnw_enc_cmp + + w / 2, + ) + ), + pya.Point.new((cont_size + cont2cont), 0), + pya.Point.new(0, (cont_size + cont2cont)), + nxgr_h, + 1, + ) + ) + + cell.flatten(True) + return cell diff --git a/cells/klayout/pymacros/cells/fet.py b/cells/klayout/pymacros/cells/fet.py index 6cb8e733..e248fc42 100644 --- a/cells/klayout/pymacros/cells/fet.py +++ b/cells/klayout/pymacros/cells/fet.py @@ -59,6 +59,9 @@ def __init__(self): self.Type_handle.add_choice("None", "None") self.Type_handle.add_choice("Bulk Tie", "Bulk Tie") self.Type_handle.add_choice("Guard Ring", "Guard Ring") + self.Type_handle.add_choice("top", "top") + self.Type_handle.add_choice("bottom", "bottom") + self.Type_handle.add_choice("alternating", "alternating") self.param("w", self.TypeDouble, "Width", default=fet_3p3_w, unit="um") self.param("l", self.TypeDouble, "Length", default=fet_3p3_l, unit="um") @@ -67,6 +70,18 @@ def __init__(self): self.param( "grw", self.TypeDouble, "Guard Ring Width", default=fet_grw, unit="um" ) + + self.Type_handle = self.param("gate_con_pos", self.TypeList, "Gate Contact Position") + self.Type_handle.add_choice("top", "top") + self.Type_handle.add_choice("bottom", "bottom") + self.Type_handle.add_choice("alternating", "alternating") + + self.param("con_bet_fin", self.TypeBoolean, "Contact Between Fingers", default=1) + self.param("sd_con_col", self.TypeInt, "Diffusion Contacts Columns", default=1) + + self.param("interdig", self.TypeBoolean, "Interdigitation", default=0) + self.param("patt", self.TypeString,"Pattern in case of Interdigitation", default= "") + self.param("area", self.TypeDouble, "Area", readonly=True, unit="um^2") self.param("perim", self.TypeDouble, "Perimeter", readonly=True, unit="um") @@ -123,202 +138,20 @@ def transformation_from_shape_impl(self): def produce_impl(self): instance = draw_nfet( self.layout, - self.l, - self.w, - self.ld, - self.nf, - self.grw, - self.bulk, - self.volt, - self.deepnwell, - self.pcmpgr, - ) - write_cells = pya.CellInstArray( - instance.cell_index(), - pya.Trans(pya.Point(0, 0)), - pya.Vector(0, 0), - pya.Vector(0, 0), - 1, - 1, - ) - self.cell.insert(write_cells) - self.cell.flatten(1) - - -class pfet(pya.PCellDeclarationHelper): - """ - PFET Generator for GF180MCU - """ - - def __init__(self): - # Initialize super class. - super(pfet, self).__init__() - - # ===================== PARAMETERS DECLARATIONS ===================== - self.param("deepnwell", self.TypeBoolean, "Deep NWELL", default=0) - self.param("pcmpgr", self.TypeBoolean, "Deep NWELL Guard Ring", default=0) - self.Type_handle = self.param("volt", self.TypeList, "Voltage area") - self.Type_handle.add_choice("3.3V", "3.3V") - self.Type_handle.add_choice("5V", "5V") - self.Type_handle.add_choice("6V", "6V") - self.Type_handle = self.param("bulk", self.TypeList, "Bulk Type") - self.Type_handle.add_choice("None", "None") - self.Type_handle.add_choice("Bulk Tie", "Bulk Tie") - self.Type_handle.add_choice("Guard Ring", "Guard Ring") - - self.param("w", self.TypeDouble, "Width", default=fet_3p3_w, unit="um") - self.param("l", self.TypeDouble, "Length", default=fet_3p3_l, unit="um") - self.param("ld", self.TypeDouble, "Diffusion Length", default=fet_ld, unit="um") - self.param("nf", self.TypeInt, "Number of Fingers", default=1) - self.param( - "grw", self.TypeDouble, "Guard Ring Width", default=fet_grw, unit="um" - ) - self.param("area", self.TypeDouble, "Area", readonly=True, unit="um^2") - self.param("perim", self.TypeDouble, "Perimeter", readonly=True, unit="um") - - def display_text_impl(self): - # Provide a descriptive text for the cell - return "pfet(L=" + ("%.3f" % self.l) + ",W=" + ("%.3f" % self.w) + ")" - - def coerce_parameters_impl(self): - # We employ coerce_parameters_impl to decide whether the handle or the - # numeric parameter has changed (by comparing against the effective - # radius ru) and set ru to the effective radius. We also update the - # numerical value or the shape, depending on which on has not changed. - self.area = self.w * self.l - self.perim = 2 * (self.w + self.l) - # w,l must be larger or equal than min. values. - if self.volt == "3.3V": - if (self.l) < fet_3p3_l: - self.l = fet_3p3_l - if (self.w) < fet_3p3_w: - self.w = fet_3p3_w - elif self.volt == "5V": - if (self.l) < pfet_05v0_l: - self.l = pfet_05v0_l - if (self.w) < fet_5_6_w: - self.w = fet_5_6_w - elif self.volt == "6V": - if (self.l) < pfet_06v0_l: - self.l = pfet_06v0_l - if (self.w) < fet_5_6_w: - self.w = fet_5_6_w - - if (self.ld) < fet_ld: - self.ld = fet_ld - - if (self.grw) < fet_grw: - self.grw = fet_grw - - def can_create_from_shape_impl(self): - # Implement the "Create PCell from shape" protocol: we can use any shape which - # has a finite bounding box - return self.shape.is_box() or self.shape.is_polygon() or self.shape.is_path() - - def parameters_from_shape_impl(self): - # Implement the "Create PCell from shape" protocol: we set r and l from the shape's - # bounding box width and layer - self.r = self.shape.bbox().width() * self.layout.dbu / 2 - self.l = self.layout.get_info(self.layer) - - def transformation_from_shape_impl(self): - # Implement the "Create PCell from shape" protocol: we use the center of the shape's - # bounding box to determine the transformation - return pya.Trans(self.shape.bbox().center()) - - def produce_impl(self): - instance = draw_pfet( - self.layout, - self.l, - self.w, - self.ld, - self.nf, - self.grw, - self.bulk, - self.volt, - self.deepnwell, - self.pcmpgr, - ) - write_cells = pya.CellInstArray( - instance.cell_index(), - pya.Trans(pya.Point(0, 0)), - pya.Vector(0, 0), - pya.Vector(0, 0), - 1, - 1, - ) - self.cell.insert(write_cells) - self.cell.flatten(1) - - -class nfet_06v0_nvt(pya.PCellDeclarationHelper): - """ - 6V Native NFET Generator for GF180MCU - """ - - def __init__(self): - # Initialize super class. - super(nfet_06v0_nvt, self).__init__() - - # ===================== PARAMETERS DECLARATIONS ===================== - self.Type_handle = self.param("bulk", self.TypeList, "Bulk Type") - self.Type_handle.add_choice("None", "None") - self.Type_handle.add_choice("Bulk Tie", "Bulk Tie") - self.Type_handle.add_choice("Guard Ring", "Guard Ring") - - self.param("w", self.TypeDouble, "Width", default=nfet_nat_w, unit="um") - self.param("l", self.TypeDouble, "Length", default=nfet_nat_l, unit="um") - self.param("ld", self.TypeDouble, "Diffusion Length", default=fet_ld, unit="um") - self.param("nf", self.TypeInt, "Number of Fingers", default=1) - self.param( - "grw", self.TypeDouble, "Guard Ring Width", default=fet_grw, unit="um" - ) - self.param("area", self.TypeDouble, "Area", readonly=True, unit="um^2") - self.param("perim", self.TypeDouble, "Perimeter", readonly=True, unit="um") - - def display_text_impl(self): - # Provide a descriptive text for the cell - return "nfet_06v0_nvt(L=" + ("%.3f" % self.l) + ",W=" + ("%.3f" % self.w) + ")" - - def coerce_parameters_impl(self): - # We employ coerce_parameters_impl to decide whether the handle or the - # numeric parameter has changed (by comparing against the effective - # radius ru) and set ru to the effective radius. We also update the - # numerical value or the shape, depending on which on has not changed. - self.area = self.w * self.l - self.perim = 2 * (self.w + self.l) - # w,l must be larger or equal than min. values. - if (self.l) < nfet_nat_l: - self.l = nfet_nat_l - - if (self.w) < nfet_nat_w: - self.w = nfet_nat_w - - if (self.grw) < fet_grw: - self.grw = fet_grw - - if (self.ld) < fet_ld: - self.ld = fet_ld - - def can_create_from_shape_impl(self): - # Implement the "Create PCell from shape" protocol: we can use any shape which - # has a finite bounding box - return self.shape.is_box() or self.shape.is_polygon() or self.shape.is_path() - - def parameters_from_shape_impl(self): - # Implement the "Create PCell from shape" protocol: we set r and l from the shape's - # bounding box width and layer - self.r = self.shape.bbox().width() * self.layout.dbu / 2 - self.l = self.layout.get_info(self.layer) - - def transformation_from_shape_impl(self): - # Implement the "Create PCell from shape" protocol: we use the center of the shape's - # bounding box to determine the transformation - return pya.Trans(self.shape.bbox().center()) - - def produce_impl(self): - instance = draw_nfet_06v0_nvt( - self.layout, self.l, self.w, self.ld, self.nf, self.grw, self.bulk + l = self.l, + w= self.w, + sd_con_col= self.sd_con_col, + inter_sd_l= self.ld, + nf= self.nf, + grw= self.grw, + bulk= self.bulk, + volt= self.volt, + con_bet_fin= self.con_bet_fin, + gate_con_pos= self.gate_con_pos, + interdig= self.interdig, + patt= self.patt, + deepnwell= self.deepnwell, + pcmpgr= self.pcmpgr ) write_cells = pya.CellInstArray( instance.cell_index(), @@ -332,136 +165,323 @@ def produce_impl(self): self.cell.flatten(1) -class nfet_10v0_asym(pya.PCellDeclarationHelper): - """ - 10V LDNFET Generator for GF180MCU - """ - - def __init__(self): - # Initialize super class. - super(nfet_10v0_asym, self).__init__() - - # ===================== PARAMETERS DECLARATIONS ===================== - - self.param("w", self.TypeDouble, "Width", default=ldfet_w_min, unit="um") - self.param("l", self.TypeDouble, "Length", default=ldfet_l_min, unit="um") - self.param("area", self.TypeDouble, "Area", readonly=True, unit="um^2") - self.param("perim", self.TypeDouble, "Perimeter", readonly=True, unit="um") - - def display_text_impl(self): - # Provide a descriptive text for the cell - return "nfet_10v0_asym(L=" + ("%.3f" % self.l) + ",W=" + ("%.3f" % self.w) + ")" - - def coerce_parameters_impl(self): - # We employ coerce_parameters_impl to decide whether the handle or the - # numeric parameter has changed (by comparing against the effective - # radius ru) and set ru to the effective radius. We also update the - # numerical value or the shape, depending on which on has not changed. - self.area = self.w * self.l - self.perim = 2 * (self.w + self.l) - # w,l must be larger or equal than min. values. - if (self.l) < ldfet_l_min: - self.l = ldfet_l_min - if (self.l) > ldfet_l_max: - self.l = ldfet_l_max - if (self.w) < ldfet_w_min: - self.w = ldfet_w_min - if (self.w) > ldfet_w_max: - self.w = ldfet_w_max - - def can_create_from_shape_impl(self): - # Implement the "Create PCell from shape" protocol: we can use any shape which - # has a finite bounding box - return self.shape.is_box() or self.shape.is_polygon() or self.shape.is_path() - - def parameters_from_shape_impl(self): - # Implement the "Create PCell from shape" protocol: we set r and l from the shape's - # bounding box width and layer - self.r = self.shape.bbox().width() * self.layout.dbu / 2 - self.l = self.layout.get_info(self.layer) - - def transformation_from_shape_impl(self): - # Implement the "Create PCell from shape" protocol: we use the center of the shape's - # bounding box to determine the transformation - return pya.Trans(self.shape.bbox().center()) - - def produce_impl(self): - instance = draw_nfet_10v0_asym(self.layout, self.l, self.w) - write_cells = pya.CellInstArray( - instance.cell_index(), - pya.Trans(pya.Point(0, 0)), - pya.Vector(0, 0), - pya.Vector(0, 0), - 1, - 1, - ) - self.cell.insert(write_cells) - self.cell.flatten(1) - - -class pfet_10v0_asym(pya.PCellDeclarationHelper): - """ - 10V LDPFET Generator for GF180MCU - """ - - def __init__(self): - # Initialize super class. - super(pfet_10v0_asym, self).__init__() - - # ===================== PARAMETERS DECLARATIONS ===================== - - self.param("w", self.TypeDouble, "Width", default=ldfet_w_min, unit="um") - self.param("l", self.TypeDouble, "Length", default=ldfet_l_min, unit="um") - self.param("double_gr", self.TypeBoolean, "Double Guard Ring", default=1) - self.param("area", self.TypeDouble, "Area", readonly=True, unit="um^2") - self.param("perim", self.TypeDouble, "Perimeter", readonly=True, unit="um") - - def display_text_impl(self): - # Provide a descriptive text for the cell - return "pfet_10v0_asym(L=" + ("%.3f" % self.l) + ",W=" + ("%.3f" % self.w) + ")" - - def coerce_parameters_impl(self): - # We employ coerce_parameters_impl to decide whether the handle or the - # numeric parameter has changed (by comparing against the effective - # radius ru) and set ru to the effective radius. We also update the - # numerical value or the shape, depending on which on has not changed. - self.area = self.w * self.l - self.perim = 2 * (self.w + self.l) - # w,l must be larger or equal than min. values. - if (self.l) < ldfet_l_min: - self.l = ldfet_l_min - if (self.l) > ldfet_l_max: - self.l = ldfet_l_max - if (self.w) < ldfet_w_min: - self.w = ldfet_w_min - if (self.w) > ldfet_w_max: - self.w = ldfet_w_max - - def can_create_from_shape_impl(self): - # Implement the "Create PCell from shape" protocol: we can use any shape which - # has a finite bounding box - return self.shape.is_box() or self.shape.is_polygon() or self.shape.is_path() - - def parameters_from_shape_impl(self): - # Implement the "Create PCell from shape" protocol: we set r and l from the shape's - # bounding box width and layer - self.r = self.shape.bbox().width() * self.layout.dbu / 2 - self.l = self.layout.get_info(self.layer) - - def transformation_from_shape_impl(self): - # Implement the "Create PCell from shape" protocol: we use the center of the shape's - # bounding box to determine the transformation - return pya.Trans(self.shape.bbox().center()) - - def produce_impl(self): - instance = draw_pfet_10v0_asym(self.layout, self.l, self.w, self.double_gr) - write_cells = pya.CellInstArray( - instance.cell_index(), - pya.Trans(pya.Point(0, 0)), - pya.Vector(0, 0), - pya.Vector(0, 0), - 1, - 1, - ) - self.cell.insert(write_cells) - self.cell.flatten(1) +# class pfet(pya.PCellDeclarationHelper): +# """ +# PFET Generator for GF180MCU +# """ + +# def __init__(self): +# # Initialize super class. +# super(pfet, self).__init__() + +# # ===================== PARAMETERS DECLARATIONS ===================== +# self.param("deepnwell", self.TypeBoolean, "Deep NWELL", default=0) +# self.param("pcmpgr", self.TypeBoolean, "Deep NWELL Guard Ring", default=0) +# self.Type_handle = self.param("volt", self.TypeList, "Voltage area") +# self.Type_handle.add_choice("3.3V", "3.3V") +# self.Type_handle.add_choice("5V", "5V") +# self.Type_handle.add_choice("6V", "6V") +# self.Type_handle = self.param("bulk", self.TypeList, "Bulk Type") +# self.Type_handle.add_choice("None", "None") +# self.Type_handle.add_choice("Bulk Tie", "Bulk Tie") +# self.Type_handle.add_choice("Guard Ring", "Guard Ring") + +# self.param("w", self.TypeDouble, "Width", default=fet_3p3_w, unit="um") +# self.param("l", self.TypeDouble, "Length", default=fet_3p3_l, unit="um") +# self.param("ld", self.TypeDouble, "Diffusion Length", default=fet_ld, unit="um") +# self.param("nf", self.TypeInt, "Number of Fingers", default=1) +# self.param( +# "grw", self.TypeDouble, "Guard Ring Width", default=fet_grw, unit="um" +# ) +# self.param("area", self.TypeDouble, "Area", readonly=True, unit="um^2") +# self.param("perim", self.TypeDouble, "Perimeter", readonly=True, unit="um") + +# def display_text_impl(self): +# # Provide a descriptive text for the cell +# return "pfet(L=" + ("%.3f" % self.l) + ",W=" + ("%.3f" % self.w) + ")" + +# def coerce_parameters_impl(self): +# # We employ coerce_parameters_impl to decide whether the handle or the +# # numeric parameter has changed (by comparing against the effective +# # radius ru) and set ru to the effective radius. We also update the +# # numerical value or the shape, depending on which on has not changed. +# self.area = self.w * self.l +# self.perim = 2 * (self.w + self.l) +# # w,l must be larger or equal than min. values. +# if self.volt == "3.3V": +# if (self.l) < fet_3p3_l: +# self.l = fet_3p3_l +# if (self.w) < fet_3p3_w: +# self.w = fet_3p3_w +# elif self.volt == "5V": +# if (self.l) < pfet_05v0_l: +# self.l = pfet_05v0_l +# if (self.w) < fet_5_6_w: +# self.w = fet_5_6_w +# elif self.volt == "6V": +# if (self.l) < pfet_06v0_l: +# self.l = pfet_06v0_l +# if (self.w) < fet_5_6_w: +# self.w = fet_5_6_w + +# if (self.ld) < fet_ld: +# self.ld = fet_ld + +# if (self.grw) < fet_grw: +# self.grw = fet_grw + +# def can_create_from_shape_impl(self): +# # Implement the "Create PCell from shape" protocol: we can use any shape which +# # has a finite bounding box +# return self.shape.is_box() or self.shape.is_polygon() or self.shape.is_path() + +# def parameters_from_shape_impl(self): +# # Implement the "Create PCell from shape" protocol: we set r and l from the shape's +# # bounding box width and layer +# self.r = self.shape.bbox().width() * self.layout.dbu / 2 +# self.l = self.layout.get_info(self.layer) + +# def transformation_from_shape_impl(self): +# # Implement the "Create PCell from shape" protocol: we use the center of the shape's +# # bounding box to determine the transformation +# return pya.Trans(self.shape.bbox().center()) + +# def produce_impl(self): +# instance = draw_pfet( +# self.layout, +# self.l, +# self.w, +# self.ld, +# self.nf, +# self.grw, +# self.bulk, +# self.volt, +# self.deepnwell, +# self.pcmpgr, +# ) +# write_cells = pya.CellInstArray( +# instance.cell_index(), +# pya.Trans(pya.Point(0, 0)), +# pya.Vector(0, 0), +# pya.Vector(0, 0), +# 1, +# 1, +# ) +# self.cell.insert(write_cells) +# self.cell.flatten(1) + + +# class nfet_06v0_nvt(pya.PCellDeclarationHelper): +# """ +# 6V Native NFET Generator for GF180MCU +# """ + +# def __init__(self): +# # Initialize super class. +# super(nfet_06v0_nvt, self).__init__() + +# # ===================== PARAMETERS DECLARATIONS ===================== +# self.Type_handle = self.param("bulk", self.TypeList, "Bulk Type") +# self.Type_handle.add_choice("None", "None") +# self.Type_handle.add_choice("Bulk Tie", "Bulk Tie") +# self.Type_handle.add_choice("Guard Ring", "Guard Ring") + +# self.param("w", self.TypeDouble, "Width", default=nfet_nat_w, unit="um") +# self.param("l", self.TypeDouble, "Length", default=nfet_nat_l, unit="um") +# self.param("ld", self.TypeDouble, "Diffusion Length", default=fet_ld, unit="um") +# self.param("nf", self.TypeInt, "Number of Fingers", default=1) +# self.param( +# "grw", self.TypeDouble, "Guard Ring Width", default=fet_grw, unit="um" +# ) +# self.param("area", self.TypeDouble, "Area", readonly=True, unit="um^2") +# self.param("perim", self.TypeDouble, "Perimeter", readonly=True, unit="um") + +# def display_text_impl(self): +# # Provide a descriptive text for the cell +# return "nfet_06v0_nvt(L=" + ("%.3f" % self.l) + ",W=" + ("%.3f" % self.w) + ")" + +# def coerce_parameters_impl(self): +# # We employ coerce_parameters_impl to decide whether the handle or the +# # numeric parameter has changed (by comparing against the effective +# # radius ru) and set ru to the effective radius. We also update the +# # numerical value or the shape, depending on which on has not changed. +# self.area = self.w * self.l +# self.perim = 2 * (self.w + self.l) +# # w,l must be larger or equal than min. values. +# if (self.l) < nfet_nat_l: +# self.l = nfet_nat_l + +# if (self.w) < nfet_nat_w: +# self.w = nfet_nat_w + +# if (self.grw) < fet_grw: +# self.grw = fet_grw + +# if (self.ld) < fet_ld: +# self.ld = fet_ld + +# def can_create_from_shape_impl(self): +# # Implement the "Create PCell from shape" protocol: we can use any shape which +# # has a finite bounding box +# return self.shape.is_box() or self.shape.is_polygon() or self.shape.is_path() + +# def parameters_from_shape_impl(self): +# # Implement the "Create PCell from shape" protocol: we set r and l from the shape's +# # bounding box width and layer +# self.r = self.shape.bbox().width() * self.layout.dbu / 2 +# self.l = self.layout.get_info(self.layer) + +# def transformation_from_shape_impl(self): +# # Implement the "Create PCell from shape" protocol: we use the center of the shape's +# # bounding box to determine the transformation +# return pya.Trans(self.shape.bbox().center()) + +# def produce_impl(self): +# instance = draw_nfet_06v0_nvt( +# self.layout, self.l, self.w, self.ld, self.nf, self.grw, self.bulk +# ) +# write_cells = pya.CellInstArray( +# instance.cell_index(), +# pya.Trans(pya.Point(0, 0)), +# pya.Vector(0, 0), +# pya.Vector(0, 0), +# 1, +# 1, +# ) +# self.cell.insert(write_cells) +# self.cell.flatten(1) + + +# class nfet_10v0_asym(pya.PCellDeclarationHelper): +# """ +# 10V LDNFET Generator for GF180MCU +# """ + +# def __init__(self): +# # Initialize super class. +# super(nfet_10v0_asym, self).__init__() + +# # ===================== PARAMETERS DECLARATIONS ===================== + +# self.param("w", self.TypeDouble, "Width", default=ldfet_w_min, unit="um") +# self.param("l", self.TypeDouble, "Length", default=ldfet_l_min, unit="um") +# self.param("area", self.TypeDouble, "Area", readonly=True, unit="um^2") +# self.param("perim", self.TypeDouble, "Perimeter", readonly=True, unit="um") + +# def display_text_impl(self): +# # Provide a descriptive text for the cell +# return "nfet_10v0_asym(L=" + ("%.3f" % self.l) + ",W=" + ("%.3f" % self.w) + ")" + +# def coerce_parameters_impl(self): +# # We employ coerce_parameters_impl to decide whether the handle or the +# # numeric parameter has changed (by comparing against the effective +# # radius ru) and set ru to the effective radius. We also update the +# # numerical value or the shape, depending on which on has not changed. +# self.area = self.w * self.l +# self.perim = 2 * (self.w + self.l) +# # w,l must be larger or equal than min. values. +# if (self.l) < ldfet_l_min: +# self.l = ldfet_l_min +# if (self.l) > ldfet_l_max: +# self.l = ldfet_l_max +# if (self.w) < ldfet_w_min: +# self.w = ldfet_w_min +# if (self.w) > ldfet_w_max: +# self.w = ldfet_w_max + +# def can_create_from_shape_impl(self): +# # Implement the "Create PCell from shape" protocol: we can use any shape which +# # has a finite bounding box +# return self.shape.is_box() or self.shape.is_polygon() or self.shape.is_path() + +# def parameters_from_shape_impl(self): +# # Implement the "Create PCell from shape" protocol: we set r and l from the shape's +# # bounding box width and layer +# self.r = self.shape.bbox().width() * self.layout.dbu / 2 +# self.l = self.layout.get_info(self.layer) + +# def transformation_from_shape_impl(self): +# # Implement the "Create PCell from shape" protocol: we use the center of the shape's +# # bounding box to determine the transformation +# return pya.Trans(self.shape.bbox().center()) + +# def produce_impl(self): +# instance = draw_nfet_10v0_asym(self.layout, self.l, self.w) +# write_cells = pya.CellInstArray( +# instance.cell_index(), +# pya.Trans(pya.Point(0, 0)), +# pya.Vector(0, 0), +# pya.Vector(0, 0), +# 1, +# 1, +# ) +# self.cell.insert(write_cells) +# self.cell.flatten(1) + + +# class pfet_10v0_asym(pya.PCellDeclarationHelper): +# """ +# 10V LDPFET Generator for GF180MCU +# """ + +# def __init__(self): +# # Initialize super class. +# super(pfet_10v0_asym, self).__init__() + +# # ===================== PARAMETERS DECLARATIONS ===================== + +# self.param("w", self.TypeDouble, "Width", default=ldfet_w_min, unit="um") +# self.param("l", self.TypeDouble, "Length", default=ldfet_l_min, unit="um") +# self.param("double_gr", self.TypeBoolean, "Double Guard Ring", default=1) +# self.param("area", self.TypeDouble, "Area", readonly=True, unit="um^2") +# self.param("perim", self.TypeDouble, "Perimeter", readonly=True, unit="um") + +# def display_text_impl(self): +# # Provide a descriptive text for the cell +# return "pfet_10v0_asym(L=" + ("%.3f" % self.l) + ",W=" + ("%.3f" % self.w) + ")" + +# def coerce_parameters_impl(self): +# # We employ coerce_parameters_impl to decide whether the handle or the +# # numeric parameter has changed (by comparing against the effective +# # radius ru) and set ru to the effective radius. We also update the +# # numerical value or the shape, depending on which on has not changed. +# self.area = self.w * self.l +# self.perim = 2 * (self.w + self.l) +# # w,l must be larger or equal than min. values. +# if (self.l) < ldfet_l_min: +# self.l = ldfet_l_min +# if (self.l) > ldfet_l_max: +# self.l = ldfet_l_max +# if (self.w) < ldfet_w_min: +# self.w = ldfet_w_min +# if (self.w) > ldfet_w_max: +# self.w = ldfet_w_max + +# def can_create_from_shape_impl(self): +# # Implement the "Create PCell from shape" protocol: we can use any shape which +# # has a finite bounding box +# return self.shape.is_box() or self.shape.is_polygon() or self.shape.is_path() + +# def parameters_from_shape_impl(self): +# # Implement the "Create PCell from shape" protocol: we set r and l from the shape's +# # bounding box width and layer +# self.r = self.shape.bbox().width() * self.layout.dbu / 2 +# self.l = self.layout.get_info(self.layer) + +# def transformation_from_shape_impl(self): +# # Implement the "Create PCell from shape" protocol: we use the center of the shape's +# # bounding box to determine the transformation +# return pya.Trans(self.shape.bbox().center()) + +# def produce_impl(self): +# instance = draw_pfet_10v0_asym(self.layout, self.l, self.w, self.double_gr) +# write_cells = pya.CellInstArray( +# instance.cell_index(), +# pya.Trans(pya.Point(0, 0)), +# pya.Vector(0, 0), +# pya.Vector(0, 0), +# 1, +# 1, +# ) +# self.cell.insert(write_cells) +# self.cell.flatten(1) diff --git a/cells/klayout/pymacros/cells/layers_def.py b/cells/klayout/pymacros/cells/layers_def.py new file mode 100644 index 00000000..c59db7e8 --- /dev/null +++ b/cells/klayout/pymacros/cells/layers_def.py @@ -0,0 +1,31 @@ +# Copyright 2022 GlobalFoundries PDK Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +######################################################################################################################## +## layers definition for Klayout of GF180MCU +######################################################################################################################## + +from gdsfactory.types import LayerSpec + +comp_layer : LayerSpec = (22 , 0 ) +poly2_layer: LayerSpec = (30 , 0 ) +nplus_layer: LayerSpec = (32 , 0 ) +pplus_layer: LayerSpec = (31 , 0 ) +contact_layer : LayerSpec = (33 , 0 ) +metal1_layer: LayerSpec = (34 , 0 ) +dnwell_layer : LayerSpec = (12 , 0 ) +lvpwell_layer : LayerSpec = (204, 0 ) +dualgate_layer: LayerSpec = (55 , 0 ) +v5_xtor_layer : LayerSpec = (112, 1 ) +