| ################################################################################################ |
| # 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 |