blob: 3c93726abdc63a27eb8cac32c94764a72d169e7a [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
#
# https://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.
################################################################################################
if FEOL
#================================================
#----------------P+ POLY RESISTOR----------------
#================================================
pres_poly = poly2.and(pplus).interacting(sab).interacting(res_mk).not_interacting(resistor)
pres_poly_lv_mv = pres_poly.not(hvpolyrs)
pres_poly_hv = pres_poly.and(hvpolyrs)
# Rule PRES.1 : Minimum width of Poly2 resistor. is 0.8µm
logger.info('Executing rule PRES.1')
pres1_l1_lm = pres_poly_lv_mv.width(0.8.um, euclidian).polygons(0.001)
pres1_l1_lm.output('PRES.1', 'PRES.1 : Minimum width of Poly2 resistor. : 0.8µm')
pres1_l1_lm.forget
# Rule PRES.1_HV : Minimum width of Poly2 resistor. is 0.8µm
logger.info('Executing rule PRES.1_HV')
pres1_l1_h = pres_poly_hv.width(0.8.um, euclidian).polygons(0.001)
pres1_l1_h.output('PRES.1_HV', 'PRES.1_HV : Minimum width of Poly2 resistor. : 0.8µm')
pres1_l1_h.forget
# Rule PRES.2: Minimum space between Poly2 resistors. is 0.4µm
logger.info('Executing rule PRES.2')
pres2_l1_lm = pres_poly_lv_mv.isolated(0.4.um, euclidian).polygons(0.001)
pres2_l1_lm.output('PRES.2', 'PRES.2 : Minimum space between Poly2 resistors. : 0.4µm')
pres2_l1_lm.forget
# Rule PRES.2_HV: Minimum space between Poly2 resistors. is 0.4µm
logger.info('Executing rule PRES.2_HV')
pres2_l1_h = pres_poly_hv.isolated(0.4.um, euclidian).polygons(0.001)
pres2_l1_h.output('PRES.2_HV', 'PRES.2_HV : Minimum space between Poly2 resistors. : 0.4µm')
pres2_l1_h.forget
# Rule PRES.3: Minimum space from Poly2 resistor to COMP. 0.6µm
logger.info('Executing rule PRES.3')
pres3_l1_lm = pres_poly_lv_mv.separation(comp, 0.6.um, euclidian).polygons(0.001).or(comp.not_outside(pres_poly))
pres3_l1_lm.output('PRES.3', 'PRES.3 : Minimum space from Poly2 resistor to COMP. is 0.6µm')
pres3_l1_lm.forget
# Rule PRES.3_HV: Minimum space from Poly2 resistor to COMP. 0.6µm
logger.info('Executing rule PRES.3_HV')
pres3_l1_h = pres_poly_hv.separation(comp, 0.6.um, euclidian).polygons(0.001).or(comp.not_outside(pres_poly))
pres3_l1_h.output('PRES.3_HV', 'PRES.3_HV : Minimum space from Poly2 resistor to COMP. is 0.6µm')
pres3_l1_h.forget
# Rule PRES.4: Minimum space from Poly2 resistor to unrelated Poly2. is 0.6µm
logger.info('Executing rule PRES.4')
pres4_l1_lm = pres_poly_lv_mv.separation(poly2.not_interacting(sab), 0.6.um, euclidian).polygons(0.001)
pres4_l1_lm.output('PRES.4', 'PRES.4 : Minimum space from Poly2 resistor to unrelated Poly2. : 0.6µm')
pres4_l1_lm.forget
# Rule PRES.4_HV: Minimum space from Poly2 resistor to unrelated Poly2. is 0.6µm
logger.info('Executing rule PRES.4_HV')
pres4_l1_h = pres_poly_hv.separation(poly2.not_interacting(sab), 0.6.um, euclidian).polygons(0.001)
pres4_l1_h.output('PRES.4_HV', 'PRES.4_HV : Minimum space from Poly2 resistor to unrelated Poly2. : 0.6µm')
pres4_l1_h.forget
# Rule PRES.5: Minimum PPlus implant enclose Poly2 resistor. is 0.3µm
logger.info('Executing rule PRES.5')
pres5_l1_lm = pplus.enclosing(pres_poly_lv_mv, 0.3.um, euclidian).polygons(0.001)
pres5_l2_lm = pres_poly_lv_mv.not_outside(pplus).not(pplus)
pres5_l_lm = pres5_l1_lm.or(pres5_l2_lm)
pres5_l_lm.output('PRES.5', 'PRES.5 : Minimum PPlus implant overlap of Poly2 resistor. : 0.3µm')
pres5_l1_lm.forget
pres5_l2_lm.forget
pres5_l_lm.forget
# Rule PRES.5_HV: Minimum PPlus implant enclose Poly2 resistor. is 0.3µm
logger.info('Executing rule PRES.5_HV')
pres5_l1_h = pplus.enclosing(pres_poly_hv, 0.3.um, euclidian).polygons(0.001)
pres5_l2_h = pres_poly_hv.not_outside(pplus).not(pplus)
pres5_l_h = pres5_l1_h.or(pres5_l2_h)
pres5_l_h.output('PRES.5_HV', 'PRES.5_HV : Minimum PPlus implant overlap of Poly2 resistor. : 0.3µm')
pres5_l1_h.forget
pres5_l2_h.forget
pres5_l_h.forget
# Rule PRES.6: Minimum salicide block overlap of Poly2 resistor in width direction is 0.3µm.
logger.info('Executing rule PRES.6')
pres6_l1 = sab.enclosing(pres_poly_lv_mv,0.3.um).polygons(0.001)
pres6_l1.output('PRES.6', 'PRES.6 : Minimum salicide block overlap of Poly2 resistor in width direction. : 0.3µm')
pres6_l1.forget
# Rule PRES.6_HV: Minimum salicide block overlap of Poly2 resistor in width direction is 0.3µm.
logger.info('Executing rule PRES.6_HV')
pres6_l1 = sab.enclosing(pres_poly_hv,0.3.um).polygons(0.001)
pres6_l1.output('PRES.6_HV', 'PRES.6_HV : Minimum salicide block overlap of Poly2 resistor in width direction. : 0.3µm')
pres6_l1.forget
# Rule PRES.7: Space from salicide block to contact on Poly2 resistor is 0.22um.
logger.info('Executing rule PRES.7')
pres7_l1_lm = contact.inside(pres_poly_lv_mv).separation(sab,0.22.um).polygons(0.001).or(contact.inside(pres_poly_lv_mv).interacting(sab))
pres7_l1_lm.output('PRES.7', 'PRES.7 : Space from salicide block to contact on Poly2 resistor.: 0.22um')
pres7_l1_lm.forget
# Rule PRES.7_HV: Space from salicide block to contact on Poly2 resistor is 0.22um.
logger.info('Executing rule PRES.7_HV')
pres7_l1_h = contact.inside(pres_poly_hv).separation(sab,0.22.um).polygons(0.001).or(contact.inside(pres_poly_hv).interacting(sab))
pres7_l1_h.output('PRES.7_HV', 'PRES.7_HV : Space from salicide block to contact on Poly2 resistor.: 0.22um')
pres7_l1_h.forget
# rule PRES.8 is not a DRC check
# Rule PRES.9a : All High Voltage Poly2 resistors shall be covered by “HVPOLYRS” Marking layer (to identify HV Poly2 resistors). Min “HVPOLYRS” overlap of poly2 is 0.0µm.
pres9a_l1 = pres_poly.interacting(hvpolyrs).not(hvpolyrs)
pres9a_l1.output('PRES.9a','PRES.9a : All High Voltage Poly2 resistors shall be covered by HVPOLYRS Marking layer (to identify HV Poly2 resistors). Min HVPOLYRS overlap of poly2 is 0.0µm.')
pres9a_l1.forget
# Rule PRES.9b : Minimum Poly2 to Guard-ring space is 0.7µm,
# Following layers are not allowed between Poly2 resistor & guard ring: ((Nwell OR ndif) OUTSIDE DNWELL), gate, IND_MK, FuseTop, HVNDDD, HVPDDD)
logger.info('Executing rule PRES.9b')
pres9b_gr = (pcomp.outside(dnwell)).or(ncomp.inside(dnwell))
pres9b_l1 = poly2.interacting(pres_poly_hv).separation(pres9b_gr,0.7.um).polygons(0.001)
pres9b_l2 = pres9b_gr.holes.not(pres_poly_hv).interacting((nwell.outside(dnwell).or(tgate.or(ind_mk.or(fusetop.or(hvnddd.or(hvpddd)))))))
pres9b_l3 = pres_poly_hv.not_inside(pres9b_gr.holes)
pres9b_l = pres9b_l1.or(pres9b_l2.or(pres9b_l3))
pres9b_l.output('PRES.9b','Rule PRES.9b : Minimum Poly2 to Guard-ring space is 0.7µm, Following layers are not allowed between Poly2 resistor & guard ring: ((Nwell OR ndif) OUTSIDE DNWELL), gate, IND_MK, FuseTop, HVNDDD, HVPDDD)')
pres9b_l.forget
pres9b_l1.forget
pres9b_l2.forget
# Rule PRES.10 : The total field (STI) area (X*Y) for Poly2 resistors should not be larger than 15000 um2,
# However, If the total area >15000um2, both sides of STI field area should not be larger than 80 um
logger.info('Executing rule PRES.10')
pres10_l1 = pres_poly.with_area(15000.01.um,nil).edges
pres10_l2 = pres10_l1.with_length(80.01.um,nil)
pres10_l = pres10_l1.or(pres10_l2)
pres10_l.output('PRES.10','Rule PRES.10 : The total field (STI) area (X*Y) for Poly2 resistors should not be larger than 15000 um2, However, If the total area >15000um2, both sides of STI field area should not be larger than 80 um')
mk_pres11a = res_mk.edges.not(poly2.and(pplus).and(sab).edges).inside_part(poly2)
# Rule PRES.11a: Pplus Poly2 resistor shall be covered by RES_MK marking. RES_MK length shall be coincide with resistor length (Defined by SAB length) and width covering the width of Poly2.
logger.info('Executing rule PRES.11a')
pres11a_l1 = res_mk.interacting(pres_poly).interacting(mk_pres11a)
pres11a_l1.output('PRES.11a', 'PRES.11a : Pplus Poly2 resistor shall be covered by RES_MK marking. RES_MK length shall be coincide with resistor length (Defined by SAB length) and width covering the width of Poly2.')
pres11a_l1.forget
mk_pres11a.forget
# Rule PRES.11b: If the size of single RES_MK mark layer is greater than 15000um2
## and both side (X and Y) are greater than 80um.
## then the minimum spacing to adjacent RES_MK layer. is 20µm
logger.info('Executing rule PRES.11b')
pres11b = res_mk.with_area(15_000.001.um, nil).edges.with_length(80.001.um, nil)
pres11b_l1 = pres11b.separation(res_mk.edges, 20.um)
pres11b_l1.output('PRES.11b',
'PRES.11b : If the size of single RES_MK mark layer is greater than 15000um2
and both side (X and Y) are greater than 80um.
then the minimum spacing to adjacent RES_MK layer. : 20µm')
pres11b_l1.forget
pres11b.forget
pres_poly.forget
end #FEOL