blob: 0064ca145d3f0d4a9e8599c593a35d19e4ab792f [file] [log] [blame]
# 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.
########################################################################################################################
## Resistor Pcells Generators for Klayout of GF180MCU
########################################################################################################################
import pya
tol = 1.05
def number_spc_contacts(box_width, min_enc, cont_spacing, cont_width):
""" Calculate number of cantacts in a given dimensions and the free space for symmetry.
By getting the min enclosure,the width of the box,the width ans spacing of the contacts.
Parameters
----------
box_width (double) : length you place the via or cont. in
min_enc (double) : spacing between the edge of the box and the first contact.
cont_spacing (double) : spacing between different contacts
cont_width (double) : contacts in the same direction
"""
spc_cont = box_width - 2 * min_enc
num_cont = int((spc_cont + cont_spacing) / (cont_width + cont_spacing))
free_spc = box_width - (num_cont * cont_width +
(num_cont - 1) * cont_spacing)
return num_cont, free_spc
def draw_metal_res(layout, l, w , res_type):
'''
Usage:-
used to draw 2-terminal Metal resistor by specifying parameters
Arguments:-
layout : Object of layout
l : Float of diff length
w : Float of diff width
'''
# Define layers
metal1 = layout.layer(34 , 0 )
metal2 = layout.layer(36 , 0 )
metal3 = layout.layer(42 , 0 )
metaltop = layout.layer(53 , 0 )
metal1_res = layout.layer(110, 11 )
metal2_res = layout.layer(110, 12 )
metal3_res = layout.layer(110, 13 )
metaltop_res = layout.layer(110, 16 )
# VARIABLES
dbu_PERCISION = 1/layout.dbu
metal_res_w = w * dbu_PERCISION
metal_res_l = l * dbu_PERCISION
if res_type == "rm1":
metal_res = metal1_res
metal = metal1
metal_res_enc = 0.23 * dbu_PERCISION
elif res_type == "rm2":
metal_res = metal2_res
metal = metal2
metal_res_enc = 0.28 * dbu_PERCISION
elif res_type == "rm3":
metal_res = metal3_res
metal = metal3
metal_res_enc = 0.28 * dbu_PERCISION
elif res_type == "tm6k":
metal_res = metaltop_res
metal = metaltop
metal_res_enc = 0.36 * dbu_PERCISION
elif res_type == "tm9k" or res_type == "tm11k":
metal_res = metaltop_res
metal = metaltop
metal_res_enc = 0.44 * dbu_PERCISION
elif res_type == "tm30k":
metal_res = metaltop_res
metal = metaltop
metal_res_enc = 1.8 * dbu_PERCISION
else:
metal_res = metal1_res
metal = metal1
metal_res_enc = 0.23 * dbu_PERCISION
# Inserting rm cell
cell_index = layout.add_cell("rm")
rm_cell = layout.cell(cell_index)
# Inserting metal_res
rm_cell.shapes(metal_res).insert(pya.Box(0, 0, metal_res_w, metal_res_l))
# Inserting metal
rm_cell.shapes(metal).insert(pya.Box(-metal_res_enc, 0 , metal_res_w+metal_res_enc, metal_res_l))
rm_cell.flatten(True)
return rm_cell
def draw_nplus_s_res(layout, l, w , sub, deepnwell, pcmpgr):
'''
Usage:-
used to draw 3-terminal salicided n+ diffusion resistor (Outside DNWELL) by specifying parameters
Arguments:-
layout : Object of layout
l : Float of diff length
w : Float of diff width
'''
# Define layers
dnwell = layout.layer(12 , 0 )
comp = layout.layer(22 , 0 )
lvpwell = layout.layer(204, 0 )
pplus = layout.layer(31 , 0 )
nplus = layout.layer(32 , 0 )
contact = layout.layer(33 , 0 )
metal1 = layout.layer(34 , 0 )
res_mk = layout.layer(110, 5 )
# VARIABLES
dbu_PERCISION = 1/layout.dbu
nplus_s_res_w = w * dbu_PERCISION
nplus_s_res_l = l * dbu_PERCISION
cmp_res_enc = 0.29 * dbu_PERCISION
implant_cmp_enc = 0.16 * dbu_PERCISION
ncmp_pcmp_spc = 0.72 * dbu_PERCISION
pcmp_width = 0.36 * dbu_PERCISION
metal_width = 0.34 * dbu_PERCISION
met_cont_enc = 0.06 * dbu_PERCISION
comp_cont_enc = 0.07 * dbu_PERCISION
cont_size = 0.22 * dbu_PERCISION
cont_min_spc = 0.25 * dbu_PERCISION
cmp_met_cont_enc_diff = 0.01 * dbu_PERCISION
min_cmp_area = 0.2025 * dbu_PERCISION * dbu_PERCISION
tie_violat = 0 * dbu_PERCISION
gr_w = 0.36 * dbu_PERCISION
dnwell_enc_lvpwell = 2.5 * dbu_PERCISION
pcmp_gr2dnw = 2.5 * dbu_PERCISION
lvpwell_enc_pcmp = 0.12 * dbu_PERCISION
lvpwell_enc_ncmp = 0.43 * dbu_PERCISION
# Inserting nplus_s_res cell
cell_index = layout.add_cell("nplus_s_resistor")
nplus_s_res_cell = layout.cell(cell_index)
# Inserting a contact cell
cont_cell_index = layout.add_cell("contact")
cont_cell = layout.cell(cont_cell_index)
cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size))
# Inserting res_mk
nplus_s_res_cell.shapes(res_mk).insert(pya.Box(0, 0, nplus_s_res_w, nplus_s_res_l))
# Inserting n diffusion
nplus_s_res_cell.shapes(comp).insert(pya.Box(-cmp_res_enc, 0, nplus_s_res_w+cmp_res_enc, nplus_s_res_l))
nplus_s_res_cell.shapes(nplus).insert(pya.Box(-cmp_res_enc-implant_cmp_enc, -implant_cmp_enc , nplus_s_res_w+cmp_res_enc+implant_cmp_enc, nplus_s_res_l+implant_cmp_enc))
# Inserting ncomp metal
nplus_s_res_cell.shapes(metal1).insert(pya.Box(-cont_size-met_cont_enc , cmp_met_cont_enc_diff , met_cont_enc , nplus_s_res_l-cmp_met_cont_enc_diff)) #left
nplus_s_res_cell.shapes(metal1).insert(pya.Box(nplus_s_res_w-met_cont_enc, cmp_met_cont_enc_diff , nplus_s_res_w+cont_size+met_cont_enc , nplus_s_res_l-cmp_met_cont_enc_diff)) # Right
# Inserting ncomp contacts
num_ncmp_left_con_1, ncmp_left_con_free_spc_1 = number_spc_contacts(metal_width, met_cont_enc, cont_min_spc, cont_size)
num_ncmp_left_con_2, ncmp_left_con_free_spc_2 = number_spc_contacts(nplus_s_res_l-2*cmp_met_cont_enc_diff, met_cont_enc, cont_min_spc, cont_size)
ncmp_left_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-cont_size-met_cont_enc+ncmp_left_con_free_spc_1 / 2, cmp_met_cont_enc_diff+ncmp_left_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_left_con_1, num_ncmp_left_con_2)
nplus_s_res_cell.insert(ncmp_left_con_arr)
num_ncmp_right_con_1, ncmp_right_con_free_spc_1 = number_spc_contacts(metal_width, met_cont_enc, cont_min_spc, cont_size)
num_ncmp_right_con_2, ncmp_right_con_free_spc_2 = number_spc_contacts(nplus_s_res_l-2*cmp_met_cont_enc_diff, met_cont_enc, cont_min_spc, cont_size)
ncmp_right_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(nplus_s_res_w-met_cont_enc+ncmp_right_con_free_spc_1 / 2, cmp_met_cont_enc_diff+ncmp_right_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_right_con_1, num_ncmp_right_con_2)
nplus_s_res_cell.insert(ncmp_right_con_arr)
if deepnwell == True:
sub = 1
# Inserting lvpwell
nplus_s_res_cell.shapes(lvpwell).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width-lvpwell_enc_pcmp, -lvpwell_enc_ncmp , nplus_s_res_w+cmp_res_enc+lvpwell_enc_ncmp, nplus_s_res_l+lvpwell_enc_ncmp))
# Inserting dnwell
nplus_s_res_cell.shapes(dnwell).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width-lvpwell_enc_pcmp-dnwell_enc_lvpwell, -lvpwell_enc_ncmp-dnwell_enc_lvpwell , nplus_s_res_w+cmp_res_enc+lvpwell_enc_ncmp+dnwell_enc_lvpwell, nplus_s_res_l+lvpwell_enc_ncmp+dnwell_enc_lvpwell))
# Inserting Guard Ring
if pcmpgr == True:
cmp_inner = pya.Box(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width-lvpwell_enc_pcmp-dnwell_enc_lvpwell-pcmp_gr2dnw, -lvpwell_enc_ncmp-dnwell_enc_lvpwell-pcmp_gr2dnw , nplus_s_res_w+cmp_res_enc+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw, nplus_s_res_l+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw)
cmp_outer = pya.Box(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width-lvpwell_enc_pcmp-dnwell_enc_lvpwell-pcmp_gr2dnw-gr_w, -lvpwell_enc_ncmp-dnwell_enc_lvpwell-pcmp_gr2dnw-gr_w , nplus_s_res_w+cmp_res_enc+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw+gr_w, nplus_s_res_l+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw+gr_w)
cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner)
nplus_s_res_cell.shapes(comp).insert(cmp_gr)
pp_inner = pya.Box(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width-lvpwell_enc_pcmp-dnwell_enc_lvpwell-pcmp_gr2dnw+implant_cmp_enc, -lvpwell_enc_ncmp-dnwell_enc_lvpwell-pcmp_gr2dnw+implant_cmp_enc , nplus_s_res_w+cmp_res_enc+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw-implant_cmp_enc, nplus_s_res_l+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw-implant_cmp_enc)
pp_outer = pya.Box(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width-lvpwell_enc_pcmp-dnwell_enc_lvpwell-pcmp_gr2dnw-gr_w-implant_cmp_enc, -lvpwell_enc_ncmp-dnwell_enc_lvpwell-pcmp_gr2dnw-gr_w-implant_cmp_enc , nplus_s_res_w+cmp_res_enc+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw+gr_w+implant_cmp_enc, nplus_s_res_l+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw+gr_w+implant_cmp_enc)
pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner)
nplus_s_res_cell.shapes(pplus).insert(pp_gr)
else:
# Inserting lvpwell
nplus_s_res_cell.shapes(lvpwell).insert(pya.Box(-cmp_res_enc-implant_cmp_enc, -implant_cmp_enc , nplus_s_res_w+cmp_res_enc+implant_cmp_enc, nplus_s_res_l+implant_cmp_enc))
if sub == 1:
# Inserting p diffusion
if (nplus_s_res_l * pcmp_width) < min_cmp_area:
tie_violat = (min_cmp_area/pcmp_width - nplus_s_res_l)/2 * tol
nplus_s_res_cell.shapes(comp).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width, -tie_violat, -cmp_res_enc-ncmp_pcmp_spc, nplus_s_res_l+tie_violat))
nplus_s_res_cell.shapes(pplus).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width-implant_cmp_enc, -implant_cmp_enc-tie_violat , -cmp_res_enc-ncmp_pcmp_spc+implant_cmp_enc, nplus_s_res_l+implant_cmp_enc+tie_violat))
# Inserting pcomp metal
nplus_s_res_cell.shapes(metal1).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width, -tie_violat, -cmp_res_enc-ncmp_pcmp_spc, nplus_s_res_l+tie_violat))
# Inserting pcomp contacts
num_pcmp_con_1, pcmp_con_free_spc_1 = number_spc_contacts(pcmp_width, comp_cont_enc, cont_min_spc, cont_size)
num_pcmp_con_2, pcmp_con_free_spc_2 = number_spc_contacts(nplus_s_res_l, comp_cont_enc, cont_min_spc, cont_size)
pcmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width+pcmp_con_free_spc_1 / 2, pcmp_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_pcmp_con_1, num_pcmp_con_2)
nplus_s_res_cell.insert(pcmp_con_arr)
nplus_s_res_cell.flatten(True)
return nplus_s_res_cell
def draw_pplus_s_res(layout, l, w, deepnwell, pcmpgr):
'''
Usage:-
used to draw3-terminal salicided P+ diffusion resistor (Outside DNWELL) by specifying parameters
Arguments:-
layout : Object of layout
l : Float of diff length
w : Float of diff width
'''
# Define layers
dnwell = layout.layer(12 , 0 )
comp = layout.layer(22 , 0 )
nwell = layout.layer(21 , 0 )
pplus = layout.layer(31 , 0 )
nplus = layout.layer(32 , 0 )
contact = layout.layer(33 , 0 )
metal1 = layout.layer(34 , 0 )
res_mk = layout.layer(110, 5 )
# VARIABLES
dbu_PERCISION = 1/layout.dbu
pplus_s_res_w = w * dbu_PERCISION
pplus_s_res_l = l * dbu_PERCISION
cmp_res_enc = 0.29 * dbu_PERCISION
implant_cmp_enc = 0.16 * dbu_PERCISION
nwell_pcmp_enc = 0.8 * dbu_PERCISION
nwell_ncmp_enc = 0.12 * dbu_PERCISION
ncmp_pcmp_spc = 0.32 * dbu_PERCISION
ncmp_width = 0.36 * dbu_PERCISION
metal_width = 0.34 * dbu_PERCISION
met_cont_enc = 0.06 * dbu_PERCISION
comp_cont_enc = 0.07 * dbu_PERCISION
cont_size = 0.22 * dbu_PERCISION
cont_min_spc = 0.25 * dbu_PERCISION
cmp_met_cont_enc_diff = 0.01 * dbu_PERCISION
min_cmp_area = 0.2025 * dbu_PERCISION * dbu_PERCISION
tie_violat = 0 * dbu_PERCISION
dnwell_ncmp_enc = 0.62 * dbu_PERCISION
dnwell_pcmp_enc = 0.93 * dbu_PERCISION
pcmp_gr2dnw = 2.5 * dbu_PERCISION
gr_w = 0.36 * dbu_PERCISION
# Inserting pplus_s_res cell
cell_index = layout.add_cell("pplus_s_resistor")
pplus_s_res_cell = layout.cell(cell_index)
# Inserting a contact cell
cont_cell_index = layout.add_cell("contact")
cont_cell = layout.cell(cont_cell_index)
cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size))
# Inserting res_mk
pplus_s_res_cell.shapes(res_mk).insert(pya.Box(0, 0, pplus_s_res_w, pplus_s_res_l))
# Inserting p diffusion
pplus_s_res_cell.shapes(comp).insert(pya.Box(-cmp_res_enc, 0, pplus_s_res_w+cmp_res_enc, pplus_s_res_l))
pplus_s_res_cell.shapes(pplus).insert(pya.Box(-cmp_res_enc-implant_cmp_enc, -implant_cmp_enc , pplus_s_res_w+cmp_res_enc+implant_cmp_enc, pplus_s_res_l+implant_cmp_enc))
# Inserting pcomp metal
pplus_s_res_cell.shapes(metal1).insert(pya.Box(-cont_size-met_cont_enc , cmp_met_cont_enc_diff , met_cont_enc , pplus_s_res_l-cmp_met_cont_enc_diff)) #left
pplus_s_res_cell.shapes(metal1).insert(pya.Box(pplus_s_res_w-met_cont_enc, cmp_met_cont_enc_diff , pplus_s_res_w+cont_size+met_cont_enc , pplus_s_res_l-cmp_met_cont_enc_diff)) # Right
# Inserting pcomp contacts
num_pcmp_left_con_1, pcmp_left_con_free_spc_1 = number_spc_contacts(metal_width, met_cont_enc, cont_min_spc, cont_size)
num_pcmp_left_con_2, pcmp_left_con_free_spc_2 = number_spc_contacts(pplus_s_res_l-2*cmp_met_cont_enc_diff, met_cont_enc, cont_min_spc, cont_size)
pcmp_left_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-cont_size-met_cont_enc+pcmp_left_con_free_spc_1 / 2, cmp_met_cont_enc_diff+pcmp_left_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_pcmp_left_con_1, num_pcmp_left_con_2)
pplus_s_res_cell.insert(pcmp_left_con_arr)
num_pcmp_right_con_1, pcmp_right_con_free_spc_1 = number_spc_contacts(metal_width, met_cont_enc, cont_min_spc, cont_size)
num_pcmp_right_con_2, pcmp_right_con_free_spc_2 = number_spc_contacts(pplus_s_res_l-2*cmp_met_cont_enc_diff, met_cont_enc, cont_min_spc, cont_size)
pcmp_right_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(pplus_s_res_w-met_cont_enc+pcmp_right_con_free_spc_1 / 2, cmp_met_cont_enc_diff+pcmp_right_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_pcmp_right_con_1, num_pcmp_right_con_2)
pplus_s_res_cell.insert(pcmp_right_con_arr)
# Inserting n diffusion
if (pplus_s_res_l * ncmp_width) < min_cmp_area:
tie_violat = (min_cmp_area/ncmp_width - pplus_s_res_l)/2 * tol
pplus_s_res_cell.shapes(comp).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width, -tie_violat, -cmp_res_enc-ncmp_pcmp_spc, pplus_s_res_l+tie_violat))
pplus_s_res_cell.shapes(nplus).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width-implant_cmp_enc, -implant_cmp_enc-tie_violat , -cmp_res_enc-ncmp_pcmp_spc+implant_cmp_enc, pplus_s_res_l+implant_cmp_enc+tie_violat))
# Inserting ncomp metal
pplus_s_res_cell.shapes(metal1).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width, -tie_violat, -cmp_res_enc-ncmp_pcmp_spc, pplus_s_res_l+tie_violat))
# Inserting ncomp contacts
num_ncmp_con_1, ncmp_con_free_spc_1 = number_spc_contacts(ncmp_width, comp_cont_enc, cont_min_spc, cont_size)
num_ncmp_con_2, ncmp_con_free_spc_2 = number_spc_contacts(pplus_s_res_l, comp_cont_enc, cont_min_spc, cont_size)
ncmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width+ncmp_con_free_spc_1 / 2, ncmp_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_con_1, num_ncmp_con_2)
pplus_s_res_cell.insert(ncmp_con_arr)
if deepnwell == True:
# Inserting dnwell
pplus_s_res_cell.shapes(dnwell).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width-dnwell_ncmp_enc, -dnwell_pcmp_enc , pplus_s_res_w+cmp_res_enc+dnwell_pcmp_enc, pplus_s_res_l+dnwell_pcmp_enc))
# Inserting Guard Ring
if pcmpgr == True:
cmp_inner = pya.Box(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width-dnwell_ncmp_enc-pcmp_gr2dnw, -dnwell_pcmp_enc-pcmp_gr2dnw , pplus_s_res_w+cmp_res_enc+dnwell_pcmp_enc+pcmp_gr2dnw, pplus_s_res_l+dnwell_pcmp_enc+pcmp_gr2dnw)
cmp_outer = pya.Box(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width-dnwell_ncmp_enc-pcmp_gr2dnw-gr_w, -dnwell_pcmp_enc-pcmp_gr2dnw-gr_w , pplus_s_res_w+cmp_res_enc+dnwell_pcmp_enc+pcmp_gr2dnw+gr_w, pplus_s_res_l+dnwell_pcmp_enc+pcmp_gr2dnw+gr_w)
cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner)
pplus_s_res_cell.shapes(comp).insert(cmp_gr)
pp_inner = pya.Box(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width-dnwell_ncmp_enc-pcmp_gr2dnw+implant_cmp_enc, -dnwell_pcmp_enc-pcmp_gr2dnw+implant_cmp_enc , pplus_s_res_w+cmp_res_enc+dnwell_pcmp_enc+pcmp_gr2dnw-implant_cmp_enc, pplus_s_res_l+dnwell_pcmp_enc+pcmp_gr2dnw-implant_cmp_enc)
pp_outer = pya.Box(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width-dnwell_ncmp_enc-pcmp_gr2dnw-gr_w-implant_cmp_enc, -dnwell_pcmp_enc-pcmp_gr2dnw-gr_w-implant_cmp_enc , pplus_s_res_w+cmp_res_enc+dnwell_pcmp_enc+pcmp_gr2dnw+gr_w+implant_cmp_enc, pplus_s_res_l+dnwell_pcmp_enc+pcmp_gr2dnw+gr_w+implant_cmp_enc)
pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner)
pplus_s_res_cell.shapes(pplus).insert(pp_gr)
else:
# Inserting nwell
pplus_s_res_cell.shapes(nwell).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width-nwell_ncmp_enc, -nwell_pcmp_enc , pplus_s_res_w+cmp_res_enc+nwell_pcmp_enc, pplus_s_res_l+nwell_pcmp_enc))
pplus_s_res_cell.flatten(True)
return pplus_s_res_cell
def draw_nplus_u_res(layout, l, w , sub, deepnwell, pcmpgr):
'''
Usage:-
used to draw 3-terminal unsalicided n+ diffusion resistor (Outside DNWELL) by specifying parameters
Arguments:-
layout : Object of layout
l : Float of diff length
w : Float of diff width
'''
# Define layers
dnwell = layout.layer(12 , 0 )
comp = layout.layer(22 , 0 )
lvpwell = layout.layer(204, 0 )
pplus = layout.layer(31 , 0 )
nplus = layout.layer(32 , 0 )
contact = layout.layer(33 , 0 )
metal1 = layout.layer(34 , 0 )
sab = layout.layer(49 , 0 )
res_mk = layout.layer(110, 5 )
# VARIABLES
dbu_PERCISION = 1/layout.dbu
nplus_u_res_w = w * dbu_PERCISION
nplus_u_res_l = l * dbu_PERCISION
cmp_res_enc = 0.44 * dbu_PERCISION
sab_res_enc = 0.23 * dbu_PERCISION
implant_cmp_enc = 0.18 * dbu_PERCISION
ncmp_pcmp_spc = 0.76 * dbu_PERCISION
pcmp_width = 0.36 * dbu_PERCISION
metal_width = 0.34 * dbu_PERCISION
met_cont_enc = 0.06 * dbu_PERCISION
comp_cont_enc = 0.07 * dbu_PERCISION
cont_size = 0.22 * dbu_PERCISION
cont_min_spc = 0.25 * dbu_PERCISION
cmp_met_cont_enc_diff = 0.01 * dbu_PERCISION
min_cmp_area = 0.2025 * dbu_PERCISION * dbu_PERCISION
tie_violat = 0 * dbu_PERCISION
gr_w = 0.36 * dbu_PERCISION
dnwell_enc_lvpwell = 2.5 * dbu_PERCISION
pcmp_gr2dnw = 2.5 * dbu_PERCISION
lvpwell_enc_pcmp = 0.12 * dbu_PERCISION
lvpwell_enc_ncmp = 0.43 * dbu_PERCISION
# Inserting nplus_u_res cell
cell_index = layout.add_cell("nplus_u_resistor")
nplus_u_res_cell = layout.cell(cell_index)
# Inserting a contact cell
cont_cell_index = layout.add_cell("contact")
cont_cell = layout.cell(cont_cell_index)
cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size))
# Inserting res_mk
nplus_u_res_cell.shapes(res_mk).insert(pya.Box(0, 0, nplus_u_res_w, nplus_u_res_l))
# Inserting sab
nplus_u_res_cell.shapes(sab).insert(pya.Box(0, -sab_res_enc, nplus_u_res_w, nplus_u_res_l+sab_res_enc))
# Inserting n diffusion
nplus_u_res_cell.shapes(comp).insert(pya.Box(-cmp_res_enc, 0, nplus_u_res_w+cmp_res_enc, nplus_u_res_l))
nplus_u_res_cell.shapes(nplus).insert(pya.Box(-cmp_res_enc-implant_cmp_enc, -implant_cmp_enc , nplus_u_res_w+cmp_res_enc+implant_cmp_enc, nplus_u_res_l+implant_cmp_enc))
# Inserting ncomp metal
nplus_u_res_cell.shapes(metal1).insert(pya.Box(-cmp_res_enc+cmp_met_cont_enc_diff , cmp_met_cont_enc_diff , -cmp_res_enc+cmp_met_cont_enc_diff+metal_width , nplus_u_res_l-cmp_met_cont_enc_diff)) #left
nplus_u_res_cell.shapes(metal1).insert(pya.Box(nplus_u_res_w+cmp_res_enc-cmp_met_cont_enc_diff-metal_width, cmp_met_cont_enc_diff , nplus_u_res_w+cmp_res_enc-cmp_met_cont_enc_diff , nplus_u_res_l-cmp_met_cont_enc_diff)) # Right
# Inserting ncomp contacts
num_ncmp_left_con_1, ncmp_left_con_free_spc_1 = number_spc_contacts(metal_width, met_cont_enc, cont_min_spc, cont_size)
num_ncmp_left_con_2, ncmp_left_con_free_spc_2 = number_spc_contacts(nplus_u_res_l-2*cmp_met_cont_enc_diff, met_cont_enc, cont_min_spc, cont_size)
ncmp_left_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-cmp_res_enc+cmp_met_cont_enc_diff+ncmp_left_con_free_spc_1 / 2, cmp_met_cont_enc_diff+ncmp_left_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_left_con_1, num_ncmp_left_con_2)
nplus_u_res_cell.insert(ncmp_left_con_arr)
num_ncmp_right_con_1, ncmp_right_con_free_spc_1 = number_spc_contacts(metal_width, met_cont_enc, cont_min_spc, cont_size)
num_ncmp_right_con_2, ncmp_right_con_free_spc_2 = number_spc_contacts(nplus_u_res_l-2*cmp_met_cont_enc_diff, met_cont_enc, cont_min_spc, cont_size)
ncmp_right_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(nplus_u_res_w+cmp_res_enc-cmp_met_cont_enc_diff-metal_width+ncmp_right_con_free_spc_1 / 2, cmp_met_cont_enc_diff+ncmp_right_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_right_con_1, num_ncmp_right_con_2)
nplus_u_res_cell.insert(ncmp_right_con_arr)
if deepnwell == True:
sub = 1
# Inserting lvpwell
nplus_u_res_cell.shapes(lvpwell).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width-lvpwell_enc_pcmp, -lvpwell_enc_ncmp , nplus_u_res_w+cmp_res_enc+lvpwell_enc_ncmp, nplus_u_res_l+lvpwell_enc_ncmp))
# Inserting dnwell
nplus_u_res_cell.shapes(dnwell).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width-lvpwell_enc_pcmp-dnwell_enc_lvpwell, -lvpwell_enc_ncmp-dnwell_enc_lvpwell , nplus_u_res_w+cmp_res_enc+lvpwell_enc_ncmp+dnwell_enc_lvpwell, nplus_u_res_l+lvpwell_enc_ncmp+dnwell_enc_lvpwell))
# Inserting Guard Ring
if pcmpgr == True:
cmp_inner = pya.Box(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width-lvpwell_enc_pcmp-dnwell_enc_lvpwell-pcmp_gr2dnw, -lvpwell_enc_ncmp-dnwell_enc_lvpwell-pcmp_gr2dnw , nplus_u_res_w+cmp_res_enc+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw, nplus_u_res_l+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw)
cmp_outer = pya.Box(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width-lvpwell_enc_pcmp-dnwell_enc_lvpwell-pcmp_gr2dnw-gr_w, -lvpwell_enc_ncmp-dnwell_enc_lvpwell-pcmp_gr2dnw-gr_w , nplus_u_res_w+cmp_res_enc+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw+gr_w, nplus_u_res_l+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw+gr_w)
cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner)
nplus_u_res_cell.shapes(comp).insert(cmp_gr)
pp_inner = pya.Box(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width-lvpwell_enc_pcmp-dnwell_enc_lvpwell-pcmp_gr2dnw+implant_cmp_enc, -lvpwell_enc_ncmp-dnwell_enc_lvpwell-pcmp_gr2dnw+implant_cmp_enc , nplus_u_res_w+cmp_res_enc+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw-implant_cmp_enc, nplus_u_res_l+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw-implant_cmp_enc)
pp_outer = pya.Box(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width-lvpwell_enc_pcmp-dnwell_enc_lvpwell-pcmp_gr2dnw-gr_w-implant_cmp_enc, -lvpwell_enc_ncmp-dnwell_enc_lvpwell-pcmp_gr2dnw-gr_w-implant_cmp_enc , nplus_u_res_w+cmp_res_enc+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw+gr_w+implant_cmp_enc, nplus_u_res_l+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw+gr_w+implant_cmp_enc)
pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner)
nplus_u_res_cell.shapes(pplus).insert(pp_gr)
else:
# Inserting lvpwell
nplus_u_res_cell.shapes(lvpwell).insert(pya.Box(-cmp_res_enc-implant_cmp_enc, -implant_cmp_enc , nplus_u_res_w+cmp_res_enc+implant_cmp_enc, nplus_u_res_l+implant_cmp_enc))
if sub == 1:
# Inserting p diffusion
if (nplus_u_res_l * pcmp_width) < min_cmp_area:
tie_violat = (min_cmp_area/pcmp_width - nplus_u_res_l)/2 * tol
nplus_u_res_cell.shapes(comp).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width, -tie_violat, -cmp_res_enc-ncmp_pcmp_spc, nplus_u_res_l+tie_violat))
nplus_u_res_cell.shapes(pplus).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width-implant_cmp_enc, -implant_cmp_enc-tie_violat , -cmp_res_enc-ncmp_pcmp_spc+implant_cmp_enc, nplus_u_res_l+tie_violat+implant_cmp_enc))
# Inserting pcomp metal
nplus_u_res_cell.shapes(metal1).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width, -tie_violat, -cmp_res_enc-ncmp_pcmp_spc, nplus_u_res_l+tie_violat))
# Inserting pcomp contacts
num_pcmp_con_1, pcmp_con_free_spc_1 = number_spc_contacts(pcmp_width, comp_cont_enc, cont_min_spc, cont_size)
num_pcmp_con_2, pcmp_con_free_spc_2 = number_spc_contacts(nplus_u_res_l, comp_cont_enc, cont_min_spc, cont_size)
pcmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-cmp_res_enc-ncmp_pcmp_spc-pcmp_width+pcmp_con_free_spc_1 / 2, pcmp_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_pcmp_con_1, num_pcmp_con_2)
nplus_u_res_cell.insert(pcmp_con_arr)
nplus_u_res_cell.flatten(True)
return nplus_u_res_cell
def draw_pplus_u_res(layout, l, w, deepnwell, pcmpgr):
'''
Usage:-
used to draw 3-terminal unsalicided P+ diffusion resistor (Outsdie DNWELL) by specifying parameters
Arguments:-
layout : Object of layout
l : Float of diff length
w : Float of diff width
'''
# Define layers
dnwell = layout.layer(12 , 0 )
comp = layout.layer(22 , 0 )
nwell = layout.layer(21 , 0 )
pplus = layout.layer(31 , 0 )
nplus = layout.layer(32 , 0 )
contact = layout.layer(33 , 0 )
metal1 = layout.layer(34 , 0 )
sab = layout.layer(49 , 0 )
res_mk = layout.layer(110, 5 )
# VARIABLES
dbu_PERCISION = 1/layout.dbu
pplus_u_res_w = w * dbu_PERCISION
pplus_u_res_l = l * dbu_PERCISION
cmp_res_enc = 0.44 * dbu_PERCISION
sab_res_enc = 0.23 * dbu_PERCISION
implant_cmp_enc = 0.18 * dbu_PERCISION
nwell_ncmp_enc = 0.12 * dbu_PERCISION
nwell_pcmp_enc = 0.93 * dbu_PERCISION
ncmp_pcmp_spc = 0.34 * dbu_PERCISION
ncmp_width = 0.36 * dbu_PERCISION
metal_width = 0.34 * dbu_PERCISION
met_cont_enc = 0.06 * dbu_PERCISION
comp_cont_enc = 0.07 * dbu_PERCISION
cont_size = 0.22 * dbu_PERCISION
cont_min_spc = 0.25 * dbu_PERCISION
cmp_met_cont_enc_diff = 0.01 * dbu_PERCISION
min_cmp_area = 0.2025 * dbu_PERCISION * dbu_PERCISION
tie_violat = 0 * dbu_PERCISION
dnwell_ncmp_enc = 0.62 * dbu_PERCISION
dnwell_pcmp_enc = 0.93 * dbu_PERCISION
pcmp_gr2dnw = 2.5 * dbu_PERCISION
gr_w = 0.36 * dbu_PERCISION
# Inserting pplus_u_res cell
cell_index = layout.add_cell("pplus_u_resistor")
pplus_u_res_cell = layout.cell(cell_index)
# Inserting a contact cell
cont_cell_index = layout.add_cell("contact")
cont_cell = layout.cell(cont_cell_index)
cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size))
# Inserting res_mk
pplus_u_res_cell.shapes(res_mk).insert(pya.Box(0, 0, pplus_u_res_w, pplus_u_res_l))
# Inserting sab
pplus_u_res_cell.shapes(sab).insert(pya.Box(0, -sab_res_enc, pplus_u_res_w, pplus_u_res_l+sab_res_enc))
# Inserting p diffusion
pplus_u_res_cell.shapes(comp).insert(pya.Box(-cmp_res_enc, 0, pplus_u_res_w+cmp_res_enc, pplus_u_res_l))
pplus_u_res_cell.shapes(pplus).insert(pya.Box(-cmp_res_enc-implant_cmp_enc, -implant_cmp_enc , pplus_u_res_w+cmp_res_enc+implant_cmp_enc, pplus_u_res_l+implant_cmp_enc))
# Inserting pcomp metal
pplus_u_res_cell.shapes(metal1).insert(pya.Box(-cmp_res_enc+cmp_met_cont_enc_diff , cmp_met_cont_enc_diff , -cmp_res_enc+cmp_met_cont_enc_diff+metal_width , pplus_u_res_l-cmp_met_cont_enc_diff)) #left
pplus_u_res_cell.shapes(metal1).insert(pya.Box(pplus_u_res_w+cmp_res_enc-cmp_met_cont_enc_diff-metal_width, cmp_met_cont_enc_diff , pplus_u_res_w+cmp_res_enc-cmp_met_cont_enc_diff , pplus_u_res_l-cmp_met_cont_enc_diff)) # Right
# Inserting pcomp contacts
num_pcmp_left_con_1, pcmp_left_con_free_spc_1 = number_spc_contacts(metal_width, met_cont_enc, cont_min_spc, cont_size)
num_pcmp_left_con_2, pcmp_left_con_free_spc_2 = number_spc_contacts(pplus_u_res_l-2*cmp_met_cont_enc_diff, met_cont_enc, cont_min_spc, cont_size)
pcmp_left_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-cmp_res_enc+cmp_met_cont_enc_diff+pcmp_left_con_free_spc_1 / 2, cmp_met_cont_enc_diff+pcmp_left_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_pcmp_left_con_1, num_pcmp_left_con_2)
pplus_u_res_cell.insert(pcmp_left_con_arr)
num_pcmp_right_con_1, pcmp_right_con_free_spc_1 = number_spc_contacts(metal_width, met_cont_enc, cont_min_spc, cont_size)
num_pcmp_right_con_2, pcmp_right_con_free_spc_2 = number_spc_contacts(pplus_u_res_l-2*cmp_met_cont_enc_diff, met_cont_enc, cont_min_spc, cont_size)
pcmp_right_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(pplus_u_res_w+cmp_res_enc-cmp_met_cont_enc_diff-metal_width+pcmp_right_con_free_spc_1 / 2, cmp_met_cont_enc_diff+pcmp_right_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_pcmp_right_con_1, num_pcmp_right_con_2)
pplus_u_res_cell.insert(pcmp_right_con_arr)
# Inserting n diffusion
if (pplus_u_res_l * ncmp_width) < min_cmp_area:
tie_violat = (min_cmp_area/ncmp_width - pplus_u_res_l)/2 * tol
pplus_u_res_cell.shapes(comp).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width, -tie_violat, -cmp_res_enc-ncmp_pcmp_spc, pplus_u_res_l+tie_violat))
pplus_u_res_cell.shapes(nplus).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width-implant_cmp_enc, -implant_cmp_enc-tie_violat , -cmp_res_enc-ncmp_pcmp_spc+implant_cmp_enc, pplus_u_res_l+implant_cmp_enc+tie_violat))
# Inserting ncomp metal
pplus_u_res_cell.shapes(metal1).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width, -tie_violat, -cmp_res_enc-ncmp_pcmp_spc, pplus_u_res_l+tie_violat))
# Inserting ncomp contacts
num_ncmp_con_1, ncmp_con_free_spc_1 = number_spc_contacts(ncmp_width, comp_cont_enc, cont_min_spc, cont_size)
num_ncmp_con_2, ncmp_con_free_spc_2 = number_spc_contacts(pplus_u_res_l, comp_cont_enc, cont_min_spc, cont_size)
ncmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width+ncmp_con_free_spc_1 / 2, ncmp_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_con_1, num_ncmp_con_2)
pplus_u_res_cell.insert(ncmp_con_arr)
if deepnwell == True:
# Inserting dnwell
pplus_u_res_cell.shapes(dnwell).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width-dnwell_ncmp_enc, -dnwell_pcmp_enc , pplus_u_res_w+cmp_res_enc+dnwell_pcmp_enc, pplus_u_res_l+dnwell_pcmp_enc))
# Inserting Guard Ring
if pcmpgr == True:
cmp_inner = pya.Box(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width-dnwell_ncmp_enc-pcmp_gr2dnw, -dnwell_pcmp_enc-pcmp_gr2dnw , pplus_u_res_w+cmp_res_enc+dnwell_pcmp_enc+pcmp_gr2dnw, pplus_u_res_l+dnwell_pcmp_enc+pcmp_gr2dnw)
cmp_outer = pya.Box(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width-dnwell_ncmp_enc-pcmp_gr2dnw-gr_w, -dnwell_pcmp_enc-pcmp_gr2dnw-gr_w , pplus_u_res_w+cmp_res_enc+dnwell_pcmp_enc+pcmp_gr2dnw+gr_w, pplus_u_res_l+dnwell_pcmp_enc+pcmp_gr2dnw+gr_w)
cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner)
pplus_u_res_cell.shapes(comp).insert(cmp_gr)
pp_inner = pya.Box(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width-dnwell_ncmp_enc-pcmp_gr2dnw+implant_cmp_enc, -dnwell_pcmp_enc-pcmp_gr2dnw+implant_cmp_enc , pplus_u_res_w+cmp_res_enc+dnwell_pcmp_enc+pcmp_gr2dnw-implant_cmp_enc, pplus_u_res_l+dnwell_pcmp_enc+pcmp_gr2dnw-implant_cmp_enc)
pp_outer = pya.Box(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width-dnwell_ncmp_enc-pcmp_gr2dnw-gr_w-implant_cmp_enc, -dnwell_pcmp_enc-pcmp_gr2dnw-gr_w-implant_cmp_enc , pplus_u_res_w+cmp_res_enc+dnwell_pcmp_enc+pcmp_gr2dnw+gr_w+implant_cmp_enc, pplus_u_res_l+dnwell_pcmp_enc+pcmp_gr2dnw+gr_w+implant_cmp_enc)
pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner)
pplus_u_res_cell.shapes(pplus).insert(pp_gr)
else:
# Inserting nwell
pplus_u_res_cell.shapes(nwell).insert(pya.Box(-cmp_res_enc-ncmp_pcmp_spc-ncmp_width-nwell_ncmp_enc, -nwell_pcmp_enc , pplus_u_res_w+cmp_res_enc+nwell_pcmp_enc, pplus_u_res_l+nwell_pcmp_enc))
pplus_u_res_cell.flatten(True)
return pplus_u_res_cell
def draw_nwell_res(layout, l, w):
'''
Usage:-
used to draw 3-terminal Nwell resistor under STI (Outside DNWELL) by specifying parameters
Arguments:-
layout : Object of layout
l : Float of diff length
w : Float of diff width
'''
# Define layers
comp = layout.layer(22 , 0 )
nwell = layout.layer(21 , 0 )
pplus = layout.layer(31 , 0 )
nplus = layout.layer(32 , 0 )
contact = layout.layer(33 , 0 )
metal1 = layout.layer(34 , 0 )
res_mk = layout.layer(110, 5 )
# VARIABLES
dbu_PERCISION = 1/layout.dbu
nwell_res_w = w * dbu_PERCISION
nwell_res_l = l * dbu_PERCISION
nwell_res_enc = 0.48 * dbu_PERCISION
res_nwell_ext = 0.5 * dbu_PERCISION
implant_cmp_enc = 0.16 * dbu_PERCISION
nwell_cmp_enc = 0.12 * dbu_PERCISION
ncmp_pcmp_spc = 0.84 * dbu_PERCISION
cmp_width = 0.36 * dbu_PERCISION
metal_width = 0.34 * dbu_PERCISION
met_cont_enc = 0.06 * dbu_PERCISION
comp_cont_enc = 0.07 * dbu_PERCISION
cont_size = 0.22 * dbu_PERCISION
cont_min_spc = 0.25 * dbu_PERCISION
cmp_met_cont_enc_diff = 0.01 * dbu_PERCISION
# Inserting nwell_res cell
cell_index = layout.add_cell("nwell_resistor")
nwell_res_cell = layout.cell(cell_index)
# Inserting a contact cell
cont_cell_index = layout.add_cell("contact")
cont_cell = layout.cell(cont_cell_index)
cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size))
# Inserting res_mk
nwell_res_cell.shapes(res_mk).insert(pya.Box(0, -res_nwell_ext, nwell_res_w, nwell_res_l+res_nwell_ext))
# Inserting nwell
nwell_res_cell.shapes(nwell).insert(pya.Box(-nwell_res_enc, 0, nwell_res_w+nwell_res_enc, nwell_res_l))
# Inserting n diffusion
nwell_res_cell.shapes(comp).insert(pya.Box(-cmp_width, nwell_cmp_enc, 0, nwell_res_l-nwell_cmp_enc)) #left
nwell_res_cell.shapes(comp).insert(pya.Box(nwell_res_w, nwell_cmp_enc, nwell_res_w+cmp_width, nwell_res_l-nwell_cmp_enc)) #right
nwell_res_cell.shapes(nplus).insert(pya.Box(-cmp_width-implant_cmp_enc, nwell_cmp_enc-implant_cmp_enc , implant_cmp_enc, nwell_res_l-nwell_cmp_enc+implant_cmp_enc))
nwell_res_cell.shapes(nplus).insert(pya.Box(nwell_res_w-implant_cmp_enc, nwell_cmp_enc-implant_cmp_enc , nwell_res_w+cmp_width+implant_cmp_enc, nwell_res_l-nwell_cmp_enc+implant_cmp_enc))
# Inserting ncomp metal
nwell_res_cell.shapes(metal1).insert(pya.Box(-cmp_width, nwell_cmp_enc, 0, nwell_res_l-nwell_cmp_enc)) #left
nwell_res_cell.shapes(metal1).insert(pya.Box(nwell_res_w, nwell_cmp_enc, nwell_res_w+cmp_width, nwell_res_l-nwell_cmp_enc)) #right
# Inserting ncomp contacts
num_ncmp_left_con_1, ncmp_left_con_free_spc_1 = number_spc_contacts(cmp_width, comp_cont_enc, cont_min_spc, cont_size)
num_ncmp_left_con_2, ncmp_left_con_free_spc_2 = number_spc_contacts(nwell_res_l-2*nwell_cmp_enc, comp_cont_enc, cont_min_spc, cont_size)
ncmp_left_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-cmp_width+ncmp_left_con_free_spc_1 / 2, nwell_cmp_enc+ncmp_left_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_left_con_1, num_ncmp_left_con_2)
nwell_res_cell.insert(ncmp_left_con_arr)
num_ncmp_right_con_1, ncmp_right_con_free_spc_1 = number_spc_contacts(cmp_width, comp_cont_enc, cont_min_spc, cont_size)
num_ncmp_right_con_2, ncmp_right_con_free_spc_2 = number_spc_contacts(nwell_res_l-2*nwell_cmp_enc, comp_cont_enc, cont_min_spc, cont_size)
ncmp_right_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(nwell_res_w+ncmp_right_con_free_spc_1 / 2, nwell_cmp_enc+ncmp_right_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_right_con_1, num_ncmp_right_con_2)
nwell_res_cell.insert(ncmp_right_con_arr)
# Inserting p diffusion
nwell_res_cell.shapes(comp).insert(pya.Box(-cmp_width-ncmp_pcmp_spc-cmp_width, 0, -cmp_width-ncmp_pcmp_spc , nwell_res_l))
nwell_res_cell.shapes(pplus).insert(pya.Box(-cmp_width-ncmp_pcmp_spc-cmp_width-implant_cmp_enc, -implant_cmp_enc, -cmp_width-ncmp_pcmp_spc+implant_cmp_enc , nwell_res_l+implant_cmp_enc))
# Inserting pcomp metal
nwell_res_cell.shapes(metal1).insert(pya.Box(-cmp_width-ncmp_pcmp_spc-cmp_width, 0, -cmp_width-ncmp_pcmp_spc , nwell_res_l))
# Inserting pcomp contacts
num_pcmp_con_1, pcmp_con_free_spc_1 = number_spc_contacts(cmp_width, comp_cont_enc, cont_min_spc, cont_size)
num_pcmp_con_2, pcmp_con_free_spc_2 = number_spc_contacts(nwell_res_l, comp_cont_enc, cont_min_spc, cont_size)
pcmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-cmp_width-ncmp_pcmp_spc-cmp_width+pcmp_con_free_spc_1 / 2, pcmp_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_pcmp_con_1, num_pcmp_con_2)
nwell_res_cell.insert(pcmp_con_arr)
nwell_res_cell.flatten(True)
return nwell_res_cell
def draw_pwell_res(layout, l, w, pcmpgr):
'''
Usage:-
used to draw 3-terminal Pwell resistor under STI (Outside DNWELL) by specifying parameters
Arguments:-
layout : Object of layout
l : Float of diff length
w : Float of diff width
'''
# Define layers
comp = layout.layer(22 , 0 )
dnwell = layout.layer(12 , 0 )
lvpwell = layout.layer(204, 0 )
pplus = layout.layer(31 , 0 )
nplus = layout.layer(32 , 0 )
contact = layout.layer(33 , 0 )
metal1 = layout.layer(34 , 0 )
res_mk = layout.layer(110, 5 )
# VARIABLES
dbu_PERCISION = 1/layout.dbu
pwell_res_w = w * dbu_PERCISION
pwell_res_l = l * dbu_PERCISION
pwell_res_enc = 0.48 * dbu_PERCISION
dnwell_lvpwell_enc = 2.5 * dbu_PERCISION
res_pwell_ext = 0.5 * dbu_PERCISION
implant_cmp_enc = 0.16 * dbu_PERCISION
pwell_cmp_enc = 0.12 * dbu_PERCISION
ncmp_pcmp_spc = 0.84 * dbu_PERCISION
cmp_width = 0.36 * dbu_PERCISION
comp_cont_enc = 0.07 * dbu_PERCISION
cont_size = 0.22 * dbu_PERCISION
cont_min_spc = 0.25 * dbu_PERCISION
pcmp_gr2dnw = 2.5 * dbu_PERCISION
gr_w = 0.36 * dbu_PERCISION
# Inserting pwell_res cell
cell_index = layout.add_cell("pwell_resistor")
pwell_res_cell = layout.cell(cell_index)
# Inserting a contact cell
cont_cell_index = layout.add_cell("contact")
cont_cell = layout.cell(cont_cell_index)
cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size))
# Inserting res_mk
pwell_res_cell.shapes(res_mk).insert(pya.Box(0, -res_pwell_ext, pwell_res_w, pwell_res_l+res_pwell_ext))
# Inserting pwell
pwell_res_cell.shapes(lvpwell).insert(pya.Box(-pwell_res_enc, 0, pwell_res_w+pwell_res_enc, pwell_res_l))
# Inserting DNWELL
pwell_res_cell.shapes(dnwell).insert(pya.Box(-pwell_res_enc-dnwell_lvpwell_enc, -dnwell_lvpwell_enc, pwell_res_w+pwell_res_enc+dnwell_lvpwell_enc, pwell_res_l+dnwell_lvpwell_enc))
# Inserting Guard Ring
if pcmpgr == True:
cmp_inner = pya.Box(-pwell_res_enc-dnwell_lvpwell_enc-pcmp_gr2dnw, -dnwell_lvpwell_enc-pcmp_gr2dnw, pwell_res_w+pwell_res_enc+dnwell_lvpwell_enc+pcmp_gr2dnw, pwell_res_l+dnwell_lvpwell_enc+pcmp_gr2dnw)
cmp_outer = pya.Box(-pwell_res_enc-dnwell_lvpwell_enc-pcmp_gr2dnw-gr_w, -dnwell_lvpwell_enc-pcmp_gr2dnw-gr_w, pwell_res_w+pwell_res_enc+dnwell_lvpwell_enc+pcmp_gr2dnw+gr_w, pwell_res_l+dnwell_lvpwell_enc+pcmp_gr2dnw+gr_w)
cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner)
pwell_res_cell.shapes(comp).insert(cmp_gr)
pp_inner = pya.Box(-pwell_res_enc-dnwell_lvpwell_enc-pcmp_gr2dnw+implant_cmp_enc, -dnwell_lvpwell_enc-pcmp_gr2dnw+implant_cmp_enc, pwell_res_w+pwell_res_enc+dnwell_lvpwell_enc+pcmp_gr2dnw-implant_cmp_enc, pwell_res_l+dnwell_lvpwell_enc+pcmp_gr2dnw-implant_cmp_enc)
pp_outer = pya.Box(-pwell_res_enc-dnwell_lvpwell_enc-pcmp_gr2dnw-gr_w-implant_cmp_enc, -dnwell_lvpwell_enc-pcmp_gr2dnw-gr_w-implant_cmp_enc, pwell_res_w+pwell_res_enc+dnwell_lvpwell_enc+pcmp_gr2dnw+gr_w+implant_cmp_enc, pwell_res_l+dnwell_lvpwell_enc+pcmp_gr2dnw+gr_w+implant_cmp_enc)
pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner)
pwell_res_cell.shapes(pplus).insert(pp_gr)
# Inserting p diffusion
pwell_res_cell.shapes(comp).insert(pya.Box(-cmp_width, pwell_cmp_enc, 0, pwell_res_l-pwell_cmp_enc)) #left
pwell_res_cell.shapes(comp).insert(pya.Box(pwell_res_w, pwell_cmp_enc, pwell_res_w+cmp_width, pwell_res_l-pwell_cmp_enc)) #right
pwell_res_cell.shapes(pplus).insert(pya.Box(-cmp_width-implant_cmp_enc, pwell_cmp_enc-implant_cmp_enc , implant_cmp_enc, pwell_res_l-pwell_cmp_enc+implant_cmp_enc))
pwell_res_cell.shapes(pplus).insert(pya.Box(pwell_res_w-implant_cmp_enc, pwell_cmp_enc-implant_cmp_enc , pwell_res_w+cmp_width+implant_cmp_enc, pwell_res_l-pwell_cmp_enc+implant_cmp_enc))
# Inserting ncomp metal
pwell_res_cell.shapes(metal1).insert(pya.Box(-cmp_width, pwell_cmp_enc, 0, pwell_res_l-pwell_cmp_enc)) #left
pwell_res_cell.shapes(metal1).insert(pya.Box(pwell_res_w, pwell_cmp_enc, pwell_res_w+cmp_width, pwell_res_l-pwell_cmp_enc)) #right
# Inserting pcomp contacts
num_pcmp_left_con_1, pcmp_left_con_free_spc_1 = number_spc_contacts(cmp_width, comp_cont_enc, cont_min_spc, cont_size)
num_pcmp_left_con_2, pcmp_left_con_free_spc_2 = number_spc_contacts(pwell_res_l-2*pwell_cmp_enc, comp_cont_enc, cont_min_spc, cont_size)
pcmp_left_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-cmp_width+pcmp_left_con_free_spc_1 / 2, pwell_cmp_enc+pcmp_left_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_pcmp_left_con_1, num_pcmp_left_con_2)
pwell_res_cell.insert(pcmp_left_con_arr)
num_ncmp_right_con_1, ncmp_right_con_free_spc_1 = number_spc_contacts(cmp_width, comp_cont_enc, cont_min_spc, cont_size)
num_ncmp_right_con_2, ncmp_right_con_free_spc_2 = number_spc_contacts(pwell_res_l-2*pwell_cmp_enc, comp_cont_enc, cont_min_spc, cont_size)
ncmp_right_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(pwell_res_w+ncmp_right_con_free_spc_1 / 2, pwell_cmp_enc+ncmp_right_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_right_con_1, num_ncmp_right_con_2)
pwell_res_cell.insert(ncmp_right_con_arr)
# Inserting n diffusion
pwell_res_cell.shapes(comp).insert(pya.Box(-cmp_width-ncmp_pcmp_spc-cmp_width, 0, -cmp_width-ncmp_pcmp_spc , pwell_res_l))
pwell_res_cell.shapes(nplus).insert(pya.Box(-cmp_width-ncmp_pcmp_spc-cmp_width-implant_cmp_enc, -implant_cmp_enc, -cmp_width-ncmp_pcmp_spc+implant_cmp_enc , pwell_res_l+implant_cmp_enc))
# Inserting pcomp metal
pwell_res_cell.shapes(metal1).insert(pya.Box(-cmp_width-ncmp_pcmp_spc-cmp_width, 0, -cmp_width-ncmp_pcmp_spc , pwell_res_l))
# Inserting pcomp contacts
num_ncmp_con_1, ncmp_con_free_spc_1 = number_spc_contacts(cmp_width, comp_cont_enc, cont_min_spc, cont_size)
num_ncmp_con_2, ncmp_con_free_spc_2 = number_spc_contacts(pwell_res_l, comp_cont_enc, cont_min_spc, cont_size)
ncmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-cmp_width-ncmp_pcmp_spc-cmp_width+ncmp_con_free_spc_1 / 2, ncmp_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_con_1, num_ncmp_con_2)
pwell_res_cell.insert(ncmp_con_arr)
pwell_res_cell.flatten(True)
return pwell_res_cell
def draw_npolyf_s_res(layout, l, w, deepnwell, pcmpgr):
'''
Usage:-
used to draw 3-terminal salicided n+ poly resistor (Outside DNWELL) by specifying parameters
Arguments:-
layout : Object of layout
l : Float of diff length
w : Float of diff width
'''
# Define layers
dnwell = layout.layer(12 , 0 )
comp = layout.layer(22 , 0 )
poly = layout.layer(30 , 0 )
pplus = layout.layer(31 , 0 )
nplus = layout.layer(32 , 0 )
contact = layout.layer(33 , 0 )
metal1 = layout.layer(34 , 0 )
res_mk = layout.layer(110, 5 )
# VARIABLES
dbu_PERCISION = 1/layout.dbu
npolyf_s_res_w = w * dbu_PERCISION
npolyf_s_res_l = l * dbu_PERCISION
poly_res_enc = 0.29 * dbu_PERCISION
implant_cmp_enc = 0.16 * dbu_PERCISION
implant_poly_enc = 0.3 * dbu_PERCISION
npoly_pcmp_spc = 0.72 * dbu_PERCISION
pcmp_width = 0.36 * dbu_PERCISION
metal_width = 0.34 * dbu_PERCISION
met_cont_enc = 0.06 * dbu_PERCISION
comp_cont_enc = 0.07 * dbu_PERCISION
cont_size = 0.22 * dbu_PERCISION
cont_min_spc = 0.25 * dbu_PERCISION
cmp_met_cont_enc_diff = 0.01 * dbu_PERCISION
dnwell_enc_ncmp = 0.62 * dbu_PERCISION
dnwell_enc_poly = 1.34 * dbu_PERCISION
pcmp_gr2dnw = 2.5 * dbu_PERCISION
gr_w = 0.36 * dbu_PERCISION
# Inserting npolyf_s_res cell
cell_index = layout.add_cell("npolyf_s_resistor")
npolyf_s_res_cell = layout.cell(cell_index)
# Inserting a contact cell
cont_cell_index = layout.add_cell("contact")
cont_cell = layout.cell(cont_cell_index)
cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size))
# Inserting res_mk
npolyf_s_res_cell.shapes(res_mk).insert(pya.Box(0, 0, npolyf_s_res_w, npolyf_s_res_l))
# Inserting n poly
npolyf_s_res_cell.shapes(poly).insert(pya.Box(-poly_res_enc, 0, npolyf_s_res_w+poly_res_enc, npolyf_s_res_l))
npolyf_s_res_cell.shapes(nplus).insert(pya.Box(-poly_res_enc-implant_poly_enc, -implant_poly_enc , npolyf_s_res_w+poly_res_enc+implant_poly_enc, npolyf_s_res_l+implant_poly_enc))
# Inserting ncomp metal
npolyf_s_res_cell.shapes(metal1).insert(pya.Box(-cont_size-met_cont_enc , cmp_met_cont_enc_diff , met_cont_enc , npolyf_s_res_l-cmp_met_cont_enc_diff)) #left
npolyf_s_res_cell.shapes(metal1).insert(pya.Box(npolyf_s_res_w-met_cont_enc, cmp_met_cont_enc_diff , npolyf_s_res_w+cont_size+met_cont_enc , npolyf_s_res_l-cmp_met_cont_enc_diff)) # Right
# Inserting ncomp contacts
num_ncmp_left_con_1, ncmp_left_con_free_spc_1 = number_spc_contacts(metal_width, met_cont_enc, cont_min_spc, cont_size)
num_ncmp_left_con_2, ncmp_left_con_free_spc_2 = number_spc_contacts(npolyf_s_res_l-2*cmp_met_cont_enc_diff, met_cont_enc, cont_min_spc, cont_size)
ncmp_left_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-cont_size-met_cont_enc+ncmp_left_con_free_spc_1 / 2, cmp_met_cont_enc_diff+ncmp_left_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_left_con_1, num_ncmp_left_con_2)
npolyf_s_res_cell.insert(ncmp_left_con_arr)
num_ncmp_right_con_1, ncmp_right_con_free_spc_1 = number_spc_contacts(metal_width, met_cont_enc, cont_min_spc, cont_size)
num_ncmp_right_con_2, ncmp_right_con_free_spc_2 = number_spc_contacts(npolyf_s_res_l-2*cmp_met_cont_enc_diff, met_cont_enc, cont_min_spc, cont_size)
ncmp_right_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(npolyf_s_res_w-met_cont_enc+ncmp_right_con_free_spc_1 / 2, cmp_met_cont_enc_diff+ncmp_right_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_right_con_1, num_ncmp_right_con_2)
npolyf_s_res_cell.insert(ncmp_right_con_arr)
# Inserting p diffusion
npolyf_s_res_cell.shapes(comp).insert(pya.Box(-poly_res_enc-npoly_pcmp_spc-pcmp_width, 0, -poly_res_enc-npoly_pcmp_spc, npolyf_s_res_l))
# Inserting pcomp metal
npolyf_s_res_cell.shapes(metal1).insert(pya.Box(-poly_res_enc-npoly_pcmp_spc-pcmp_width, 0, -poly_res_enc-npoly_pcmp_spc, npolyf_s_res_l))
# Inserting pcomp contacts
num_pcmp_con_1, pcmp_con_free_spc_1 = number_spc_contacts(pcmp_width, comp_cont_enc, cont_min_spc, cont_size)
num_pcmp_con_2, pcmp_con_free_spc_2 = number_spc_contacts(npolyf_s_res_l, comp_cont_enc, cont_min_spc, cont_size)
pcmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-poly_res_enc-npoly_pcmp_spc-pcmp_width+pcmp_con_free_spc_1 / 2, pcmp_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_pcmp_con_1, num_pcmp_con_2)
npolyf_s_res_cell.insert(pcmp_con_arr)
if deepnwell == True:
# Inserting Ntap
npolyf_s_res_cell.shapes(nplus).insert(pya.Box(-poly_res_enc-npoly_pcmp_spc-pcmp_width-implant_cmp_enc, -implant_cmp_enc , -poly_res_enc-npoly_pcmp_spc+implant_cmp_enc, npolyf_s_res_l+implant_cmp_enc))
# Inserting dnwell
npolyf_s_res_cell.shapes(dnwell).insert(pya.Box(-poly_res_enc-npoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp, -dnwell_enc_poly , npolyf_s_res_w+poly_res_enc+dnwell_enc_poly, npolyf_s_res_l+dnwell_enc_poly))
# Inserting Guard Ring
if pcmpgr == True:
cmp_inner = pya.Box(-poly_res_enc-npoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw, -dnwell_enc_poly-pcmp_gr2dnw , npolyf_s_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw, npolyf_s_res_l+dnwell_enc_poly+pcmp_gr2dnw)
cmp_outer = pya.Box(-poly_res_enc-npoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw-gr_w, -dnwell_enc_poly-pcmp_gr2dnw-gr_w , npolyf_s_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw+gr_w, npolyf_s_res_l+dnwell_enc_poly+pcmp_gr2dnw+gr_w)
cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner)
npolyf_s_res_cell.shapes(comp).insert(cmp_gr)
pp_inner = pya.Box(-poly_res_enc-npoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw+implant_cmp_enc, -dnwell_enc_poly-pcmp_gr2dnw+implant_cmp_enc , npolyf_s_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw-implant_cmp_enc, npolyf_s_res_l+dnwell_enc_poly+pcmp_gr2dnw-implant_cmp_enc)
pp_outer = pya.Box(-poly_res_enc-npoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw-gr_w-implant_cmp_enc, -dnwell_enc_poly-pcmp_gr2dnw-gr_w-implant_cmp_enc , npolyf_s_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw+gr_w+implant_cmp_enc, npolyf_s_res_l+dnwell_enc_poly+pcmp_gr2dnw+gr_w+implant_cmp_enc)
pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner)
npolyf_s_res_cell.shapes(pplus).insert(pp_gr)
else:
npolyf_s_res_cell.shapes(pplus).insert(pya.Box(-poly_res_enc-npoly_pcmp_spc-pcmp_width-implant_cmp_enc, -implant_cmp_enc , -poly_res_enc-npoly_pcmp_spc+implant_cmp_enc, npolyf_s_res_l+implant_cmp_enc))
npolyf_s_res_cell.flatten(True)
return npolyf_s_res_cell
def draw_ppolyf_s_res(layout, l, w, deepnwell, pcmpgr):
'''
Usage:-
used to draw 3-terminal salicided p+ poly resistor (Outside DNWELL) by specifying parameters
Arguments:-
layout : Object of layout
l : Float of diff length
w : Float of diff width
'''
# Define layers
dnwell = layout.layer(12 , 0 )
comp = layout.layer(22 , 0 )
poly = layout.layer(30 , 0 )
pplus = layout.layer(31 , 0 )
nplus = layout.layer(32 , 0 )
contact = layout.layer(33 , 0 )
metal1 = layout.layer(34 , 0 )
res_mk = layout.layer(110, 5 )
# VARIABLES
dbu_PERCISION = 1/layout.dbu
ppolyf_s_res_w = w * dbu_PERCISION
ppolyf_s_res_l = l * dbu_PERCISION
poly_res_enc = 0.29 * dbu_PERCISION
implant_cmp_enc = 0.16 * dbu_PERCISION
implant_poly_enc = 0.3 * dbu_PERCISION
ppoly_pcmp_spc = 0.86 * dbu_PERCISION
pcmp_width = 0.36 * dbu_PERCISION
metal_width = 0.34 * dbu_PERCISION
met_cont_enc = 0.06 * dbu_PERCISION
comp_cont_enc = 0.07 * dbu_PERCISION
cont_size = 0.22 * dbu_PERCISION
cont_min_spc = 0.25 * dbu_PERCISION
cmp_met_cont_enc_diff = 0.01 * dbu_PERCISION
dnwell_enc_ncmp = 0.62 * dbu_PERCISION
dnwell_enc_poly = 1.34 * dbu_PERCISION
pcmp_gr2dnw = 2.5 * dbu_PERCISION
gr_w = 0.36 * dbu_PERCISION
# Inserting ppolyf_s_res cell
cell_index = layout.add_cell("ppolyf_s_resistor")
ppolyf_s_res_cell = layout.cell(cell_index)
# Inserting a contact cell
cont_cell_index = layout.add_cell("contact")
cont_cell = layout.cell(cont_cell_index)
cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size))
# Inserting res_mk
ppolyf_s_res_cell.shapes(res_mk).insert(pya.Box(0, 0, ppolyf_s_res_w, ppolyf_s_res_l))
# Inserting n poly
ppolyf_s_res_cell.shapes(poly).insert(pya.Box(-poly_res_enc, 0, ppolyf_s_res_w+poly_res_enc, ppolyf_s_res_l))
ppolyf_s_res_cell.shapes(pplus).insert(pya.Box(-poly_res_enc-implant_poly_enc, -implant_poly_enc , ppolyf_s_res_w+poly_res_enc+implant_poly_enc, ppolyf_s_res_l+implant_poly_enc))
# Inserting ncomp metal
ppolyf_s_res_cell.shapes(metal1).insert(pya.Box(-cont_size-met_cont_enc , cmp_met_cont_enc_diff , met_cont_enc , ppolyf_s_res_l-cmp_met_cont_enc_diff)) #left
ppolyf_s_res_cell.shapes(metal1).insert(pya.Box(ppolyf_s_res_w-met_cont_enc, cmp_met_cont_enc_diff , ppolyf_s_res_w+cont_size+met_cont_enc , ppolyf_s_res_l-cmp_met_cont_enc_diff)) # Right
# Inserting ncomp contacts
num_ncmp_left_con_1, ncmp_left_con_free_spc_1 = number_spc_contacts(metal_width, met_cont_enc, cont_min_spc, cont_size)
num_ncmp_left_con_2, ncmp_left_con_free_spc_2 = number_spc_contacts(ppolyf_s_res_l-2*cmp_met_cont_enc_diff, met_cont_enc, cont_min_spc, cont_size)
ncmp_left_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-cont_size-met_cont_enc+ncmp_left_con_free_spc_1 / 2, cmp_met_cont_enc_diff+ncmp_left_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_left_con_1, num_ncmp_left_con_2)
ppolyf_s_res_cell.insert(ncmp_left_con_arr)
num_ncmp_right_con_1, ncmp_right_con_free_spc_1 = number_spc_contacts(metal_width, met_cont_enc, cont_min_spc, cont_size)
num_ncmp_right_con_2, ncmp_right_con_free_spc_2 = number_spc_contacts(ppolyf_s_res_l-2*cmp_met_cont_enc_diff, met_cont_enc, cont_min_spc, cont_size)
ncmp_right_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(ppolyf_s_res_w-met_cont_enc+ncmp_right_con_free_spc_1 / 2, cmp_met_cont_enc_diff+ncmp_right_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_right_con_1, num_ncmp_right_con_2)
ppolyf_s_res_cell.insert(ncmp_right_con_arr)
# Inserting p diffusion
ppolyf_s_res_cell.shapes(comp).insert(pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width, 0, -poly_res_enc-ppoly_pcmp_spc, ppolyf_s_res_l))
# Inserting pcomp metal
ppolyf_s_res_cell.shapes(metal1).insert(pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width, 0, -poly_res_enc-ppoly_pcmp_spc, ppolyf_s_res_l))
# Inserting pcomp contacts
num_pcmp_con_1, pcmp_con_free_spc_1 = number_spc_contacts(pcmp_width, comp_cont_enc, cont_min_spc, cont_size)
num_pcmp_con_2, pcmp_con_free_spc_2 = number_spc_contacts(ppolyf_s_res_l, comp_cont_enc, cont_min_spc, cont_size)
pcmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-poly_res_enc-ppoly_pcmp_spc-pcmp_width+pcmp_con_free_spc_1 / 2, pcmp_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_pcmp_con_1, num_pcmp_con_2)
ppolyf_s_res_cell.insert(pcmp_con_arr)
if deepnwell == True:
# Inserting Ntap
ppolyf_s_res_cell.shapes(nplus).insert(pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-implant_cmp_enc, -implant_cmp_enc , -poly_res_enc-ppoly_pcmp_spc+implant_cmp_enc, ppolyf_s_res_l+implant_cmp_enc))
# Inserting dnwell
ppolyf_s_res_cell.shapes(dnwell).insert(pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp, -dnwell_enc_poly , ppolyf_s_res_w+poly_res_enc+dnwell_enc_poly, ppolyf_s_res_l+dnwell_enc_poly))
# Inserting Guard Ring
if pcmpgr == True:
cmp_inner = pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw, -dnwell_enc_poly-pcmp_gr2dnw , ppolyf_s_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw, ppolyf_s_res_l+dnwell_enc_poly+pcmp_gr2dnw)
cmp_outer = pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw-gr_w, -dnwell_enc_poly-pcmp_gr2dnw-gr_w , ppolyf_s_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw+gr_w, ppolyf_s_res_l+dnwell_enc_poly+pcmp_gr2dnw+gr_w)
cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner)
ppolyf_s_res_cell.shapes(comp).insert(cmp_gr)
pp_inner = pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw+implant_cmp_enc, -dnwell_enc_poly-pcmp_gr2dnw+implant_cmp_enc , ppolyf_s_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw-implant_cmp_enc, ppolyf_s_res_l+dnwell_enc_poly+pcmp_gr2dnw-implant_cmp_enc)
pp_outer = pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw-gr_w-implant_cmp_enc, -dnwell_enc_poly-pcmp_gr2dnw-gr_w-implant_cmp_enc , ppolyf_s_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw+gr_w+implant_cmp_enc, ppolyf_s_res_l+dnwell_enc_poly+pcmp_gr2dnw+gr_w+implant_cmp_enc)
pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner)
ppolyf_s_res_cell.shapes(pplus).insert(pp_gr)
else:
ppolyf_s_res_cell.shapes(pplus).insert(pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-implant_cmp_enc, -implant_cmp_enc , -poly_res_enc-ppoly_pcmp_spc+implant_cmp_enc, ppolyf_s_res_l+implant_cmp_enc))
ppolyf_s_res_cell.flatten(True)
return ppolyf_s_res_cell
def draw_npolyf_u_res(layout, l, w, deepnwell, pcmpgr):
'''
Usage:-
used to draw 3-terminal unsalicided n+ poly resistor (Outside DNWELL) by specifying parameters
Arguments:-
layout : Object of layout
l : Float of diff length
w : Float of diff width
'''
# Define layers
dnwell = layout.layer(12 , 0 )
comp = layout.layer(22 , 0 )
poly = layout.layer(30 , 0 )
pplus = layout.layer(31 , 0 )
nplus = layout.layer(32 , 0 )
contact = layout.layer(33 , 0 )
metal1 = layout.layer(34 , 0 )
sab = layout.layer(49 , 0 )
res_mk = layout.layer(110, 5 )
# VARIABLES
dbu_PERCISION = 1/layout.dbu
npolyf_u_res_w = w * dbu_PERCISION
npolyf_u_res_l = l * dbu_PERCISION
poly_res_enc = 0.51 * dbu_PERCISION
sab_res_enc = 0.28 * dbu_PERCISION
implant_cmp_enc = 0.16 * dbu_PERCISION
implant_poly_enc = 0.3 * dbu_PERCISION
npoly_pcmp_spc = 0.72 * dbu_PERCISION
pcmp_width = 0.36 * dbu_PERCISION
metal_width = 0.34 * dbu_PERCISION
met_cont_enc = 0.06 * dbu_PERCISION
comp_cont_enc = 0.07 * dbu_PERCISION
cont_size = 0.22 * dbu_PERCISION
cont_min_spc = 0.25 * dbu_PERCISION
cmp_met_cont_enc_diff = 0.01 * dbu_PERCISION
dnwell_enc_ncmp = 0.62 * dbu_PERCISION
dnwell_enc_poly = 1.34 * dbu_PERCISION
pcmp_gr2dnw = 2.5 * dbu_PERCISION
gr_w = 0.36 * dbu_PERCISION
# Inserting npolyf_u_res cell
cell_index = layout.add_cell("npolyf_u_resistor")
npolyf_u_res_cell = layout.cell(cell_index)
# Inserting a contact cell
cont_cell_index = layout.add_cell("contact")
cont_cell = layout.cell(cont_cell_index)
cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size))
# Inserting res_mk
npolyf_u_res_cell.shapes(res_mk).insert(pya.Box(0, 0, npolyf_u_res_w, npolyf_u_res_l))
# Inserting sab
npolyf_u_res_cell.shapes(sab).insert(pya.Box(0, -sab_res_enc, npolyf_u_res_w, npolyf_u_res_l+sab_res_enc))
# Inserting n poly
npolyf_u_res_cell.shapes(poly).insert(pya.Box(-poly_res_enc, 0, npolyf_u_res_w+poly_res_enc, npolyf_u_res_l))
npolyf_u_res_cell.shapes(nplus).insert(pya.Box(-poly_res_enc-implant_poly_enc, -implant_poly_enc , npolyf_u_res_w+poly_res_enc+implant_poly_enc, npolyf_u_res_l+implant_poly_enc))
# Inserting npoly metal
npolyf_u_res_cell.shapes(metal1).insert(pya.Box(-poly_res_enc+cmp_met_cont_enc_diff , cmp_met_cont_enc_diff , -poly_res_enc+cmp_met_cont_enc_diff+metal_width , npolyf_u_res_l-cmp_met_cont_enc_diff)) #left
npolyf_u_res_cell.shapes(metal1).insert(pya.Box(npolyf_u_res_w+poly_res_enc-cmp_met_cont_enc_diff-metal_width, cmp_met_cont_enc_diff , npolyf_u_res_w+poly_res_enc-cmp_met_cont_enc_diff , npolyf_u_res_l-cmp_met_cont_enc_diff)) # Right
# Inserting npoly contacts
num_ncmp_left_con_1, ncmp_left_con_free_spc_1 = number_spc_contacts(metal_width, met_cont_enc, cont_min_spc, cont_size)
num_ncmp_left_con_2, ncmp_left_con_free_spc_2 = number_spc_contacts(npolyf_u_res_l-2*cmp_met_cont_enc_diff, met_cont_enc, cont_min_spc, cont_size)
ncmp_left_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-poly_res_enc+cmp_met_cont_enc_diff+ncmp_left_con_free_spc_1 / 2, cmp_met_cont_enc_diff+ncmp_left_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_left_con_1, num_ncmp_left_con_2)
npolyf_u_res_cell.insert(ncmp_left_con_arr)
num_ncmp_right_con_1, ncmp_right_con_free_spc_1 = number_spc_contacts(metal_width, met_cont_enc, cont_min_spc, cont_size)
num_ncmp_right_con_2, ncmp_right_con_free_spc_2 = number_spc_contacts(npolyf_u_res_l-2*cmp_met_cont_enc_diff, met_cont_enc, cont_min_spc, cont_size)
ncmp_right_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(npolyf_u_res_w+poly_res_enc-cmp_met_cont_enc_diff-metal_width+ncmp_right_con_free_spc_1 / 2, cmp_met_cont_enc_diff+ncmp_right_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_right_con_1, num_ncmp_right_con_2)
npolyf_u_res_cell.insert(ncmp_right_con_arr)
# Inserting p diffusion
npolyf_u_res_cell.shapes(comp).insert(pya.Box(-poly_res_enc-npoly_pcmp_spc-pcmp_width, 0, -poly_res_enc-npoly_pcmp_spc, npolyf_u_res_l))
# Inserting pcomp metal
npolyf_u_res_cell.shapes(metal1).insert(pya.Box(-poly_res_enc-npoly_pcmp_spc-pcmp_width, 0, -poly_res_enc-npoly_pcmp_spc, npolyf_u_res_l))
# Inserting pcomp contacts
num_pcmp_con_1, pcmp_con_free_spc_1 = number_spc_contacts(pcmp_width, comp_cont_enc, cont_min_spc, cont_size)
num_pcmp_con_2, pcmp_con_free_spc_2 = number_spc_contacts(npolyf_u_res_l, comp_cont_enc, cont_min_spc, cont_size)
pcmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-poly_res_enc-npoly_pcmp_spc-pcmp_width+pcmp_con_free_spc_1 / 2, pcmp_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_pcmp_con_1, num_pcmp_con_2)
npolyf_u_res_cell.insert(pcmp_con_arr)
if deepnwell == True:
# Inserting Ntap
npolyf_u_res_cell.shapes(nplus).insert(pya.Box(-poly_res_enc-npoly_pcmp_spc-pcmp_width-implant_cmp_enc, -implant_cmp_enc , -poly_res_enc-npoly_pcmp_spc+implant_cmp_enc, npolyf_u_res_l+implant_cmp_enc))
# Inserting dnwell
npolyf_u_res_cell.shapes(dnwell).insert(pya.Box(-poly_res_enc-npoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp, -dnwell_enc_poly , npolyf_u_res_w+poly_res_enc+dnwell_enc_poly, npolyf_u_res_l+dnwell_enc_poly))
# Inserting Guard Ring
if pcmpgr == True:
cmp_inner = pya.Box(-poly_res_enc-npoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw, -dnwell_enc_poly-pcmp_gr2dnw , npolyf_u_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw, npolyf_u_res_l+dnwell_enc_poly+pcmp_gr2dnw)
cmp_outer = pya.Box(-poly_res_enc-npoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw-gr_w, -dnwell_enc_poly-pcmp_gr2dnw-gr_w , npolyf_u_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw+gr_w, npolyf_u_res_l+dnwell_enc_poly+pcmp_gr2dnw+gr_w)
cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner)
npolyf_u_res_cell.shapes(comp).insert(cmp_gr)
pp_inner = pya.Box(-poly_res_enc-npoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw+implant_cmp_enc, -dnwell_enc_poly-pcmp_gr2dnw+implant_cmp_enc , npolyf_u_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw-implant_cmp_enc, npolyf_u_res_l+dnwell_enc_poly+pcmp_gr2dnw-implant_cmp_enc)
pp_outer = pya.Box(-poly_res_enc-npoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw-gr_w-implant_cmp_enc, -dnwell_enc_poly-pcmp_gr2dnw-gr_w-implant_cmp_enc , npolyf_u_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw+gr_w+implant_cmp_enc, npolyf_u_res_l+dnwell_enc_poly+pcmp_gr2dnw+gr_w+implant_cmp_enc)
pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner)
npolyf_u_res_cell.shapes(pplus).insert(pp_gr)
else:
npolyf_u_res_cell.shapes(pplus).insert(pya.Box(-poly_res_enc-npoly_pcmp_spc-pcmp_width-implant_cmp_enc, -implant_cmp_enc , -poly_res_enc-npoly_pcmp_spc+implant_cmp_enc, npolyf_u_res_l+implant_cmp_enc))
npolyf_u_res_cell.flatten(True)
return npolyf_u_res_cell
def draw_ppolyf_u_res(layout, l, w, deepnwell, pcmpgr):
'''
Usage:-
used to draw 3-terminal unsalicided p+ poly resistor (Outside DNWELL) by specifying parameters
Arguments:-
layout : Object of layout
l : Float of diff length
w : Float of diff width
'''
# Define layers
dnwell = layout.layer(12 , 0 )
comp = layout.layer(22 , 0 )
poly = layout.layer(30 , 0 )
pplus = layout.layer(31 , 0 )
nplus = layout.layer(32 , 0 )
contact = layout.layer(33 , 0 )
metal1 = layout.layer(34 , 0 )
sab = layout.layer(49 , 0 )
res_mk = layout.layer(110, 5 )
# VARIABLES
dbu_PERCISION = 1/layout.dbu
ppolyf_u_res_w = w * dbu_PERCISION
ppolyf_u_res_l = l * dbu_PERCISION
poly_res_enc = 0.51 * dbu_PERCISION
sab_res_enc = 0.28 * dbu_PERCISION
implant_cmp_enc = 0.16 * dbu_PERCISION
implant_poly_enc = 0.3 * dbu_PERCISION
ppoly_pcmp_spc = 0.86 * dbu_PERCISION
pcmp_width = 0.36 * dbu_PERCISION
metal_width = 0.34 * dbu_PERCISION
met_cont_enc = 0.06 * dbu_PERCISION
comp_cont_enc = 0.07 * dbu_PERCISION
cont_size = 0.22 * dbu_PERCISION
cont_min_spc = 0.25 * dbu_PERCISION
cmp_met_cont_enc_diff = 0.01 * dbu_PERCISION
dnwell_enc_ncmp = 0.62 * dbu_PERCISION
dnwell_enc_poly = 1.34 * dbu_PERCISION
pcmp_gr2dnw = 2.5 * dbu_PERCISION
gr_w = 0.36 * dbu_PERCISION
# Inserting ppolyf_u_res cell
cell_index = layout.add_cell("ppolyf_u_resistor")
ppolyf_u_res_cell = layout.cell(cell_index)
# Inserting a contact cell
cont_cell_index = layout.add_cell("contact")
cont_cell = layout.cell(cont_cell_index)
cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size))
# Inserting res_mk
ppolyf_u_res_cell.shapes(res_mk).insert(pya.Box(0, 0, ppolyf_u_res_w, ppolyf_u_res_l))
# Inserting sab
ppolyf_u_res_cell.shapes(sab).insert(pya.Box(0, -sab_res_enc, ppolyf_u_res_w, ppolyf_u_res_l+sab_res_enc))
# Inserting p poly
ppolyf_u_res_cell.shapes(poly).insert(pya.Box(-poly_res_enc, 0, ppolyf_u_res_w+poly_res_enc, ppolyf_u_res_l))
ppolyf_u_res_cell.shapes(pplus).insert(pya.Box(-poly_res_enc-implant_poly_enc, -implant_poly_enc , ppolyf_u_res_w+poly_res_enc+implant_poly_enc, ppolyf_u_res_l+implant_poly_enc))
# Inserting npoly metal
ppolyf_u_res_cell.shapes(metal1).insert(pya.Box(-poly_res_enc+cmp_met_cont_enc_diff , cmp_met_cont_enc_diff , -poly_res_enc+cmp_met_cont_enc_diff+metal_width , ppolyf_u_res_l-cmp_met_cont_enc_diff)) #left
ppolyf_u_res_cell.shapes(metal1).insert(pya.Box(ppolyf_u_res_w+poly_res_enc-cmp_met_cont_enc_diff-metal_width, cmp_met_cont_enc_diff , ppolyf_u_res_w+poly_res_enc-cmp_met_cont_enc_diff , ppolyf_u_res_l-cmp_met_cont_enc_diff)) # Right
# Inserting npoly contacts
num_ncmp_left_con_1, ncmp_left_con_free_spc_1 = number_spc_contacts(metal_width, met_cont_enc, cont_min_spc, cont_size)
num_ncmp_left_con_2, ncmp_left_con_free_spc_2 = number_spc_contacts(ppolyf_u_res_l-2*cmp_met_cont_enc_diff, met_cont_enc, cont_min_spc, cont_size)
ncmp_left_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-poly_res_enc+cmp_met_cont_enc_diff+ncmp_left_con_free_spc_1 / 2, cmp_met_cont_enc_diff+ncmp_left_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_left_con_1, num_ncmp_left_con_2)
ppolyf_u_res_cell.insert(ncmp_left_con_arr)
num_ncmp_right_con_1, ncmp_right_con_free_spc_1 = number_spc_contacts(metal_width, met_cont_enc, cont_min_spc, cont_size)
num_ncmp_right_con_2, ncmp_right_con_free_spc_2 = number_spc_contacts(ppolyf_u_res_l-2*cmp_met_cont_enc_diff, met_cont_enc, cont_min_spc, cont_size)
ncmp_right_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(ppolyf_u_res_w+poly_res_enc-cmp_met_cont_enc_diff-metal_width+ncmp_right_con_free_spc_1 / 2, cmp_met_cont_enc_diff+ncmp_right_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_right_con_1, num_ncmp_right_con_2)
ppolyf_u_res_cell.insert(ncmp_right_con_arr)
# Inserting p diffusion
ppolyf_u_res_cell.shapes(comp).insert(pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width, 0, -poly_res_enc-ppoly_pcmp_spc, ppolyf_u_res_l))
# Inserting pcomp metal
ppolyf_u_res_cell.shapes(metal1).insert(pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width, 0, -poly_res_enc-ppoly_pcmp_spc, ppolyf_u_res_l))
# Inserting pcomp contacts
num_pcmp_con_1, pcmp_con_free_spc_1 = number_spc_contacts(pcmp_width, comp_cont_enc, cont_min_spc, cont_size)
num_pcmp_con_2, pcmp_con_free_spc_2 = number_spc_contacts(ppolyf_u_res_l, comp_cont_enc, cont_min_spc, cont_size)
pcmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-poly_res_enc-ppoly_pcmp_spc-pcmp_width+pcmp_con_free_spc_1 / 2, pcmp_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_pcmp_con_1, num_pcmp_con_2)
ppolyf_u_res_cell.insert(pcmp_con_arr)
if deepnwell == True:
# Inserting Ntap
ppolyf_u_res_cell.shapes(nplus).insert(pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-implant_cmp_enc, -implant_cmp_enc , -poly_res_enc-ppoly_pcmp_spc+implant_cmp_enc, ppolyf_u_res_l+implant_cmp_enc))
# Inserting dnwell
ppolyf_u_res_cell.shapes(dnwell).insert(pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp, -dnwell_enc_poly , ppolyf_u_res_w+poly_res_enc+dnwell_enc_poly, ppolyf_u_res_l+dnwell_enc_poly))
# Inserting Guard Ring
if pcmpgr == True:
cmp_inner = pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw, -dnwell_enc_poly-pcmp_gr2dnw , ppolyf_u_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw, ppolyf_u_res_l+dnwell_enc_poly+pcmp_gr2dnw)
cmp_outer = pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw-gr_w, -dnwell_enc_poly-pcmp_gr2dnw-gr_w , ppolyf_u_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw+gr_w, ppolyf_u_res_l+dnwell_enc_poly+pcmp_gr2dnw+gr_w)
cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner)
ppolyf_u_res_cell.shapes(comp).insert(cmp_gr)
pp_inner = pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw+implant_cmp_enc, -dnwell_enc_poly-pcmp_gr2dnw+implant_cmp_enc , ppolyf_u_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw-implant_cmp_enc, ppolyf_u_res_l+dnwell_enc_poly+pcmp_gr2dnw-implant_cmp_enc)
pp_outer = pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw-gr_w-implant_cmp_enc, -dnwell_enc_poly-pcmp_gr2dnw-gr_w-implant_cmp_enc , ppolyf_u_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw+gr_w+implant_cmp_enc, ppolyf_u_res_l+dnwell_enc_poly+pcmp_gr2dnw+gr_w+implant_cmp_enc)
pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner)
ppolyf_u_res_cell.shapes(pplus).insert(pp_gr)
else:
ppolyf_u_res_cell.shapes(pplus).insert(pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-implant_cmp_enc, -implant_cmp_enc , -poly_res_enc-ppoly_pcmp_spc+implant_cmp_enc, ppolyf_u_res_l+implant_cmp_enc))
ppolyf_u_res_cell.flatten(True)
return ppolyf_u_res_cell
def draw_ppolyf_u_high_Rs_res(layout, l, w , volt, deepnwell, pcmpgr):
'''
Usage:-
used to draw high-Rs p+ poly resistor (outside DNWELL) by specifying parameters
Arguments:-
layout : Object of layout
l : Float of diff length
w : Float of diff width
'''
# Define layers
dnwell = layout.layer(12 , 0 )
comp = layout.layer(22 , 0 )
poly = layout.layer(30 , 0 )
nplus = layout.layer(32 , 0 )
pplus = layout.layer(31 , 0 )
contact = layout.layer(33 , 0 )
metal1 = layout.layer(34 , 0 )
sab = layout.layer(49 , 0 )
res_mk = layout.layer(110, 5 )
resistor = layout.layer(62 , 0 )
dualgate = layout.layer(55 , 0 )
# VARIABLES
dbu_PERCISION = 1/layout.dbu
ppolyf_u_high_Rs_res_w = w * dbu_PERCISION
ppolyf_u_high_Rs_res_l = l * dbu_PERCISION
poly_res_enc = 0.64 * dbu_PERCISION
sab_res_enc = 0.28 * dbu_PERCISION
sab_res_ext = 0.1 * dbu_PERCISION
implant_cmp_enc = 0.02 * dbu_PERCISION
implant_poly_enc = 0.18 * dbu_PERCISION
ppoly_pcmp_spc = 0.7 * dbu_PERCISION
pcmp_width = 0.42 * dbu_PERCISION
metal_width = 0.34 * dbu_PERCISION
met_cont_enc = 0.06 * dbu_PERCISION
comp_cont_enc = 0.07 * dbu_PERCISION
cont_size = 0.22 * dbu_PERCISION
cont_min_spc = 0.25 * dbu_PERCISION
cmp_met_cont_enc_diff = 0.01 * dbu_PERCISION
resistor_poly_enc = 0.4 * dbu_PERCISION
dnwell_enc_ncmp = 0.62 * dbu_PERCISION
dnwell_enc_poly = 1.34 * dbu_PERCISION
pcmp_gr2dnw = 2.5 * dbu_PERCISION
gr_w = 0.36 * dbu_PERCISION
dg_enc_dnwell = 0.5 * dbu_PERCISION
if volt == "5/6V":
dnwell_enc_ncmp = 0.66 * dbu_PERCISION
# Inserting ppolyf_u_high_Rs_res cell
cell_index = layout.add_cell("ppolyf_u_high_Rs_resistor")
ppolyf_u_high_Rs_res_cell = layout.cell(cell_index)
# Inserting a contact cell
cont_cell_index = layout.add_cell("contact")
cont_cell = layout.cell(cont_cell_index)
cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size))
# Inserting res_mk
ppolyf_u_high_Rs_res_cell.shapes(res_mk).insert(pya.Box(0, 0, ppolyf_u_high_Rs_res_w, ppolyf_u_high_Rs_res_l))
# Inserting sab
ppolyf_u_high_Rs_res_cell.shapes(sab).insert(pya.Box(-sab_res_ext, -sab_res_enc, ppolyf_u_high_Rs_res_w+sab_res_ext, ppolyf_u_high_Rs_res_l+sab_res_enc))
# Inserting p poly
ppolyf_u_high_Rs_res_cell.shapes(poly).insert(pya.Box(-poly_res_enc, 0, ppolyf_u_high_Rs_res_w+poly_res_enc, ppolyf_u_high_Rs_res_l))
ppolyf_u_high_Rs_res_cell.shapes(pplus).insert(pya.Box(-poly_res_enc-implant_poly_enc, -implant_poly_enc , 0 , ppolyf_u_high_Rs_res_l+implant_poly_enc))
ppolyf_u_high_Rs_res_cell.shapes(pplus).insert(pya.Box(ppolyf_u_high_Rs_res_w, -implant_poly_enc , ppolyf_u_high_Rs_res_w+poly_res_enc+implant_poly_enc, ppolyf_u_high_Rs_res_l+implant_poly_enc))
# Inserting npoly metal
ppolyf_u_high_Rs_res_cell.shapes(metal1).insert(pya.Box(-poly_res_enc+cmp_met_cont_enc_diff , cmp_met_cont_enc_diff , -poly_res_enc+cmp_met_cont_enc_diff+metal_width , ppolyf_u_high_Rs_res_l-cmp_met_cont_enc_diff)) #left
ppolyf_u_high_Rs_res_cell.shapes(metal1).insert(pya.Box(ppolyf_u_high_Rs_res_w+poly_res_enc-cmp_met_cont_enc_diff-metal_width, cmp_met_cont_enc_diff , ppolyf_u_high_Rs_res_w+poly_res_enc-cmp_met_cont_enc_diff , ppolyf_u_high_Rs_res_l-cmp_met_cont_enc_diff)) # Right
# Inserting npoly contacts
num_ncmp_left_con_1, ncmp_left_con_free_spc_1 = number_spc_contacts(metal_width, met_cont_enc, cont_min_spc, cont_size)
num_ncmp_left_con_2, ncmp_left_con_free_spc_2 = number_spc_contacts(ppolyf_u_high_Rs_res_l-2*cmp_met_cont_enc_diff, met_cont_enc, cont_min_spc, cont_size)
ncmp_left_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-poly_res_enc+cmp_met_cont_enc_diff+ncmp_left_con_free_spc_1 / 2, cmp_met_cont_enc_diff+ncmp_left_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_left_con_1, num_ncmp_left_con_2)
ppolyf_u_high_Rs_res_cell.insert(ncmp_left_con_arr)
num_ncmp_right_con_1, ncmp_right_con_free_spc_1 = number_spc_contacts(metal_width, met_cont_enc, cont_min_spc, cont_size)
num_ncmp_right_con_2, ncmp_right_con_free_spc_2 = number_spc_contacts(ppolyf_u_high_Rs_res_l-2*cmp_met_cont_enc_diff, met_cont_enc, cont_min_spc, cont_size)
ncmp_right_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(ppolyf_u_high_Rs_res_w+poly_res_enc-cmp_met_cont_enc_diff-metal_width+ncmp_right_con_free_spc_1 / 2, cmp_met_cont_enc_diff+ncmp_right_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_ncmp_right_con_1, num_ncmp_right_con_2)
ppolyf_u_high_Rs_res_cell.insert(ncmp_right_con_arr)
# Inserting p diffusion
ppolyf_u_high_Rs_res_cell.shapes(comp).insert(pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width, 0, -poly_res_enc-ppoly_pcmp_spc, ppolyf_u_high_Rs_res_l))
# Inserting pcomp metal
ppolyf_u_high_Rs_res_cell.shapes(metal1).insert(pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width, 0, -poly_res_enc-ppoly_pcmp_spc, ppolyf_u_high_Rs_res_l))
# Inserting pcomp contacts
num_pcmp_con_1, pcmp_con_free_spc_1 = number_spc_contacts(pcmp_width, comp_cont_enc, cont_min_spc, cont_size)
num_pcmp_con_2, pcmp_con_free_spc_2 = number_spc_contacts(ppolyf_u_high_Rs_res_l, comp_cont_enc, cont_min_spc, cont_size)
pcmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans(
pya.Point(-poly_res_enc-ppoly_pcmp_spc-pcmp_width+pcmp_con_free_spc_1 / 2, pcmp_con_free_spc_2/2)),
pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size),
num_pcmp_con_1, num_pcmp_con_2)
ppolyf_u_high_Rs_res_cell.insert(pcmp_con_arr)
# Inserting resistor
ppolyf_u_high_Rs_res_cell.shapes(resistor).insert(pya.Box(-poly_res_enc-resistor_poly_enc, -resistor_poly_enc , ppolyf_u_high_Rs_res_w+poly_res_enc+resistor_poly_enc, ppolyf_u_high_Rs_res_l+resistor_poly_enc))
if deepnwell == True:
# Inserting Ntap
ppolyf_u_high_Rs_res_cell.shapes(nplus).insert(pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-implant_cmp_enc, -implant_cmp_enc , -poly_res_enc-ppoly_pcmp_spc+implant_cmp_enc, ppolyf_u_high_Rs_res_l+implant_cmp_enc))
# Inserting dnwell
ppolyf_u_high_Rs_res_cell.shapes(dnwell).insert(pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp, -dnwell_enc_poly , ppolyf_u_high_Rs_res_w+poly_res_enc+dnwell_enc_poly, ppolyf_u_high_Rs_res_l+dnwell_enc_poly))
# for 5/6V
# Inserting dualgate
if volt == "5/6V":
ppolyf_u_high_Rs_res_cell.shapes(dualgate).insert(pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-dg_enc_dnwell, -dnwell_enc_poly-dg_enc_dnwell , ppolyf_u_high_Rs_res_w+poly_res_enc+dnwell_enc_poly+dg_enc_dnwell, ppolyf_u_high_Rs_res_l+dnwell_enc_poly+dg_enc_dnwell))
# Inserting Guard Ring
if pcmpgr == True:
cmp_inner = pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw, -dnwell_enc_poly-pcmp_gr2dnw , ppolyf_u_high_Rs_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw, ppolyf_u_high_Rs_res_l+dnwell_enc_poly+pcmp_gr2dnw)
cmp_outer = pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw-gr_w, -dnwell_enc_poly-pcmp_gr2dnw-gr_w , ppolyf_u_high_Rs_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw+gr_w, ppolyf_u_high_Rs_res_l+dnwell_enc_poly+pcmp_gr2dnw+gr_w)
cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner)
ppolyf_u_high_Rs_res_cell.shapes(comp).insert(cmp_gr)
pp_inner = pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw+implant_cmp_enc, -dnwell_enc_poly-pcmp_gr2dnw+implant_cmp_enc , ppolyf_u_high_Rs_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw-implant_cmp_enc, ppolyf_u_high_Rs_res_l+dnwell_enc_poly+pcmp_gr2dnw-implant_cmp_enc)
pp_outer = pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-dnwell_enc_ncmp-pcmp_gr2dnw-gr_w-implant_cmp_enc, -dnwell_enc_poly-pcmp_gr2dnw-gr_w-implant_cmp_enc , ppolyf_u_high_Rs_res_w+poly_res_enc+dnwell_enc_poly+pcmp_gr2dnw+gr_w+implant_cmp_enc, ppolyf_u_high_Rs_res_l+dnwell_enc_poly+pcmp_gr2dnw+gr_w+implant_cmp_enc)
pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner)
ppolyf_u_high_Rs_res_cell.shapes(pplus).insert(pp_gr)
else:
ppolyf_u_high_Rs_res_cell.shapes(pplus).insert(pya.Box(-poly_res_enc-ppoly_pcmp_spc-pcmp_width-implant_cmp_enc, -implant_cmp_enc , -poly_res_enc-ppoly_pcmp_spc+implant_cmp_enc, ppolyf_u_high_Rs_res_l+implant_cmp_enc))
# for 5/6V
# Inserting dualgate
if volt == "5/6V":
ppolyf_u_high_Rs_res_cell.shapes(dualgate).insert(pya.Box(-poly_res_enc-resistor_poly_enc, -resistor_poly_enc , ppolyf_u_high_Rs_res_w+poly_res_enc+resistor_poly_enc, ppolyf_u_high_Rs_res_l+resistor_poly_enc))
ppolyf_u_high_Rs_res_cell.flatten(True)
return ppolyf_u_high_Rs_res_cell